name = "rustc_macros"
version = "0.1.0"
dependencies = [
+ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
$ ./x.py build && sudo ./x.py install
```
+ If after running `sudo ./x.py install` you see an error message like
+
+ ```
+ error: failed to load source for a dependency on 'cc'
+ ```
+
+ then run these two commands and then try `sudo ./x.py install` again:
+
+ ```
+ $ cargo install cargo-vendor
+ ```
+
+ ```
+ $ cargo vendor
+ ```
+
> ***Note:*** Install locations can be adjusted by copying the config file
> from `./config.toml.example` to `./config.toml`, and
> adjusting the `prefix` option under `[install]`. Various other options, such
let path = builder.src.join("src/doc").join(markdown);
- let favicon = builder.src.join("src/doc/favicon.inc");
+ let header = builder.src.join("src/doc/redirect.inc");
let footer = builder.src.join("src/doc/footer.inc");
let version_info = out.join("version_info.html");
cmd.arg("--html-after-content").arg(&footer)
.arg("--html-before-content").arg(&version_info)
- .arg("--html-in-header").arg(&favicon)
+ .arg("--html-in-header").arg(&header)
.arg("--markdown-no-toc")
.arg("--markdown-playground-url")
.arg("https://play.rust-lang.org/")
--- /dev/null
+<meta name="robots" content="noindex,follow">
+<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
--- /dev/null
+# NB: This file is not automatically deployed. After changes, it needs to be uploaded manually to doc.rust-lang.org
+User-agent: *
+Disallow: /0.3/
+Disallow: /0.4/
+Disallow: /0.5/
+Disallow: /0.6/
+Disallow: /0.7/
+Disallow: /0.8/
+Disallow: /0.9/
+Disallow: /0.10/
+Disallow: /0.11.0/
+Disallow: /0.12.0/
+Disallow: /1.0.0-alpha/
+Disallow: /1.0.0-alpha.2/
+Disallow: /1.0.0-beta/
+Disallow: /1.0.0-beta.2/
+Disallow: /1.0.0-beta.3/
+Disallow: /1.0.0-beta.4/
+Disallow: /1.0.0-beta.5/
fn next_back(&mut self) -> Option<I::Item> {
(**self).next_back()
}
+ fn nth_back(&mut self, n: usize) -> Option<I::Item> {
+ (**self).nth_back(n)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {
#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]
+#![feature(iter_nth_back)]
// Allow testing this library
if self <= other { self } else { other }
}
- /// Returns max if self is greater than max, and min if self is less than min.
- /// Otherwise this will return self. Panics if min > max.
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
///
/// # Examples
///
assert!(min <= max);
if self < min {
min
- }
- else if self > max {
+ } else if self > max {
max
} else {
self
//! Traits for conversions between types.
//!
-//! The traits in this module provide a general way to talk about conversions
-//! from one type to another. They follow the standard Rust conventions of
-//! `as`/`into`/`from`.
+//! The traits in this module provide a way to convert from one type to another type.
+//! Each trait serves a different purpose:
//!
-//! Like many traits, these are often used as bounds for generic functions, to
-//! support arguments of multiple types.
+//! - Implement the [`AsRef`] trait for cheap reference-to-reference conversions
+//! - Implement the [`AsMut`] trait for cheap mutable-to-mutable conversions
+//! - Implement the [`From`] trait for consuming value-to-value conversions
+//! - Implement the [`Into`] trait for consuming value-to-value conversions to types
+//! outside the current crate
+//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
+//! but should be implemented when the conversion can fail.
//!
-//! - Implement the `As*` traits for reference-to-reference conversions
-//! - Implement the [`Into`] trait when you want to consume the value in the conversion
-//! - The [`From`] trait is the most flexible, useful for value _and_ reference conversions
-//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], but allow for the
-//! conversion to fail
+//! The traits in this module are often used as trait bounds for generic functions such that to
+//! arguments of multiple types are supported. See the documentation of each trait for examples.
//!
-//! As a library author, you should prefer implementing [`From<T>`][`From`] or
+//! As a library author, you should always prefer implementing [`From<T>`][`From`] or
//! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
//! as [`From`] and [`TryFrom`] provide greater flexibility and offer
//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a
-//! blanket implementation in the standard library. However, there are some cases
-//! where this is not possible, such as creating conversions into a type defined
-//! outside your library, so implementing [`Into`] instead of [`From`] is
-//! sometimes necessary.
+//! blanket implementation in the standard library. Only implement [`Into`] or [`TryInto`]
+//! when a conversion to a type outside the current crate is required.
//!
//! # Generic Implementations
//!
#[inline]
pub const fn identity<T>(x: T) -> T { x }
-/// A cheap reference-to-reference conversion. Used to convert a value to a
-/// reference value within generic code.
+/// Used to do a cheap reference-to-reference conversion.
///
-/// `AsRef` is very similar to, but serves a slightly different purpose than,
-/// [`Borrow`].
+/// This trait is similar to [`AsMut`] which is used for converting between mutable references.
+/// If you need to do a costly conversion it is better to implement [`From`] with type
+/// `&T` or write a custom function.
///
-/// `AsRef` is to be used when wishing to convert to a reference of another
-/// type.
-/// `Borrow` is more related to the notion of taking the reference. It is
-/// useful when wishing to abstract over the type of reference
-/// (`&T`, `&mut T`) or allow both the referenced and owned type to be treated
-/// in the same manner.
///
-/// The key difference between the two traits is the intention:
+/// `AsRef` is very similar to, but serves a slightly different purpose than [`Borrow`]:
///
/// - Use `AsRef` when the goal is to simply convert into a reference
/// - Use `Borrow` when the goal is related to writing code that is agnostic to
///
/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
///
-/// **Note: this trait must not fail**. If the conversion can fail, use a
+/// **Note: This trait must not fail**. If the conversion can fail, use a
/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
///
/// # Examples
///
-/// Both [`String`] and `&str` implement `AsRef<str>`:
+/// By using trait bounds we can accept arguments of different types as long as they can be
+/// converted a the specified type `T`.
+///
+/// For example: By creating a generic function that takes an `AsRef<str>` we express that we
+/// want to accept all references that can be converted to &str as an argument.
+/// Since both [`String`] and `&str` implement `AsRef<str>` we can accept both as input argument.
///
/// [`String`]: ../../std/string/struct.String.html
///
fn as_ref(&self) -> &T;
}
-/// A cheap, mutable reference-to-mutable reference conversion.
+/// Used to do a cheap mutable-to-mutable reference conversion.
///
-/// This trait is similar to `AsRef` but used for converting between mutable
-/// references.
+/// This trait is similar to [`AsRef`] but used for converting between mutable
+/// references. If you need to do a costly conversion it is better to
+/// implement [`From`] with type `&mut T` or write a custom function.
///
-/// **Note: this trait must not fail**. If the conversion can fail, use a
+/// **Note: This trait must not fail**. If the conversion can fail, use a
/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
///
/// # Examples
///
-/// [`Box<T>`] implements `AsMut<T>`:
-///
-/// [`Box<T>`]: ../../std/boxed/struct.Box.html
-///
+/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
+/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
+/// write a function `add_one`that takes all arguments that can be converted to `&mut u64`.
+/// Because [`Box<T>`] implements `AsMut<T>` `add_one` accepts arguments of type
+/// `&mut Box<u64>` as well:
/// ```
/// fn add_one<T: AsMut<u64>>(num: &mut T) {
/// *num.as_mut() += 1;
/// add_one(&mut boxed_num);
/// assert_eq!(*boxed_num, 1);
/// ```
-///
+/// [`Box<T>`]: ../../std/boxed/struct.Box.html
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
fn as_mut(&mut self) -> &mut T;
}
-/// A conversion that consumes `self`, which may or may not be expensive. The
-/// reciprocal of [`From`][From].
+/// A value-to-value conversion that consumes the input value. The
+/// opposite of [`From`].
///
-/// **Note: this trait must not fail**. If the conversion can fail, use
-/// [`TryInto`] or a dedicated method which returns an [`Option<T>`] or a
-/// [`Result<T, E>`].
+/// One should only implement [`Into`] if a conversion to a type outside the current crate is
+/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because
+/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to
+/// the blanket implementation in the standard library. [`From`] cannot do these type of
+/// conversions because of Rust's orphaning rules.
///
-/// Library authors should not directly implement this trait, but should prefer
-/// implementing the [`From`][From] trait, which offers greater flexibility and
-/// provides an equivalent `Into` implementation for free, thanks to a blanket
-/// implementation in the standard library.
+/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`].
///
/// # Generic Implementations
///
-/// - [`From<T>`][From]` for U` implies `Into<U> for T`
-/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
+/// - [`From<T>`]` for U` implies `Into<U> for T`
+/// - [`Into`]` is reflexive, which means that `Into<T> for T` is implemented
///
-/// # Implementing `Into`
+/// # Implementing `Into` for conversions to external types
///
-/// There is one exception to implementing `Into`, and it's kind of esoteric.
-/// If the destination type is not part of the current crate, and it uses a
-/// generic variable, then you can't implement `From` directly. For example,
-/// take this crate:
+/// If the destination type is not part of the current crate
+/// then you can't implement [`From`] directly.
+/// For example, take this code:
///
/// ```compile_fail
/// struct Wrapper<T>(Vec<T>);
/// }
/// }
/// ```
-///
-/// To fix this, you can implement `Into` directly:
+/// This will fail to compile because we cannot implement a trait for a type
+/// if both the trait and the type are not defined by the current crate.
+/// This is due to Rust's orphaning rules. To bypass this, you can implement `Into` directly:
///
/// ```
/// struct Wrapper<T>(Vec<T>);
/// }
/// ```
///
-/// This won't always allow the conversion: for example, `try!` and `?`
-/// always use `From`. However, in most cases, people use `Into` to do the
-/// conversions, and this will allow that.
+/// It is important to understand that `Into` does not provide a [`From`] implementation
+/// (as [`From`] does with `Into`). Therefore, you should always try to implement [`From`]
+/// and then fall back to `Into` if [`From`] can't be implemented.
///
-/// In almost all cases, you should try to implement `From`, then fall back
-/// to `Into` if `From` can't be implemented.
+/// Prefer using `Into` over [`From`] when specifying trait bounds on a generic function
+/// to ensure that types that only implement `Into` can be used as well.
///
/// # Examples
///
/// [`String`] implements `Into<Vec<u8>>`:
///
+/// In order to express that we want a generic function to take all arguments that can be
+/// converted to a specified type `T`, we can use a trait bound of `Into<T>`.
+/// For example: The function `is_hello` takes all arguments that can be converted into a
+/// `Vec<u8>`.
+///
/// ```
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
/// let bytes = b"hello".to_vec();
fn into(self) -> T;
}
-/// Simple and safe type conversions in to `Self`. It is the reciprocal of
-/// `Into`.
+/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
+/// [`Into`].
///
-/// This trait is useful when performing error handling as described by
-/// [the book][book] and is closely related to the `?` operator.
+/// One should always prefer implementing [`From`] over [`Into`]
+/// because implementing [`From`] automatically provides one with a implementation of [`Into`]
+/// thanks to the blanket implementation in the standard library.
///
-/// When constructing a function that is capable of failing the return type
-/// will generally be of the form `Result<T, E>`.
+/// Only implement [`Into`] if a conversion to a type outside the current crate is required.
+/// [`From`] cannot do these type of conversions because of Rust's orphaning rules.
+/// See [`Into`] for more details.
///
-/// The `From` trait allows for simplification of error handling by providing a
-/// means of returning a single error type that encapsulates numerous possible
-/// erroneous situations.
+/// Prefer using [`Into`] over using [`From`] when specifying trait bounds on a generic function.
+/// This way, types that directly implement [`Into`] can be used as arguments as well.
///
-/// This trait is not limited to error handling, rather the general case for
-/// this trait would be in any type conversions to have an explicit definition
-/// of how they are performed.
+/// The [`From`] is also very useful when performing error handling. When constructing a function
+/// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
+/// The `From` trait simplifies error handling by allowing a function to return a single error type
+/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
+/// details.
///
-/// **Note: this trait must not fail**. If the conversion can fail, use
-/// [`TryFrom`] or a dedicated method which returns an [`Option<T>`] or a
-/// [`Result<T, E>`].
+/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
///
/// # Generic Implementations
///
-/// - `From<T> for U` implies [`Into<U>`]` for T`
-/// - [`from`] is reflexive, which means that `From<T> for T` is implemented
+/// - [`From<T>`]` for U` implies [`Into<U>`]` for T`
+/// - [`From`] is reflexive, which means that `From<T> for T` is implemented
///
/// # Examples
///
/// [`String`] implements `From<&str>`:
///
+/// An explicit conversion from a &str to a String is done as follows:
/// ```
/// let string = "hello".to_string();
/// let other_string = String::from("hello");
/// assert_eq!(string, other_string);
/// ```
///
-/// An example usage for error handling:
+/// While performing error handling it is often useful to implement `From` for your own error type.
+/// By converting underlying error types to our own custom error type that encapsulates the
+/// underlying error type, we can return a single error type without losing information on the
+/// underlying cause. The '?' operator automatically converts the underlying error type to our
+/// custom error type by calling `Into<CliError>::into` which is automatically provided when
+/// implementing `From`. The compiler then infers which implementation of `Into` should be used.
///
/// ```
/// use std::fs;
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
- #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
- unsafe {
- asm!("pause" ::: "memory" : "volatile");
+ #[cfg(
+ all(
+ any(target_arch = "x86", target_arch = "x86_64"),
+ target_feature = "sse2"
+ )
+ )] {
+ #[cfg(target_arch = "x86")] {
+ unsafe { crate::arch::x86::_mm_pause() };
+ }
+
+ #[cfg(target_arch = "x86_64")] {
+ unsafe { crate::arch::x86_64::_mm_pause() };
+ }
}
- #[cfg(target_arch = "aarch64")]
- unsafe {
- asm!("yield" ::: "memory" : "volatile");
+ #[cfg(
+ any(
+ target_arch = "aarch64",
+ all(target_arch = "arm", target_feature = "v6")
+ )
+ )] {
+ #[cfg(target_arch = "aarch64")] {
+ unsafe { crate::arch::aarch64::__yield() };
+ }
+ #[cfg(target_arch = "arm")] {
+ unsafe { crate::arch::arm::__yield() };
+ }
}
}
let mut written = self.sign.len();
for part in self.parts {
- match part.write(&mut out[written..]) {
- Some(len) => { written += len; }
- None => { return None; }
- }
+ let len = part.write(&mut out[written..])?;
+ written += len;
}
Some(written)
}
/// Since the last element is zero, it would underflow. Thus, the resulting
/// value is `None`.
///
+ /// Here is a variation on the previous example, showing that no
+ /// further elements are taken from `iter` after the first `None`.
+ ///
+ /// ```
+ /// let items = vec![3_u16, 2, 1, 10];
+ ///
+ /// let mut shared = 0;
+ ///
+ /// let res: Option<Vec<u16>> = items
+ /// .iter()
+ /// .map(|x| { shared += x; x.checked_sub(2) })
+ /// .collect();
+ ///
+ /// assert_eq!(res, None);
+ /// assert_eq!(shared, 6);
+ /// ```
+ ///
+ /// Since the third element caused an underflow, no further elements were taken,
+ /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
+ ///
/// [`Iterator`]: ../iter/trait.Iterator.html
#[inline]
fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
/// However the pointer may still dangle if it isn't dereferenced.
///
/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
-/// for your use case, you should include some PhantomData in your type to
+/// for your use case, you should include some [`PhantomData`] in your type to
/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
/// Usually this won't be necessary; covariance is correct for most safe abstractions,
-/// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they
+/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they
/// provide a public API that follows the normal shared XOR mutable rules of Rust.
///
/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
/// is never used for mutation.
///
+/// [`PhantomData`]: ../marker/struct.PhantomData.html
/// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
/// some other means.
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
- #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
+ #[rustc_const_unstable(feature = "const_ptr_nonnull")]
pub const fn dangling() -> Self {
unsafe {
let ptr = mem::align_of::<T>() as *mut T;
/// Cast to a pointer of another type
#[stable(feature = "nonnull_cast", since = "1.27.0")]
#[inline]
- #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
+ #[rustc_const_unstable(feature = "const_ptr_nonnull")]
pub const fn cast<U>(self) -> NonNull<U> {
unsafe {
NonNull::new_unchecked(self.as_ptr() as *mut U)
/// ).collect();
/// assert_eq!(res, Ok(vec![2, 3]));
/// ```
+ ///
+ /// Here is another example that tries to subtract one from another list
+ /// of integers, this time checking for underflow:
+ ///
+ /// ```
+ /// let v = vec![1, 2, 0];
+ /// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|
+ /// x.checked_sub(1).ok_or("Underflow!")
+ /// ).collect();
+ /// assert_eq!(res, Err("Underflow!"));
+ /// ```
+ ///
+ /// Here is a variation on the previous example, showing that no
+ /// further elements are taken from `iter` after the first `Err`.
+ ///
+ /// ```
+ /// let v = vec![3, 2, 1, 10];
+ /// let mut shared = 0;
+ /// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32| {
+ /// shared += x;
+ /// x.checked_sub(2).ok_or("Underflow!")
+ /// }).collect();
+ /// assert_eq!(res, Err("Underflow!"));
+ /// assert_eq!(shared, 6);
+ /// ```
+ ///
+ /// Since the third element caused an underflow, no further elements were taken,
+ /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
#[inline]
fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
ret
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let (end, overflow) = self.v.len().overflowing_sub(n);
+ if end < self.size || overflow {
+ self.v = &[];
+ None
+ } else {
+ let ret = &self.v[end-self.size..end];
+ self.v = &self.v[..end-1];
+ Some(ret)
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_windows_nth_back() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.windows(2);
+ assert_eq!(c.nth_back(2).unwrap()[0], 2);
+ assert_eq!(c.next_back().unwrap()[1], 2);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c2 = v2.windows(4);
+ assert_eq!(c2.nth_back(1).unwrap()[1], 1);
+ assert_eq!(c2.next_back(), None);
+}
+
#[test]
fn test_windows_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
// Represents the MIR for a fn; also used as the task node for
// things read/modify that MIR.
- [] MirConstQualif(DefId),
- [] MirBuilt(DefId),
- [] MirConst(DefId),
- [] MirValidated(DefId),
- [] MirOptimized(DefId),
[] MirShim { instance_def: InstanceDef<'tcx> },
[] BorrowCheckKrate,
[] CollectModItemTypes(DefId),
[] Reachability,
- [] MirKeys,
[eval_always] CrateVariances,
// Nodes representing bits of computed IR in the tcx. Each shared
[anon] TraitSelect,
[] ParamEnv(DefId),
- [] Environment(DefId),
[] DescribeDef(DefId),
// FIXME(mw): DefSpans are not really inputs since they are derived from
[] HasGlobalAllocator(CrateNum),
[] HasPanicHandler(CrateNum),
[input] ExternCrate(DefId),
- [eval_always] LintLevels,
[] Specializes { impl1: DefId, impl2: DefId },
[input] InScopeTraits(DefIndex),
[input] ModuleExports(DefId),
[input] UsedCrateSource(CrateNum),
[input] PostorderCnums,
- // These queries are not expected to have inputs -- as a result, they
- // are not good candidates for "replay" because they are essentially
- // pure functions of their input (and hence the expectation is that
- // no caller would be green **apart** from just these
- // queries). Making them anonymous avoids hashing the result, which
- // may save a bit of time.
- [anon] EraseRegionsTy { ty: Ty<'tcx> },
-
[input] Freevars(DefId),
[input] MaybeUnusedTraitImport(DefId),
[input] MaybeUnusedExternCrates,
[input] Features,
- [] ProgramClausesFor(DefId),
- [] ProgramClausesForEnv(traits::Environment<'tcx>),
- [] WasmImportModuleMap(CrateNum),
[] ForeignModules(CrateNum),
[] UpstreamMonomorphizations(CrateNum),
let mut is_transparent = false;
for hint in &hints {
- let name = if let Some(name) = hint.ident_str() {
- name
- } else {
- // Invalid repr hint like repr(42). We don't check for unrecognized hints here
- // (libsyntax does that), so just ignore it.
- continue;
- };
-
- let (article, allowed_targets) = match name {
- "C" | "align" => {
+ let (article, allowed_targets) = match hint.name_or_empty().get() {
+ name @ "C" | name @ "align" => {
is_c |= name == "C";
if target != Target::Struct &&
target != Target::Union &&
use self::Namespace::*;
+/// Encodes if a `Def::Ctor` is the constructor of an enum variant or a struct.
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
+pub enum CtorOf {
+ /// This `Def::Ctor` is a synthesized constructor of a tuple or unit struct.
+ Struct,
+ /// This `Def::Ctor` is a synthesized constructor of a tuple or unit variant.
+ Variant,
+}
+
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorKind {
/// Constructor function automatically created by a tuple struct/variant.
pub enum Def {
// Type namespace
Mod(DefId),
- Struct(DefId), // `DefId` refers to `NodeId` of the struct itself
+ /// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
+ Struct(DefId),
Union(DefId),
Enum(DefId),
+ /// `DefId` refers to the variant itself, `Def::Ctor` refers to its constructor if it exists.
Variant(DefId),
Trait(DefId),
/// `existential type Foo: Bar;`
Const(DefId),
ConstParam(DefId),
Static(DefId, bool /* is_mutbl */),
- StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor
- VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant
+ /// `DefId` refers to the struct or enum variant's constructor.
+ Ctor(DefId, CtorOf, CtorKind),
SelfCtor(DefId /* impl */), // `DefId` refers to the impl
Method(DefId),
AssociatedConst(DefId),
pub fn opt_def_id(&self) -> Option<DefId> {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
- Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
+ Def::Variant(id) | Def::Ctor(id, ..) | Def::Enum(id) |
Def::TyAlias(id) | Def::TraitAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
- Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
Def::Fn(..) => "function",
Def::Mod(..) => "module",
Def::Static(..) => "static",
- Def::Variant(..) => "variant",
- Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
- Def::VariantCtor(.., CtorKind::Const) => "unit variant",
- Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
Def::Enum(..) => "enum",
+ Def::Variant(..) => "variant",
+ Def::Ctor(_, CtorOf::Variant, CtorKind::Fn) => "tuple variant",
+ Def::Ctor(_, CtorOf::Variant, CtorKind::Const) => "unit variant",
+ Def::Ctor(_, CtorOf::Variant, CtorKind::Fictive) => "struct variant",
+ Def::Struct(..) => "struct",
+ Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) => "tuple struct",
+ Def::Ctor(_, CtorOf::Struct, CtorKind::Const) => "unit struct",
+ Def::Ctor(_, CtorOf::Struct, CtorKind::Fictive) =>
+ bug!("impossible struct constructor"),
Def::Existential(..) => "existential type",
Def::TyAlias(..) => "type alias",
Def::TraitAlias(..) => "trait alias",
Def::AssociatedTy(..) => "associated type",
Def::AssociatedExistential(..) => "associated existential type",
- Def::Struct(..) => "struct",
- Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
- Def::StructCtor(.., CtorKind::Const) => "unit struct",
- Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
Def::SelfCtor(..) => "self constructor",
Def::Union(..) => "union",
Def::Trait(..) => "trait",
generics: &'v Generics,
parent_item_id: HirId) {
visitor.visit_ident(variant.node.ident);
+ visitor.visit_id(variant.node.id);
visitor.visit_variant_data(&variant.node.data,
variant.node.ident.name,
generics,
pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
- visitor.visit_id(struct_definition.hir_id());
+ if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() {
+ visitor.visit_id(ctor_hir_id);
+ }
walk_list!(visitor, visit_struct_field, struct_definition.fields());
}
}
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(v.node.id);
Spanned {
node: hir::VariantKind {
ident: v.node.ident,
+ id: hir_id,
attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data),
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
match *vdata {
- VariantData::Struct(ref fields, id, recovered) => {
- let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
-
- hir::VariantData::Struct(
- fields
- .iter()
- .enumerate()
- .map(|f| self.lower_struct_field(f))
- .collect(),
- hir_id,
- recovered,
- )
- },
+ VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
+ fields.iter().enumerate().map(|f| self.lower_struct_field(f)).collect(),
+ recovered,
+ ),
VariantData::Tuple(ref fields, id) => {
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
},
VariantData::Unit(id) => {
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
-
hir::VariantData::Unit(hir_id)
},
}
// }
// expand <head>
- let head = self.lower_expr(head);
+ let mut head = self.lower_expr(head);
let head_sp = head.span;
let desugared_span = self.mark_span_with_reason(
CompilerDesugaringKind::ForLoop,
head_sp,
None,
);
+ head.span = desugared_span;
let iter = self.str_to_ident("iter");
this.insert(i.span, i.hir_id, Node::Item(i));
this.with_parent(i.hir_id, |this| {
if let ItemKind::Struct(ref struct_def, _) = i.node {
- // If this is a tuple-like struct, register the constructor.
- if !struct_def.is_struct() {
- this.insert(i.span, struct_def.hir_id(), Node::StructCtor(struct_def));
+ // If this is a tuple or unit-like struct, register the constructor.
+ if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+ this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
}
}
intravisit::walk_item(this, i);
}
fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
- self.insert(v.span, v.node.data.hir_id(), Node::Variant(v));
- self.with_parent(v.node.data.hir_id(), |this| {
+ self.insert(v.span, v.node.id, Node::Variant(v));
+ self.with_parent(v.node.id, |this| {
+ // Register the constructor of this variant.
+ if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
+ this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
+ }
intravisit::walk_variant(this, v, g, item_id);
});
}
self.with_parent(def, |this| {
match i.node {
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
- // If this is a tuple-like struct, register the constructor.
- if !struct_def.is_struct() {
- this.create_def(struct_def.id(),
- DefPathData::StructCtor,
- REGULAR_SPACE,
- i.span);
+ // If this is a unit or tuple-like struct, register the constructor.
+ if let Some(ctor_hir_id) = struct_def.ctor_id() {
+ this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, i.span);
}
}
_ => {}
}
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
- let def = self.create_def(v.node.data.id(),
+ let def = self.create_def(v.node.id,
DefPathData::EnumVariant(v.node.ident.as_interned_str()),
REGULAR_SPACE,
v.span);
- self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
+ self.with_parent(def, |this| {
+ if let Some(ctor_hir_id) = v.node.data.ctor_id() {
+ this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, v.span);
+ }
+ visit::walk_variant(this, v, g, item_id)
+ });
}
fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
EnumVariant(InternedString),
/// A struct field
Field(InternedString),
- /// Implicit ctor for a tuple-like struct
- StructCtor,
+ /// Implicit ctor for a unit or tuple-like struct or enum variant.
+ Ctor,
/// A constant expression (see {ast,hir}::AnonConst).
AnonConst,
/// An `impl Trait` type node
CrateRoot |
Misc |
ClosureExpr |
- StructCtor |
+ Ctor |
AnonConst |
ImplTrait => None
}
Impl => "{{impl}}",
Misc => "{{misc}}",
ClosureExpr => "{{closure}}",
- StructCtor => "{{constructor}}",
+ Ctor => "{{constructor}}",
AnonConst => "{{constant}}",
ImplTrait => "{{opaque}}",
};
}
}
Node::Variant(variant) => {
- let def_id = self.local_def_id_from_hir_id(variant.node.data.hir_id());
+ let def_id = self.local_def_id_from_hir_id(variant.node.id);
Some(Def::Variant(def_id))
}
- Node::StructCtor(variant) => {
- let def_id = self.local_def_id_from_hir_id(variant.hir_id());
- Some(Def::StructCtor(def_id, def::CtorKind::from_hir(variant)))
+ Node::Ctor(variant_data) => {
+ let ctor_of = match self.find(self.get_parent_node(node_id)) {
+ Some(Node::Item(..)) => def::CtorOf::Struct,
+ Some(Node::Variant(..)) => def::CtorOf::Variant,
+ _ => unreachable!(),
+ };
+ variant_data.ctor_hir_id()
+ .map(|hir_id| self.local_def_id_from_hir_id(hir_id))
+ .map(|def_id| Def::Ctor(def_id, ctor_of, def::CtorKind::from_hir(variant_data)))
}
Node::AnonConst(_) |
Node::Field(_) |
Node::AnonConst(_) => {
BodyOwnerKind::Const
}
- Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
- Node::StructCtor(..) |
+ Node::Ctor(..) |
Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
_ => bug!("struct ID bound to non-struct {}", self.hir_to_string(id))
}
}
- Some(Node::StructCtor(data)) => data,
Some(Node::Variant(variant)) => &variant.node.data,
+ Some(Node::Ctor(data)) => data,
_ => bug!("expected struct or variant, found {}", self.hir_to_string(id))
}
}
Node::Lifetime(lt) => lt.name.ident().name,
Node::GenericParam(param) => param.name.ident().name,
Node::Binding(&Pat { node: PatKind::Binding(_, _, l, _), .. }) => l.name,
- Node::StructCtor(_) => self.name(self.get_parent(id)),
+ Node::Ctor(..) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id))
}
}
Some(Node::Expr(ref e)) => Some(&*e.attrs),
Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
Some(Node::GenericParam(param)) => Some(¶m.attrs[..]),
- // unit/tuple structs take the attributes straight from
- // the struct definition.
- Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
+ // Unit/tuple structs/variants take the attributes straight from
+ // the struct/variant definition.
+ Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
_ => None
};
attrs.unwrap_or(&[])
Some(Node::Binding(pat)) => pat.span,
Some(Node::Pat(pat)) => pat.span,
Some(Node::Block(block)) => block.span,
- Some(Node::StructCtor(_)) => self.expect_item(self.get_parent(id)).span,
+ Some(Node::Ctor(..)) => match self.find(self.get_parent_node(id)) {
+ Some(Node::Item(item)) => item.span,
+ Some(Node::Variant(variant)) => variant.span,
+ _ => unreachable!(),
+ }
Some(Node::Lifetime(lifetime)) => lifetime.span,
Some(Node::GenericParam(param)) => param.span,
Some(Node::Visibility(&Spanned {
// these cases do not carry enough information in the
// hir_map to reconstruct their full structure for pretty
// printing.
- Node::StructCtor(_) => bug!("cannot print isolated StructCtor"),
+ Node::Ctor(..) => bug!("cannot print isolated Ctor"),
Node::Local(a) => self.print_local_decl(&a),
Node::MacroDef(_) => bug!("cannot print MacroDef"),
Node::Crate => bug!("cannot print Crate"),
Some(Node::Local(_)) => {
format!("local {}{}", map.node_to_pretty_string(id), id_str)
}
- Some(Node::StructCtor(_)) => {
- format!("struct_ctor {}{}", path_str(), id_str)
+ Some(Node::Ctor(..)) => {
+ format!("ctor {}{}", path_str(), id_str)
}
Some(Node::Lifetime(_)) => {
format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct VariantKind {
+ /// Name of the variant.
#[stable_hasher(project(name))]
pub ident: Ident,
+ /// Attributes of the variant.
pub attrs: HirVec<Attribute>,
+ /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`).
+ pub id: HirId,
+ /// Fields and constructor id of the variant.
pub data: VariantData,
/// Explicit discriminant (e.g., `Foo = 1`).
pub disr_expr: Option<AnonConst>,
pub enum UseKind {
/// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
/// Also produced for each element of a list `use`, e.g.
- // `use foo::{a, b}` lowers to `use foo::a; use foo::b;`.
+ /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`.
Single,
/// Glob import, e.g., `use foo::*`.
}
}
-/// Fields and Ids of enum variants and structs
-///
-/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all
-/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants).
-/// One shared Id can be successfully used for these two purposes.
-/// Id of the whole enum lives in `Item`.
-///
-/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
-/// used for `Struct`-structs (but still present). Structures don't have an analogue of "Id of
-/// the variant itself" from enum variants.
-/// Id of the whole struct lives in `Item`.
+/// Fields and constructor ids of enum variants and structs
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum VariantData {
- Struct(HirVec<StructField>, HirId, /* recovered */ bool),
+ /// Struct variant.
+ ///
+ /// e.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
+ Struct(HirVec<StructField>, /* recovered */ bool),
+ /// Tuple variant.
+ ///
+ /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
Tuple(HirVec<StructField>, HirId),
+ /// Unit variant.
+ ///
+ /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
Unit(HirId),
}
impl VariantData {
+ /// Return the fields of this variant.
pub fn fields(&self) -> &[StructField] {
match *self {
VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields,
_ => &[],
}
}
- pub fn hir_id(&self) -> HirId {
+
+ /// Return the `HirId` of this variant's constructor, if it has one.
+ pub fn ctor_hir_id(&self) -> Option<HirId> {
match *self {
- VariantData::Struct(_, hir_id, _)
- | VariantData::Tuple(_, hir_id)
- | VariantData::Unit(hir_id) => hir_id,
- }
- }
- pub fn is_struct(&self) -> bool {
- if let VariantData::Struct(..) = *self {
- true
- } else {
- false
- }
- }
- pub fn is_tuple(&self) -> bool {
- if let VariantData::Tuple(..) = *self {
- true
- } else {
- false
- }
- }
- pub fn is_unit(&self) -> bool {
- if let VariantData::Unit(..) = *self {
- true
- } else {
- false
+ VariantData::Struct(_, _) => None,
+ VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id),
}
}
}
Local(&'hir Local),
MacroDef(&'hir MacroDef),
- /// StructCtor represents a tuple struct.
- StructCtor(&'hir VariantData),
+ /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
+ /// with synthesized constructors.
+ Ctor(&'hir VariantData),
Lifetime(&'hir Lifetime),
GenericParam(&'hir GenericParam),
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
use crate::hir::def_id::DefId;
use crate::hir::{self, HirId, PatKind};
use syntax::ast;
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
match path.def {
- Def::Variant(..) | Def::VariantCtor(..) => true,
+ Def::Variant(..) => true,
_ => false
}
}
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
match path.def {
- Def::Variant(id) |
- Def::VariantCtor(id, ..) => variants.push(id),
+ Def::Variant(id) => variants.push(id),
+ Def::Ctor(id, CtorOf::Variant, ..) => variants.push(id),
_ => ()
}
}
-> io::Result<()> {
self.print_name(name)?;
self.print_generic_params(&generics.params)?;
- if !struct_def.is_struct() {
- if struct_def.is_tuple() {
- self.popen()?;
- self.commasep(Inconsistent, struct_def.fields(), |s, field| {
- s.maybe_print_comment(field.span.lo())?;
- s.print_outer_attributes(&field.attrs)?;
- s.print_visibility(&field.vis)?;
- s.print_type(&field.ty)
- })?;
- self.pclose()?;
- }
- self.print_where_clause(&generics.where_clause)?;
- if print_finalizer {
- self.s.word(";")?;
+ match struct_def {
+ hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
+ if let hir::VariantData::Tuple(..) = struct_def {
+ self.popen()?;
+ self.commasep(Inconsistent, struct_def.fields(), |s, field| {
+ s.maybe_print_comment(field.span.lo())?;
+ s.print_outer_attributes(&field.attrs)?;
+ s.print_visibility(&field.vis)?;
+ s.print_type(&field.ty)
+ })?;
+ self.pclose()?;
+ }
+ self.print_where_clause(&generics.where_clause)?;
+ if print_finalizer {
+ self.s.word(";")?;
+ }
+ self.end()?;
+ self.end() // close the outer-box
}
- self.end()?;
- self.end() // close the outer-box
- } else {
- self.print_where_clause(&generics.where_clause)?;
- self.nbsp()?;
- self.bopen()?;
- self.hardbreak_if_not_bol()?;
-
- for field in struct_def.fields() {
+ hir::VariantData::Struct(..) => {
+ self.print_where_clause(&generics.where_clause)?;
+ self.nbsp()?;
+ self.bopen()?;
self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(field.span.lo())?;
- self.print_outer_attributes(&field.attrs)?;
- self.print_visibility(&field.vis)?;
- self.print_ident(field.ident)?;
- self.word_nbsp(":")?;
- self.print_type(&field.ty)?;
- self.s.word(",")?;
- }
- self.bclose(span)
+ for field in struct_def.fields() {
+ self.hardbreak_if_not_bol()?;
+ self.maybe_print_comment(field.span.lo())?;
+ self.print_outer_attributes(&field.attrs)?;
+ self.print_visibility(&field.vis)?;
+ self.print_ident(field.ident)?;
+ self.word_nbsp(":")?;
+ self.print_type(&field.ty)?;
+ self.s.word(",")?;
+ }
+
+ self.bclose(span)
+ }
}
}
//! constituents)
use crate::infer::InferCtxt;
+use crate::traits::DomainGoal;
+use crate::ty::error::TypeError;
use crate::ty::fold::{TypeFoldable, TypeVisitor};
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
use crate::ty::subst::Kind;
use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::error::TypeError;
-use crate::traits::DomainGoal;
use rustc_data_structures::fx::FxHashMap;
+use std::fmt::Debug;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum NormalizationStrategy {
first_free_index: ty::DebruijnIndex,
scopes: &[BoundRegionScope<'tcx>],
) -> ty::Region<'tcx> {
+ debug!("replace_bound_regions(scopes={:?})", scopes);
if let ty::ReLateBound(debruijn, br) = r {
Self::lookup_bound_region(*debruijn, br, first_free_index, scopes)
} else {
fn relate_projection_ty(
&mut self,
projection_ty: ty::ProjectionTy<'tcx>,
- value_ty: ty::Ty<'tcx>
+ value_ty: ty::Ty<'tcx>,
) -> Ty<'tcx> {
use crate::infer::type_variable::TypeVariableOrigin;
use crate::traits::WhereClause;
match value_ty.sty {
ty::Projection(other_projection_ty) => {
- let var = self.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
+ let var = self
+ .infcx
+ .next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
self.relate_projection_ty(projection_ty, var);
self.relate_projection_ty(other_projection_ty, var);
var
projection_ty,
ty: value_ty,
};
- self.delegate.push_domain_goal(
- DomainGoal::Holds(WhereClause::ProjectionEq(projection))
- );
+ self.delegate
+ .push_domain_goal(DomainGoal::Holds(WhereClause::ProjectionEq(projection)));
value_ty
}
}
}
- /// Relate a type inference variable with a value type.
- fn relate_ty_var(
+ /// Relate a type inference variable with a value type. This works
+ /// by creating a "generalization" G of the value where all the
+ /// lifetimes are replaced with fresh inference values. This
+ /// genearlization G becomes the value of the inference variable,
+ /// and is then related in turn to the value. So e.g. if you had
+ /// `vid = ?0` and `value = &'a u32`, we might first instantiate
+ /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
+ /// and then relate `&'0 u32` with `&'a u32` (resulting in
+ /// relations between `'0` and `'a`).
+ ///
+ /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
+ /// -- in other words, it is always a (unresolved) inference
+ /// variable `vid` and a type `ty` that are being related, but the
+ /// vid may appear either as the "a" type or the "b" type,
+ /// depending on where it appears in the tuple. The trait
+ /// `VidValuePair` lets us work with the vid/type while preserving
+ /// the "sidedness" when necessary -- the sidedness is relevant in
+ /// particular for the variance and set of in-scope things.
+ fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
&mut self,
- vid: ty::TyVid,
- value_ty: Ty<'tcx>
+ pair: PAIR,
) -> RelateResult<'tcx, Ty<'tcx>> {
- debug!("relate_ty_var(vid={:?}, value_ty={:?})", vid, value_ty);
+ debug!("relate_ty_var({:?})", pair);
+ let vid = pair.vid();
+ let value_ty = pair.value_ty();
+
+ // FIXME -- this logic assumes invariance, but that is wrong.
+ // This only presently applies to chalk integration, as NLL
+ // doesn't permit type variables to appear on both sides (and
+ // doesn't use lazy norm).
match value_ty.sty {
ty::Infer(ty::TyVar(value_vid)) => {
// Two type variables: just equate them.
- self.infcx.type_variables.borrow_mut().equate(vid, value_vid);
+ self.infcx
+ .type_variables
+ .borrow_mut()
+ .equate(vid, value_vid);
return Ok(value_ty);
}
- ty::Projection(projection_ty)
- if D::normalization() == NormalizationStrategy::Lazy =>
- {
+ ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
}
assert!(!generalized_ty.has_infer_types());
}
- self.infcx.type_variables.borrow_mut().instantiate(vid, generalized_ty);
+ self.infcx
+ .type_variables
+ .borrow_mut()
+ .instantiate(vid, generalized_ty);
// The generalized values we extract from `canonical_var_values` have
// been fully instantiated and hence the set of scopes we have
// doesn't matter -- just to be sure, put an empty vector
// in there.
- let old_a_scopes = ::std::mem::replace(&mut self.a_scopes, vec![]);
+ let old_a_scopes = ::std::mem::replace(pair.vid_scopes(self), vec![]);
// Relate the generalized kind to the original one.
- let result = self.relate(&generalized_ty, &value_ty);
+ let result = pair.relate_generalized_ty(self, generalized_ty);
// Restore the old scopes now.
- self.a_scopes = old_a_scopes;
+ *pair.vid_scopes(self) = old_a_scopes;
debug!("relate_ty_var: complete, result = {:?}", result);
result
fn generalize_value<T: Relate<'tcx>>(
&mut self,
value: T,
- for_vid: ty::TyVid
+ for_vid: ty::TyVid,
) -> RelateResult<'tcx, T> {
let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
}
}
+/// When we instantiate a inference variable with a value in
+/// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
+/// but the ordering may vary (depending on whether the inference
+/// variable was found on the `a` or `b` sides). Therefore, this trait
+/// allows us to factor out common code, while preserving the order
+/// when needed.
+trait VidValuePair<'tcx>: Debug {
+ /// Extract the inference variable (which could be either the
+ /// first or second part of the tuple).
+ fn vid(&self) -> ty::TyVid;
+
+ /// Extract the value it is being related to (which will be the
+ /// opposite part of the tuple from the vid).
+ fn value_ty(&self) -> Ty<'tcx>;
+
+ /// Extract the scopes that apply to whichever side of the tuple
+ /// the vid was found on. See the comment where this is called
+ /// for more details on why we want them.
+ fn vid_scopes<D: TypeRelatingDelegate<'tcx>>(
+ &self,
+ relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
+ ) -> &'r mut Vec<BoundRegionScope<'tcx>>;
+
+ /// Given a generalized type G that should replace the vid, relate
+ /// G to the value, putting G on whichever side the vid would have
+ /// appeared.
+ fn relate_generalized_ty<D>(
+ &self,
+ relate: &mut TypeRelating<'_, '_, 'tcx, D>,
+ generalized_ty: Ty<'tcx>,
+ ) -> RelateResult<'tcx, Ty<'tcx>>
+ where
+ D: TypeRelatingDelegate<'tcx>;
+}
+
+impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
+ fn vid(&self) -> ty::TyVid {
+ self.0
+ }
+
+ fn value_ty(&self) -> Ty<'tcx> {
+ self.1
+ }
+
+ fn vid_scopes<D>(
+ &self,
+ relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
+ ) -> &'r mut Vec<BoundRegionScope<'tcx>>
+ where
+ D: TypeRelatingDelegate<'tcx>,
+ {
+ &mut relate.a_scopes
+ }
+
+ fn relate_generalized_ty<D>(
+ &self,
+ relate: &mut TypeRelating<'_, '_, 'tcx, D>,
+ generalized_ty: Ty<'tcx>,
+ ) -> RelateResult<'tcx, Ty<'tcx>>
+ where
+ D: TypeRelatingDelegate<'tcx>,
+ {
+ relate.relate(&generalized_ty, &self.value_ty())
+ }
+}
+
+// In this case, the "vid" is the "b" type.
+impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
+ fn vid(&self) -> ty::TyVid {
+ self.1
+ }
+
+ fn value_ty(&self) -> Ty<'tcx> {
+ self.0
+ }
+
+ fn vid_scopes<D>(
+ &self,
+ relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
+ ) -> &'r mut Vec<BoundRegionScope<'tcx>>
+ where
+ D: TypeRelatingDelegate<'tcx>,
+ {
+ &mut relate.b_scopes
+ }
+
+ fn relate_generalized_ty<D>(
+ &self,
+ relate: &mut TypeRelating<'_, '_, 'tcx, D>,
+ generalized_ty: Ty<'tcx>,
+ ) -> RelateResult<'tcx, Ty<'tcx>>
+ where
+ D: TypeRelatingDelegate<'tcx>,
+ {
+ relate.relate(&self.value_ty(), &generalized_ty)
+ }
+}
+
impl<D> TypeRelation<'me, 'gcx, 'tcx> for TypeRelating<'me, 'gcx, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
// Forbid inference variables in the RHS.
bug!("unexpected inference var {:?}", b)
} else {
- self.relate_ty_var(vid, a)
+ self.relate_ty_var((a, vid))
}
}
- (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var(vid, b),
+ (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
(&ty::Projection(projection_ty), _)
if D::normalization() == NormalizationStrategy::Lazy =>
drop(variables);
self.relate(&u, &u)
}
- TypeVariableValue::Unknown { universe: _universe } => {
+ TypeVariableValue::Unknown {
+ universe: _universe,
+ } => {
if self.ambient_variance == ty::Bivariant {
// FIXME: we may need a WF predicate (related to #54105).
}
let u = self.tcx().mk_ty_var(new_var_id);
debug!(
"generalize: replacing original vid={:?} with new={:?}",
- vid,
- u
+ vid, u
);
return Ok(u);
}
}
}
- ty::Infer(ty::IntVar(_)) |
- ty::Infer(ty::FloatVar(_)) => {
+ ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) => {
// No matter what mode we are in,
// integer/floating-point types must be equal to be
// relatable.
if self.universe.cannot_name(placeholder.universe) {
debug!(
"TypeGeneralizer::tys: root universe {:?} cannot name\
- placeholder in universe {:?}",
- self.universe,
- placeholder.universe
+ placeholder in universe {:?}",
+ self.universe, placeholder.universe
);
Err(TypeError::Mismatch)
} else {
}
}
- _ => {
- relate::super_relate_tys(self, a, a)
- }
+ _ => relate::super_relate_tys(self, a, a),
}
}
v: &'tcx hir::Variant,
g: &'tcx hir::Generics,
item_id: hir::HirId) {
- self.with_lint_attrs(v.node.data.hir_id(), &v.node.attrs, |cx| {
+ self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| {
run_lints!(cx, check_variant, v, g);
hir_visit::walk_variant(cx, v, g, item_id);
run_lints!(cx, check_variant_post, v, g);
item_id: ast::NodeId,
_: Span) {
run_early_pass!(self, check_struct_def, s, ident, g, item_id);
- self.check_id(s.id());
+ if let Some(ctor_hir_id) = s.ctor_id() {
+ self.check_id(ctor_hir_id);
+ }
ast_visit::walk_struct_def(self, s);
run_early_pass!(self, check_struct_def_post, s, ident, g, item_id);
}
struct_span_err!(sess, span, E0452, "malformed lint attribute")
};
for attr in attrs {
- let level = match attr.ident_str().and_then(|name| Level::from_str(name)) {
+ let level = match Level::from_str(&attr.name_or_empty()) {
None => continue,
Some(lvl) => lvl,
};
pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
let attrs = tcx.hir().attrs_by_hir_id(id);
- for attr in attrs {
- if attr.ident_str().and_then(Level::from_str).is_some() {
- return true;
- }
- }
- false
+ attrs.iter().any(|attr| Level::from_str(&attr.name_or_empty()).is_some())
}
fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
v: &'tcx hir::Variant,
g: &'tcx hir::Generics,
item_id: hir::HirId) {
- self.with_lint_attrs(v.node.data.hir_id(), &v.node.attrs, |builder| {
+ self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| {
intravisit::walk_variant(builder, v, g, item_id);
})
}
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir::itemlikevisit::ItemLikeVisitor;
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
use crate::hir::CodegenFnAttrFlags;
use crate::hir::def_id::{DefId, LOCAL_CRATE};
use crate::lint;
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn check_def_id(&mut self, def_id: DefId) {
if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
- if should_explore(self.tcx, hir_id) ||
- self.struct_constructors.contains_key(&hir_id) {
+ if should_explore(self.tcx, hir_id) || self.struct_constructors.contains_key(&hir_id) {
self.worklist.push(hir_id);
}
self.live_symbols.insert(hir_id);
_ if self.in_pat => (),
Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) |
Def::Local(..) | Def::Upvar(..) => {}
- Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
- if let Some(enum_id) = self.tcx.parent(variant_id) {
- self.check_def_id(enum_id);
+ Def::Ctor(ctor_def_id, CtorOf::Variant, ..) => {
+ let variant_id = self.tcx.parent(ctor_def_id).unwrap();
+ let enum_id = self.tcx.parent(variant_id).unwrap();
+ self.check_def_id(enum_id);
+ if !self.ignore_variant_stack.contains(&ctor_def_id) {
+ self.check_def_id(variant_id);
}
+ }
+ Def::Variant(variant_id) => {
+ let enum_id = self.tcx.parent(variant_id).unwrap();
+ self.check_def_id(enum_id);
if !self.ignore_variant_stack.contains(&variant_id) {
self.check_def_id(variant_id);
}
self.worklist.push(item.hir_id);
}
match item.node {
- hir::ItemKind::Enum(ref enum_def, _) if allow_dead_code => {
- self.worklist.extend(enum_def.variants.iter()
- .map(|variant| variant.node.data.hir_id()));
+ hir::ItemKind::Enum(ref enum_def, _) => {
+ if allow_dead_code {
+ self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
+ }
+
+ for variant in &enum_def.variants {
+ if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+ self.struct_constructors.insert(ctor_hir_id, variant.node.id);
+ }
+ }
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
for trait_item_ref in trait_item_refs {
}
}
hir::ItemKind::Struct(ref variant_data, _) => {
- self.struct_constructors.insert(variant_data.hir_id(), item.hir_id);
+ if let Some(ctor_hir_id) = variant_data.ctor_hir_id() {
+ self.struct_constructors.insert(ctor_hir_id, item.hir_id);
+ }
}
_ => ()
}
}
fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
- !self.symbol_is_live(variant.data.hir_id())
+ !self.symbol_is_live(variant.id)
&& !has_allow_dead_code_or_lang_attr(self.tcx,
- variant.data.hir_id(),
+ variant.id,
&variant.attrs)
}
g: &'tcx hir::Generics,
id: hir::HirId) {
if self.should_warn_about_variant(&variant.node) {
- self.warn_dead_code(variant.node.data.hir_id(), variant.span, variant.node.ident.name,
+ self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name,
"variant", "constructed");
} else {
intravisit::walk_variant(self, variant, g, id);
use self::TrackMatchMode::*;
use self::OverloadedCallType::*;
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
use crate::hir::def_id::DefId;
use crate::infer::InferCtxt;
use crate::middle::mem_categorization as mc;
use crate::middle::region;
-use crate::ty::{self, TyCtxt, adjustment};
+use crate::ty::{self, DefIdTree, TyCtxt, adjustment};
use crate::hir::{self, PatKind};
use rustc_data_structures::sync::Lrc;
};
let def = mc.tables.qpath_def(qpath, pat.hir_id);
match def {
- Def::Variant(variant_did) |
- Def::VariantCtor(variant_did, ..) => {
+ Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => {
+ let variant_did = mc.tcx.parent(variant_ctor_did).unwrap();
+ let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
+
+ debug!("variantctor downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
+ delegate.matched_pat(pat, &downcast_cmt, match_mode);
+ }
+ Def::Variant(variant_did) => {
let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
delegate.matched_pat(pat, &downcast_cmt, match_mode);
}
- Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+ Def::Struct(..) | Def::Ctor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, &cmt_pat, match_mode);
for meta in metas {
if let Some(mi) = meta.meta_item() {
// Find the `feature = ".."` meta-item.
- match (mi.ident_str(), mi.value_str()) {
- (Some("feature"), val) => feature = val,
- (Some("since"), val) => since = val,
+ match (mi.name_or_empty().get(), mi.value_str()) {
+ ("feature", val) => feature = val,
+ ("since", val) => since = val,
_ => {}
}
}
use crate::hir::def_id::{DefId, LocalDefId};
use crate::hir::Node;
use crate::infer::InferCtxt;
-use crate::hir::def::{Def, CtorKind};
+use crate::hir::def::{CtorOf, Def, CtorKind};
use crate::ty::adjustment;
use crate::ty::{self, DefIdTree, Ty, TyCtxt};
use crate::ty::fold::TypeFoldable;
hir_id, expr_ty, def);
match def {
- Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::ConstParam(..) |
+ Def::Ctor(..) | Def::Const(..) | Def::ConstParam(..) |
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
}
debug!("access to unresolvable pattern {:?}", pat);
return Err(())
}
- Def::VariantCtor(def_id, CtorKind::Fn) => {
- let enum_def = self.tcx.parent(def_id).unwrap();
- (self.cat_downcast_if_needed(pat, cmt, def_id),
- self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
+ Def::Ctor(variant_ctor_did, CtorOf::Variant, CtorKind::Fn) => {
+ let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
+ let enum_did = self.tcx.parent(variant_did).unwrap();
+ (self.cat_downcast_if_needed(pat, cmt, variant_did),
+ self.tcx.adt_def(enum_did)
+ .variant_with_ctor_id(variant_ctor_did).fields.len())
}
- Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
+ Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) | Def::SelfCtor(..) => {
let ty = self.pat_ty_unadjusted(&pat)?;
match ty.sty {
ty::Adt(adt_def, _) => {
debug!("access to unresolvable pattern {:?}", pat);
return Err(())
}
- Def::Variant(variant_did) |
- Def::VariantCtor(variant_did, ..) => {
+ Def::Ctor(variant_ctor_did, CtorOf::Variant, _) => {
+ let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
+ self.cat_downcast_if_needed(pat, cmt, variant_did)
+ }
+ Def::Variant(variant_did) => {
self.cat_downcast_if_needed(pat, cmt, variant_did)
}
_ => cmt,
// Nothing to recurse on for these
Node::ForeignItem(_) |
Node::Variant(_) |
- Node::StructCtor(_) |
+ Node::Ctor(..) |
Node::Field(_) |
Node::Ty(_) |
Node::MacroDef(_) => {}
} else {
// Emit errors for non-staged-api crates.
for attr in attrs {
- if let Some(tag) = attr.ident_str() {
- if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
- attr::mark_used(attr);
- self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
- outside of the standard library");
- }
+ let name = attr.name_or_empty();
+ if ["unstable", "stable", "rustc_deprecated"].contains(&name.get()) {
+ attr::mark_used(attr);
+ self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
+ outside of the standard library");
}
}
self.in_trait_impl = true;
}
hir::ItemKind::Struct(ref sd, _) => {
- if !sd.is_struct() {
- self.annotate(sd.hir_id(), &i.attrs, i.span, AnnotationKind::Required, |_| {})
+ if let Some(ctor_hir_id) = sd.ctor_hir_id() {
+ self.annotate(ctor_hir_id, &i.attrs, i.span, AnnotationKind::Required, |_| {})
}
}
_ => {}
}
fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
- self.annotate(var.node.data.hir_id(), &var.node.attrs, var.span, AnnotationKind::Required,
- |v| { intravisit::walk_variant(v, var, g, item_id) })
+ self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required,
+ |v| {
+ if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() {
+ v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required,
+ |_| {});
+ }
+
+ intravisit::walk_variant(v, var, g, item_id)
+ })
}
fn visit_struct_field(&mut self, s: &'tcx StructField) {
}
fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
- self.check_missing_stability(var.node.data.hir_id(), var.span, "variant");
+ self.check_missing_stability(var.node.id, var.span, "variant");
intravisit::walk_variant(self, var, g, item_id);
}
if let hir::Node::Expr(_) = self.hir().get_by_hir_id(id) {
diag.span_suggestion(
span,
- &msg,
+ "replace the use of the deprecated item",
suggestion.to_string(),
Applicability::MachineApplicable,
);
/// static or static mut variable
Static(Box<Static<'tcx>>),
-
- /// Constant code promoted to an injected static
- Promoted(Box<(Promoted, Ty<'tcx>)>),
}
-/// The `DefId` of a static, along with its normalized type (which is
-/// stored to avoid requiring normalization when reading MIR).
+/// We store the normalized type to avoid requiring normalization when reading MIR
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct Static<'tcx> {
- pub def_id: DefId,
pub ty: Ty<'tcx>,
+ pub kind: StaticKind,
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable)]
+pub enum StaticKind {
+ Promoted(Promoted),
+ Static(DefId),
}
impl_stable_hash_for!(struct Static<'tcx> {
- def_id,
- ty
+ ty,
+ kind
});
/// The `Projection` data structure defines things of the form `B.x`
match self {
Place::Base(PlaceBase::Local(local)) => Some(*local),
Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
- Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
+ Place::Base(PlaceBase::Static(..)) => None,
}
}
}
match *self {
Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
- Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
- fmt,
- "({}: {:?})",
- ty::tls::with(|tcx| tcx.def_path_str(def_id)),
- ty
- ),
- Base(PlaceBase::Promoted(ref promoted)) => write!(
- fmt,
- "({:?}: {:?})",
- promoted.0,
- promoted.1
- ),
+ Base(PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) })) => {
+ write!(
+ fmt,
+ "({}: {:?})",
+ ty::tls::with(|tcx| tcx.def_path_str(def_id)),
+ ty
+ )
+ },
+ Base(PlaceBase::Static(
+ box self::Static { ty, kind: StaticKind::Promoted(promoted) })
+ ) => {
+ write!(
+ fmt,
+ "({:?}: {:?})",
+ promoted,
+ ty
+ )
+ },
Projection(ref data) => match data.elem {
ProjectionElem::Downcast(ref adt_def, index) => {
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
ty::tls::with(|tcx| {
let substs = tcx.lift(&substs).expect("could not lift for printing");
FmtPrinter::new(tcx, f, Namespace::ValueNS)
- .print_def_path(variant_def.did, substs)?;
+ .print_def_path(variant_def.def_id, substs)?;
Ok(())
})?;
match *self {
Place::Base(PlaceBase::Local(index)) =>
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
- Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
Place::Base(PlaceBase::Static(ref data)) =>
PlaceTy::Ty { ty: data.ty },
Place::Projection(ref proj) =>
self.super_place(place, context, location);
}
- fn visit_static(&mut self,
- static_: & $($mutability)? Static<'tcx>,
- context: PlaceContext<'tcx>,
- location: Location) {
- self.super_static(static_, context, location);
- }
-
fn visit_projection(&mut self,
place: & $($mutability)? PlaceProjection<'tcx>,
context: PlaceContext<'tcx>,
Place::Base(PlaceBase::Local(local)) => {
self.visit_local(local, context, location);
}
- Place::Base(PlaceBase::Static(static_)) => {
- self.visit_static(static_, context, location);
+ Place::Base(PlaceBase::Static(box Static { kind, ty })) => {
+ if let StaticKind::Static(def_id) = kind {
+ self.visit_def_id(& $($mutability)? *def_id, location)
+ }
+ self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
}
- Place::Base(PlaceBase::Promoted(promoted)) => {
- self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
- },
Place::Projection(proj) => {
self.visit_projection(proj, context, location);
}
}
}
- fn super_static(&mut self,
- static_: & $($mutability)? Static<'tcx>,
- _context: PlaceContext<'tcx>,
- location: Location) {
- let Static { def_id, ty } = static_;
- self.visit_def_id(def_id, location);
- self.visit_ty(ty, TyContext::Location(location));
- }
-
fn super_projection(&mut self,
proj: & $($mutability)? PlaceProjection<'tcx>,
context: PlaceContext<'tcx>,
use crate::ty::query::QueryDescription;
use crate::ty::query::queries;
-use crate::ty::TyCtxt;
-use crate::ty;
-use crate::hir::def_id::CrateNum;
+use crate::ty::{self, Ty, TyCtxt};
+use crate::hir::def_id::{DefId, CrateNum};
use crate::dep_graph::SerializedDepNodeIndex;
+use crate::traits;
use std::borrow::Cow;
// Each of these queries corresponds to a function pointer field in the
query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
desc { "looking up the native libraries of a linked crate" }
}
+
+ query lint_levels(_: CrateNum) -> Lrc<lint::LintLevelMap> {
+ eval_always
+ desc { "computing the lint levels for items in this crate" }
+ }
}
Codegen {
desc { "checking if the crate is_panic_runtime" }
}
}
+
+ Codegen {
+ /// Set of all the `DefId`s in this crate that have MIR associated with
+ /// them. This includes all the body owners, but also things like struct
+ /// constructors.
+ query mir_keys(_: CrateNum) -> Lrc<DefIdSet> {
+ desc { "getting a list of all mir_keys" }
+ }
+
+ /// Maps DefId's that have an associated Mir to the result
+ /// of the MIR qualify_consts pass. The actual meaning of
+ /// the value isn't known except to the pass itself.
+ query mir_const_qualif(key: DefId) -> (u8, Lrc<BitSet<mir::Local>>) {
+ cache { key.is_local() }
+ }
+
+ /// Fetch the MIR for a given `DefId` right after it's built - this includes
+ /// unreachable code.
+ query mir_built(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {}
+
+ /// Fetch the MIR for a given `DefId` up till the point where it is
+ /// ready for const evaluation.
+ ///
+ /// See the README for the `mir` module for details.
+ query mir_const(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+ no_hash
+ }
+
+ query mir_validated(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+ no_hash
+ }
+
+ /// MIR after our optimization passes have run. This is MIR that is ready
+ /// for codegen. This is also the only query that can fetch non-local MIR, at present.
+ query optimized_mir(key: DefId) -> &'tcx mir::Mir<'tcx> {
+ cache { key.is_local() }
+ load_cached(tcx, id) {
+ let mir: Option<crate::mir::Mir<'tcx>> = tcx.queries.on_disk_cache
+ .try_load_query_result(tcx, id);
+ mir.map(|x| tcx.alloc_mir(x))
+ }
+ }
+ }
+
+ TypeChecking {
+ // Erases regions from `ty` to yield a new type.
+ // Normally you would just use `tcx.erase_regions(&value)`,
+ // however, which uses this query as a kind of cache.
+ query erase_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
+ // This query is not expected to have input -- as a result, it
+ // is not a good candidates for "replay" because it is essentially a
+ // pure function of its input (and hence the expectation is that
+ // no caller would be green **apart** from just these
+ // queries). Making it anonymous avoids hashing the result, which
+ // may save a bit of time.
+ anon
+ no_force
+ desc { "erasing regions from `{:?}`", ty }
+ }
+
+ query program_clauses_for(_: DefId) -> Clauses<'tcx> {
+ desc { "generating chalk-style clauses" }
+ }
+
+ query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> {
+ no_force
+ desc { "generating chalk-style clauses for environment" }
+ }
+
+ // Get the chalk-style environment of the given item.
+ query environment(_: DefId) -> traits::Environment<'tcx> {
+ desc { "return a chalk-style environment" }
+ }
+ }
+
+ Linking {
+ query wasm_import_module_map(_: CrateNum) -> Lrc<FxHashMap<DefId, String>> {
+ desc { "wasm import module map" }
+ }
+ }
}
_ => ArgKind::empty()
}).collect::<Vec<ArgKind>>())
}
- Node::Variant(&hir::Variant {
- span,
- node: hir::VariantKind {
- data: hir::VariantData::Tuple(ref fields, ..),
- ..
- },
- ..
- }) => {
- (self.tcx.sess.source_map().def_span(span),
- fields.iter().map(|field|
- ArgKind::Arg(field.ident.to_string(), "_".to_string())
- ).collect::<Vec<_>>())
- }
- Node::StructCtor(ref variant_data) => {
- (self.tcx.sess.source_map().def_span(
- self.tcx.hir().span_by_hir_id(variant_data.hir_id())),
- vec![ArgKind::empty(); variant_data.fields().len()])
+ Node::Ctor(ref variant_data) => {
+ let span = variant_data.ctor_hir_id()
+ .map(|hir_id| self.tcx.hir().span_by_hir_id(hir_id))
+ .unwrap_or(DUMMY_SP);
+ let span = self.tcx.sess.source_map().def_span(span);
+
+ (span, vec![ArgKind::empty(); variant_data.fields().len()])
}
_ => panic!("non-FnLike node found: {:?}", node),
}
for command in self.subcommands.iter().chain(Some(self)).rev() {
if let Some(ref condition) = command.condition {
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
- c.ident_str().map_or(false, |name| {
+ c.ident().map_or(false, |ident| {
options.contains(&(
- name.to_string(),
+ ident.to_string(),
c.value_str().map(|s| s.as_str().to_string())
))
})
type Item = DefId;
fn next(&mut self) -> Option<DefId> {
- let def_id = match self.stack.pop() {
- Some(def_id) => def_id,
- None => { return None; }
- };
-
+ let def_id = self.stack.pop()?;
let predicates = self.tcx.super_predicates_of(def_id);
let visited = &mut self.visited;
self.stack.extend(
fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
ty.uninhabited_from(self)
}
-
- pub fn is_enum_variant_uninhabited_from(self,
- module: DefId,
- variant: &'tcx VariantDef,
- substs: SubstsRef<'tcx>)
- -> bool
- {
- self.variant_inhabitedness_forest(variant, substs).contains(self, module)
- }
-
- pub fn is_variant_uninhabited_from_all_modules(self,
- variant: &'tcx VariantDef,
- substs: SubstsRef<'tcx>)
- -> bool
- {
- !self.variant_inhabitedness_forest(variant, substs).is_empty()
- }
-
- fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: SubstsRef<'tcx>)
- -> DefIdForest {
- // Determine the ADT kind:
- let adt_def_id = self.adt_def_id_of_variant(variant);
- let adt_kind = self.adt_def(adt_def_id).adt_kind();
-
- // Compute inhabitedness forest:
- variant.uninhabited_from(self, substs, adt_kind)
- }
}
impl<'a, 'gcx, 'tcx> AdtDef {
impl<'a, 'gcx, 'tcx> VariantDef {
/// Calculate the forest of DefIds from which this variant is visibly uninhabited.
- fn uninhabited_from(
+ pub fn uninhabited_from(
&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: SubstsRef<'tcx>,
_ => return true
};
match tcx.def_key(def_id).disambiguated_data.data {
- DefPathData::StructCtor |
- DefPathData::EnumVariant(..) |
- DefPathData::ClosureExpr => true,
+ DefPathData::Ctor | DefPathData::ClosureExpr => true,
_ => false
}
}
use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap};
use crate::hir::{HirId, Node};
-use crate::hir::def::{Def, CtorKind, ExportMap};
+use crate::hir::def::{Def, CtorOf, CtorKind, ExportMap};
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use crate::hir::map::DefPathData;
use rustc_data_structures::svh::Svh;
use rustc_macros::HashStable;
use crate::ich::Fingerprint;
#[derive(HashStable)]
pub struct AdtFlags: u32 {
const NO_ADT_FLAGS = 0;
+ /// Indicates whether the ADT is an enum.
const IS_ENUM = 1 << 0;
+ /// Indicates whether the ADT is a union.
const IS_UNION = 1 << 1;
+ /// Indicates whether the ADT is a struct.
const IS_STRUCT = 1 << 2;
+ /// Indicates whether the ADT is a struct and has a constructor.
const HAS_CTOR = 1 << 3;
+ /// Indicates whether the type is a `PhantomData`.
const IS_PHANTOM_DATA = 1 << 4;
+ /// Indicates whether the type has a `#[fundamental]` attribute.
const IS_FUNDAMENTAL = 1 << 5;
+ /// Indicates whether the type is a `Box`.
const IS_BOX = 1 << 6;
/// Indicates whether the type is an `Arc`.
const IS_ARC = 1 << 7;
}
}
+/// Definition of a variant -- a struct's fields or a enum variant.
#[derive(Debug)]
pub struct VariantDef {
- /// The variant's `DefId`. If this is a tuple-like struct,
- /// this is the `DefId` of the struct's ctor.
- pub did: DefId,
- pub ident: Ident, // struct's name if this is a struct
+ /// `DefId` that identifies the variant itself.
+ /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
+ pub def_id: DefId,
+ /// `DefId` that identifies the variant's constructor.
+ /// If this variant is a struct variant, then this is `None`.
+ pub ctor_def_id: Option<DefId>,
+ /// Variant or struct name.
+ pub ident: Ident,
+ /// Discriminant of this variant.
pub discr: VariantDiscr,
+ /// Fields of this variant.
pub fields: Vec<FieldDef>,
+ /// Type of constructor of variant.
pub ctor_kind: CtorKind,
+ /// Flags of the variant (e.g. is field list non-exhaustive)?
flags: VariantFlags,
+ /// Recovered?
pub recovered: bool,
}
impl<'a, 'gcx, 'tcx> VariantDef {
/// Creates a new `VariantDef`.
///
- /// - `did` is the `DefId` used for the variant.
- /// This is the constructor `DefId` for tuple stucts, and the variant `DefId` for everything
- /// else.
- /// - `attribute_def_id` is the DefId that has the variant's attributes.
- /// This is the struct `DefId` for structs, and the variant `DefId` for variants.
+ /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
+ /// represents an enum variant).
+ ///
+ /// `ctor_did` is the `DefId` that identifies the constructor of unit or
+ /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
///
- /// Note that we *could* use the constructor `DefId`, because the constructor attributes
- /// redirect to the base attributes, but compiling a small crate requires
- /// loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
+ /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
+ /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
+ /// to go through the redirect of checking the ctor's attributes - but compiling a small crate
+ /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
/// built-in trait), and we do not want to load attributes twice.
///
/// If someone speeds up attribute loading to not be a performance concern, they can
/// remove this hack and use the constructor `DefId` everywhere.
pub fn new(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- did: DefId,
ident: Ident,
+ variant_did: Option<DefId>,
+ ctor_def_id: Option<DefId>,
discr: VariantDiscr,
fields: Vec<FieldDef>,
- adt_kind: AdtKind,
ctor_kind: CtorKind,
- attribute_def_id: DefId,
+ adt_kind: AdtKind,
+ parent_did: DefId,
recovered: bool,
) -> Self {
- debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr,
- fields, adt_kind, ctor_kind, attribute_def_id);
+ debug!(
+ "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?},
+ fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})",
+ ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did,
+ );
+
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
- if adt_kind == AdtKind::Struct && tcx.has_attr(attribute_def_id, "non_exhaustive") {
- debug!("found non-exhaustive field list for {:?}", did);
+ if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, "non_exhaustive") {
+ debug!("found non-exhaustive field list for {:?}", parent_did);
flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
}
+
VariantDef {
- did,
+ def_id: variant_did.unwrap_or(parent_did),
+ ctor_def_id,
ident,
discr,
fields,
}
}
+ /// Is this field list non-exhaustive?
#[inline]
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}
impl_stable_hash_for!(struct VariantDef {
- did,
+ def_id,
+ ctor_def_id,
ident -> (ident.name),
discr,
fields,
/// The definition of an abstract data type -- a struct or enum.
///
-/// These are all interned (by `intern_adt_def`) into the `adt_defs`
-/// table.
+/// These are all interned (by `intern_adt_def`) into the `adt_defs` table.
pub struct AdtDef {
+ /// `DefId` of the struct, enum or union item.
pub did: DefId,
+ /// Variants of the ADT. If this is a struct or enum, then there will be a single variant.
pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
+ /// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?)
flags: AdtFlags,
+ /// Repr options provided by the user.
pub repr: ReprOptions,
}
}
impl<'a, 'gcx, 'tcx> AdtDef {
- fn new(tcx: TyCtxt<'_, '_, '_>,
- did: DefId,
- kind: AdtKind,
- variants: IndexVec<VariantIdx, VariantDef>,
- repr: ReprOptions) -> Self {
+ /// Creates a new `AdtDef`.
+ fn new(
+ tcx: TyCtxt<'_, '_, '_>,
+ did: DefId,
+ kind: AdtKind,
+ variants: IndexVec<VariantIdx, VariantDef>,
+ repr: ReprOptions
+ ) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;
AdtKind::Struct => AdtFlags::IS_STRUCT,
};
- if let AdtKind::Struct = kind {
- let variant_def = &variants[VariantIdx::new(0)];
- let def_key = tcx.def_key(variant_def.did);
- match def_key.disambiguated_data.data {
- DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
- _ => (),
- }
+ if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_def_id.is_some() {
+ flags |= AdtFlags::HAS_CTOR;
}
let attrs = tcx.get_attrs(did);
}
}
+ /// Returns `true` if this is a struct.
#[inline]
pub fn is_struct(&self) -> bool {
self.flags.contains(AdtFlags::IS_STRUCT)
}
+ /// Returns `true` if this is a union.
#[inline]
pub fn is_union(&self) -> bool {
self.flags.contains(AdtFlags::IS_UNION)
}
+ /// Returns `true` if this is a enum.
#[inline]
pub fn is_enum(&self) -> bool {
self.flags.contains(AdtFlags::IS_ENUM)
}
+ /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`.
#[inline]
pub fn is_variant_list_non_exhaustive(&self) -> bool {
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}
}
+ /// Returns a description of this abstract data type.
pub fn descr(&self) -> &'static str {
match self.adt_kind() {
AdtKind::Struct => "struct",
}
}
+ /// Returns a description of a variant of this abstract data type.
#[inline]
pub fn variant_descr(&self) -> &'static str {
match self.adt_kind() {
}
pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
- self.variants
- .iter()
- .find(|v| v.did == vid)
+ self.variants.iter().find(|v| v.def_id == vid)
.expect("variant_with_id: unknown variant")
}
+ pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef {
+ self.variants.iter().find(|v| v.ctor_def_id == Some(cid))
+ .expect("variant_with_ctor_id: unknown variant")
+ }
+
pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
- self.variants
- .iter_enumerated()
- .find(|(_, v)| v.did == vid)
- .expect("variant_index_with_id: unknown variant")
- .0
+ self.variants.iter_enumerated().find(|(_, v)| v.def_id == vid)
+ .expect("variant_index_with_id: unknown variant").0
+ }
+
+ pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx {
+ self.variants.iter_enumerated().find(|(_, v)| v.ctor_def_id == Some(cid))
+ .expect("variant_index_with_ctor_id: unknown variant").0
}
pub fn variant_of_def(&self, def: Def) -> &VariantDef {
match def {
- Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
- Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+ Def::Variant(vid) => self.variant_with_id(vid),
+ Def::Ctor(cid, ..) => self.variant_with_ctor_id(cid),
+ Def::Struct(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
Def::SelfCtor(..) => self.non_enum_variant(),
_ => bug!("unexpected def {:?} in variant_of_def", def)
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
variant.fields.iter().position(|field| {
- self.adjust_ident(ident, variant.did, hir::DUMMY_HIR_ID).0 == field.ident.modern()
+ self.adjust_ident(ident, variant.def_id, hir::DUMMY_HIR_ID).0 == field.ident.modern()
})
}
// or variant or their constructors, panics otherwise.
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
match def {
- Def::Variant(did) | Def::VariantCtor(did, ..) => {
+ Def::Variant(did) => {
let enum_did = self.parent(did).unwrap();
self.adt_def(enum_did).variant_with_id(did)
}
Def::Struct(did) | Def::Union(did) => {
self.adt_def(did).non_enum_variant()
}
- Def::StructCtor(ctor_did, ..) => {
- let did = self.parent(ctor_did).expect("struct ctor has no parent");
- self.adt_def(did).non_enum_variant()
+ Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => {
+ let variant_did = self.parent(variant_ctor_did).unwrap();
+ let enum_did = self.parent(variant_did).unwrap();
+ self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
+ }
+ Def::Ctor(ctor_did, CtorOf::Struct, ..) => {
+ let struct_did = self.parent(ctor_did).expect("struct ctor has no parent");
+ self.adt_def(struct_did).non_enum_variant()
}
_ => bug!("expect_variant_def used with unexpected def {:?}", def)
}
}
- /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part.
- pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId {
- let def_key = self.def_key(variant_def.did);
- match def_key.disambiguated_data.data {
- // for enum variants and tuple structs, the def-id of the ADT itself
- // is the *parent* of the variant
- DefPathData::EnumVariant(..) | DefPathData::StructCtor =>
- DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() },
-
- // otherwise, for structs and unions, they share a def-id
- _ => variant_def.did,
- }
- }
-
pub fn item_name(self, id: DefId) -> InternedString {
if id.index == CRATE_DEF_INDEX {
self.original_crate_name(id.krate).as_interned_str()
} else {
let def_key = self.def_key(id);
- // The name of a StructCtor is that of its struct parent.
- if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data {
- self.item_name(DefId {
- krate: id.krate,
- index: def_key.parent.unwrap()
- })
- } else {
- def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| {
+ match def_key.disambiguated_data.data {
+ // The name of a constructor is that of its parent.
+ hir_map::DefPathData::Ctor =>
+ self.item_name(DefId {
+ krate: id.krate,
+ index: def_key.parent.unwrap()
+ }),
+ _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| {
bug!("item_name: no name for {:?}", self.def_path(id));
- })
+ }),
}
}
}
let mut cur_def_key = self.tcx().def_key(def_id);
debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
- // For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
- if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
- let parent = DefId {
- krate: def_id.krate,
- index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
- };
+ // For a constructor we want the name of its parent rather than <unnamed>.
+ match cur_def_key.disambiguated_data.data {
+ DefPathData::Ctor => {
+ let parent = DefId {
+ krate: def_id.krate,
+ index: cur_def_key.parent
+ .expect("DefPathData::Ctor/VariantData missing a parent"),
+ };
- cur_def_key = self.tcx().def_key(parent);
+ cur_def_key = self.tcx().def_key(parent);
+ },
+ _ => {},
}
let visible_parent = match visible_parent_map.get(&def_id).cloned() {
DefPathData::AnonConst |
DefPathData::ConstParam(..) |
DefPathData::ClosureExpr |
- DefPathData::StructCtor => Namespace::ValueNS,
+ DefPathData::Ctor => Namespace::ValueNS,
DefPathData::MacroDef(..) => Namespace::MacroNS,
// Skip `::{{constructor}}` on tuple/unit structs.
match disambiguated_data.data {
- DefPathData::StructCtor => return Ok(self),
+ DefPathData::Ctor => return Ok(self),
_ => {}
}
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
- fn describe(_tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>) -> Cow<'static, str> {
- format!("erasing regions from `{:?}`", ty).into()
- }
-}
-
impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> {
fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> Cow<'static, str> {
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> {
- fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
- "getting a list of all mir_keys".into()
- }
-}
-
impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> Cow<'static, str> {
format!("computing the symbol for `{}`", instance).into()
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> {
- fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
- "computing the lint levels for items in this crate".into()
- }
-}
-
impl<'tcx> QueryDescription<'tcx> for queries::specializes<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> Cow<'static, str> {
"computing whether impls specialize one another".into()
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> {
- #[inline]
- fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, def_id: Self::Key) -> bool {
- def_id.is_local()
- }
-
- fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- id: SerializedDepNodeIndex)
- -> Option<Self::Value> {
- let mir: Option<crate::mir::Mir<'tcx>> = tcx.queries.on_disk_cache
- .try_load_query_result(tcx, id);
- mir.map(|x| tcx.alloc_mir(x))
- }
-}
-
impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, SubstsRef<'tcx>)) -> Cow<'static, str> {
format!("testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0)).into()
}
}
-impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
- fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
- "generating chalk-style clauses".into()
- }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
- fn describe(_tcx: TyCtxt<'_, '_, '_>, _: traits::Environment<'tcx>) -> Cow<'static, str> {
- "generating chalk-style clauses for environment".into()
- }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::environment<'tcx> {
- fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
- "return a chalk-style environment".into()
- }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
- fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
- "wasm import module map".into()
- }
-}
-
impl<'tcx> QueryDescription<'tcx> for queries::dllimport_foreign_items<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
- "wasm import module map".into()
+ "dllimport_foreign_items".into()
}
}
impl_disk_cacheable_query!(unsafety_check_result, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(borrowck, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(mir_const_qualif, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(check_match, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(def_symbol_name, |_, _| true);
impl_disk_cacheable_query!(predicates_of, |_, def_id| def_id.is_local());
[] fn inherent_impls: InherentImpls(DefId) -> Lrc<Vec<DefId>>,
},
- Codegen {
- /// Set of all the `DefId`s in this crate that have MIR associated with
- /// them. This includes all the body owners, but also things like struct
- /// constructors.
- [] fn mir_keys: mir_keys(CrateNum) -> Lrc<DefIdSet>,
-
- /// Maps DefId's that have an associated Mir to the result
- /// of the MIR qualify_consts pass. The actual meaning of
- /// the value isn't known except to the pass itself.
- [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<BitSet<mir::Local>>),
-
- /// Fetch the MIR for a given `DefId` right after it's built - this includes
- /// unreachable code.
- [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
-
- /// Fetch the MIR for a given `DefId` up till the point where it is
- /// ready for const evaluation.
- ///
- /// See the README for the `mir` module for details.
- [no_hash] fn mir_const: MirConst(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
-
- [no_hash] fn mir_validated: MirValidated(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
-
- /// MIR after our optimization passes have run. This is MIR that is ready
- /// for codegen. This is also the only query that can fetch non-local MIR, at present.
- [] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>,
- },
-
TypeChecking {
/// The result of unsafety-checking this `DefId`.
[] fn unsafety_check_result: UnsafetyCheckResult(DefId) -> mir::UnsafetyCheckResult,
Other {
[] fn module_exports: ModuleExports(DefId) -> Option<Lrc<Vec<Export>>>,
- [] fn lint_levels: lint_levels_node(CrateNum) -> Lrc<lint::LintLevelMap>,
},
TypeChecking {
},
TypeChecking {
- // Erases regions from `ty` to yield a new type.
- // Normally you would just use `tcx.erase_regions(&value)`,
- // however, which uses this query as a kind of cache.
- [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>,
-
/// Do not call this query directly: invoke `normalize` instead.
[] fn normalize_projection_ty: NormalizeProjectionTy(
CanonicalProjectionGoal<'tcx>
[] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
},
-
- TypeChecking {
- [] fn program_clauses_for: ProgramClausesFor(DefId) -> Clauses<'tcx>,
-
- [] fn program_clauses_for_env: ProgramClausesForEnv(
- traits::Environment<'tcx>
- ) -> Clauses<'tcx>,
-
- // Get the chalk-style environment of the given item.
- [] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
- },
-
- Linking {
- [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
- -> Lrc<FxHashMap<DefId, String>>,
- },
]}
//////////////////////////////////////////////////////////////////////
DepConstructor::CodegenFnAttrs { 0: id }
}
-fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
- DepConstructor::EraseRegionsTy { ty }
-}
-
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
DepConstructor::TypeParamPredicates {
item_id,
DepConstructor::ConstEvalRaw { param_env }
}
-fn mir_keys<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
- DepConstructor::MirKeys
-}
-
fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::CrateVariances
}
DepConstructor::Layout { param_env }
}
-fn lint_levels_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
- DepConstructor::LintLevels
-}
-
fn specializes_node<'tcx>((a, b): (DefId, DefId)) -> DepConstructor<'tcx> {
DepConstructor::Specializes { impl1: a, impl2: b }
}
DepKind::CompileCodegenUnit |
DepKind::FulfillObligation |
DepKind::VtableMethods |
- DepKind::EraseRegionsTy |
DepKind::NormalizeProjectionTy |
DepKind::NormalizeTyAfterErasingRegions |
DepKind::ImpliedOutlivesBounds |
DepKind::TypeOpNormalizeFnSig |
DepKind::SubstituteNormalizeAndTestPredicates |
DepKind::MethodAutoderefSteps |
- DepKind::InstanceDefSizeEstimate |
- DepKind::ProgramClausesForEnv |
-
- // This one should never occur in this context
- DepKind::Null => {
+ DepKind::InstanceDefSizeEstimate => {
bug!("force_from_dep_node() - Encountered {:?}", dep_node)
}
},
DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
DepKind::CheckPrivateInPublic => { force!(check_private_in_public, LOCAL_CRATE); }
- DepKind::MirBuilt => { force!(mir_built, def_id!()); }
- DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
- DepKind::MirConst => { force!(mir_const, def_id!()); }
- DepKind::MirValidated => { force!(mir_validated, def_id!()); }
- DepKind::MirOptimized => { force!(optimized_mir, def_id!()); }
DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
DepKind::CheckModImplWf => { force!(check_mod_impl_wf, def_id!()); }
DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
- DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
DepKind::AssociatedItems => { force!(associated_item, def_id!()); }
DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
DepKind::CheckMatch => { force!(check_match, def_id!()); }
DepKind::ParamEnv => { force!(param_env, def_id!()); }
- DepKind::Environment => { force!(environment, def_id!()); }
DepKind::DescribeDef => { force!(describe_def, def_id!()); }
DepKind::DefSpan => { force!(def_span, def_id!()); }
DepKind::LookupStability => { force!(lookup_stability, def_id!()); }
DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); }
DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
- DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); }
DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
DepKind::ModuleExports => { force!(module_exports, def_id!()); }
DepKind::IsSanitizerRuntime => { force!(is_sanitizer_runtime, krate!()); }
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
- DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
- DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
DepKind::UpstreamMonomorphizations => {
impl_load_from_cache!(
TypeckTables => typeck_tables_of,
- MirOptimized => optimized_mir,
+ optimized_mir => optimized_mir,
UnsafetyCheckResult => unsafety_check_result,
BorrowCheck => borrowck,
MirBorrowCheck => mir_borrowck,
- MirConstQualif => mir_const_qualif,
+ mir_const_qualif => mir_const_qualif,
SymbolName => def_symbol_name,
ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
CheckMatch => check_match,
/// Returns `true` if this `DefId` refers to the implicit constructor for
/// a tuple struct like `struct Foo(u32)`, and `false` otherwise.
- pub fn is_struct_constructor(self, def_id: DefId) -> bool {
- self.def_key(def_id).disambiguated_data.data == DefPathData::StructCtor
+ pub fn is_constructor(self, def_id: DefId) -> bool {
+ self.def_key(def_id).disambiguated_data.data == DefPathData::Ctor
}
/// Given the `DefId` of a fn or closure, returns the `DefId` of
use std::rc::Rc;
use rustc_data_structures::sync::Lrc;
use std::hash::{Hash, Hasher};
+use syntax::source_map::CompilerDesugaringKind;
use syntax_pos::{MultiSpan, Span};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use log::debug;
let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap();
match tcx.hir().get_by_hir_id(owner_id) {
- Node::StructCtor(_) |
- Node::Variant(_) => {
+ Node::Ctor(..) => {
// We get invoked with anything that has MIR, but some of
// those things (notably the synthesized constructors from
// tuple structs/variants) do not have an associated body
},
moved_lp.ty));
}
+ if let (Some(CompilerDesugaringKind::ForLoop), Ok(snippet)) = (
+ move_span.compiler_desugaring_kind(),
+ self.tcx.sess.source_map().span_to_snippet(move_span),
+ ) {
+ if !snippet.starts_with("&") {
+ err.span_suggestion(
+ move_span,
+ "consider borrowing this to avoid moving it into the for loop",
+ format!("&{}", snippet),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
// Note: we used to suggest adding a `ref binding` or calling
// `clone` but those suggestions have been removed because
// Enums
//=-----------------------------------------------------------------------------
-// DWARF variant support is only available starting in LLVM 7.
+// DWARF variant support is only available starting in LLVM 8.
// Although the earlier enum debug info output did not work properly
// in all situations, it is better for the time being to continue to
// sometimes emit the old style rather than emit something completely
-// useless when rust is compiled against LLVM 6 or older. This
-// function decides which representation will be emitted.
+// useless when rust is compiled against LLVM 6 or older. LLVM 7
+// contains an early version of the DWARF variant support, and will
+// crash when handling the new debug info format. This function
+// decides which representation will be emitted.
fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
// On MSVC we have to use the fallback mode, because LLVM doesn't
// lower variant parts to PDB.
pub struct InlineAsmDiagnostic<'ll> {
pub cookie: c_uint,
pub message: &'ll Twine,
- pub instruction: &'ll Value,
+ pub instruction: Option<&'ll Value>,
}
impl InlineAsmDiagnostic<'ll> {
InlineAsmDiagnostic {
cookie,
message: message.unwrap(),
- instruction: instruction.unwrap(),
+ instruction,
}
}
}
use rustc::middle::lang_items;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
-use rustc::mir;
+use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
use rustc::mir::interpret::EvalErrorKind;
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
use rustc_target::spec::abi::Abi;
// but specified directly in the code. This means it gets promoted
// and we can then extract the value by evaluating the promoted.
mir::Operand::Copy(
- mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+ Place::Base(
+ PlaceBase::Static(
+ box Static { kind: StaticKind::Promoted(promoted), ty }
+ )
+ )
) |
mir::Operand::Move(
- mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+ Place::Base(
+ PlaceBase::Static(
+ box Static { kind: StaticKind::Promoted(promoted), ty }
+ )
+ )
) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
instance: self.instance,
- promoted: Some(index),
+ promoted: Some(promoted),
};
let c = bx.tcx().const_eval(param_env.and(cid));
let (llval, ty) = self.simd_shuffle_indices(
let result = match *place {
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
- mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
+ mir::Place::Base(
+ mir::PlaceBase::Static(
+ box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }
+ )
+ ) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
instance: self.instance,
- promoted: Some(index),
+ promoted: Some(promoted),
};
let layout = cx.layout_of(self.monomorphize(&ty));
match bx.tcx().const_eval(param_env.and(cid)) {
}
}
}
- mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
+ mir::Place::Base(
+ mir::PlaceBase::Static(
+ box mir::Static { ty, kind: mir::StaticKind::Static(def_id) }
+ )
+ ) => {
// NB: The layout of a static may be unsized as is the case when working
// with a static that is an extern_type.
let layout = cx.layout_of(self.monomorphize(&ty));
// Skip `::{{constructor}}` on tuple/unit structs.
match disambiguated_data.data {
- DefPathData::StructCtor => return Ok(self),
+ DefPathData::Ctor => return Ok(self),
_ => {}
}
let body = tcx.hir().body(body_id);
let cfg = cfg::CFG::new(tcx, &body);
let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
+ let hir_id = code.id();
+ // We have to disassemble the hir_id because name must be ASCII
+ // alphanumeric. This does not appear in the rendered graph, so it does not
+ // have to be user friendly.
+ let name = format!(
+ "hir_id_{}_{}_{}",
+ hir_id.owner.address_space().index(),
+ hir_id.owner.as_array_index(),
+ hir_id.local_id.index(),
+ );
let lcfg = LabelledCFG {
tcx,
cfg: &cfg,
- name: format!("node_{}", code.id()),
+ name,
labelled_edges,
};
label_strs::ImplTraitRef,
];
-/// DepNodes for MirBuilt/Optimized, which is relevant in "executable"
+/// DepNodes for mir_built/Optimized, which is relevant in "executable"
/// code, i.e., functions+methods
const BASE_MIR: &[&str] = &[
- label_strs::MirOptimized,
- label_strs::MirBuilt,
+ label_strs::optimized_mir,
+ label_strs::mir_built,
];
/// Struct, Enum and Union DepNodes
if let Some(value) = item.value_str() {
value
} else {
- let msg = if let Some(name) = item.ident_str() {
- format!("associated value expected for `{}`", name)
+ let msg = if let Some(ident) = item.ident() {
+ format!("associated value expected for `{}`", ident)
} else {
"expected an associated value".to_string()
};
fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) {
self.check_missing_docs_attrs(cx,
- Some(v.node.data.hir_id()),
+ Some(v.node.id),
&v.node.attrs,
v.span,
"a variant");
impl EarlyLintPass for DeprecatedAttr {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
+ let name = attr.name_or_empty();
for &&(n, _, _, ref g) in &self.depr_attrs {
- if attr.ident_str() == Some(n) {
+ if name == n {
if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
ref name,
ref reason,
}
}
- let name = attr.ident_str();
+ let name = attr.name_or_empty();
if !attr::is_used(attr) {
debug!("Emitting warning for: {:?}", attr);
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
// Is it a builtin attribute that must be used at the crate level?
let known_crate = BUILTIN_ATTRIBUTES.iter()
.find(|&&(builtin, ty, ..)| {
- name == Some(builtin) && ty == AttributeType::CrateLevel
+ name == builtin && ty == AttributeType::CrateLevel
})
.is_some();
// Has a plugin registered this attribute as one that must be used at
// the crate level?
let plugin_crate = plugin_attributes.iter()
- .find(|&&(ref x, t)| name == Some(x) && AttributeType::CrateLevel == t)
+ .find(|&&(ref x, t)| name == x.as_str() && AttributeType::CrateLevel == t)
.is_some();
if known_crate || plugin_crate {
let msg = match attr.style {
syn = { version = "0.15.22", features = ["full"] }
proc-macro2 = "0.4.24"
quote = "0.6.10"
+itertools = "0.8"
use syn::punctuated::Punctuated;
use syn;
use quote::quote;
+use itertools::Itertools;
#[allow(non_camel_case_types)]
mod kw {
/// A cycle error for this query aborting the compilation with a fatal error.
FatalCycle,
+
+ /// Don't hash the result, instead just mark a query red if it runs
+ NoHash,
+
+ /// Don't force the query
+ NoForce,
+
+ /// Generate a dep node based on the dependencies of the query
+ Anon,
+
+ // Always evaluate the query, ignoring its depdendencies
+ EvalAlways,
}
impl Parse for QueryModifier {
Ok(QueryModifier::LoadCached(tcx, id, block))
} else if modifier == "fatal_cycle" {
Ok(QueryModifier::FatalCycle)
+ } else if modifier == "no_hash" {
+ Ok(QueryModifier::NoHash)
+ } else if modifier == "no_force" {
+ Ok(QueryModifier::NoForce)
+ } else if modifier == "anon" {
+ Ok(QueryModifier::Anon)
+ } else if modifier == "eval_always" {
+ Ok(QueryModifier::EvalAlways)
} else {
Err(Error::new(modifier.span(), "unknown query modifier"))
}
/// A cycle error for this query aborting the compilation with a fatal error.
fatal_cycle: bool,
+
+ /// Don't hash the result, instead just mark a query red if it runs
+ no_hash: bool,
+
+ /// Don't force the query
+ no_force: bool,
+
+ /// Generate a dep node based on the dependencies of the query
+ anon: bool,
+
+ // Always evaluate the query, ignoring its depdendencies
+ eval_always: bool,
}
/// Process query modifiers into a struct, erroring on duplicates
let mut cache = None;
let mut desc = None;
let mut fatal_cycle = false;
+ let mut no_hash = false;
+ let mut no_force = false;
+ let mut anon = false;
+ let mut eval_always = false;
for modifier in query.modifiers.0.drain(..) {
match modifier {
QueryModifier::LoadCached(tcx, id, block) => {
}
fatal_cycle = true;
}
+ QueryModifier::NoHash => {
+ if no_hash {
+ panic!("duplicate modifier `no_hash` for query `{}`", query.name);
+ }
+ no_hash = true;
+ }
+ QueryModifier::NoForce => {
+ if no_force {
+ panic!("duplicate modifier `no_force` for query `{}`", query.name);
+ }
+ no_force = true;
+ }
+ QueryModifier::Anon => {
+ if anon {
+ panic!("duplicate modifier `anon` for query `{}`", query.name);
+ }
+ anon = true;
+ }
+ QueryModifier::EvalAlways => {
+ if eval_always {
+ panic!("duplicate modifier `eval_always` for query `{}`", query.name);
+ }
+ eval_always = true;
+ }
}
}
QueryModifiers {
cache,
desc,
fatal_cycle,
+ no_hash,
+ no_force,
+ anon,
+ eval_always,
}
}
let mut query_description_stream = quote! {};
let mut dep_node_def_stream = quote! {};
let mut dep_node_force_stream = quote! {};
+ let mut no_force_queries = Vec::new();
for group in groups.0 {
let mut group_stream = quote! {};
_ => quote! { #result_full },
};
+ let mut attributes = Vec::new();
+
// Pass on the fatal_cycle modifier
- let fatal_cycle = if modifiers.fatal_cycle {
- quote! { fatal_cycle }
- } else {
- quote! {}
+ if modifiers.fatal_cycle {
+ attributes.push(quote! { fatal_cycle });
};
+ // Pass on the no_hash modifier
+ if modifiers.no_hash {
+ attributes.push(quote! { no_hash });
+ };
+
+ let mut attribute_stream = quote! {};
+
+ for e in attributes.into_iter().intersperse(quote! {,}) {
+ attribute_stream.extend(e);
+ }
// Add the query to the group
group_stream.extend(quote! {
- [#fatal_cycle] fn #name: #name(#arg) #result,
+ [#attribute_stream] fn #name: #name(#arg) #result,
});
- add_query_description_impl(&query, modifiers, &mut query_description_stream);
+ let mut attributes = Vec::new();
+
+ // Pass on the anon modifier
+ if modifiers.anon {
+ attributes.push(quote! { anon });
+ };
+ // Pass on the eval_always modifier
+ if modifiers.eval_always {
+ attributes.push(quote! { eval_always });
+ };
+ let mut attribute_stream = quote! {};
+ for e in attributes.into_iter().intersperse(quote! {,}) {
+ attribute_stream.extend(e);
+ }
// Create a dep node for the query
dep_node_def_stream.extend(quote! {
- [] #name(#arg),
+ [#attribute_stream] #name(#arg),
});
- // Add a match arm to force the query given the dep node
- dep_node_force_stream.extend(quote! {
- DepKind::#name => {
- if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
- force_ex!($tcx, #name, key);
- } else {
- return false;
+ if modifiers.no_force {
+ no_force_queries.push(name.clone());
+ } else {
+ // Add a match arm to force the query given the dep node
+ dep_node_force_stream.extend(quote! {
+ DepKind::#name => {
+ if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
+ force_ex!($tcx, #name, key);
+ } else {
+ return false;
+ }
}
- }
- });
+ });
+ }
+
+ add_query_description_impl(&query, modifiers, &mut query_description_stream);
}
let name = &group.name;
query_stream.extend(quote! {
#name { #group_stream },
});
}
+
+ // Add an arm for the no force queries to panic when trying to force them
+ for query in no_force_queries {
+ dep_node_force_stream.extend(quote! {
+ DepKind::#query |
+ });
+ }
+ dep_node_force_stream.extend(quote! {
+ DepKind::Null => {
+ bug!("Cannot force dep node: {:?}", $dep_node)
+ }
+ });
+
TokenStream::from(quote! {
macro_rules! rustc_query_append {
([$($macro:tt)*][$($other:tt)*]) => {
self.get_crate_data(def.krate).get_struct_field_names(def.index)
}
+ pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind {
+ self.get_crate_data(def.krate).get_ctor_kind(def.index)
+ }
+
+ pub fn item_attrs_untracked(&self, def: DefId, sess: &Session) -> Lrc<[ast::Attribute]> {
+ self.get_crate_data(def.krate).get_item_attrs(def.index, sess)
+ }
+
pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export> {
let mut result = vec![];
self.get_crate_data(def_id.krate)
use rustc::hir;
use rustc::middle::cstore::LinkagePreference;
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
-use rustc::hir::def::{self, Def, CtorKind};
+use rustc::hir::def::{self, Def, CtorOf, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace,
CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
use rustc::hir::map::definitions::DefPathTable;
}
}
- fn get_variant(&self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- item: &Entry<'_>,
- index: DefIndex,
- adt_kind: ty::AdtKind)
- -> ty::VariantDef
- {
+ fn get_variant(
+ &self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ item: &Entry<'_>,
+ index: DefIndex,
+ parent_did: DefId,
+ adt_kind: ty::AdtKind
+ ) -> ty::VariantDef {
let data = match item.kind {
EntryKind::Variant(data) |
EntryKind::Struct(data, _) |
_ => bug!(),
};
- let def_id = self.local_def_id(data.struct_ctor.unwrap_or(index));
- let attribute_def_id = self.local_def_id(index);
+ let variant_did = if adt_kind == ty::AdtKind::Enum {
+ Some(self.local_def_id(index))
+ } else {
+ None
+ };
+ let ctor_did = data.ctor.map(|index| self.local_def_id(index));
ty::VariantDef::new(
tcx,
- def_id,
Ident::from_interned_str(self.item_name(index)),
+ variant_did,
+ ctor_did,
data.discr,
item.children.decode(self).map(|index| {
let f = self.entry(index);
vis: f.visibility.decode(self)
}
}).collect(),
- adt_kind,
data.ctor_kind,
- attribute_def_id,
+ adt_kind,
+ parent_did,
false,
)
}
item.children
.decode(self)
.map(|index| {
- self.get_variant(tcx, &self.entry(index), index, kind)
+ self.get_variant(tcx, &self.entry(index), index, did, kind)
})
.collect()
} else {
- std::iter::once(self.get_variant(tcx, &item, item_id, kind)).collect()
+ std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect()
};
tcx.alloc_adt_def(did, kind, variants, repr)
// Re-export lists automatically contain constructors when necessary.
match def {
Def::Struct(..) => {
- if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
+ if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) {
let ctor_kind = self.get_ctor_kind(child_index);
- let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
- callback(def::Export {
- def: ctor_def,
- vis: self.get_visibility(ctor_def_id.index),
- ident, span,
- });
+ let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Struct, ctor_kind);
+ let vis = self.get_visibility(ctor_def_id.index);
+ callback(def::Export { def: ctor_def, vis, ident, span });
}
}
Def::Variant(def_id) => {
// Braced variants, unlike structs, generate unusable names in
// value namespace, they are reserved for possible future use.
+ // It's ok to use the variant's id as a ctor id since an
+ // error will be reported on any use of such resolution anyway.
+ let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
let ctor_kind = self.get_ctor_kind(child_index);
- let ctor_def = Def::VariantCtor(def_id, ctor_kind);
- let vis = self.get_visibility(child_index);
+ let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
+ let vis = self.get_visibility(ctor_def_id.index);
callback(def::Export { def: ctor_def, ident, vis, span });
}
_ => {}
}
}
- pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
+ pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
match self.entry(node_id).kind {
EntryKind::Struct(data, _) => {
- data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
+ data.decode(self).ctor.map(|index| self.local_def_id(index))
+ }
+ EntryKind::Variant(data) => {
+ data.decode(self).ctor.map(|index| self.local_def_id(index))
}
_ => None,
}
return Lrc::new([]);
}
- // The attributes for a tuple struct are attached to the definition, not the ctor;
+ // The attributes for a tuple struct/variant are attached to the definition, not the ctor;
// we assume that someone passing in a tuple struct ctor is actually wanting to
// look at the definition
let def_key = self.def_key(node_id);
- let item_id = if def_key.disambiguated_data.data == DefPathData::StructCtor {
+ let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor {
def_key.parent.unwrap()
} else {
node_id
/// will have to lookup the adt-def by its id, and that gives us
/// the right to access any information in the adt-def (including,
/// e.g., the length of the various vectors).
- fn encode_enum_variant_info(&mut self,
- (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>))
- -> Entry<'tcx> {
+ fn encode_enum_variant_info(
+ &mut self,
+ (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+ ) -> Entry<'tcx> {
let tcx = self.tcx;
let def = tcx.adt_def(enum_did);
let variant = &def.variants[index];
- let def_id = variant.did;
+ let def_id = variant.def_id;
debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
let data = VariantData {
ctor_kind: variant.ctor_kind,
discr: variant.discr,
- struct_ctor: None,
- ctor_sig: if variant.ctor_kind == CtorKind::Fn {
- Some(self.lazy(&tcx.fn_sig(def_id)))
- } else {
- None
- }
+ ctor: variant.ctor_def_id.map(|did| did.index),
+ ctor_sig: None,
};
let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
}
}
+ /// Encode the constructor for the given variant of the given ADT. See
+ /// `encode_enum_variant_info` for an explanation about why the index is untracked.
+ fn encode_enum_variant_ctor(
+ &mut self,
+ (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+ ) -> Entry<'tcx> {
+ let tcx = self.tcx;
+ let def = tcx.adt_def(enum_did);
+ let variant = &def.variants[index];
+ let def_id = variant.ctor_def_id.unwrap();
+ debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id);
+
+ let data = VariantData {
+ ctor_kind: variant.ctor_kind,
+ discr: variant.discr,
+ ctor: Some(def_id.index),
+ ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+ Some(self.lazy(&tcx.fn_sig(def_id)))
+ } else {
+ None
+ }
+ };
+
+ // Variant constructors have the same visibility as the parent enums.
+ let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
+ let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis;
+
+ Entry {
+ kind: EntryKind::Variant(self.lazy(&data)),
+ visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)),
+ span: self.lazy(&tcx.def_span(def_id)),
+ attributes: LazySeq::empty(),
+ children: LazySeq::empty(),
+ stability: self.encode_stability(def_id),
+ deprecation: self.encode_deprecation(def_id),
+
+ ty: Some(self.encode_item_type(def_id)),
+ inherent_impls: LazySeq::empty(),
+ variances: if variant.ctor_kind == CtorKind::Fn {
+ self.encode_variances_of(def_id)
+ } else {
+ LazySeq::empty()
+ },
+ generics: Some(self.encode_generics(def_id)),
+ predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
+
+ mir: self.encode_optimized_mir(def_id),
+ }
+ }
+
fn encode_info_for_mod(&mut self,
FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
&[ast::Attribute],
let def_id = field.did;
debug!("IsolatedEncoder::encode_field({:?})", def_id);
- let variant_id = tcx.hir().as_local_hir_id(variant.did).unwrap();
+ let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
let variant_data = tcx.hir().expect_variant_data(variant_id);
Entry {
let data = VariantData {
ctor_kind: variant.ctor_kind,
discr: variant.discr,
- struct_ctor: Some(def_id.index),
+ ctor: Some(def_id.index),
ctor_sig: if variant.ctor_kind == CtorKind::Fn {
Some(self.lazy(&tcx.fn_sig(def_id)))
} else {
// Encode def_ids for each field and method
// for methods, write all the stuff get_trait_method
// needs to know
- let struct_ctor = if !struct_def.is_struct() {
- Some(tcx.hir().local_def_id_from_hir_id(struct_def.hir_id()).index)
- } else {
- None
- };
+ let ctor = struct_def.ctor_hir_id()
+ .map(|ctor_hir_id| tcx.hir().local_def_id_from_hir_id(ctor_hir_id).index);
let repr_options = get_repr_options(&tcx, def_id);
EntryKind::Struct(self.lazy(&VariantData {
ctor_kind: variant.ctor_kind,
discr: variant.discr,
- struct_ctor,
+ ctor,
ctor_sig: None,
}), repr_options)
}
EntryKind::Union(self.lazy(&VariantData {
ctor_kind: variant.ctor_kind,
discr: variant.discr,
- struct_ctor: None,
+ ctor: None,
ctor_sig: None,
}), repr_options)
}
hir::ItemKind::Enum(..) => {
let def = self.tcx.adt_def(def_id);
self.lazy_seq(def.variants.iter().map(|v| {
- assert!(v.did.is_local());
- v.did.index
+ assert!(v.def_id.is_local());
+ v.def_id.index
}))
}
hir::ItemKind::Struct(..) |
let def = self.tcx.adt_def(def_id);
for (i, variant) in def.variants.iter_enumerated() {
- self.record(variant.did,
+ self.record(variant.def_id,
IsolatedEncoder::encode_enum_variant_info,
(def_id, Untracked(i)));
+
+ if let Some(ctor_def_id) = variant.ctor_def_id {
+ self.record(ctor_def_id,
+ IsolatedEncoder::encode_enum_variant_ctor,
+ (def_id, Untracked(i)));
+ }
}
}
hir::ItemKind::Struct(ref struct_def, _) => {
self.encode_fields(def_id);
// If the struct has a constructor, encode it.
- if !struct_def.is_struct() {
- let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(struct_def.hir_id());
+ if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+ let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
self.record(ctor_def_id,
IsolatedEncoder::encode_struct_ctor,
(def_id, ctor_def_id));
pub struct VariantData<'tcx> {
pub ctor_kind: CtorKind,
pub discr: ty::VariantDiscr,
-
- /// If this is a struct's only variant, this
- /// is the index of the "struct ctor" item.
- pub struct_ctor: Option<DefIndex>,
-
+ /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
+ pub ctor: Option<DefIndex>,
/// If this is a tuple struct or variant
/// ctor, this is its "function" signature.
pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
impl_stable_hash_for!(struct VariantData<'tcx> {
ctor_kind,
discr,
- struct_ctor,
+ ctor,
ctor_sig
});
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
- TerminatorKind, VarBindingForm,
+ Static, StaticKind, TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, DefIdTree};
use rustc::ty::print::Print;
including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match *place {
- Place::Base(PlaceBase::Promoted(_)) => {
- buf.push_str("promoted");
- }
Place::Base(PlaceBase::Local(local)) => {
self.append_local_to_string(local, buf)?;
}
- Place::Base(PlaceBase::Static(ref static_)) => {
- buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
+ buf.push_str("promoted");
+ }
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
+ buf.push_str(&self.infcx.tcx.item_name(def_id).to_string());
}
Place::Projection(ref proj) => {
match proj.elem {
let local = &self.mir.local_decls[local];
self.describe_field_from_ty(&local.ty, field)
}
- Place::Base(PlaceBase::Promoted(ref prom)) =>
- self.describe_field_from_ty(&prom.1, field),
Place::Base(PlaceBase::Static(ref static_)) =>
self.describe_field_from_ty(&static_.ty, field),
Place::Projection(ref proj) => match proj.elem {
/// Checks if a place is a thread-local static.
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
- if let Place::Base(PlaceBase::Static(statik)) = place {
- let attrs = self.infcx.tcx.get_attrs(statik.def_id);
+ if let Place::Base(
+ PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })
+ ) = place {
+ let attrs = self.infcx.tcx.get_attrs(*def_id);
let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
debug!(
let tcx = self.infcx.tcx;
match place {
Place::Base(PlaceBase::Local(_)) |
- Place::Base(PlaceBase::Static(_)) |
- Place::Base(PlaceBase::Promoted(_)) => {
+ Place::Base(PlaceBase::Static(_)) => {
StorageDeadOrDrop::LocalStorageDead
}
Place::Projection(box PlaceProjection { base, elem }) => {
use rustc::lint::builtin::UNUSED_MUT;
use rustc::middle::borrowck::SignalledError;
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
+use rustc::mir::{
+ ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase, Static, StaticKind
+};
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
use rustc::ty::query::Providers;
// Return early if we are not supposed to use MIR borrow checker for this function.
return_early = !tcx.has_attr(def_id, "rustc_mir") && !tcx.use_mir_borrowck();
- if tcx.is_struct_constructor(def_id) {
- // We are not borrow checking the automatically generated struct constructors
+ if tcx.is_constructor(def_id) {
+ // We are not borrow checking the automatically generated struct/variant constructors
// because we want to accept structs such as this (taken from the `linked-hash-map`
// crate):
// ```rust
let mut flow_inits = FlowAtLocation::new(do_dataflow(
tcx,
mir,
- id,
+ def_id,
&attributes,
&dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
let flow_borrows = FlowAtLocation::new(do_dataflow(
tcx,
mir,
- id,
+ def_id,
&attributes,
&dead_unwinds,
Borrows::new(tcx, mir, regioncx.clone(), &borrow_set),
let flow_uninits = FlowAtLocation::new(do_dataflow(
tcx,
mir,
- id,
+ def_id,
&attributes,
&dead_unwinds,
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
let flow_ever_inits = FlowAtLocation::new(do_dataflow(
tcx,
mir,
- id,
+ def_id,
&attributes,
&dead_unwinds,
EverInitializedPlaces::new(tcx, mir, &mdpe),
}
Operand::Move(Place::Base(PlaceBase::Static(..)))
| Operand::Copy(Place::Base(PlaceBase::Static(..)))
- | Operand::Move(Place::Base(PlaceBase::Promoted(..)))
- | Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
| Operand::Constant(..) => {}
}
}
//
// FIXME: allow thread-locals to borrow other thread locals?
let (might_be_alive, will_be_dropped) = match root_place {
- Place::Base(PlaceBase::Promoted(_)) => (true, false),
- Place::Base(PlaceBase::Static(_)) => {
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
+ (true, false)
+ }
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(_), .. })) => {
// Thread-locals might be dropped after the function exits, but
// "true" statics will never be.
- let is_thread_local = self.is_place_thread_local(&root_place);
- (true, is_thread_local)
+ (true, self.is_place_thread_local(&root_place))
}
Place::Base(PlaceBase::Local(_)) => {
// Locals are always dropped at function exit, and if they
match *last_prefix {
Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
}
}
let mut place = place;
loop {
match *place {
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
// assigning to `x` does not require `x` be initialized.
break;
self.used_mut_upvars.push(field);
}
}
- RootPlace {
- place: Place::Base(PlaceBase::Promoted(..)),
- is_local_mutation_allowed: _,
- } => {}
RootPlace {
place: Place::Base(PlaceBase::Static(..)),
is_local_mutation_allowed: _,
}
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
- Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
- place,
- is_local_mutation_allowed,
- }),
- Place::Base(PlaceBase::Static(ref static_)) => {
- if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
+ Place::Base(PlaceBase::Static(box Static{kind: StaticKind::Promoted(_), ..})) =>
+ Ok(RootPlace {
+ place,
+ is_local_mutation_allowed,
+ }),
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
+ if self.infcx.tcx.is_static(def_id) != Some(hir::Mutability::MutMutable) {
Err(place)
} else {
Ok(RootPlace {
use rustc::hir;
use rustc::hir::Node;
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
-use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
+use rustc::mir::{
+ Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
+};
use rustc::mir::{Terminator, TerminatorKind};
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
}
}
- Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
+ Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) =>
+ unreachable!(),
- Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+ Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })) => {
if let Place::Base(PlaceBase::Static(_)) = access_place {
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
reason = String::new();
context: PlaceContext<'_>,
) -> PlaceTy<'tcx> {
debug!("sanitize_place: {:?}", place);
- let place_ty = match *place {
+ let place_ty = match place {
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
- ty: self.mir.local_decls[index].ty,
+ ty: self.mir.local_decls[*index].ty,
},
- Place::Base(PlaceBase::Promoted(box (index, sty))) => {
+ Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
let sty = self.sanitize_type(place, sty);
-
- if !self.errors_reported {
- let promoted_mir = &self.mir.promoted[index];
- self.sanitize_promoted(promoted_mir, location);
-
- let promoted_ty = promoted_mir.return_ty();
-
- if let Err(terr) = self.cx.eq_types(
- sty,
- promoted_ty,
- location.to_locations(),
- ConstraintCategory::Boring,
- ) {
- span_mirbug!(
- self,
+ let check_err =
+ |verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
+ place: &Place<'tcx>,
+ ty,
+ sty| {
+ if let Err(terr) = verifier.cx.eq_types(
+ sty,
+ ty,
+ location.to_locations(),
+ ConstraintCategory::Boring,
+ ) {
+ span_mirbug!(
+ verifier,
place,
"bad promoted type ({:?}: {:?}): {:?}",
- promoted_ty,
+ ty,
sty,
terr
);
+ };
};
- }
- PlaceTy::Ty { ty: sty }
- }
- Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
- let sty = self.sanitize_type(place, sty);
- let ty = self.tcx().type_of(def_id);
- let ty = self.cx.normalize(ty, location);
- if let Err(terr) =
- self.cx
- .eq_types(ty, sty, location.to_locations(), ConstraintCategory::Boring)
- {
- span_mirbug!(
- self,
- place,
- "bad static type ({:?}: {:?}): {:?}",
- ty,
- sty,
- terr
- );
+ match kind {
+ StaticKind::Promoted(promoted) => {
+ if !self.errors_reported {
+ let promoted_mir = &self.mir.promoted[*promoted];
+ self.sanitize_promoted(promoted_mir, location);
+
+ let promoted_ty = promoted_mir.return_ty();
+ check_err(self, place, promoted_ty, sty);
+ }
+ }
+ StaticKind::Static(def_id) => {
+ let ty = self.tcx().type_of(*def_id);
+ let ty = self.cx.normalize(ty, location);
+
+ check_err(self, place, ty, sty);
+ }
}
PlaceTy::Ty { ty: sty }
}
return;
}
- if tcx.is_struct_constructor(def_id) {
- // We just assume that the automatically generated struct constructors are
+ if tcx.is_constructor(def_id) {
+ // We just assume that the automatically generated struct/variant constructors are
// correct. See the comment in the `mir_borrowck` implementation for an
// explanation why we need this.
return;
/// This is called for all Yield statements on movable generators
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
match place {
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Static(..)) => false,
Place::Base(PlaceBase::Local(..)) => true,
Place::Projection(box proj) => {
use rustc::hir;
use rustc::mir::ProjectionElem;
-use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
+use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability, Static, StaticKind};
use rustc::ty::{self, TyCtxt};
use crate::borrow_check::borrow_set::LocalsStateAtExit;
locals_state_at_exit: &LocalsStateAtExit,
) -> bool {
match self {
- Place::Base(PlaceBase::Promoted(_)) => false,
-
// If a local variable is immutable, then we only need to track borrows to guard
// against two kinds of errors:
// * The variable being dropped while still borrowed (e.g., because the fn returns
}
}
}
- Place::Base(PlaceBase::Static(static_)) => {
- tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
+ false,
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
+ tcx.is_static(*def_id) == Some(hir::Mutability::MutMutable)
}
Place::Projection(proj) => match proj.elem {
ProjectionElem::Field(..)
loop {
match p {
Place::Projection(pi) => p = &pi.base,
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Static(_)) => return None,
Place::Base(PlaceBase::Local(l)) => return Some(*l),
}
use crate::borrow_check::Overlap;
use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
-use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
+use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, StaticKind};
use rustc::ty::{self, TyCtxt};
use std::cmp::max;
op,
),
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
let list = PlaceComponents {
component: place,
Overlap::Disjoint
}
}
- (Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
- if static1.def_id != static2.def_id {
- debug!("place_element_conflict: DISJOINT-STATIC");
- Overlap::Disjoint
- } else if tcx.is_static(static1.def_id) == Some(hir::Mutability::MutMutable) {
- // We ignore mutable statics - they can only be unsafe code.
- debug!("place_element_conflict: IGNORE-STATIC-MUT");
- Overlap::Disjoint
- } else {
- debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
- Overlap::EqualOrDisjoint
- }
- }
- (Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
- if p1.0 == p2.0 {
- if let ty::Array(_, size) = p1.1.sty {
- if size.unwrap_usize(tcx) == 0 {
- // Ignore conflicts with promoted [T; 0].
- debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
- return Overlap::Disjoint;
+ (Place::Base(PlaceBase::Static(s1)), Place::Base(PlaceBase::Static(s2))) => {
+ match (&s1.kind, &s2.kind) {
+ (StaticKind::Static(def_id_1), StaticKind::Static(def_id_2)) => {
+ if def_id_1 != def_id_2 {
+ debug!("place_element_conflict: DISJOINT-STATIC");
+ Overlap::Disjoint
+ } else if tcx.is_static(*def_id_1) == Some(hir::Mutability::MutMutable) {
+ // We ignore mutable statics - they can only be unsafe code.
+ debug!("place_element_conflict: IGNORE-STATIC-MUT");
+ Overlap::Disjoint
+ } else {
+ debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
+ Overlap::EqualOrDisjoint
}
+ },
+ (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
+ if promoted_1 == promoted_2 {
+ if let ty::Array(_, size) = s1.ty.sty {
+ if size.unwrap_usize(tcx) == 0 {
+ // Ignore conflicts with promoted [T; 0].
+ debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
+ return Overlap::Disjoint;
+ }
+ }
+ // the same promoted - base case, equal
+ debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
+ Overlap::EqualOrDisjoint
+ } else {
+ // different promoteds - base case, disjoint
+ debug!("place_element_conflict: DISJOINT-PROMOTED");
+ Overlap::Disjoint
+ }
+ },
+ (_, _) => {
+ debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
+ Overlap::Disjoint
}
- // the same promoted - base case, equal
- debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
- Overlap::EqualOrDisjoint
- } else {
- // different promoteds - base case, disjoint
- debug!("place_element_conflict: DISJOINT-PROMOTED");
- Overlap::Disjoint
}
}
- (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
- (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
- (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
- (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
(Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
(Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
}
match *cursor {
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Local(_)) |
Place::Base(PlaceBase::Static(_)) => return false,
Place::Projection(ref proj) => {
'cursor: loop {
let proj = match *cursor {
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
Place::Base(PlaceBase::Static(_)) => {
self.next = None;
block.and(place)
}
ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
- def_id: id,
ty: expr.ty,
+ kind: StaticKind::Static(id),
})))),
ExprKind::PlaceTypeAscription { source, user_ty } => {
i == variant_index || {
self.hir.tcx().features().never_type &&
self.hir.tcx().features().exhaustive_patterns &&
- self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
+ !v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
}
});
if irrefutable {
// Figure out what primary body this item has.
let (body_id, return_ty_span) = match tcx.hir().get_by_hir_id(id) {
- Node::Variant(variant) =>
- return create_constructor_shim(tcx, id, &variant.node.data),
- Node::StructCtor(ctor) =>
- return create_constructor_shim(tcx, id, ctor),
+ Node::Ctor(ctor) => return create_constructor_shim(tcx, id, ctor),
Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, decl, body_id, _, _), .. })
| Node::Item(hir::Item { node: hir::ItemKind::Fn(decl, _, _, body_id), .. })
//! Hook into libgraphviz for rendering dataflow graphs for MIR.
-use rustc::hir::HirId;
+use rustc::hir::def_id::DefId;
use rustc::mir::{BasicBlock, Mir};
use std::fs;
use std::marker::PhantomData;
use std::path::Path;
+use crate::util::graphviz_safe_def_name;
+
use super::{BitDenotation, DataflowState};
use super::DataflowBuilder;
use super::DebugFormatted;
pub trait MirWithFlowState<'tcx> {
type BD: BitDenotation<'tcx>;
- fn hir_id(&self) -> HirId;
+ fn def_id(&self) -> DefId;
fn mir(&self) -> &Mir<'tcx>;
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
}
where BD: BitDenotation<'tcx>
{
type BD = BD;
- fn hir_id(&self) -> HirId { self.hir_id }
+ fn def_id(&self) -> DefId { self.def_id }
fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
}
let g = Graph { mbcx, phantom: PhantomData, render_idx };
let mut v = Vec::new();
dot::render(&g, &mut v)?;
- debug!("print_borrowck_graph_to path: {} hir_id: {}",
- path.display(), mbcx.hir_id);
+ debug!("print_borrowck_graph_to path: {} def_id: {:?}",
+ path.display(), mbcx.def_id);
fs::write(path, v)
}
type Node = Node;
type Edge = Edge;
fn graph_id(&self) -> dot::Id<'_> {
- dot::Id::new(format!("graph_for_node_{}",
- self.mbcx.hir_id()))
- .unwrap()
+ let name = graphviz_safe_def_name(self.mbcx.def_id());
+ dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap()
}
fn node_id(&self, n: &Node) -> dot::Id<'_> {
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
match *place {
Place::Base(PlaceBase::Local(l)) => Some(l),
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Static(..)) => None,
Place::Projection(ref proj) => {
match proj.elem {
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::work_queue::WorkQueue;
-use rustc::hir::HirId;
+use rustc::hir::def_id::DefId;
use rustc::ty::{self, TyCtxt};
use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
use rustc::mir::traversal;
where
BD: BitDenotation<'tcx>
{
- hir_id: HirId,
+ def_id: DefId,
flow_state: DataflowAnalysis<'a, 'tcx, BD>,
print_preflow_to: Option<String>,
print_postflow_to: Option<String>,
pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- hir_id: HirId,
+ def_id: DefId,
attributes: &[ast::Attribute],
dead_unwinds: &BitSet<BasicBlock>,
bd: BD,
P: Fn(&BD, BD::Idx) -> DebugFormatted
{
let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd);
- flow_state.run(tcx, hir_id, attributes, p)
+ flow_state.run(tcx, def_id, attributes, p)
}
impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx>
{
pub(crate) fn run<P>(self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- hir_id: HirId,
+ def_id: DefId,
attributes: &[ast::Attribute],
p: P) -> DataflowResults<'tcx, BD>
where P: Fn(&BD, BD::Idx) -> DebugFormatted
name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");
let mut mbcx = DataflowBuilder {
- hir_id,
+ def_id,
print_preflow_to, print_postflow_to, flow_state: self,
};
debug!("lookup({:?})", place);
match *place {
Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
- Place::Base(PlaceBase::Promoted(..)) |
Place::Base(PlaceBase::Static(..)) => {
Err(MoveError::cannot_move_out_of(self.loc, Static))
}
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
match *place {
Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
- Place::Base(PlaceBase::Promoted(_)) |
Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
Place::Projection(ref proj) => {
match self.find(&proj.base) {
use crate::hair::cx::to_ref::ToRef;
use crate::hair::util::UserAnnotatedTyHelpers;
use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{CtorOf, Def, CtorKind};
use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
expr_ty.ty_adt_def().and_then(|adt_def| {
match path.def {
- Def::VariantCtor(variant_id, CtorKind::Fn) => {
- Some((adt_def, adt_def.variant_index_with_id(variant_id)))
- }
- Def::StructCtor(_, CtorKind::Fn) |
+ Def::Ctor(ctor_id, _, CtorKind::Fn) =>
+ Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))),
Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
_ => None,
}
.ty_adt_def()
.and_then(|adt_def| {
match def {
- Def::VariantCtor(variant_id, CtorKind::Const) => {
- let idx = adt_def.variant_index_with_id(variant_id);
+ Def::Ctor(variant_ctor_id, CtorOf::Variant, CtorKind::Const) => {
+ let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
let (d, o) = adt_def.discriminant_def_for_variant(idx);
use rustc::ty::util::IntTypeExt;
let ty = adt_def.repr.discr_type();
// `Fn` but with the user-given substitutions.
Def::Fn(_) |
Def::Method(_) |
- Def::StructCtor(_, CtorKind::Fn) |
- Def::VariantCtor(_, CtorKind::Fn) |
+ Def::Ctor(_, _, CtorKind::Fn) |
Def::Const(_) |
Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty),
// `None`). This has the type of the enum/struct that defines
// this variant -- but with the substitutions given by the
// user.
- Def::StructCtor(_def_id, CtorKind::Const) |
- Def::VariantCtor(_def_id, CtorKind::Const) =>
+ Def::Ctor(_, _, CtorKind::Const) =>
cx.user_substs_applied_to_ty_of_hir_id(hir_id),
// `Self` is used in expression as a tuple struct constructor or an unit struct constructor
// A regular function, constructor function or a constant.
Def::Fn(_) |
Def::Method(_) |
- Def::StructCtor(_, CtorKind::Fn) |
- Def::VariantCtor(_, CtorKind::Fn) |
+ Def::Ctor(_, _, CtorKind::Fn) |
Def::SelfCtor(..) => {
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
debug!("convert_path_expr: user_ty={:?}", user_ty);
}
},
- Def::StructCtor(def_id, CtorKind::Const) |
- Def::VariantCtor(def_id, CtorKind::Const) => {
+ Def::Ctor(def_id, _, CtorKind::Const) => {
let user_provided_types = cx.tables.user_provided_types();
let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
ty::Adt(adt_def, substs) => {
ExprKind::Adt {
adt_def,
- variant_index: adt_def.variant_index_with_id(def_id),
+ variant_index: adt_def.variant_index_with_ctor_id(def_id),
substs,
user_ty: user_provided_type,
fields: vec![],
use rustc::hir::def_id::DefId;
use rustc::hir::RangeEnd;
-use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
use rustc::mir::Field;
_ => false,
}
}
-
- fn is_variant_uninhabited(&self,
- variant: &'tcx ty::VariantDef,
- substs: SubstsRef<'tcx>)
- -> bool
- {
- if self.tcx.features().exhaustive_patterns {
- self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
- } else {
- false
- }
- }
}
#[derive(Clone, Debug, PartialEq)]
-pub enum Constructor<'tcx> {
+enum Constructor<'tcx> {
/// The constructor of all patterns that don't vary by constructor,
/// e.g., struct patterns and fixed-length arrays.
Single,
adt: &'tcx ty::AdtDef,
) -> VariantIdx {
match self {
- &Variant(vid) => adt.variant_index_with_id(vid),
+ &Variant(id) => adt.variant_index_with_id(id),
&Single => {
assert!(!adt.is_enum());
VariantIdx::new(0)
}
ty::Adt(def, substs) if def.is_enum() => {
def.variants.iter()
- .filter(|v| !cx.is_variant_uninhabited(v, substs))
- .map(|v| Variant(v.did))
+ .filter(|v| {
+ !cx.tcx.features().exhaustive_patterns ||
+ !v.uninhabited_from(cx.tcx, substs, def.adt_kind()).contains(cx.tcx, cx.module)
+ })
+ .map(|v| Variant(v.def_id))
.collect()
}
ty::Char => {
PatternKind::Binding { .. } | PatternKind::Wild => None,
PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
PatternKind::Variant { adt_def, variant_index, .. } => {
- Some(vec![Variant(adt_def.variants[variant_index].did)])
+ Some(vec![Variant(adt_def.variants[variant_index].def_id)])
}
PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let ref variant = adt_def.variants[variant_index];
- if *constructor == Variant(variant.did) {
- Some(patterns_for_variant(subpatterns, wild_patterns))
- } else {
- None
- }
+ Some(Variant(variant.def_id))
+ .filter(|variant_constructor| variant_constructor == constructor)
+ .map(|_| patterns_for_variant(subpatterns, wild_patterns))
}
PatternKind::Leaf { ref subpatterns } => {
use rustc::ty::subst::{SubstsRef, Kind};
use rustc::ty::layout::VariantIdx;
use rustc::hir::{self, PatKind, RangeEnd};
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{CtorOf, Def, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use rustc_data_structures::indexed_vec::Idx;
ty: Ty<'tcx>,
subpatterns: Vec<FieldPattern<'tcx>>,
) -> PatternKind<'tcx> {
+ let def = match def {
+ Def::Ctor(variant_ctor_id, CtorOf::Variant, ..) => {
+ let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
+ Def::Variant(variant_id)
+ },
+ def => def,
+ };
+
let mut kind = match def {
- Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
+ Def::Variant(variant_id) => {
let enum_id = self.tcx.parent(variant_id).unwrap();
let adt_def = self.tcx.adt_def(enum_id);
if adt_def.is_enum() {
}
}
- Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+ Def::Struct(..) | Def::Ctor(_, CtorOf::Struct, ..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
PatternKind::Leaf { subpatterns }
}
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
use rustc::mir::PlaceBase;
+ use rustc::mir::{Static, StaticKind};
Ok(match *mir_place {
- Base(PlaceBase::Promoted(ref promoted)) => {
+ Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })) => {
let instance = self.frame().instance;
self.const_eval_raw(GlobalId {
instance,
- promoted: Some(promoted.0),
+ promoted: Some(promoted),
})?
}
- Base(PlaceBase::Static(ref static_)) => {
- assert!(!static_.ty.needs_subst());
- let layout = self.layout_of(static_.ty)?;
- let instance = ty::Instance::mono(*self.tcx, static_.def_id);
+ Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty })) => {
+ assert!(!ty.needs_subst());
+ let layout = self.layout_of(ty)?;
+ let instance = ty::Instance::mono(*self.tcx, def_id);
let cid = GlobalId {
instance,
promoted: None
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::session::config::EntryFnType;
-use rustc::mir::{self, Location, Promoted};
+use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind};
use rustc::mir::visit::Visitor as MirVisitor;
use rustc::mir::mono::MonoItem;
use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled};
self.super_terminator_kind(block, kind, location);
}
- fn visit_static(&mut self,
- static_: &mir::Static<'tcx>,
+ fn visit_place(&mut self,
+ place: &mir::Place<'tcx>,
context: mir::visit::PlaceContext<'tcx>,
location: Location) {
- debug!("visiting static {:?} @ {:?}", static_.def_id, location);
+ match place {
+ Place::Base(
+ PlaceBase::Static(box Static{ kind:StaticKind::Static(def_id), .. })
+ ) => {
+ debug!("visiting static {:?} @ {:?}", def_id, location);
- let tcx = self.tcx;
- let instance = Instance::mono(tcx, static_.def_id);
- if should_monomorphize_locally(tcx, &instance) {
- self.output.push(MonoItem::Static(static_.def_id));
+ let tcx = self.tcx;
+ let instance = Instance::mono(tcx, *def_id);
+ if should_monomorphize_locally(tcx, &instance) {
+ self.output.push(MonoItem::Static(*def_id));
+ }
+ }
+ _ => {}
}
- self.super_static(static_, context, location);
+ self.super_place(place, context, location);
}
}
};
let variant_no = if adt_def.is_enum() {
- adt_def.variant_index_with_id(def_id)
+ adt_def.variant_index_with_ctor_id(def_id)
} else {
VariantIdx::new(0)
};
match *place {
// Locals and statics have stable addresses, for sure
Base(PlaceBase::Local { .. }) |
- Base(PlaceBase::Promoted { .. }) |
Base(PlaceBase::Static { .. }) =>
true,
// Recurse for projections
&Place::Base(PlaceBase::Local(..)) => {
// locals are safe
}
- &Place::Base(PlaceBase::Promoted(_)) => {
+ &Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => {
bug!("unsafety checking should happen before promotion")
}
- &Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+ &Place::Base(
+ PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })
+ ) => {
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
self.require_unsafe("use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations \
use rustc::hir::def::Def;
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
-use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
+use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind, Static, StaticKind};
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult};
// an `Index` projection would throw us off-track.
_ => None,
},
- Place::Base(PlaceBase::Promoted(ref promoted)) => {
+ Place::Base(
+ PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
+ ) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
let instance = Instance::new(self.source.def_id(), substs);
let cid = GlobalId {
instance,
- promoted: Some(promoted.0),
+ promoted: Some(promoted),
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
{
debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
- let id = tcx.hir().as_local_hir_id(src.def_id()).unwrap();
+ let def_id = src.def_id();
let param_env = tcx.param_env(src.def_id()).with_reveal_all();
let move_data = match MoveData::gather_moves(mir, tcx) {
Ok(move_data) => move_data,
move_data,
param_env,
};
- let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
+ let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env);
let flow_inits =
- do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+ do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
let flow_uninits =
- do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+ do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
MaybeUninitializedPlaces::new(tcx, mir, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
fn find_dead_unwinds<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
- id: hir::HirId,
+ def_id: hir::def_id::DefId,
env: &MoveDataParamEnv<'tcx, 'tcx>)
-> BitSet<BasicBlock>
{
// reach cleanup blocks, which can't have unwind edges themselves.
let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
let flow_inits =
- do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+ do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
FxHashMap<BasicBlock, liveness::LiveVarSet>,
) {
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
- let hir_id = tcx.hir().as_local_hir_id(source.def_id()).unwrap();
+ let def_id = source.def_id();
// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
let storage_live_analysis = MaybeStorageLive::new(mir);
let storage_live =
- do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, storage_live_analysis,
+ do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, storage_live_analysis,
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
// Find the MIR locals which do not use StorageLive/StorageDead statements.
let borrowed_locals = if !movable {
let analysis = HaveBeenBorrowedLocals::new(mir);
let result =
- do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, analysis,
+ do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, analysis,
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
Some((analysis, result))
} else {
// Return pointer; update the place itself
*place = self.destination.clone();
},
- Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
- if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
- promoted.0 = p;
+ Place::Base(
+ PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })
+ ) => {
+ if let Some(p) = self.promoted_map.get(*promoted).cloned() {
+ *promoted = p;
}
},
- _ => self.super_place(place, _ctxt, _location),
+ _ => self.super_place(place, _ctxt, _location)
}
}
let promoted_id = Promoted::new(self.source.promoted.len());
let mut promoted_place = |ty, span| {
promoted.span = span;
- promoted.local_decls[RETURN_PLACE] =
- LocalDecl::new_return_place(ty, span);
- Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
+ promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
+ Place::Base(
+ PlaceBase::Static(box Static{ kind: StaticKind::Promoted(promoted_id), ty })
+ )
};
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
match candidate {
fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
match *place {
Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
- Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
- Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
+ Place::Base(PlaceBase::Static(box Static {kind: StaticKind::Promoted(_), .. })) =>
+ bug!("qualifying already promoted MIR"),
+ Place::Base(PlaceBase::Static(ref static_)) => {
+ Self::in_static(cx, static_)
+ },
Place::Projection(ref proj) => Self::in_projection(cx, proj),
}
}
const IDX: usize = 2;
fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool {
- // Only allow statics (not consts) to refer to other statics.
- let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
+ match static_.kind {
+ StaticKind::Promoted(_) => unreachable!(),
+ StaticKind::Static(def_id) => {
+ // Only allow statics (not consts) to refer to other statics.
+ let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
- !allowed ||
- cx.tcx.get_attrs(static_.def_id).iter().any(|attr| attr.check_name("thread_local"))
+ !allowed ||
+ cx.tcx.get_attrs(def_id).iter().any(
+ |attr| attr.check_name("thread_local"
+ ))
+ }
+ }
}
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
);
dest = &proj.base;
},
- Place::Base(PlaceBase::Promoted(..)) =>
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
bug!("promoteds don't exist yet during promotion"),
- Place::Base(PlaceBase::Static(..)) => {
+ Place::Base(PlaceBase::Static(box Static{ kind: _, .. })) => {
// Catch more errors in the destination. `visit_place` also checks that we
// do not try to access statics from constants or try to mutate statics
self.visit_place(
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
self.super_place(place, context, location);
match *place {
- Place::Base(PlaceBase::Local(_)) |
- Place::Base(PlaceBase::Promoted(_)) => {}
- Place::Base(PlaceBase::Static(ref global)) => {
+ Place::Base(PlaceBase::Local(_)) => {}
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
+ unreachable!()
+ }
+ Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
if self.tcx
- .get_attrs(global.def_id)
+ .get_attrs(def_id)
.iter()
.any(|attr| attr.check_name("thread_local")) {
if self.mode != Mode::Fn {
match place {
Place::Base(PlaceBase::Local(_)) => Ok(()),
// promoteds are always fine, they are essentially constants
- Place::Base(PlaceBase::Promoted(_)) => Ok(()),
- Place::Base(PlaceBase::Static(_)) =>
+ Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => Ok(()),
+ Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) =>
Err((span, "cannot access `static` items in const fn".into())),
Place::Projection(proj) => {
match proj.elem {
use syntax_pos::Span;
use rustc::ty::{self, TyCtxt};
-use rustc::hir;
+use rustc::hir::def_id::DefId;
use rustc::mir::{self, Mir, Location};
use rustc_data_structures::bit_set::BitSet;
use crate::transform::{MirPass, MirSource};
fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>, mir: &mut Mir<'tcx>) {
let def_id = src.def_id();
- let id = tcx.hir().as_local_hir_id(def_id).unwrap();
if !tcx.has_attr(def_id, "rustc_mir") {
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
return;
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
let flow_inits =
- do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+ do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
let flow_uninits =
- do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+ do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
let flow_def_inits =
- do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+ do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
DefinitelyInitializedPlaces::new(tcx, mir, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
- sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);
+ sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits);
}
if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() {
- sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits);
+ sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits);
}
if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() {
- sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits);
+ sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits);
}
if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() {
tcx.sess.fatal("stop_after_dataflow ended compilation");
/// errors are not intended to be used for unit tests.)
pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
- id: hir::HirId,
+ def_id: DefId,
_attributes: &[ast::Attribute],
results: &DataflowResults<'tcx, O>)
where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx>
{
- debug!("sanity_check_via_rustc_peek id: {:?}", id);
+ debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id);
// FIXME: this is not DRY. Figure out way to abstract this and
// `dataflow::build_sets`. (But note it is doing non-standard
// stuff, so such generalization may not be realistic.)
use rustc::hir::def_id::DefId;
use rustc::mir::*;
use rustc::ty::TyCtxt;
+use rustc_data_structures::indexed_vec::Idx;
use std::fmt::Debug;
use std::io::{self, Write};
Ok(())
}
+// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
+// it does not have to be user friendly.
+pub fn graphviz_safe_def_name(def_id: DefId) -> String {
+ format!(
+ "{}_{}_{}",
+ def_id.krate.index(),
+ def_id.index.address_space().index(),
+ def_id.index.as_array_index(),
+ )
+}
+
/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
def_id: DefId,
w: &mut W) -> io::Result<()>
where W: Write
{
- writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_hir_id(def_id).unwrap())?;
+ writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;
// Global graph properties
writeln!(w, r#" graph [fontname="monospace"];"#)?;
pub use self::alignment::is_disaligned;
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
-pub use self::graphviz::{write_mir_graphviz};
+pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
pub use self::graphviz::write_node_label as write_graphviz_node_label;
/// If possible, suggest replacing `ref` with `ref mut`.
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::def::CtorKind;
use rustc::mir::*;
use rustc::mir::visit::Visitor;
use rustc::ty::{self, TyCtxt};
trace!("write_mir_sig: {:?}", src.instance);
let descr = tcx.describe_def(src.def_id());
let is_function = match descr {
- Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Variant(..)) |
- Some(Def::StructCtor(_, CtorKind::Fn)) => true,
+ Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Ctor(..)) => true,
_ => tcx.is_closure(src.def_id()),
};
match (descr, src.promoted) {
(_, Some(i)) => write!(w, "{:?} in ", i)?,
- (Some(Def::StructCtor(..)), _) => write!(w, "struct ")?,
- (Some(Def::Const(_)), _)
- | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?,
+ (Some(Def::Const(_)), _) | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?,
(Some(Def::Static(_, /*is_mutbl*/false)), _) => write!(w, "static ")?,
(Some(Def::Static(_, /*is_mutbl*/true)), _) => write!(w, "static mut ")?,
(_, _) if is_function => write!(w, "fn ")?,
}
}
ItemKind::Union(ref vdata, _) => {
- if !vdata.is_struct() {
+ if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
self.err_handler().span_err(item.span,
"tuple and unit unions are not permitted");
}
// The `..` are the names of fields to dump.
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
- let name = meta_item.ident_str().unwrap_or("");
- match name {
+ match meta_item.name_or_empty().get() {
"abi" => {
self.tcx
.sess
);
}
- _ => {
+ name => {
self.tcx.sess.span_err(
meta_item.span(),
&format!("unrecognized field name `{}`", name),
hir::ExprKind::Path(ref qpath) => {
let def = v.tables.qpath_def(qpath, e.hir_id);
match def {
- Def::VariantCtor(..) | Def::StructCtor(..) |
- Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable,
+ Def::Ctor(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) =>
+ Promotable,
// References to a static that are themselves within a static
// are inherently promotable with the exception
Def::Err
};
let def_result = match def {
- Def::StructCtor(_, CtorKind::Fn) |
- Def::VariantCtor(_, CtorKind::Fn) |
+ Def::Ctor(_, _, CtorKind::Fn) |
Def::SelfCtor(..) => Promotable,
Def::Fn(did) => v.handle_const_fn_call(did),
Def::Method(did) => {
for plugin in plugins {
// plugins must have a name and can't be key = value
- match plugin.ident_str() {
- Some(name) if !plugin.is_value_str() => {
- let args = plugin.meta_item_list().map(ToOwned::to_owned);
- loader.load_plugin(plugin.span(), name, args.unwrap_or_default());
- },
- _ => call_malformed_plugin_attribute(sess, attr.span),
+ let name = plugin.name_or_empty();
+ if !name.is_empty() && !plugin.is_value_str() {
+ let args = plugin.meta_item_list().map(ToOwned::to_owned);
+ loader.load_plugin(plugin.span(), &name, args.unwrap_or_default());
+ } else {
+ call_malformed_plugin_attribute(sess, attr.span);
}
}
}
node => bug!("unexpected node kind: {:?}", node),
}
}
- Node::StructCtor(vdata) => {
- let struct_hir_id = tcx.hir().get_parent_item(hir_id);
- let item = match tcx.hir().get_by_hir_id(struct_hir_id) {
- Node::Item(item) => item,
- node => bug!("unexpected node kind: {:?}", node),
- };
- let (mut ctor_vis, mut span, mut descr) =
- (ty::Visibility::from_hir(&item.vis, struct_hir_id, tcx),
- item.vis.span, item.vis.node.descr());
- for field in vdata.fields() {
- let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
- if ctor_vis.is_at_least(field_vis, tcx) {
- ctor_vis = field_vis;
- span = field.vis.span;
- descr = field.vis.node.descr();
+ Node::Ctor(vdata) => {
+ let parent_hir_id = tcx.hir().get_parent_node_by_hir_id(hir_id);
+ match tcx.hir().get_by_hir_id(parent_hir_id) {
+ Node::Variant(..) => {
+ let parent_did = tcx.hir().local_def_id_from_hir_id(parent_hir_id);
+ return def_id_visibility(tcx, parent_did);
}
- }
+ Node::Item(..) => {
+ let item = match tcx.hir().get_by_hir_id(parent_hir_id) {
+ Node::Item(item) => item,
+ node => bug!("unexpected node kind: {:?}", node),
+ };
+ let (mut ctor_vis, mut span, mut descr) =
+ (ty::Visibility::from_hir(&item.vis, parent_hir_id, tcx),
+ item.vis.span, item.vis.node.descr());
+ for field in vdata.fields() {
+ let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
+ if ctor_vis.is_at_least(field_vis, tcx) {
+ ctor_vis = field_vis;
+ span = field.vis.span;
+ descr = field.vis.node.descr();
+ }
+ }
- // If the structure is marked as non_exhaustive then lower the
- // visibility to within the crate.
- if ctor_vis == ty::Visibility::Public {
- let adt_def = tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
- if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
- ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
- span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span;
- descr = "crate-visible";
+ // If the structure is marked as non_exhaustive then lower the
+ // visibility to within the crate.
+ if ctor_vis == ty::Visibility::Public {
+ let adt_def =
+ tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
+ if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
+ ctor_vis =
+ ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+ span = attr::find_by_name(&item.attrs, "non_exhaustive")
+ .unwrap().span;
+ descr = "crate-visible";
+ }
+ }
+
+ return (ctor_vis, span, descr);
}
+ node => bug!("unexpected node kind: {:?}", node),
}
-
- return (ctor_vis, span, descr);
}
Node::Expr(expr) => {
return (ty::Visibility::Restricted(
match item.node {
hir::ItemKind::Enum(ref def, _) => {
for variant in &def.variants {
- let variant_level = self.update(variant.node.data.hir_id(), item_level);
+ let variant_level = self.update(variant.node.id, item_level);
+ if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+ self.update(ctor_hir_id, item_level);
+ }
for field in variant.node.data.fields() {
self.update(field.hir_id, variant_level);
}
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
- if !def.is_struct() {
- self.update(def.hir_id(), item_level);
+ if let Some(ctor_hir_id) = def.ctor_hir_id() {
+ self.update(ctor_hir_id, item_level);
}
for field in def.fields() {
if field.vis.node.is_pub() {
self.reach(item.hir_id, item_level).generics().predicates();
}
for variant in &def.variants {
- let variant_level = self.get(variant.node.data.hir_id());
+ let variant_level = self.get(variant.node.id);
if variant_level.is_some() {
for field in variant.node.data.fields() {
self.reach(field.hir_id, variant_level).ty();
v: &'tcx hir::Variant,
g: &'tcx hir::Generics,
item_id: hir::HirId) {
- if self.access_levels.is_reachable(v.node.data.hir_id()) {
+ if self.access_levels.is_reachable(v.node.id) {
self.in_variant = true;
intravisit::walk_variant(self, v, g, item_id);
self.in_variant = false;
}
// Empty groups `a::b::{}` are turned into synthetic `self` imports
- // `a::b::c::{self as _}`, so that their prefixes are correctly
+ // `a::b::c::{self as __dummy}`, so that their prefixes are correctly
// resolved and checked for privacy/stability/etc.
if items.is_empty() && !empty_for_self(&prefix) {
let new_span = prefix[prefix.len() - 1].ident.span;
Ident::new(keywords::SelfLower.name(), new_span)
),
kind: ast::UseTreeKind::Simple(
- Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)),
+ Some(Ident::new(Name::gensym("__dummy"), new_span)),
ast::DUMMY_NODE_ID,
ast::DUMMY_NODE_ID,
),
// If this is a tuple or unit struct, define a name
// in the value namespace as well.
- if !struct_def.is_struct() {
- let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
- CtorKind::from_ast(struct_def));
+ if let Some(ctor_node_id) = struct_def.ctor_id() {
+ let ctor_def = Def::Ctor(self.definitions.local_def_id(ctor_node_id),
+ CtorOf::Struct,
+ CtorKind::from_ast(struct_def));
self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
}
vis: ty::Visibility,
expansion: Mark) {
let ident = variant.node.ident;
- let def_id = self.definitions.local_def_id(variant.node.data.id());
// Define a name in the type namespace.
+ let def_id = self.definitions.local_def_id(variant.node.id);
let def = Def::Variant(def_id);
self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
// Define a constructor name in the value namespace.
// Braced variants, unlike structs, generate unusable names in
// value namespace, they are reserved for possible future use.
+ // It's ok to use the variant's id as a ctor id since an
+ // error will be reported on any use of such resolution anyway.
+ let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id);
+ let ctor_def_id = self.definitions.local_def_id(ctor_node_id);
let ctor_kind = CtorKind::from_ast(&variant.node.data);
- let ctor_def = Def::VariantCtor(def_id, ctor_kind);
-
+ let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
}
Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
}
- Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
+ Def::Fn(..) | Def::Static(..) | Def::Const(..) |
+ Def::Ctor(_, CtorOf::Variant, ..) => {
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
}
- Def::StructCtor(def_id, ..) => {
+ Def::Ctor(def_id, CtorOf::Struct, ..) => {
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
if let Some(struct_def_id) =
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use log::debug;
-use rustc::hir::def::*;
-use rustc::hir::def::Namespace::*;
+use rustc::hir::def::{Def, CtorKind, Namespace::*};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::session::config::nightly_options;
-use syntax::ast::{ExprKind};
+use syntax::ast::{Expr, ExprKind};
use syntax::symbol::keywords;
use syntax_pos::Span;
let ns = source.namespace();
let is_expected = &|def| source.is_expected(def);
+ let path_sep = |err: &mut DiagnosticBuilder<'_>, expr: &Expr| match expr.node {
+ ExprKind::Field(_, ident) => {
+ err.span_suggestion(
+ expr.span,
+ "use the path separator to refer to an item",
+ format!("{}::{}", path_str, ident),
+ Applicability::MaybeIncorrect,
+ );
+ true
+ }
+ ExprKind::MethodCall(ref segment, ..) => {
+ let span = expr.span.with_hi(segment.ident.span.hi());
+ err.span_suggestion(
+ span,
+ "use the path separator to refer to an item",
+ format!("{}::{}", path_str, segment.ident),
+ Applicability::MaybeIncorrect,
+ );
+ true
+ }
+ _ => false,
+ };
+
match (def, source) {
(Def::Macro(..), _) => {
err.span_suggestion(
Applicability::MaybeIncorrect,
);
if path_str == "try" && span.rust_2015() {
- err.note("if you want the `try` keyword, \
- you need to be in the 2018 edition");
+ err.note("if you want the `try` keyword, you need to be in the 2018 edition");
}
}
(Def::TyAlias(..), PathSource::Trait(_)) => {
err.note("did you mean to use a trait alias?");
}
}
- (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
- ExprKind::Field(_, ident) => {
- err.span_suggestion(
- parent.span,
- "use the path separator to refer to an item",
- format!("{}::{}", path_str, ident),
- Applicability::MaybeIncorrect,
- );
- }
- ExprKind::MethodCall(ref segment, ..) => {
- let span = parent.span.with_hi(segment.ident.span.hi());
- err.span_suggestion(
- span,
- "use the path separator to refer to an item",
- format!("{}::{}", path_str, segment.ident),
- Applicability::MaybeIncorrect,
- );
- }
- _ => return false,
+ (Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) {
+ return false;
},
(Def::Enum(..), PathSource::TupleStruct)
| (Def::Enum(..), PathSource::Expr(..)) => {
= self.struct_constructors.get(&def_id).cloned() {
let accessible_ctor = self.is_accessible(ctor_vis);
if is_expected(ctor_def) && !accessible_ctor {
- err.span_label(span, format!("constructor is not visible \
- here due to private fields"));
+ err.span_label(
+ span,
+ format!("constructor is not visible here due to private fields"),
+ );
}
} else {
// HACK(estebank): find a better way to figure out that this was a
}
}
match source {
- PathSource::Expr(Some(parent)) => {
- match parent.node {
- ExprKind::MethodCall(ref path_assignment, _) => {
- err.span_suggestion(
- sm.start_point(parent.span)
- .to(path_assignment.ident.span),
- "use `::` to access an associated function",
- format!("{}::{}",
- path_str,
- path_assignment.ident),
- Applicability::MaybeIncorrect
- );
- },
- _ => {
- err.span_label(
- span,
- format!("did you mean `{} {{ /* fields */ }}`?",
- path_str),
- );
- },
- }
- },
+ PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) {
+ err.span_label(
+ span,
+ format!("did you mean `{} {{ /* fields */ }}`?", path_str),
+ );
+ }
PathSource::Expr(None) if followed_by_brace == true => {
if let Some((sp, snippet)) = closing_brace {
err.span_suggestion(
} else {
err.span_label(
span,
- format!("did you mean `({} {{ /* fields */ }})`?",
- path_str),
+ format!("did you mean `({} {{ /* fields */ }})`?", path_str),
);
}
},
_ => {
err.span_label(
span,
- format!("did you mean `{} {{ /* fields */ }}`?",
- path_str),
+ format!("did you mean `{} {{ /* fields */ }}`?", path_str),
);
},
}
}
(Def::Union(..), _) |
(Def::Variant(..), _) |
- (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
- err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
- path_str));
+ (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => {
+ err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str));
}
(Def::SelfTy(..), _) if ns == ValueNS => {
err.span_label(span, fallback_label);
- err.note("can't use `Self` as a constructor, you must use the \
- implemented struct");
+ err.note("can't use `Self` as a constructor, you must use the implemented struct");
}
(Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
err.note("can't use a type alias as a constructor");
_ => false,
},
PathSource::Expr(..) => match def {
- Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
- Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
+ Def::Ctor(_, _, CtorKind::Const) | Def::Ctor(_, _, CtorKind::Fn) |
Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
Def::SelfCtor(..) | Def::ConstParam(..) => true,
_ => false,
},
PathSource::Pat => match def {
- Def::StructCtor(_, CtorKind::Const) |
- Def::VariantCtor(_, CtorKind::Const) |
+ Def::Ctor(_, _, CtorKind::Const) |
Def::Const(..) | Def::AssociatedConst(..) |
Def::SelfCtor(..) => true,
_ => false,
},
PathSource::TupleStruct => match def {
- Def::StructCtor(_, CtorKind::Fn) |
- Def::VariantCtor(_, CtorKind::Fn) |
- Def::SelfCtor(..) => true,
+ Def::Ctor(_, _, CtorKind::Fn) | Def::SelfCtor(..) => true,
_ => false,
},
PathSource::Struct => match def {
debug!("(resolving function) entering function");
let (rib_kind, asyncness) = match function_kind {
FnKind::ItemFn(_, ref header, ..) =>
- (ItemRibKind, header.asyncness.node),
+ (FnItemRibKind, header.asyncness.node),
FnKind::Method(_, ref sig, _, _) =>
(TraitOrImplItemRibKind, sig.header.asyncness.node),
FnKind::Closure(_) =>
/// upvars).
TraitOrImplItemRibKind,
+ /// We passed through a function definition. Disallow upvars.
+ /// Permit only those const parameters that are specified in the function's generics.
+ FnItemRibKind,
+
/// We passed through an item scope. Disallow upvars.
ItemRibKind,
fn is_variant(&self) -> bool {
match self.kind {
NameBindingKind::Def(Def::Variant(..), _) |
- NameBindingKind::Def(Def::VariantCtor(..), _) => true,
+ NameBindingKind::Def(Def::Ctor(_, CtorOf::Variant, ..), _) => true,
_ => false,
}
}
let is_syntactic_ambiguity = opt_pat.is_none() &&
bmode == BindingMode::ByValue(Mutability::Immutable);
match def {
- Def::StructCtor(_, CtorKind::Const) |
- Def::VariantCtor(_, CtorKind::Const) |
+ Def::Ctor(_, _, CtorKind::Const) |
Def::Const(..) if is_syntactic_ambiguity => {
// Disambiguate in favor of a unit struct/variant
// or constant pattern.
self.record_use(ident, ValueNS, binding.unwrap(), false);
Some(PathResolution::new(def))
}
- Def::StructCtor(..) | Def::VariantCtor(..) |
- Def::Const(..) | Def::Static(..) => {
+ Def::Ctor(..) | Def::Const(..) | Def::Static(..) => {
// This is unambiguously a fresh binding, either syntactically
// (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
// to something unusable as a pattern (e.g., constructor function),
resolution
}
- fn type_ascription_suggestion(&self,
- err: &mut DiagnosticBuilder<'_>,
- base_span: Span) {
+ /// Only used in a specific case of type ascription suggestions
+ #[doc(hidden)]
+ fn get_colon_suggestion_span(&self, start: Span) -> Span {
+ let cm = self.session.source_map();
+ start.to(cm.next_point(start))
+ }
+
+ fn type_ascription_suggestion(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ base_span: Span,
+ ) {
debug!("type_ascription_suggetion {:?}", base_span);
let cm = self.session.source_map();
+ let base_snippet = cm.span_to_snippet(base_span);
debug!("self.current_type_ascription {:?}", self.current_type_ascription);
if let Some(sp) = self.current_type_ascription.last() {
let mut sp = *sp;
// Try to find the `:`; bail on first non-':' / non-whitespace.
sp = cm.next_point(sp);
if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
- debug!("snippet {:?}", snippet);
let line_sp = cm.lookup_char_pos(sp.hi()).line;
let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;
- debug!("{:?} {:?}", line_sp, line_base_sp);
if snippet == ":" {
- err.span_label(base_span,
- "expecting a type here because of type ascription");
+ let mut show_label = true;
if line_sp != line_base_sp {
err.span_suggestion_short(
sp,
";".to_string(),
Applicability::MaybeIncorrect,
);
+ } else {
+ let colon_sp = self.get_colon_suggestion_span(sp);
+ let after_colon_sp = self.get_colon_suggestion_span(
+ colon_sp.shrink_to_hi(),
+ );
+ if !cm.span_to_snippet(after_colon_sp).map(|s| s == " ")
+ .unwrap_or(false)
+ {
+ err.span_suggestion(
+ colon_sp,
+ "maybe you meant to write a path separator here",
+ "::".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ show_label = false;
+ }
+ if let Ok(base_snippet) = base_snippet {
+ let mut sp = after_colon_sp;
+ for _ in 0..100 {
+ // Try to find an assignment
+ sp = cm.next_point(sp);
+ let snippet = cm.span_to_snippet(sp.to(cm.next_point(sp)));
+ match snippet {
+ Ok(ref x) if x.as_str() == "=" => {
+ err.span_suggestion(
+ base_span,
+ "maybe you meant to write an assignment here",
+ format!("let {}", base_snippet),
+ Applicability::MaybeIncorrect,
+ );
+ show_label = false;
+ break;
+ }
+ Ok(ref x) if x.as_str() == "\n" => break,
+ Err(_) => break,
+ Ok(_) => {}
+ }
+ }
+ }
+ }
+ if show_label {
+ err.span_label(base_span,
+ "expecting a type here because of type ascription");
}
break;
} else if !snippet.trim().is_empty() {
seen.insert(node_id, depth);
}
}
- ItemRibKind | TraitOrImplItemRibKind => {
+ ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => {
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
ConstantItemRibKind => {
// Nothing to do. Continue.
}
- ItemRibKind => {
+ ItemRibKind | FnItemRibKind => {
// This was an attempt to use a type parameter outside its scope.
if record_used {
resolve_error(
}
}
Def::ConstParam(..) => {
- // A const param is always declared in a signature, which is always followed by
- // some kind of function rib kind (specifically, ItemRibKind in the case of a
- // normal function), so we can skip the first rib as it will be guaranteed to
- // (spuriously) conflict with the const param.
- for rib in &ribs[1..] {
- if let ItemRibKind = rib.kind {
+ let mut ribs = ribs.iter().peekable();
+ if let Some(Rib { kind: FnItemRibKind, .. }) = ribs.peek() {
+ // When declaring const parameters inside function signatures, the first rib
+ // is always a `FnItemRibKind`. In this case, we can skip it, to avoid it
+ // (spuriously) conflicting with the const param.
+ ribs.next();
+ }
+ for rib in ribs {
+ if let ItemRibKind | FnItemRibKind = rib.kind {
// This was an attempt to use a const parameter outside its scope.
if record_used {
resolve_error(
} else {
// Items from the prelude
if !module.no_implicit_prelude {
- names.extend(self.extern_prelude.iter().map(|(ident, _)| {
- TypoSuggestion {
- candidate: ident.name,
- article: "a",
- kind: "crate",
- }
+ names.extend(self.extern_prelude.clone().iter().flat_map(|(ident, _)| {
+ self.crate_loader
+ .maybe_process_path_extern(ident.name, ident.span)
+ .and_then(|crate_id| {
+ let crate_mod = Def::Mod(DefId {
+ krate: crate_id,
+ index: CRATE_DEF_INDEX,
+ });
+
+ if filter_fn(crate_mod) {
+ Some(TypoSuggestion {
+ candidate: ident.name,
+ article: "a",
+ kind: "crate",
+ })
+ } else {
+ None
+ }
+ })
}));
+
if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names);
}
// outside crate private modules => no need to check this)
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
let did = match def {
- Def::StructCtor(did, _) | Def::VariantCtor(did, _) =>
- self.parent(did),
+ Def::Ctor(did, ..) => self.parent(did),
_ => def.opt_def_id(),
};
candidates.push(ImportSuggestion { did, path });
Ok(binding) => {
let imported_binding = this.import(binding, directive);
target_bindings[ns].set(Some(imported_binding));
- let conflict = this.try_define(parent, target, ns, imported_binding);
- if let Err(old_binding) = conflict {
- this.report_conflict(parent, target, ns, imported_binding, old_binding);
- }
+ this.define(parent, target, ns, imported_binding);
}
}
});
None => continue,
};
- // Filter away "empty import canaries" and ambiguous imports.
+ // Filter away ambiguous and gensymed imports. Gensymed imports
+ // (e.g. implicitly injected `std`) cannot be properly encoded in metadata,
+ // so they can cause name conflict errors downstream.
let is_good_import = binding.is_import() && !binding.is_ambiguity() &&
- binding.vis != ty::Visibility::Invisible;
+ !(ident.name.is_gensymed() && ident.name != "_");
if is_good_import || binding.is_macro_def() {
let def = binding.def();
if def != Def::Err {
};
let (value, fields) = match item.node {
- ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), _) |
- ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), _) => {
+ ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), ..) |
+ ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), ..) => {
let include_priv_fields = !self.save_ctxt.config.pub_only;
let fields_str = fields
.iter()
let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
- let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt);
+ let id = id_from_node_id(variant.node.id, &self.save_ctxt);
let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
self.dumper.dump_def(
}
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
- let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt);
+ let id = id_from_node_id(variant.node.id, &self.save_ctxt);
let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
self.dumper.dump_def(
for field in variant.node.data.fields() {
- self.process_struct_field_def(field, variant.node.data.id());
+ self.process_struct_field_def(field, variant.node.id);
self.visit_ty(&field.ty);
}
}
);
}
}
- HirDef::StructCtor(..) |
- HirDef::VariantCtor(..) |
+ HirDef::Ctor(_, _, _) |
HirDef::Const(..) |
HirDef::AssociatedConst(..) |
HirDef::Struct(..) |
mod sig;
use rustc::hir;
-use rustc::hir::def::Def as HirDef;
+use rustc::hir::def::{CtorOf, Def as HirDef};
use rustc::hir::Node;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::privacy::AccessLevels;
parent: None,
children: def.variants
.iter()
- .map(|v| id_from_node_id(v.node.data.id(), self))
+ .map(|v| id_from_node_id(v.node.id, self))
.collect(),
decl_id: None,
docs: self.docs_for_attrs(&item.attrs),
ref_id: id_from_node_id(id, self),
})
}
- HirDef::Static(..) |
- HirDef::Const(..) |
- HirDef::AssociatedConst(..) |
- HirDef::VariantCtor(..) => {
- Some(Ref {
- kind: RefKind::Variable,
- span,
- ref_id: id_from_def_id(def.def_id()),
- })
- }
HirDef::Trait(def_id) if fn_type(path_seg) => {
Some(Ref {
kind: RefKind::Type,
ref_id: id_from_def_id(def_id),
})
}
- HirDef::StructCtor(def_id, _) => {
+ HirDef::Ctor(def_id, CtorOf::Struct, ..) => {
// This is a reference to a tuple struct where the def_id points
// to an invisible constructor function. That is not a very useful
// def, so adjust to point to the tuple struct itself.
ref_id: id_from_def_id(parent_def_id),
})
}
+ HirDef::Static(..) |
+ HirDef::Const(..) |
+ HirDef::AssociatedConst(..) |
+ HirDef::Ctor(..) => {
+ Some(Ref {
+ kind: RefKind::Variable,
+ span,
+ ref_id: id_from_def_id(def.def_id()),
+ })
+ }
HirDef::Method(decl_id) => {
let def_id = if decl_id.is_local() {
let ti = self.tcx.associated_item(decl_id);
refs: vec![],
})
}
- Def::AssociatedConst(..) | Def::Variant(..) | Def::VariantCtor(..) => {
+ Def::AssociatedConst(..) | Def::Variant(..) | Def::Ctor(..) => {
let len = self.segments.len();
if len < 2 {
return Err("Bad path");
impl Sig for ast::Variant_ {
- fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
+ fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let mut text = self.ident.to_string();
match self.data {
- ast::VariantData::Struct(ref fields, id, r) => {
+ ast::VariantData::Struct(ref fields, r) => {
+ let id = parent_id.unwrap();
let name_def = SigElement {
id: id_from_node_id(id, scx),
start: offset,
+++ /dev/null
-use rustc::traits::{
- WellFormed,
- FromEnv,
- DomainGoal,
- GoalKind,
- Clause,
- Clauses,
- ProgramClause,
- ProgramClauseCategory,
- Environment,
-};
-use rustc::ty;
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc_target::spec::abi;
-use super::ChalkInferenceContext;
-use crate::lowering::Lower;
-use crate::generic_types;
-use std::iter;
-
-fn assemble_clauses_from_impls<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- trait_def_id: DefId,
- clauses: &mut Vec<Clause<'tcx>>
-) {
- tcx.for_each_impl(trait_def_id, |impl_def_id| {
- clauses.extend(
- tcx.program_clauses_for(impl_def_id)
- .into_iter()
- .cloned()
- );
- });
-}
-
-fn assemble_clauses_from_assoc_ty_values<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- trait_def_id: DefId,
- clauses: &mut Vec<Clause<'tcx>>
-) {
- tcx.for_each_impl(trait_def_id, |impl_def_id| {
- for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
- clauses.extend(
- tcx.program_clauses_for(*def_id)
- .into_iter()
- .cloned()
- );
- }
- });
-}
-
-fn assemble_builtin_sized_impls<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- sized_def_id: DefId,
- ty: ty::Ty<'tcx>,
- clauses: &mut Vec<Clause<'tcx>>
-) {
- let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
- let clause = ProgramClause {
- goal: ty::TraitPredicate {
- trait_ref: ty::TraitRef {
- def_id: sized_def_id,
- substs: tcx.mk_substs_trait(ty, &[]),
- },
- }.lower(),
- hypotheses: tcx.mk_goals(
- nested.iter()
- .cloned()
- .map(|nested_ty| ty::TraitRef {
- def_id: sized_def_id,
- substs: tcx.mk_substs_trait(nested_ty, &[]),
- })
- .map(|trait_ref| ty::TraitPredicate { trait_ref })
- .map(|pred| GoalKind::DomainGoal(pred.lower()))
- .map(|goal_kind| tcx.mk_goal(goal_kind))
- ),
- category: ProgramClauseCategory::Other,
- };
- // Bind innermost bound vars that may exist in `ty` and `nested`.
- clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
- };
-
- match &ty.sty {
- // Non parametric primitive types.
- ty::Bool |
- ty::Char |
- ty::Int(..) |
- ty::Uint(..) |
- ty::Float(..) |
- ty::Error |
- ty::Never => push_builtin_impl(ty, &[]),
-
- // These ones are always `Sized`.
- &ty::Array(_, length) => {
- push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
- }
- ty::RawPtr(ptr) => {
- push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
- }
- &ty::Ref(_, _, mutbl) => {
- push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
- }
- ty::FnPtr(fn_ptr) => {
- let fn_ptr = fn_ptr.skip_binder();
- let fn_ptr = generic_types::fn_ptr(
- tcx,
- fn_ptr.inputs_and_output.len(),
- fn_ptr.c_variadic,
- fn_ptr.unsafety,
- fn_ptr.abi
- );
- push_builtin_impl(fn_ptr, &[]);
- }
- &ty::FnDef(def_id, ..) => {
- push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
- }
- &ty::Closure(def_id, ..) => {
- push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
- }
- &ty::Generator(def_id, ..) => {
- push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
- }
-
- // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
- &ty::Tuple(type_list) => {
- let type_list = generic_types::type_list(tcx, type_list.len());
- push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
- }
-
- // Struct def
- ty::Adt(adt_def, _) => {
- let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
- let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
- let sized_constraint = adt_def.sized_constraint(tcx)
- .iter()
- .map(|ty| ty.subst(tcx, substs))
- .collect::<Vec<_>>();
- push_builtin_impl(adt, &sized_constraint);
- }
-
- // Artificially trigger an ambiguity.
- ty::Infer(..) => {
- // Everybody can find at least two types to unify against:
- // general ty vars, int vars and float vars.
- push_builtin_impl(tcx.types.i32, &[]);
- push_builtin_impl(tcx.types.u32, &[]);
- push_builtin_impl(tcx.types.f32, &[]);
- push_builtin_impl(tcx.types.f64, &[]);
- }
-
- ty::Projection(_projection_ty) => {
- // FIXME: add builtin impls from the associated type values found in
- // trait impls of `projection_ty.trait_ref(tcx)`.
- }
-
- // The `Sized` bound can only come from the environment.
- ty::Param(..) |
- ty::Placeholder(..) |
- ty::UnnormalizedProjection(..) => (),
-
- // Definitely not `Sized`.
- ty::Foreign(..) |
- ty::Str |
- ty::Slice(..) |
- ty::Dynamic(..) |
- ty::Opaque(..) => (),
-
- ty::Bound(..) |
- ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
- }
-}
-
-fn wf_clause_for_raw_ptr<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- mutbl: hir::Mutability
-) -> Clauses<'tcx> {
- let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
-
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
- hypotheses: ty::List::empty(),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::Implies(wf_clause);
-
- // `forall<T> { WellFormed(*const T). }`
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_fn_ptr<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- arity_and_output: usize,
- c_variadic: bool,
- unsafety: hir::Unsafety,
- abi: abi::Abi
-) -> Clauses<'tcx> {
- let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, c_variadic, unsafety, abi);
-
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
- hypotheses: ty::List::empty(),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
- // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
- // where `n + 1` == `arity_and_output`
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
- let ty = generic_types::bound(tcx, 0);
- let slice_ty = tcx.mk_slice(ty);
-
- let sized_trait = match tcx.lang_items().sized_trait() {
- Some(def_id) => def_id,
- None => return ty::List::empty(),
- };
- let sized_implemented = ty::TraitRef {
- def_id: sized_trait,
- substs: tcx.mk_substs_trait(ty, ty::List::empty()),
- };
- let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
- trait_ref: sized_implemented
- }.lower();
-
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
- hypotheses: tcx.mk_goals(
- iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
- ),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
- // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_array<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- length: &'tcx ty::Const<'tcx>
-) -> Clauses<'tcx> {
- let ty = generic_types::bound(tcx, 0);
- let array_ty = tcx.mk_ty(ty::Array(ty, length));
-
- let sized_trait = match tcx.lang_items().sized_trait() {
- Some(def_id) => def_id,
- None => return ty::List::empty(),
- };
- let sized_implemented = ty::TraitRef {
- def_id: sized_trait,
- substs: tcx.mk_substs_trait(ty, ty::List::empty()),
- };
- let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
- trait_ref: sized_implemented
- }.lower();
-
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
- hypotheses: tcx.mk_goals(
- iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
- ),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
- // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_tuple<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- arity: usize
-) -> Clauses<'tcx> {
- let type_list = generic_types::type_list(tcx, arity);
- let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
-
- let sized_trait = match tcx.lang_items().sized_trait() {
- Some(def_id) => def_id,
- None => return ty::List::empty(),
- };
-
- // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
- // hypotheses is actually empty.
- let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
- .map(|ty| ty::TraitRef {
- def_id: sized_trait,
- substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
- })
- .map(|trait_ref| ty::TraitPredicate { trait_ref })
- .map(|predicate| predicate.lower());
-
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
- hypotheses: tcx.mk_goals(
- sized_implemented.map(|domain_goal| {
- tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
- })
- ),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
- // ```
- // forall<T1, ..., Tn-1, Tn> {
- // WellFormed((T1, ..., Tn)) :-
- // Implemented(T1: Sized),
- // ...
- // Implemented(Tn-1: Sized).
- // }
- // ```
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_ref<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- mutbl: hir::Mutability
-) -> Clauses<'tcx> {
- let region = tcx.mk_region(
- ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
- );
- let ty = generic_types::bound(tcx, 1);
- let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
- ty,
- mutbl,
- });
-
- let _outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
- hypotheses: ty::List::empty(),
-
- // FIXME: restore this later once we get better at handling regions
- // hypotheses: tcx.mk_goals(
- // iter::once(tcx.mk_goal(outlives.into_goal()))
- // ),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
- // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_fn_def<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- def_id: DefId
-) -> Clauses<'tcx> {
- let fn_def = generic_types::fn_def(tcx, def_id);
-
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
- hypotheses: ty::List::empty(),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
- // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
- // where `def_id` maps to the `some_fn` function definition
- tcx.mk_clauses(iter::once(wf_clause))
-}
-
-impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
- pub(super) fn program_clauses_impl(
- &self,
- environment: &Environment<'tcx>,
- goal: &DomainGoal<'tcx>,
- ) -> Vec<Clause<'tcx>> {
- use rustc::traits::WhereClause::*;
- use rustc::infer::canonical::OriginalQueryValues;
-
- let goal = self.infcx.resolve_type_vars_if_possible(goal);
-
- debug!("program_clauses(goal = {:?})", goal);
-
- let mut clauses = match goal {
- DomainGoal::Holds(Implemented(trait_predicate)) => {
- // These come from:
- // * implementations of the trait itself (rule `Implemented-From-Impl`)
- // * the trait decl (rule `Implemented-From-Env`)
-
- let mut clauses = vec![];
-
- assemble_clauses_from_impls(
- self.infcx.tcx,
- trait_predicate.def_id(),
- &mut clauses
- );
-
- if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
- assemble_builtin_sized_impls(
- self.infcx.tcx,
- trait_predicate.def_id(),
- trait_predicate.self_ty(),
- &mut clauses
- );
- }
-
- // FIXME: we need to add special rules for builtin impls:
- // * `Copy` / `Clone`
- // * `Sized`
- // * `Unsize`
- // * `Generator`
- // * `FnOnce` / `FnMut` / `Fn`
- // * trait objects
- // * auto traits
-
- // Rule `Implemented-From-Env` will be computed from the environment.
- clauses
- }
-
- DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
- // These come from:
- // * the assoc type definition (rule `ProjectionEq-Placeholder`)
- // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
- let clauses = self.infcx.tcx.program_clauses_for(
- projection_predicate.projection_ty.item_def_id
- ).into_iter()
-
- // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
- .filter(|clause| clause.category() == ProgramClauseCategory::Other)
-
- .cloned()
- .collect::<Vec<_>>();
-
- // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
- // from the environment.
- clauses
- }
-
- DomainGoal::Holds(RegionOutlives(..)) => {
- // These come from:
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
- // All of these rules are computed in the environment.
- vec![]
- }
-
- DomainGoal::Holds(TypeOutlives(..)) => {
- // These come from:
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
- // All of these rules are computed in the environment.
- vec![]
- }
-
- DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
- // These come from -- the trait decl (rule `WellFormed-TraitRef`).
- self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
- .into_iter()
-
- // only select `WellFormed-TraitRef`
- .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-
- .cloned()
- .collect()
- }
-
- DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
- // These come from:
- // * the associated type definition if `ty` refers to an unnormalized
- // associated type (rule `WellFormed-AssocTy`)
- // * custom rules for built-in types
- // * the type definition otherwise (rule `WellFormed-Type`)
- let clauses = match ty.sty {
- ty::Projection(data) => {
- self.infcx.tcx.program_clauses_for(data.item_def_id)
- }
-
- // These types are always WF.
- ty::Bool |
- ty::Char |
- ty::Int(..) |
- ty::Uint(..) |
- ty::Float(..) |
- ty::Str |
- ty::Param(..) |
- ty::Placeholder(..) |
- ty::Error |
- ty::Never => {
- let wf_clause = ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
- hypotheses: ty::List::empty(),
- category: ProgramClauseCategory::WellFormed,
- };
- let wf_clause = Clause::Implies(wf_clause);
-
- self.infcx.tcx.mk_clauses(iter::once(wf_clause))
- }
-
- // Always WF (recall that we do not check for parameters to be WF).
- ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
-
- // Always WF (recall that we do not check for parameters to be WF).
- ty::FnPtr(fn_ptr) => {
- let fn_ptr = fn_ptr.skip_binder();
- wf_clause_for_fn_ptr(
- self.infcx.tcx,
- fn_ptr.inputs_and_output.len(),
- fn_ptr.c_variadic,
- fn_ptr.unsafety,
- fn_ptr.abi
- )
- }
-
- // WF if inner type is `Sized`.
- ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
-
- // WF if inner type is `Sized`.
- ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
-
- // WF if all types but the last one are `Sized`.
- ty::Tuple(types) => wf_clause_for_tuple(
- self.infcx.tcx,
- types.len()
- ),
-
- // WF if `sub_ty` outlives `region`.
- ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
-
- ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
-
- ty::Dynamic(..) => {
- // FIXME: no rules yet for trait objects
- ty::List::empty()
- }
-
- ty::Adt(def, ..) => {
- self.infcx.tcx.program_clauses_for(def.did)
- }
-
- // FIXME: these are probably wrong
- ty::Foreign(def_id) |
- ty::Closure(def_id, ..) |
- ty::Generator(def_id, ..) |
- ty::Opaque(def_id, ..) => {
- self.infcx.tcx.program_clauses_for(def_id)
- }
-
- // Artificially trigger an ambiguity.
- ty::Infer(..) => {
- let tcx = self.infcx.tcx;
- let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
- let clauses = types.iter()
- .cloned()
- .map(|ty| ProgramClause {
- goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
- hypotheses: ty::List::empty(),
- category: ProgramClauseCategory::WellFormed,
- })
- .map(|clause| Clause::Implies(clause));
- tcx.mk_clauses(clauses)
- }
-
- ty::GeneratorWitness(..) |
- ty::UnnormalizedProjection(..) |
- ty::Bound(..) => {
- bug!("unexpected type {:?}", ty)
- }
- };
-
- clauses.into_iter()
- .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
- .cloned()
- .collect()
- }
-
- DomainGoal::FromEnv(FromEnv::Trait(..)) => {
- // These come from:
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
- // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
- // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
-
- // All of these rules are computed in the environment.
- vec![]
- }
-
- DomainGoal::FromEnv(FromEnv::Ty(..)) => {
- // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
- // comes from the environment).
- vec![]
- }
-
- DomainGoal::Normalize(projection_predicate) => {
- // These come from -- assoc ty values (rule `Normalize-From-Impl`).
- let mut clauses = vec![];
-
- assemble_clauses_from_assoc_ty_values(
- self.infcx.tcx,
- projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
- &mut clauses
- );
-
- clauses
- }
- };
-
- debug!("program_clauses: clauses = {:?}", clauses);
- debug!("program_clauses: adding clauses from environment = {:?}", environment);
-
- let mut _orig_query_values = OriginalQueryValues::default();
- let canonical_environment = self.infcx.canonicalize_query(
- environment,
- &mut _orig_query_values
- ).value;
- let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
-
- debug!("program_clauses: env_clauses = {:?}", env_clauses);
-
- clauses.extend(env_clauses.into_iter().cloned());
- clauses.extend(environment.clauses.iter().cloned());
- clauses
- }
-}
--- /dev/null
+use rustc::traits::{
+ GoalKind,
+ Clause,
+ ProgramClause,
+ ProgramClauseCategory,
+};
+use rustc::ty;
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::hir::def_id::DefId;
+use crate::lowering::Lower;
+use crate::generic_types;
+
+crate fn assemble_builtin_unsize_impls<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ unsize_def_id: DefId,
+ source: ty::Ty<'tcx>,
+ target: ty::Ty<'tcx>,
+ clauses: &mut Vec<Clause<'tcx>>
+) {
+ match (&source.sty, &target.sty) {
+ (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
+ if data_a.principal_def_id() != data_b.principal_def_id()
+ || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b))
+ {
+ return;
+ }
+
+ // FIXME: rules for trait upcast
+ }
+
+ (_, &ty::Dynamic(..)) => {
+ // FIXME: basically, we should have something like:
+ // ```
+ // forall<T> {
+ // Implemented(T: Unsize< for<...> dyn Trait<...> >) :-
+ // for<...> Implemented(T: Trait<...>).
+ // }
+ // ```
+ // The question is: how to correctly handle the higher-ranked
+ // `for<...>` binder in order to have a generic rule?
+ // (Having generic rules is useful for caching, as we may be able
+ // to turn this function and others into tcx queries later on).
+ }
+
+ (ty::Array(_, length), ty::Slice(_)) => {
+ let ty_param = generic_types::bound(tcx, 0);
+ let array_ty = tcx.mk_ty(ty::Array(ty_param, length));
+ let slice_ty = tcx.mk_ty(ty::Slice(ty_param));
+
+ // `forall<T> { Implemented([T; N]: Unsize<[T]>). }`
+ let clause = ProgramClause {
+ goal: ty::TraitPredicate {
+ trait_ref: ty::TraitRef {
+ def_id: unsize_def_id,
+ substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()])
+ },
+ }.lower(),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::Other,
+ };
+
+ clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
+ }
+
+ (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => {
+ // FIXME: ambiguous
+ }
+
+ (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => {
+ if def_id_a != def_id_b {
+ return;
+ }
+
+ // FIXME: rules for struct unsizing
+ }
+
+ (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
+ if tys_a.len() != tys_b.len() {
+ return;
+ }
+
+ // FIXME: rules for tuple unsizing
+ }
+
+ _ => (),
+ }
+}
+
+crate fn assemble_builtin_sized_impls<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ sized_def_id: DefId,
+ ty: ty::Ty<'tcx>,
+ clauses: &mut Vec<Clause<'tcx>>
+) {
+ let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
+ let clause = ProgramClause {
+ goal: ty::TraitPredicate {
+ trait_ref: ty::TraitRef {
+ def_id: sized_def_id,
+ substs: tcx.mk_substs_trait(ty, &[]),
+ },
+ }.lower(),
+ hypotheses: tcx.mk_goals(
+ nested.iter()
+ .cloned()
+ .map(|nested_ty| ty::TraitRef {
+ def_id: sized_def_id,
+ substs: tcx.mk_substs_trait(nested_ty, &[]),
+ })
+ .map(|trait_ref| ty::TraitPredicate { trait_ref })
+ .map(|pred| GoalKind::DomainGoal(pred.lower()))
+ .map(|goal_kind| tcx.mk_goal(goal_kind))
+ ),
+ category: ProgramClauseCategory::Other,
+ };
+ // Bind innermost bound vars that may exist in `ty` and `nested`.
+ clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
+ };
+
+ match &ty.sty {
+ // Non parametric primitive types.
+ ty::Bool |
+ ty::Char |
+ ty::Int(..) |
+ ty::Uint(..) |
+ ty::Float(..) |
+ ty::Error |
+ ty::Never => push_builtin_impl(ty, &[]),
+
+ // These ones are always `Sized`.
+ &ty::Array(_, length) => {
+ push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
+ }
+ ty::RawPtr(ptr) => {
+ push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
+ }
+ &ty::Ref(_, _, mutbl) => {
+ push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
+ }
+ ty::FnPtr(fn_ptr) => {
+ let fn_ptr = fn_ptr.skip_binder();
+ let fn_ptr = generic_types::fn_ptr(
+ tcx,
+ fn_ptr.inputs_and_output.len(),
+ fn_ptr.c_variadic,
+ fn_ptr.unsafety,
+ fn_ptr.abi
+ );
+ push_builtin_impl(fn_ptr, &[]);
+ }
+ &ty::FnDef(def_id, ..) => {
+ push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
+ }
+ &ty::Closure(def_id, ..) => {
+ push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
+ }
+ &ty::Generator(def_id, ..) => {
+ push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
+ }
+
+ // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
+ &ty::Tuple(type_list) => {
+ let type_list = generic_types::type_list(tcx, type_list.len());
+ push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
+ }
+
+ // Struct def
+ ty::Adt(adt_def, _) => {
+ let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
+ let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
+ let sized_constraint = adt_def.sized_constraint(tcx)
+ .iter()
+ .map(|ty| ty.subst(tcx, substs))
+ .collect::<Vec<_>>();
+ push_builtin_impl(adt, &sized_constraint);
+ }
+
+ // Artificially trigger an ambiguity.
+ ty::Infer(..) => {
+ // Everybody can find at least two types to unify against:
+ // general ty vars, int vars and float vars.
+ push_builtin_impl(tcx.types.i32, &[]);
+ push_builtin_impl(tcx.types.u32, &[]);
+ push_builtin_impl(tcx.types.f32, &[]);
+ push_builtin_impl(tcx.types.f64, &[]);
+ }
+
+ ty::Projection(_projection_ty) => {
+ // FIXME: add builtin impls from the associated type values found in
+ // trait impls of `projection_ty.trait_ref(tcx)`.
+ }
+
+ // The `Sized` bound can only come from the environment.
+ ty::Param(..) |
+ ty::Placeholder(..) |
+ ty::UnnormalizedProjection(..) => (),
+
+ // Definitely not `Sized`.
+ ty::Foreign(..) |
+ ty::Str |
+ ty::Slice(..) |
+ ty::Dynamic(..) |
+ ty::Opaque(..) => (),
+
+ ty::Bound(..) |
+ ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
+ }
+}
--- /dev/null
+mod builtin;
+mod primitive;
+
+use rustc::traits::{
+ WellFormed,
+ FromEnv,
+ DomainGoal,
+ Clause,
+ ProgramClause,
+ ProgramClauseCategory,
+ Environment,
+};
+use rustc::ty;
+use rustc::hir::def_id::DefId;
+use super::ChalkInferenceContext;
+use std::iter;
+
+use self::primitive::*;
+use self::builtin::*;
+
+fn assemble_clauses_from_impls<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ trait_def_id: DefId,
+ clauses: &mut Vec<Clause<'tcx>>
+) {
+ tcx.for_each_impl(trait_def_id, |impl_def_id| {
+ clauses.extend(
+ tcx.program_clauses_for(impl_def_id)
+ .into_iter()
+ .cloned()
+ );
+ });
+}
+
+fn assemble_clauses_from_assoc_ty_values<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ trait_def_id: DefId,
+ clauses: &mut Vec<Clause<'tcx>>
+) {
+ tcx.for_each_impl(trait_def_id, |impl_def_id| {
+ for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
+ clauses.extend(
+ tcx.program_clauses_for(*def_id)
+ .into_iter()
+ .cloned()
+ );
+ }
+ });
+}
+
+impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
+ pub(super) fn program_clauses_impl(
+ &self,
+ environment: &Environment<'tcx>,
+ goal: &DomainGoal<'tcx>,
+ ) -> Vec<Clause<'tcx>> {
+ use rustc::traits::WhereClause::*;
+ use rustc::infer::canonical::OriginalQueryValues;
+
+ let goal = self.infcx.resolve_type_vars_if_possible(goal);
+
+ debug!("program_clauses(goal = {:?})", goal);
+
+ let mut clauses = match goal {
+ DomainGoal::Holds(Implemented(trait_predicate)) => {
+ // These come from:
+ // * implementations of the trait itself (rule `Implemented-From-Impl`)
+ // * the trait decl (rule `Implemented-From-Env`)
+
+ let mut clauses = vec![];
+
+ assemble_clauses_from_impls(
+ self.infcx.tcx,
+ trait_predicate.def_id(),
+ &mut clauses
+ );
+
+ if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
+ assemble_builtin_sized_impls(
+ self.infcx.tcx,
+ trait_predicate.def_id(),
+ trait_predicate.self_ty(),
+ &mut clauses
+ );
+ }
+
+ if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
+ let source = trait_predicate.self_ty();
+ let target = trait_predicate.trait_ref.substs.type_at(1);
+ assemble_builtin_unsize_impls(
+ self.infcx.tcx,
+ trait_predicate.def_id(),
+ source,
+ target,
+ &mut clauses
+ );
+ }
+
+ // FIXME: we need to add special rules for other builtin impls:
+ // * `Copy` / `Clone`
+ // * `Generator`
+ // * `FnOnce` / `FnMut` / `Fn`
+ // * trait objects
+ // * auto traits
+
+ // Rule `Implemented-From-Env` will be computed from the environment.
+ clauses
+ }
+
+ DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
+ // These come from:
+ // * the assoc type definition (rule `ProjectionEq-Placeholder`)
+ // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
+ // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+ // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+ let clauses = self.infcx.tcx.program_clauses_for(
+ projection_predicate.projection_ty.item_def_id
+ ).into_iter()
+
+ // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
+ .filter(|clause| clause.category() == ProgramClauseCategory::Other)
+
+ .cloned()
+ .collect::<Vec<_>>();
+
+ // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
+ // from the environment.
+ clauses
+ }
+
+ // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause`
+ // will register them as actual region constraints later.
+ DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => {
+ vec![Clause::Implies(ProgramClause {
+ goal,
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::Other,
+ })]
+ }
+
+ DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
+ // These come from -- the trait decl (rule `WellFormed-TraitRef`).
+ self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
+ .into_iter()
+
+ // only select `WellFormed-TraitRef`
+ .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+
+ .cloned()
+ .collect()
+ }
+
+ DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
+ // These come from:
+ // * the associated type definition if `ty` refers to an unnormalized
+ // associated type (rule `WellFormed-AssocTy`)
+ // * custom rules for built-in types
+ // * the type definition otherwise (rule `WellFormed-Type`)
+ let clauses = match ty.sty {
+ ty::Projection(data) => {
+ self.infcx.tcx.program_clauses_for(data.item_def_id)
+ }
+
+ // These types are always WF.
+ ty::Bool |
+ ty::Char |
+ ty::Int(..) |
+ ty::Uint(..) |
+ ty::Float(..) |
+ ty::Str |
+ ty::Param(..) |
+ ty::Placeholder(..) |
+ ty::Error |
+ ty::Never => {
+ let wf_clause = ProgramClause {
+ goal,
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::Implies(wf_clause);
+
+ self.infcx.tcx.mk_clauses(iter::once(wf_clause))
+ }
+
+ // Always WF (recall that we do not check for parameters to be WF).
+ ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
+
+ // Always WF (recall that we do not check for parameters to be WF).
+ ty::FnPtr(fn_ptr) => {
+ let fn_ptr = fn_ptr.skip_binder();
+ wf_clause_for_fn_ptr(
+ self.infcx.tcx,
+ fn_ptr.inputs_and_output.len(),
+ fn_ptr.c_variadic,
+ fn_ptr.unsafety,
+ fn_ptr.abi
+ )
+ }
+
+ // WF if inner type is `Sized`.
+ ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
+
+ // WF if inner type is `Sized`.
+ ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
+
+ // WF if all types but the last one are `Sized`.
+ ty::Tuple(types) => wf_clause_for_tuple(
+ self.infcx.tcx,
+ types.len()
+ ),
+
+ // WF if `sub_ty` outlives `region`.
+ ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
+
+ ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
+
+ ty::Dynamic(..) => {
+ // FIXME: no rules yet for trait objects
+ ty::List::empty()
+ }
+
+ ty::Adt(def, ..) => {
+ self.infcx.tcx.program_clauses_for(def.did)
+ }
+
+ // FIXME: these are probably wrong
+ ty::Foreign(def_id) |
+ ty::Closure(def_id, ..) |
+ ty::Generator(def_id, ..) |
+ ty::Opaque(def_id, ..) => {
+ self.infcx.tcx.program_clauses_for(def_id)
+ }
+
+ // Artificially trigger an ambiguity.
+ ty::Infer(..) => {
+ let tcx = self.infcx.tcx;
+ let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
+ let clauses = types.iter()
+ .cloned()
+ .map(|ty| ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ })
+ .map(|clause| Clause::Implies(clause));
+ tcx.mk_clauses(clauses)
+ }
+
+ ty::GeneratorWitness(..) |
+ ty::UnnormalizedProjection(..) |
+ ty::Bound(..) => {
+ bug!("unexpected type {:?}", ty)
+ }
+ };
+
+ clauses.into_iter()
+ .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+ .cloned()
+ .collect()
+ }
+
+ DomainGoal::FromEnv(FromEnv::Trait(..)) => {
+ // These come from:
+ // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+ // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+ // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
+ // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
+
+ // All of these rules are computed in the environment.
+ vec![]
+ }
+
+ DomainGoal::FromEnv(FromEnv::Ty(..)) => {
+ // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
+ // comes from the environment).
+ vec![]
+ }
+
+ DomainGoal::Normalize(projection_predicate) => {
+ // These come from -- assoc ty values (rule `Normalize-From-Impl`).
+ let mut clauses = vec![];
+
+ assemble_clauses_from_assoc_ty_values(
+ self.infcx.tcx,
+ projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
+ &mut clauses
+ );
+
+ clauses
+ }
+ };
+
+ debug!("program_clauses: clauses = {:?}", clauses);
+ debug!("program_clauses: adding clauses from environment = {:?}", environment);
+
+ let mut _orig_query_values = OriginalQueryValues::default();
+ let canonical_environment = self.infcx.canonicalize_query(
+ environment,
+ &mut _orig_query_values
+ ).value;
+ let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
+
+ debug!("program_clauses: env_clauses = {:?}", env_clauses);
+
+ clauses.extend(env_clauses.into_iter().cloned());
+ clauses.extend(environment.clauses.iter().cloned());
+ clauses
+ }
+}
--- /dev/null
+use rustc::traits::{
+ WellFormed,
+ DomainGoal,
+ GoalKind,
+ Clause,
+ Clauses,
+ ProgramClause,
+ ProgramClauseCategory,
+};
+use rustc::ty;
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc_target::spec::abi;
+use crate::lowering::Lower;
+use crate::generic_types;
+use std::iter;
+
+crate fn wf_clause_for_raw_ptr<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ mutbl: hir::Mutability
+) -> Clauses<'tcx> {
+ let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::Implies(wf_clause);
+
+ // `forall<T> { WellFormed(*const T). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_fn_ptr<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ arity_and_output: usize,
+ variadic: bool,
+ unsafety: hir::Unsafety,
+ abi: abi::Abi
+) -> Clauses<'tcx> {
+ let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
+ // where `n + 1` == `arity_and_output`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+ let ty = generic_types::bound(tcx, 0);
+ let slice_ty = tcx.mk_slice(ty);
+
+ let sized_trait = match tcx.lang_items().sized_trait() {
+ Some(def_id) => def_id,
+ None => return ty::List::empty(),
+ };
+ let sized_implemented = ty::TraitRef {
+ def_id: sized_trait,
+ substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+ };
+ let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
+ trait_ref: sized_implemented
+ }.lower();
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
+ hypotheses: tcx.mk_goals(
+ iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_array<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ length: &'tcx ty::Const<'tcx>
+) -> Clauses<'tcx> {
+ let ty = generic_types::bound(tcx, 0);
+ let array_ty = tcx.mk_ty(ty::Array(ty, length));
+
+ let sized_trait = match tcx.lang_items().sized_trait() {
+ Some(def_id) => def_id,
+ None => return ty::List::empty(),
+ };
+ let sized_implemented = ty::TraitRef {
+ def_id: sized_trait,
+ substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+ };
+ let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
+ trait_ref: sized_implemented
+ }.lower();
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
+ hypotheses: tcx.mk_goals(
+ iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_tuple<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ arity: usize
+) -> Clauses<'tcx> {
+ let type_list = generic_types::type_list(tcx, arity);
+ let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
+
+ let sized_trait = match tcx.lang_items().sized_trait() {
+ Some(def_id) => def_id,
+ None => return ty::List::empty(),
+ };
+
+ // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
+ // hypotheses is actually empty.
+ let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
+ .map(|ty| ty::TraitRef {
+ def_id: sized_trait,
+ substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
+ })
+ .map(|trait_ref| ty::TraitPredicate { trait_ref })
+ .map(|predicate| predicate.lower());
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
+ hypotheses: tcx.mk_goals(
+ sized_implemented.map(|domain_goal| {
+ tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+ })
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // ```
+ // forall<T1, ..., Tn-1, Tn> {
+ // WellFormed((T1, ..., Tn)) :-
+ // Implemented(T1: Sized),
+ // ...
+ // Implemented(Tn-1: Sized).
+ // }
+ // ```
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_ref<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ mutbl: hir::Mutability
+) -> Clauses<'tcx> {
+ let region = tcx.mk_region(
+ ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
+ );
+ let ty = generic_types::bound(tcx, 1);
+ let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
+ ty,
+ mutbl,
+ });
+
+ let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
+ hypotheses: tcx.mk_goals(
+ iter::once(tcx.mk_goal(outlives.into_goal()))
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_fn_def<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ def_id: DefId
+) -> Clauses<'tcx> {
+ let fn_def = generic_types::fn_def(tcx, def_id);
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
+ // where `def_id` maps to the `some_fn` function definition
+ tcx.mk_clauses(iter::once(wf_clause))
+}
use rustc::infer::canonical::{Canonical, CanonicalVarValues};
use rustc::traits::{
DomainGoal,
+ WhereClause,
Goal,
GoalKind,
Clause,
})
);
+ // If we have a goal of the form `T: 'a` or `'a: 'b`, then just
+ // assume it is true (no subgoals) and register it as a constraint
+ // instead.
+ match goal {
+ DomainGoal::Holds(WhereClause::RegionOutlives(pred)) => {
+ assert_eq!(ex_clause.subgoals.len(), 0);
+ ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1));
+ }
+
+ DomainGoal::Holds(WhereClause::TypeOutlives(pred)) => {
+ assert_eq!(ex_clause.subgoals.len(), 0);
+ ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1));
+ }
+
+ _ => (),
+ };
+
let canonical_ex_clause = self.canonicalize_ex_clause(&ex_clause);
Ok(canonical_ex_clause)
});
substitutor.relate(&answer_table_goal.value, &selected_goal)
.map_err(|_| NoSolution)?;
- let ex_clause = substitutor.ex_clause;
-
- // FIXME: restore this later once we get better at handling regions
- // ex_clause.constraints.extend(answer_subst.constraints);
+ let mut ex_clause = substitutor.ex_clause;
+ ex_clause.constraints.extend(answer_subst.constraints);
debug!("apply_answer_subst: ex_clause = {:?}", ex_clause);
Ok(ex_clause)
use rustc::ty::{self, TyCtxt, Ty};
use rustc::hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet;
-use super::Lower;
-use crate::generic_types;
-use std::iter;
struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
);
}
- // forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` }
- ty::Ref(_, _, mutbl) => {
- let region = self.tcx.mk_region(
- ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
- );
- let ty = generic_types::bound(self.tcx, 1);
- let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
- ty,
- mutbl,
- });
-
- let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty));
-
- let clause = ProgramClause {
- goal: ty::OutlivesPredicate(ty, region).lower(),
- hypotheses: self.tcx.mk_goals(
- iter::once(self.tcx.mk_goal(from_env.into_goal()))
- ),
- category: ProgramClauseCategory::ImpliedBound,
- };
- let clause = Clause::ForAll(ty::Binder::bind(clause));
- self.round.insert(clause);
- }
-
ty::Dynamic(..) => {
// FIXME: trait object rules are not yet implemented
}
ty::RawPtr(..) |
ty::FnPtr(..) |
ty::Tuple(..) |
+ ty::Ref(..) |
ty::Never |
ty::Infer(..) |
ty::Placeholder(..) |
let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env));
let predicates = &tcx.predicates_defined_on(def_id).predicates;
+
+ // Warning: these where clauses are not substituted for bound vars yet,
+ // so that we don't need to adjust binders in the `FromEnv` rules below
+ // (see the FIXME).
let where_clauses = &predicates
.iter()
.map(|(wc, _)| wc.lower())
// `WellFormed(WC)`
let wf_conditions = where_clauses
.into_iter()
+ .map(|wc| wc.subst(tcx, bound_vars))
.map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()));
// `WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
//
// ```
// forall<P1..Pn> {
- // WellFormed(Ty<...>) :- WC1, ..., WCm`
+ // WellFormed(Ty<...>) :- WellFormed(WC1), ..., WellFormed(WCm)`
// }
// ```
// `Ty<...>`
let ty = tcx.type_of(def_id).subst(tcx, bound_vars);
- // `WC`
+ // Warning: these where clauses are not substituted for bound vars yet,
+ // so that we don't need to adjust binders in the `FromEnv` rules below
+ // (see the FIXME).
let where_clauses = tcx.predicates_of(def_id).predicates
.iter()
.map(|(wc, _)| wc.lower())
.collect::<Vec<_>>();
- // `WellFormed(Ty<...>) :- WC1, ..., WCm`
+ // `WellFormed(Ty<...>) :- WellFormed(WC1), ..., WellFormed(WCm)`
let well_formed_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
hypotheses: tcx.mk_goals(
where_clauses
.iter()
.map(|wc| wc.subst(tcx, bound_vars))
+ .map(|wc| wc.map_bound(|bound| bound.into_well_formed_goal()))
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
),
category: ProgramClauseCategory::WellFormed,
// ```
// forall<Self, P1..Pn, Pn+1..Pm> {
// WellFormed((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
- // :- Implemented(Self: Trait<P1..Pn>)
+ // :- WellFormed(Self: Trait<P1..Pn>)
// }
// ```
let trait_predicate = ty::TraitPredicate { trait_ref };
let hypothesis = tcx.mk_goal(
- DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
+ DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)).into_goal()
);
let wf_clause = ProgramClause {
use errors::{Applicability, DiagnosticId};
use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
use crate::hir::def_id::DefId;
use crate::hir::HirVec;
use crate::lint;
tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
});
if let Some(variant_def) = variant_def {
- let def = Def::Variant(variant_def.did);
+ let def = Def::Variant(variant_def.def_id);
if permit_variants {
check_type_alias_enum_variants_enabled(tcx, span);
- tcx.check_stability(variant_def.did, Some(hir_ref_id), span);
+ tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
return (qself_ty, def);
} else {
variant_resolution = Some(def);
match def {
// Case 1. Reference to a struct constructor.
- Def::StructCtor(def_id, ..) |
+ Def::Ctor(def_id, CtorOf::Struct, ..) |
Def::SelfCtor(.., def_id) => {
// Everything but the final segment should have no
// parameters at all.
}
// Case 2. Reference to a variant constructor.
- Def::Variant(def_id) |
- Def::VariantCtor(def_id, ..) => {
+ Def::Ctor(def_id, CtorOf::Variant, ..) | Def::Variant(def_id, ..) => {
let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
let (generics_def_id, index) = if let Some(adt_def) = adt_def {
debug_assert!(adt_def.is_enum());
} else if last >= 1 && segments[last - 1].args.is_some() {
// Everything but the penultimate segment should have no
// parameters at all.
+ let mut def_id = def_id;
+
+ // `Def::Ctor` -> `Def::Variant`
+ if let Def::Ctor(..) = def {
+ def_id = tcx.parent(def_id).unwrap()
+ }
+
+ // `Def::Variant` -> `Def::Item` (enum)
let enum_def_id = tcx.parent(def_id).unwrap();
(enum_def_id, last - 1)
} else {
report_unexpected_variant_def(tcx, &def, pat.span, qpath);
return tcx.types.err;
}
- Def::VariantCtor(_, CtorKind::Fictive) |
- Def::VariantCtor(_, CtorKind::Fn) => {
+ Def::Ctor(_, _, CtorKind::Fictive) |
+ Def::Ctor(_, _, CtorKind::Fn) => {
report_unexpected_variant_def(tcx, &def, pat.span, qpath);
return tcx.types.err;
}
- Def::VariantCtor(_, CtorKind::Const) |
- Def::StructCtor(_, CtorKind::Const) |
- Def::SelfCtor(..) |
+ Def::Ctor(_, _, CtorKind::Const) | Def::SelfCtor(..) |
Def::Const(..) | Def::AssociatedConst(..) => {} // OK
_ => bug!("unexpected pattern definition: {:?}", def)
}
report_unexpected_def(def);
return tcx.types.err;
}
- Def::VariantCtor(_, CtorKind::Fn) |
- Def::StructCtor(_, CtorKind::Fn) => {
+ Def::Ctor(_, _, CtorKind::Fn) => {
tcx.expect_variant_def(def)
}
_ => bug!("unexpected pattern definition: {:?}", def)
let mut inexistent_fields = vec![];
// Typecheck each field.
for &Spanned { node: ref field, span } in fields {
- let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
+ let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
struct_span_err!(tcx.sess, span, E0025,
self.field_ty(span, f, substs)
})
.unwrap_or_else(|| {
- inexistent_fields.push((span, field.ident));
+ inexistent_fields.push(field.ident);
no_field_errors = false;
tcx.types.err
})
.collect::<Vec<_>>();
if inexistent_fields.len() > 0 && !variant.recovered {
let (field_names, t, plural) = if inexistent_fields.len() == 1 {
- (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
+ (format!("a field named `{}`", inexistent_fields[0]), "this", "")
} else {
(format!("fields named {}",
inexistent_fields.iter()
- .map(|(_, name)| format!("`{}`", name))
+ .map(|ident| format!("`{}`", ident))
.collect::<Vec<String>>()
.join(", ")), "these", "s")
};
- let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
+ let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
let mut err = struct_span_err!(tcx.sess,
spans,
E0026,
"{} `{}` does not have {}",
kind_name,
- tcx.def_path_str(variant.did),
+ tcx.def_path_str(variant.def_id),
field_names);
- if let Some((span, ident)) = inexistent_fields.last() {
- err.span_label(*span,
+ if let Some(ident) = inexistent_fields.last() {
+ err.span_label(ident.span,
format!("{} `{}` does not have {} field{}",
kind_name,
- tcx.def_path_str(variant.did),
+ tcx.def_path_str(variant.def_id),
t,
plural));
if plural == "" {
find_best_match_for_name(input, &ident.as_str(), None);
if let Some(suggested_name) = suggested_name {
err.span_suggestion(
- *span,
- "did you mean",
+ ident.span,
+ "a field with a similar name exists",
suggested_name.to_string(),
Applicability::MaybeIncorrect,
);
let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.can_coerce(expr_ty, sole_field_ty) {
- let variant_path = self.tcx.def_path_str(variant.did);
+ let variant_path = self.tcx.def_path_str(variant.def_id);
// FIXME #56861: DRYer prelude filtering
Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
} else {
use errors::{Applicability, DiagnosticBuilder};
use rustc_data_structures::sync::Lrc;
use rustc::hir;
-use rustc::hir::def::Def;
+use rustc::hir::def::{CtorOf, Def};
use rustc::hir::def_id::DefId;
use rustc::traits;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
if let Some(variant_def) = variant_def {
check_type_alias_enum_variants_enabled(tcx, span);
- let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
+ // Braced variants generate unusable names in value namespace (reserved for
+ // possible future use), so variants resolved as associated items may refer to
+ // them as well. It's ok to use the variant's id as a ctor id since an
+ // error will be reported on any use of such resolution anyway.
+ let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id);
+ let def = Def::Ctor(ctor_def_id, CtorOf::Variant, variant_def.ctor_kind);
tcx.check_stability(def.def_id(), Some(expr_id), span);
return Ok(def);
}
use crate::astconv::{AstConv, PathSeg};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath};
-use rustc::hir::def::{CtorKind, Def};
+use rustc::hir::def::{CtorOf, CtorKind, Def};
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
for ((_, discr), v) in def.discriminants(tcx).zip(vs) {
// Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
- let variant_did = def.variants[VariantIdx::new(i)].did;
+ let variant_did = def.variants[VariantIdx::new(i)].def_id;
let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap();
let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
let i_span = match variant_i.node.disr_expr {
let names = variant.fields.iter().filter_map(|field| {
// ignore already set fields and private fields from non-local crates
if skip.iter().any(|x| *x == field.ident.as_str()) ||
- (variant.did.krate != LOCAL_CRATE && field.vis != Visibility::Public) {
+ (!variant.def_id.is_local() && field.vis != Visibility::Public)
+ {
None
} else {
Some(&field.ident.name)
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
variant.fields.iter().filter(|field| {
- let def_scope = self.tcx.adjust_ident(field.ident, variant.did, self.body_id).1;
+ let def_scope = self.tcx.adjust_ident(field.ident, variant.def_id, self.body_id).1;
field.vis.is_accessible_from(def_scope, self.tcx)
})
.map(|field| field.ident.name)
// Type-check each field.
for field in ast_fields {
- let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
+ let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span);
self.write_field_index(field.hir_id, i);
self.set_tainted_by_errors();
tcx.types.err
}
- Def::VariantCtor(_, CtorKind::Fictive) => {
+ Def::Ctor(_, _, CtorKind::Fictive) => {
report_unexpected_variant_def(tcx, &def, expr.span, qpath);
tcx.types.err
}
) -> Option<Span> {
// Be helpful when the user wrote `{... expr;}` and
// taking the `;` off is enough to fix the error.
- let last_stmt = match blk.stmts.last() {
- Some(s) => s,
- None => return None,
- };
+ let last_stmt = blk.stmts.last()?;
let last_expr = match last_stmt.node {
hir::StmtKind::Semi(ref e) => e,
_ => return None,
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
}
- // Rewrite `SelfCtor` to `StructCtor`
+ // Rewrite `SelfCtor` to `Ctor`
pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) {
let tcx = self.tcx;
if let Def::SelfCtor(impl_def_id) = def {
match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
- let def = Def::StructCtor(variant.did, variant.ctor_kind);
- (def, variant.did, tcx.type_of(variant.did))
+ let ctor_def_id = variant.ctor_def_id.unwrap();
+ let def = Def::Ctor(ctor_def_id, CtorOf::Struct, variant.ctor_kind);
+ (def, ctor_def_id, tcx.type_of(ctor_def_id))
}
_ => {
let mut err = tcx.sess.struct_span_err(span,
let mut user_self_ty = None;
let mut is_alias_variant_ctor = false;
match def {
- Def::VariantCtor(_, _) => {
+ Def::Ctor(_, CtorOf::Variant, _) => {
if let Some(self_ty) = self_ty {
let adt_def = self_ty.ty_adt_def().unwrap();
user_self_ty = Some(UserSelfTy {
tcx.predicates_of(def_id);
}
- if !struct_def.is_struct() {
- convert_variant_ctor(tcx, struct_def.hir_id());
+ if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+ convert_variant_ctor(tcx, ctor_hir_id);
}
}
// Convert the ctor, if any. This also registers the variant as
// an item.
- convert_variant_ctor(tcx, variant.node.data.hir_id());
+ if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+ convert_variant_ctor(tcx, ctor_hir_id);
+ }
}
}
fn convert_variant<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId,
+ variant_did: Option<DefId>,
+ ctor_did: Option<DefId>,
ident: Ident,
discr: ty::VariantDiscr,
def: &hir::VariantData,
adt_kind: ty::AdtKind,
- attribute_def_id: DefId
+ parent_did: DefId
) -> ty::VariantDef {
let mut seen_fields: FxHashMap<ast::Ident, Span> = Default::default();
- let hir_id = tcx.hir().as_local_hir_id(did).unwrap();
+ let hir_id = tcx.hir().as_local_hir_id(variant_did.unwrap_or(parent_did)).unwrap();
let fields = def
.fields()
.iter()
})
.collect();
let recovered = match def {
- hir::VariantData::Struct(_, _, r) => *r,
+ hir::VariantData::Struct(_, r) => *r,
_ => false,
};
- ty::VariantDef::new(tcx,
- did,
+ ty::VariantDef::new(
+ tcx,
ident,
+ variant_did,
+ ctor_did,
discr,
fields,
- adt_kind,
CtorKind::from_hir(def),
- attribute_def_id,
+ adt_kind,
+ parent_did,
recovered,
)
}
let (kind, variants) = match item.node {
ItemKind::Enum(ref def, _) => {
let mut distance_from_explicit = 0;
- (
- AdtKind::Enum,
- def.variants
- .iter()
- .map(|v| {
- let did = tcx.hir().local_def_id_from_hir_id(v.node.data.hir_id());
- let discr = if let Some(ref e) = v.node.disr_expr {
- distance_from_explicit = 0;
- ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
- } else {
- ty::VariantDiscr::Relative(distance_from_explicit)
- };
- distance_from_explicit += 1;
+ let variants = def.variants
+ .iter()
+ .map(|v| {
+ let variant_did = Some(tcx.hir().local_def_id_from_hir_id(v.node.id));
+ let ctor_did = v.node.data.ctor_hir_id()
+ .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+
+ let discr = if let Some(ref e) = v.node.disr_expr {
+ distance_from_explicit = 0;
+ ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
+ } else {
+ ty::VariantDiscr::Relative(distance_from_explicit)
+ };
+ distance_from_explicit += 1;
- convert_variant(tcx, did, v.node.ident, discr, &v.node.data, AdtKind::Enum,
- did)
- })
- .collect(),
- )
+ convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr,
+ &v.node.data, AdtKind::Enum, def_id)
+ })
+ .collect();
+
+ (AdtKind::Enum, variants)
}
ItemKind::Struct(ref def, _) => {
- // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
- let ctor_id = if !def.is_struct() {
- Some(tcx.hir().local_def_id_from_hir_id(def.hir_id()))
- } else {
- None
- };
- (
- AdtKind::Struct,
- std::iter::once(convert_variant(
- tcx,
- ctor_id.unwrap_or(def_id),
- item.ident,
- ty::VariantDiscr::Relative(0),
- def,
- AdtKind::Struct,
- def_id
- )).collect(),
- )
- }
- ItemKind::Union(ref def, _) => (
- AdtKind::Union,
- std::iter::once(convert_variant(
- tcx,
- def_id,
- item.ident,
- ty::VariantDiscr::Relative(0),
- def,
- AdtKind::Union,
- def_id
- )).collect(),
- ),
+ let variant_did = None;
+ let ctor_did = def.ctor_hir_id()
+ .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+
+ let variants = std::iter::once(convert_variant(
+ tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def,
+ AdtKind::Struct, def_id,
+ )).collect();
+
+ (AdtKind::Struct, variants)
+ }
+ ItemKind::Union(ref def, _) => {
+ let variant_did = None;
+ let ctor_did = def.ctor_hir_id()
+ .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+
+ let variants = std::iter::once(convert_variant(
+ tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def,
+ AdtKind::Union, def_id,
+ )).collect();
+
+ (AdtKind::Union, variants)
+ },
_ => bug!(),
};
tcx.alloc_adt_def(def_id, kind, variants, repr)
let node = tcx.hir().get_by_hir_id(hir_id);
let parent_def_id = match node {
- Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_)
- | Node::StructCtor(_) | Node::Field(_) => {
+ Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) |
+ Node::Ctor(..) | Node::Field(_) => {
let parent_id = tcx.hir().get_parent_item(hir_id);
Some(tcx.hir().local_def_id_from_hir_id(parent_id))
}
}
fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
+ checked_type_of(tcx, def_id, true).unwrap()
+}
+
+/// Same as [`type_of`] but returns [`Option`] instead of failing.
+///
+/// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
+/// you'd better just call [`type_of`] directly.
+pub fn checked_type_of<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId,
+ fail: bool,
+) -> Option<Ty<'tcx>> {
use rustc::hir::*;
- let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+ let hir_id = match tcx.hir().as_local_hir_id(def_id) {
+ Some(hir_id) => hir_id,
+ None => {
+ if !fail {
+ return None;
+ }
+ bug!("invalid node");
+ }
+ };
let icx = ItemCtxt::new(tcx, def_id);
- match tcx.hir().get_by_hir_id(hir_id) {
+ Some(match tcx.hir().get_by_hir_id(hir_id) {
Node::TraitItem(item) => match item.node {
TraitItemKind::Method(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
}
TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
TraitItemKind::Type(_, None) => {
+ if !fail {
+ return None;
+ }
span_bug!(item.span, "associated type missing default");
}
},
| ItemKind::GlobalAsm(..)
| ItemKind::ExternCrate(..)
| ItemKind::Use(..) => {
+ if !fail {
+ return None;
+ }
span_bug!(
item.span,
"compute_type_of_item: unexpected item type: {:?}",
ForeignItemKind::Type => tcx.mk_foreign(def_id),
},
- Node::StructCtor(&ref def)
- | Node::Variant(&Spanned {
+ Node::Ctor(&ref def) | Node::Variant(&Spanned {
node: hir::VariantKind { data: ref def, .. },
..
}) => match *def {
..
}) => {
if gen.is_some() {
- return tcx.typeck_tables_of(def_id).node_type(hir_id);
+ return Some(tcx.typeck_tables_of(def_id).node_type(hir_id));
}
let substs = ty::ClosureSubsts {
}
// Sanity check to make sure everything is as expected.
if !found_const {
+ if !fail {
+ return None;
+ }
bug!("no arg matching AnonConst in path")
}
match path.def {
for param in &generics.params {
if let ty::GenericParamDefKind::Const = param.kind {
if param_index == arg_index {
- return tcx.type_of(param.def_id);
+ return Some(tcx.type_of(param.def_id));
}
param_index += 1;
}
}
// This is no generic parameter associated with the arg. This is
// probably from an extra arg where one is not needed.
- return tcx.types.err;
+ return Some(tcx.types.err);
}
Def::Err => tcx.types.err,
- x => bug!("unexpected const parent path def {:?}", x),
+ x => {
+ if !fail {
+ return None;
+ }
+ bug!("unexpected const parent path def {:?}", x);
+ }
+ }
+ }
+ x => {
+ if !fail {
+ return None;
}
+ bug!("unexpected const parent path {:?}", x);
}
- x => bug!("unexpected const parent path {:?}", x),
}
}
x => {
+ if !fail {
+ return None;
+ }
bug!("unexpected const parent in type_of_def_id(): {:?}", x);
}
}
hir::GenericParamKind::Const { ref ty, .. } => {
icx.to_ty(ty)
}
- x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
+ x => {
+ if !fail {
+ return None;
+ }
+ bug!("unexpected non-type Node::GenericParam: {:?}", x)
+ },
},
x => {
+ if !fail {
+ return None;
+ }
bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
}
- }
+ })
}
fn find_existential_constraints<'a, 'tcx>(
compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
}
- StructCtor(&VariantData::Tuple(ref fields, ..))
- | Variant(&Spanned {
- node:
- hir::VariantKind {
- data: VariantData::Tuple(ref fields, ..),
- ..
- },
+ Ctor(data) | Variant(Spanned {
+ node: hir::VariantKind { data, .. },
..
- }) => {
+ }) if data.ctor_hir_id().is_some() => {
let ty = tcx.type_of(tcx.hir().get_parent_did_by_hir_id(hir_id));
- let inputs = fields
+ let inputs = data.fields()
.iter()
.map(|f| tcx.type_of(tcx.hir().local_def_id_from_hir_id(f.hir_id)));
ty::Binder::bind(tcx.mk_fn_sig(
use std::iter;
+pub use collect::checked_type_of;
+
pub struct TypeAndSubsts<'tcx> {
substs: SubstsRef<'tcx>,
ty: Ty<'tcx>,
self.visit_node_helper(item.hir_id);
if let hir::VariantData::Tuple(..) = *struct_def {
- self.visit_node_helper(struct_def.hir_id());
+ self.visit_node_helper(struct_def.ctor_hir_id().unwrap());
}
}
for variant in &enum_def.variants {
if let hir::VariantData::Tuple(..) = variant.node.data {
- self.visit_node_helper(variant.node.data.hir_id());
+ self.visit_node_helper(variant.node.data.ctor_hir_id().unwrap());
}
}
}
_ => unsupported()
},
- Node::Variant(_) | Node::StructCtor(_) => {}
+ Node::Variant(_) | Node::Ctor(..) => {}
_ => unsupported()
}
self.add_inferreds_for_item(item.hir_id);
if let hir::VariantData::Tuple(..) = *struct_def {
- self.add_inferreds_for_item(struct_def.hir_id());
+ self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
}
}
for variant in &enum_def.variants {
if let hir::VariantData::Tuple(..) = variant.node.data {
- self.add_inferreds_for_item(variant.node.data.hir_id());
+ self.add_inferreds_for_item(variant.node.data.ctor_hir_id().unwrap());
}
}
}
Def::Variant(..) => return None,
// Assume that enum variants and struct types are re-exported next to
// their constructors.
- Def::VariantCtor(..) |
- Def::StructCtor(..) |
- Def::SelfCtor(..) => return Some(Vec::new()),
+ Def::Ctor(..) | Def::SelfCtor(..) => return Some(Vec::new()),
Def::Mod(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Module);
clean::ModuleItem(build_module(cx, did, visited))
};
let predicates = cx.tcx.predicates_of(did);
+ let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
+ let decl = (did, sig).clean(cx);
+ let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx);
clean::Function {
- decl: (did, sig).clean(cx),
- generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
+ decl,
+ generics,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness,
asyncness: hir::IsAsync::NotAsync,
- }
+ },
+ all_types,
+ ret_types,
}
}
fn get_trait_type(&self) -> Option<Type> {
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
- return Some(trait_.clone());
+ Some(trait_.clone())
+ } else {
+ None
}
- None
}
}
EqPredicate { lhs: Type, rhs: Type },
}
+impl WherePredicate {
+ pub fn get_bounds(&self) -> Option<&[GenericBound]> {
+ match *self {
+ WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
+ WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
+ _ => None,
+ }
+ }
+}
+
impl Clean<WherePredicate> for hir::WherePredicate {
fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
match *self {
},
}
+impl GenericParamDefKind {
+ pub fn is_type(&self) -> bool {
+ match *self {
+ GenericParamDefKind::Type { .. } => true,
+ _ => false,
+ }
+ }
+
+ pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
+ match *self {
+ GenericParamDefKind::Type { did, .. } => {
+ rustc_typeck::checked_type_of(cx.tcx, did, false).map(|t| t.clean(cx))
+ }
+ GenericParamDefKind::Const { ref ty, .. } => Some(ty.clone()),
+ GenericParamDefKind::Lifetime => None,
+ }
+ }
+}
+
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub struct GenericParamDef {
pub name: String,
pub fn is_synthetic_type_param(&self) -> bool {
match self.kind {
GenericParamDefKind::Lifetime |
- GenericParamDefKind::Const { .. } => {
- false
- }
+ GenericParamDefKind::Const { .. } => false,
GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
}
}
+
+ pub fn is_type(&self) -> bool {
+ self.kind.is_type()
+ }
+
+ pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
+ self.kind.get_type(cx)
+ }
+
+ pub fn get_bounds(&self) -> Option<&[GenericBound]> {
+ match self.kind {
+ GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
+ _ => None,
+ }
+ }
}
impl Clean<GenericParamDef> for ty::GenericParamDef {
}
}
+/// The point of this function is to replace bounds with types.
+///
+/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
+/// `[Display, Option]` (we just returns the list of the types, we don't care about the
+/// wrapped types in here).
+fn get_real_types(
+ generics: &Generics,
+ arg: &Type,
+ cx: &DocContext<'_>,
+) -> FxHashSet<Type> {
+ let arg_s = arg.to_string();
+ let mut res = FxHashSet::default();
+ if arg.is_full_generic() {
+ if let Some(where_pred) = generics.where_predicates.iter().find(|g| {
+ match g {
+ &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
+ _ => false,
+ }
+ }) {
+ let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
+ for bound in bounds.iter() {
+ match *bound {
+ GenericBound::TraitBound(ref poly_trait, _) => {
+ for x in poly_trait.generic_params.iter() {
+ if !x.is_type() {
+ continue
+ }
+ if let Some(ty) = x.get_type(cx) {
+ let adds = get_real_types(generics, &ty, cx);
+ if !adds.is_empty() {
+ res.extend(adds);
+ } else if !ty.is_full_generic() {
+ res.insert(ty);
+ }
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ }
+ if let Some(bound) = generics.params.iter().find(|g| {
+ g.is_type() && g.name == arg_s
+ }) {
+ for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
+ if let Some(ty) = bound.get_trait_type() {
+ let adds = get_real_types(generics, &ty, cx);
+ if !adds.is_empty() {
+ res.extend(adds);
+ } else if !ty.is_full_generic() {
+ res.insert(ty.clone());
+ }
+ }
+ }
+ }
+ } else {
+ res.insert(arg.clone());
+ if let Some(gens) = arg.generics() {
+ for gen in gens.iter() {
+ if gen.is_full_generic() {
+ let adds = get_real_types(generics, gen, cx);
+ if !adds.is_empty() {
+ res.extend(adds);
+ }
+ } else {
+ res.insert(gen.clone());
+ }
+ }
+ }
+ }
+ res
+}
+
+/// Return the full list of types when bounds have been resolved.
+///
+/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
+/// `[u32, Display, Option]`.
+pub fn get_all_types(
+ generics: &Generics,
+ decl: &FnDecl,
+ cx: &DocContext<'_>,
+) -> (Vec<Type>, Vec<Type>) {
+ let mut all_types = FxHashSet::default();
+ for arg in decl.inputs.values.iter() {
+ if arg.type_.is_self_type() {
+ continue;
+ }
+ let args = get_real_types(generics, &arg.type_, cx);
+ if !args.is_empty() {
+ all_types.extend(args);
+ } else {
+ all_types.insert(arg.type_.clone());
+ }
+ }
+
+ let ret_types = match decl.output {
+ FunctionRetTy::Return(ref return_type) => {
+ let mut ret = get_real_types(generics, &return_type, cx);
+ if ret.is_empty() {
+ ret.insert(return_type.clone());
+ }
+ ret.into_iter().collect()
+ }
+ _ => Vec::new(),
+ };
+ (all_types.into_iter().collect(), ret_types)
+}
+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Method {
pub generics: Generics,
pub decl: FnDecl,
pub header: hir::FnHeader,
pub defaultness: Option<hir::Defaultness>,
+ pub all_types: Vec<Type>,
+ pub ret_types: Vec<Type>,
}
impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId,
let (generics, decl) = enter_impl_trait(cx, || {
(self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
});
+ let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
Method {
decl,
generics,
header: self.0.header,
defaultness: self.3,
+ all_types,
+ ret_types,
}
}
}
pub header: hir::FnHeader,
pub decl: FnDecl,
pub generics: Generics,
+ pub all_types: Vec<Type>,
+ pub ret_types: Vec<Type>,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub decl: FnDecl,
pub generics: Generics,
pub header: hir::FnHeader,
+ pub all_types: Vec<Type>,
+ pub ret_types: Vec<Type>,
}
impl Clean<Item> for doctree::Function {
} else {
hir::Constness::NotConst
};
+ let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
decl,
generics,
header: hir::FnHeader { constness, ..self.header },
+ all_types,
+ ret_types,
}),
}
}
FnDecl {
inputs: (&self.0.inputs[..], self.1).clean(cx),
output: self.0.output.clean(cx),
- attrs: Attributes::default()
+ attrs: Attributes::default(),
}
}
}
let (generics, decl) = enter_impl_trait(cx, || {
(self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
});
+ let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
TyMethodItem(TyMethod {
header: sig.header,
decl,
generics,
+ all_types,
+ ret_types,
})
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
ty::ImplContainer(_) => true,
ty::TraitContainer(_) => self.defaultness.has_value()
};
+ let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
if provided {
let constness = if cx.tcx.is_min_const_fn(self.def_id) {
hir::Constness::Const
asyncness: hir::IsAsync::NotAsync,
},
defaultness: Some(self.defaultness),
+ all_types,
+ ret_types,
})
} else {
TyMethodItem(TyMethod {
abi: sig.abi(),
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
- }
+ },
+ all_types,
+ ret_types,
})
}
}
_ => None
}
}
+
+ pub fn is_full_generic(&self) -> bool {
+ match *self {
+ Type::Generic(_) => true,
+ _ => false,
+ }
+ }
}
impl GetDefId for Type {
visibility: None,
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.def.hir_id()),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
inner: VariantItem(Variant {
kind: self.def.clean(cx),
}),
};
Item {
name: Some(self.ident.clean(cx)),
- attrs: inline::load_attrs(cx, self.did),
- source: cx.tcx.def_span(self.did).clean(cx),
+ attrs: inline::load_attrs(cx, self.def_id),
+ source: cx.tcx.def_span(self.def_id).clean(cx),
visibility: Some(Inherited),
- def_id: self.did,
+ def_id: self.def_id,
inner: VariantItem(Variant { kind }),
- stability: get_stability(cx, self.did),
- deprecation: get_deprecation(cx, self.did),
+ stability: get_stability(cx, self.def_id),
+ deprecation: get_deprecation(cx, self.def_id),
}
}
}
impl Clean<VariantKind> for hir::VariantData {
fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
- if self.is_struct() {
- VariantKind::Struct(self.clean(cx))
- } else if self.is_unit() {
- VariantKind::CLike
- } else {
- VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
+ match self {
+ hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
+ hir::VariantData::Tuple(..) =>
+ VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()),
+ hir::VariantData::Unit(..) => VariantKind::CLike,
}
}
}
let (generics, decl) = enter_impl_trait(cx, || {
(generics.clean(cx), (&**decl, &names[..]).clean(cx))
});
+ let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
ForeignFunctionItem(Function {
decl,
generics,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
+ all_types,
+ ret_types,
})
}
hir::ForeignItemKind::Static(ref ty, mutbl) => {
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
let diag = ctxt.sess().diagnostic();
- let name = attr.ident_str();
+ let name = attr.name_or_empty();
if attr.is_word() {
- if name == Some("no_default_passes") {
+ if name == "no_default_passes" {
report_deprecated_attr("no_default_passes", diag);
if default_passes == passes::DefaultPassOption::Default {
default_passes = passes::DefaultPassOption::None;
}
}
} else if let Some(value) = attr.value_str() {
- let sink = match name {
- Some("passes") => {
+ let sink = match name.get() {
+ "passes" => {
report_deprecated_attr("passes = \"...\"", diag);
&mut manual_passes
},
- Some("plugins") => {
+ "plugins" => {
report_deprecated_attr("plugins = \"...\"", diag);
eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \
see CVE-2018-1000622");
}
}
- if attr.is_word() && name == Some("document_private_items") {
+ if attr.is_word() && name == "document_private_items" {
if default_passes == passes::DefaultPassOption::Default {
default_passes = passes::DefaultPassOption::Private;
}
pub struct Variant {
pub name: Name,
+ pub id: hir::HirId,
pub attrs: hir::HirVec<ast::Attribute>,
pub def: hir::VariantData,
pub stab: Option<attr::Stability>,
}
Json::Array(data)
}
- None => Json::Null
+ None => Json::Null,
}
}
}
#[derive(Debug)]
struct IndexItemFunctionType {
inputs: Vec<Type>,
- output: Option<Type>,
+ output: Option<Vec<Type>>,
}
impl ToJson for IndexItemFunctionType {
fn to_json(&self) -> Json {
// If we couldn't figure out a type, just write `null`.
- if self.inputs.iter().chain(self.output.iter()).any(|ref i| i.name.is_none()) {
+ let mut iter = self.inputs.iter();
+ if match self.output {
+ Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
+ None => iter.any(|ref i| i.name.is_none()),
+ } {
Json::Null
} else {
let mut data = Vec::with_capacity(2);
data.push(self.inputs.to_json());
if let Some(ref output) = self.output {
- data.push(output.to_json());
+ if output.len() > 1 {
+ data.push(output.to_json());
+ } else {
+ data.push(output[0].to_json());
+ }
}
Json::Array(data)
}
// going to emit HTML
if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
for attr in attrs.lists("doc") {
- match (attr.ident_str(), attr.value_str()) {
- (Some("html_favicon_url"), Some(s)) => {
+ match (attr.name_or_empty().get(), attr.value_str()) {
+ ("html_favicon_url", Some(s)) => {
scx.layout.favicon = s.to_string();
}
- (Some("html_logo_url"), Some(s)) => {
+ ("html_logo_url", Some(s)) => {
scx.layout.logo = s.to_string();
}
- (Some("html_playground_url"), Some(s)) => {
+ ("html_playground_url", Some(s)) => {
markdown::PLAYGROUND.with(|slot| {
let name = krate.name.clone();
*slot.borrow_mut() = Some((Some(name), s.to_string()));
});
}
- (Some("issue_tracker_base_url"), Some(s)) => {
+ ("issue_tracker_base_url", Some(s)) => {
scx.issue_tracker_base_url = Some(s.to_string());
}
- (Some("html_no_source"), None) if attr.is_word() => {
+ ("html_no_source", None) if attr.is_word() => {
scx.include_sources = false;
}
_ => {}
let mut attrs = String::new();
for attr in &it.attrs.other_attrs {
- if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) {
+ if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty().get()) {
continue;
}
if let Some(s) = render_attribute(&attr.meta().unwrap()) {
}
fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
- let decl = match item.inner {
- clean::FunctionItem(ref f) => &f.decl,
- clean::MethodItem(ref m) => &m.decl,
- clean::TyMethodItem(ref m) => &m.decl,
- _ => return None
+ let (all_types, ret_types) = match item.inner {
+ clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types),
+ clean::MethodItem(ref m) => (&m.all_types, &m.ret_types),
+ clean::TyMethodItem(ref m) => (&m.all_types, &m.ret_types),
+ _ => return None,
};
- let inputs = decl.inputs.values.iter().map(|arg| get_index_type(&arg.type_)).collect();
- let output = match decl.output {
- clean::FunctionRetTy::Return(ref return_type) => Some(get_index_type(return_type)),
- _ => None
+ let inputs = all_types.iter().map(|arg| {
+ get_index_type(&arg)
+ }).filter(|a| a.name.is_some()).collect();
+ let output = ret_types.iter().map(|arg| {
+ get_index_type(&arg)
+ }).filter(|a| a.name.is_some()).collect::<Vec<_>>();
+ let output = if output.is_empty() {
+ None
+ } else {
+ Some(output)
};
- Some(IndexItemFunctionType { inputs: inputs, output: output })
+ Some(IndexItemFunctionType { inputs, output })
}
fn get_index_type(clean_type: &clean::Type) -> Type {
}
lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
if (lev_distance <= MAX_LEV_DISTANCE) {
- lev_distance = Math.min(checkGenerics(obj, val), lev_distance);
+ // The generics didn't match but the name kinda did so we give it
+ // a levenshtein distance value that isn't *this* good so it goes
+ // into the search results but not too high.
+ lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
} else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
// We can check if the type we're looking for is inside the generics!
var olength = obj[GENERICS_DATA].length;
var lev_distance = MAX_LEV_DISTANCE + 1;
if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
- var tmp = checkType(obj.type[OUTPUT_DATA], val, literalSearch);
- if (literalSearch === true && tmp === true) {
- return true;
+ var ret = obj.type[OUTPUT_DATA];
+ if (!obj.type[OUTPUT_DATA].length) {
+ ret = [ret];
}
- lev_distance = Math.min(tmp, lev_distance);
- if (lev_distance === 0) {
- return 0;
+ for (var x = 0; x < ret.length; ++x) {
+ var r = ret[x];
+ if (typeof r === "string") {
+ r = [r];
+ }
+ var tmp = checkType(r, val, literalSearch);
+ if (literalSearch === true) {
+ if (tmp === true) {
+ return true;
+ }
+ continue;
+ }
+ lev_distance = Math.min(tmp, lev_distance);
+ if (lev_distance === 0) {
+ return 0;
+ }
}
}
return literalSearch === true ? false : lev_distance;
border-top: 2px solid;
}
-#titles > div:not(:last-child):not(.selected) {
+#titles > div:not(:last-child) {
margin-right: 1px;
width: calc(33.3% - 1px);
}
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }
+.stab > code {
+ color: #ddd;
+}
+
#help > div {
background: #4d4d4d;
border-color: #bfbfbf;
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
+.stab > code {
+ color: #000;
+}
+
#help > div {
background: #e9e9e9;
border-color: #bfbfbf;
.and_then(|(def, fragment)| {
// Constructors are picked up in the type namespace.
match def {
- Def::StructCtor(..)
- | Def::VariantCtor(..)
- | Def::SelfCtor(..) => None,
+ Def::Ctor(..) | Def::SelfCtor(..) => None,
_ => Some((def, fragment))
}
}),
name,
variants: def.variants.iter().map(|v| Variant {
name: v.node.ident.name,
+ id: v.node.id,
attrs: v.node.attrs.clone(),
- stab: self.stability(v.node.data.hir_id()),
- depr: self.deprecation(v.node.data.hir_id()),
+ stab: self.stability(v.node.id),
+ depr: self.deprecation(v.node.id),
def: v.node.data.clone(),
whence: v.span,
}).collect(),
// Struct and variant constructors and proc macro stubs always show up alongside
// their definitions, we've already processed them so just discard these.
match path.def {
- Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) |
- Def::Macro(_, MacroKind::ProcMacroStub) => return,
+ Def::Ctor(..) | Def::SelfCtor(..) | Def::Macro(_, MacroKind::ProcMacroStub) =>
+ return,
_ => {}
}
# https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/std_detect/Cargo.toml
std_detect_file_io = []
std_detect_dlsym_getauxval = []
+
+[package.metadata.fortanix-sgx]
+# Maximum possible number of threads when testing
+threads = 125
use crate::path::Path;
#[test]
- #[cfg_attr(target_os = "emscripten", ignore)]
+ #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
fn test_self_exe_path() {
let path = current_exe();
assert!(path.is_ok());
fn test() {
assert!((!Path::new("test-path").is_absolute()));
+ #[cfg(not(target_env = "sgx"))]
current_dir().unwrap();
}
pub fn atanh(self) -> f32 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
- /// Returns max if self is greater than max, and min if self is less than min.
- /// Otherwise this returns self. Panics if min > max, min equals NaN, or max equals NaN.
+
+ /// Restrict a value to a certain interval unless it is NaN.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// Not that this function returns NaN if the initial value was NaN as
+ /// well.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
///
/// # Examples
///
/// ```
/// #![feature(clamp)]
- /// assert!((-3.0f32).clamp(-2.0f32, 1.0f32) == -2.0f32);
- /// assert!((0.0f32).clamp(-2.0f32, 1.0f32) == 0.0f32);
- /// assert!((2.0f32).clamp(-2.0f32, 1.0f32) == 1.0f32);
- /// assert!((std::f32::NAN).clamp(-2.0f32, 1.0f32).is_nan());
+ /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
+ /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
+ /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
+ /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan());
/// ```
#[unstable(feature = "clamp", issue = "44095")]
#[inline]
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
- /// Returns max if self is greater than max, and min if self is less than min.
- /// Otherwise this returns self. Panics if min > max, min equals NaN, or max equals NaN.
+ /// Restrict a value to a certain interval unless it is NaN.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// Not that this function returns NaN if the initial value was NaN as
+ /// well.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
///
/// # Examples
///
/// ```
/// #![feature(clamp)]
- /// assert!((-3.0f64).clamp(-2.0f64, 1.0f64) == -2.0f64);
- /// assert!((0.0f64).clamp(-2.0f64, 1.0f64) == 0.0f64);
- /// assert!((2.0f64).clamp(-2.0f64, 1.0f64) == 1.0f64);
- /// assert!((std::f64::NAN).clamp(-2.0f64, 1.0f64).is_nan());
+ /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
+ /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
+ /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
+ /// assert!((std::f64::NAN).clamp(-2.0, 1.0).is_nan());
/// ```
#[unstable(feature = "clamp", issue = "44095")]
#[inline]
}
}
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
mod tests {
use crate::io::prelude::*;
assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53)));
let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+ #[cfg(not(target_env = "sgx"))]
assert!(tsa(("localhost", 23924)).unwrap().contains(&a));
+ #[cfg(target_env = "sgx")]
+ let _ = a;
}
#[test]
assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53"));
let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+ #[cfg(not(target_env = "sgx"))]
assert!(tsa("localhost:23924").unwrap().contains(&a));
+ #[cfg(target_env = "sgx")]
+ let _ = a;
}
#[test]
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
+ use crate::fmt;
use crate::io::{ErrorKind, IoVec, IoVecMut};
use crate::io::prelude::*;
use crate::net::*;
use crate::net::test::{next_test_ip4, next_test_ip6};
use crate::sync::mpsc::channel;
- use crate::sys_common::AsInner;
use crate::time::{Instant, Duration};
use crate::thread;
connect(i + 1, addr);
t!(stream.write(&[i as u8]));
});
- t.join().ok().unwrap();
+ t.join().ok().expect("thread panicked");
}
}
connect(i + 1, addr);
t!(stream.write(&[99]));
});
- t.join().ok().unwrap();
+ t.join().ok().expect("thread panicked");
}
}
}
#[test]
+ // FIXME: https://github.com/fortanix/rust-sgx/issues/110
+ #[cfg_attr(target_env = "sgx", ignore)]
fn shutdown_smoke() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
}
#[test]
+ // FIXME: https://github.com/fortanix/rust-sgx/issues/110
+ #[cfg_attr(target_env = "sgx", ignore)]
fn close_readwrite_smoke() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
#[test]
fn debug() {
- let name = if cfg!(windows) {"socket"} else {"fd"};
+ #[cfg(not(target_env = "sgx"))]
+ fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+ addr
+ }
+ #[cfg(target_env = "sgx")]
+ fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+ addr.to_string()
+ }
+
+ #[cfg(unix)]
+ use crate::os::unix::io::AsRawFd;
+ #[cfg(target_env = "sgx")]
+ use crate::os::fortanix_sgx::io::AsRawFd;
+ #[cfg(not(windows))]
+ fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
+ addr.as_raw_fd()
+ }
+ #[cfg(windows)]
+ fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
+ addr.as_raw_socket()
+ }
+
+ let inner_name = if cfg!(windows) {"socket"} else {"fd"};
let socket_addr = next_test_ip4();
let listener = t!(TcpListener::bind(&socket_addr));
- let listener_inner = listener.0.socket().as_inner();
let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}",
- socket_addr, name, listener_inner);
+ render_socket_addr(&socket_addr),
+ inner_name,
+ render_inner(&listener));
assert_eq!(format!("{:?}", listener), compare);
- let stream = t!(TcpStream::connect(&("localhost",
- socket_addr.port())));
- let stream_inner = stream.0.socket().as_inner();
- let compare = format!("TcpStream {{ addr: {:?}, \
- peer: {:?}, {}: {:?} }}",
- stream.local_addr().unwrap(),
- stream.peer_addr().unwrap(),
- name,
- stream_inner);
+ let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
+ let compare = format!("TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
+ render_socket_addr(&stream.local_addr().unwrap()),
+ render_socket_addr(&stream.peer_addr().unwrap()),
+ inner_name,
+ render_inner(&stream));
assert_eq!(format!("{:?}", stream), compare);
}
// FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
// no longer has rounding errors.
#[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
#[test]
fn timeouts() {
let addr = next_test_ip4();
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn test_read_timeout() {
let addr = next_test_ip4();
let listener = t!(TcpListener::bind(&addr));
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn test_read_with_timeout() {
let addr = next_test_ip4();
let listener = t!(TcpListener::bind(&addr));
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)]
fn nodelay() {
let addr = next_test_ip4();
let _listener = t!(TcpListener::bind(&addr));
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)]
fn ttl() {
let ttl = 100;
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)]
fn set_nonblocking() {
let addr = next_test_ip4();
let listener = t!(TcpListener::bind(&addr));
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn peek() {
each_ip(&mut |addr| {
let (txdone, rxdone) = channel();
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn connect_timeout_valid() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
// all want to use ports. This function figures out which workspace
// it is running in and assigns a port range based on it.
fn base_port() -> u16 {
- let cwd = env::current_dir().unwrap();
+ let cwd = if cfg!(target_env = "sgx") {
+ String::from("sgx")
+ } else {
+ env::current_dir().unwrap().into_os_string().into_string().unwrap()
+ };
let dirs = ["32-opt", "32-nopt",
"musl-64-opt", "cross-opt",
"64-opt", "64-nopt", "64-opt-vg", "64-debug-opt",
- "all-opt", "snap3", "dist"];
+ "all-opt", "snap3", "dist", "sgx"];
dirs.iter().enumerate().find(|&(_, dir)| {
- cwd.to_str().unwrap().contains(dir)
+ cwd.contains(dir)
}).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
}
}
}
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
mod tests {
use crate::io::ErrorKind;
use crate::net::*;
});
);
- if cfg!(unix) {
+ if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
tp!("", "foo", "foo");
tp!("foo", "bar", "foo/bar");
tp!("foo/", "bar", "foo/bar");
tfn!("foo", "bar", "bar");
tfn!("foo", "", "");
tfn!("", "foo", "foo");
- if cfg!(unix) {
+ if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
tfn!(".", "foo", "./foo");
tfn!("foo/", "bar", "bar");
tfn!("foo/.", "bar", "bar");
}
}
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
mod tests {
use crate::io::prelude::*;
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_wait() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_until_wait() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_until_wake() {
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair_copy = pair.clone();
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_wake() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
for _ in 0..10000 {
assert_eq!(rx.recv().unwrap(), 1);
}
- t.join().ok().unwrap();
+ t.join().ok().expect("thread panicked");
}
#[test]
});
}
drop(tx);
- t.join().ok().unwrap();
+ t.join().ok().expect("thread panicked");
}
#[test]
tx2.send(1).unwrap();
}
});
- t1.join().ok().unwrap();
- t2.join().ok().unwrap();
+ t1.join().ok().expect("thread panicked");
+ t2.join().ok().expect("thread panicked");
}
#[test]
for _ in 0..40 {
tx.send(1).unwrap();
}
- t.join().ok().unwrap();
+ t.join().ok().expect("thread panicked");
}
#[test]
tx1.send(1).unwrap();
assert_eq!(rx2.recv().unwrap(), 2);
});
- t1.join().ok().unwrap();
- t2.join().ok().unwrap();
+ t1.join().ok().expect("thread panicked");
+ t2.join().ok().expect("thread panicked");
}
#[test]
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn oneshot_single_thread_recv_timeout() {
let (tx, rx) = channel();
tx.send(()).unwrap();
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_two_threads() {
let (tx, rx) = channel();
let stress = stress_factor() + 100;
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn recv_timeout_upgrade() {
let (tx, rx) = channel::<()>();
let timeout = Duration::from_millis(1);
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_shared() {
let (tx, rx) = channel();
let stress = stress_factor() + 100;
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn very_long_recv_timeout_wont_panic() {
let (tx, rx) = channel::<()>();
let join_handle = thread::spawn(move || {
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn shared_recv_timeout() {
let (tx, rx) = channel();
let total = 5;
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn recv_timeout() {
let (tx, rx) = sync_channel::<i32>(1);
assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout));
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_two_threads() {
let (tx, rx) = sync_channel::<i32>(0);
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_shared() {
const AMT: u32 = 1000;
const NTHREADS: u32 = 8;
Instant { t: 0 }
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
- let diff = self.t
- .checked_sub(other.t)
- .expect("second instant is later than self");
- Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+ let diff = self.t.checked_sub(other.t)?;
+ Some(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
false
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
- self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
- panic!("specified instant was later than self")
- })
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+ self.t.sub_timespec(&other.t).ok()
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
+
use core::sync::atomic::{AtomicUsize, Ordering};
use crate::io::Write;
#[macro_use]
pub mod usercalls;
+#[cfg(not(test))]
global_asm!(include_str!("entry.S"));
+#[cfg(not(test))]
#[no_mangle]
unsafe extern "C" fn tcs_init(secondary: bool) {
// Be very careful when changing this code: it runs before the binary has been
// FIXME: this item should only exist if this is linked into an executable
// (main function exists). If this is a library, the crate author should be
// able to specify this
+#[cfg(not(test))]
#[no_mangle]
extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) {
// FIXME: how to support TLS in library mode?
}
}
-#[no_mangle]
+#[cfg_attr(not(test), no_mangle)]
pub extern "C" fn panic_msg(msg: &str) -> ! {
let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
usercalls::exit(true)
const TLS_KEYS: usize = 128; // Same as POSIX minimum
const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
macro_rules! dup {
((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
(() $($val:tt)*) => ([$($val),*])
}
-static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = [
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
- AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-];
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
+static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
extern "C" {
fn get_tls_ptr() -> *const u8;
// from outside as obtained by `super::alloc`.
fn new_uninit_bytes(size: usize) -> Self {
unsafe {
- let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
- User(NonNull::new_userref(T::from_raw_sized(ptr as _, size)))
+ // Mustn't call alloc with size 0.
+ let ptr = if size > 0 {
+ super::alloc(size, T::align_of()).expect("User memory allocation failed") as _
+ } else {
+ T::align_of() as _ // dangling pointer ok for size 0
+ };
+ User(NonNull::new_userref(T::from_raw_sized(ptr, size)))
}
}
// Using a SpinMutex because we never want to exit the enclave waiting for the
// allocator.
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE"]
static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc> = SpinMutex::new(dlmalloc::DLMALLOC_INIT);
#[stable(feature = "alloc_system_type", since = "1.28.0")]
use crate::sys_common::FromInner;
use crate::slice;
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
static ARGS: AtomicUsize = AtomicUsize::new(0);
type ArgsStore = Vec<OsString>;
+#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
if argc != 0 {
let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _);
mutex.lock()
}
- pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+ pub unsafe fn wait_timeout(&self, mutex: &Mutex, _dur: Duration) -> bool {
+ mutex.unlock(); // don't hold the lock while panicking
panic!("timeout not supported in SGX");
}
}
}
-#[derive(Debug, Clone)]
+#[derive(Clone)]
pub struct TcpStream {
inner: Socket,
peer_addr: Option<String>,
}
+impl fmt::Debug for TcpStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut res = f.debug_struct("TcpStream");
+
+ if let Some(ref addr) = self.inner.local_addr {
+ res.field("addr", addr);
+ }
+
+ if let Some(ref peer) = self.peer_addr {
+ res.field("peer", peer);
+ }
+
+ res.field("fd", &self.inner.inner.as_inner())
+ .finish()
+ }
+}
+
fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
match result {
Ok(saddr) => Ok(saddr.to_string()),
Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
}
- pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+ pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
+ if dur == Duration::default() {
+ return Err(io::Error::new(io::ErrorKind::InvalidInput,
+ "cannot set a 0 duration timeout"));
+ }
Self::connect(Ok(addr)) // FIXME: ignoring timeout
}
- pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
- sgx_ineffective(())
+ pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+ match dur {
+ Some(dur) if dur == Duration::default() => {
+ return Err(io::Error::new(io::ErrorKind::InvalidInput,
+ "cannot set a 0 duration timeout"));
+ }
+ _ => sgx_ineffective(())
+ }
}
- pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
- sgx_ineffective(())
+ pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+ match dur {
+ Some(dur) if dur == Duration::default() => {
+ return Err(io::Error::new(io::ErrorKind::InvalidInput,
+ "cannot set a 0 duration timeout"));
+ }
+ _ => sgx_ineffective(())
+ }
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
}
}
-#[derive(Debug, Clone)]
+#[derive(Clone)]
pub struct TcpListener {
inner: Socket,
}
+impl fmt::Debug for TcpListener {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut res = f.debug_struct("TcpListener");
+
+ if let Some(ref addr) = self.inner.local_addr {
+ res.field("addr", addr);
+ }
+
+ res.field("fd", &self.inner.inner.as_inner())
+ .finish()
+ }
+}
+
impl TcpListener {
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
let addr = io_err_to_addr(addr)?;
unsupported()
}
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"]
static ENV: AtomicUsize = AtomicUsize::new(0);
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"]
static ENV_INIT: Once = Once::new();
type EnvStore = Mutex<HashMap<OsString, OsString>>;
+#[cfg(not(test))]
use crate::alloc::{self, Layout};
use crate::num::NonZeroUsize;
+#[cfg(not(test))]
use crate::slice;
+#[cfg(not(test))]
use crate::str;
use super::waitqueue::{
// only used by __rust_rwlock_unlock below
#[inline]
+ #[cfg_attr(test, allow(dead_code))]
unsafe fn unlock(&self) {
let rguard = self.readers.lock();
let wguard = self.writer.lock();
pub unsafe fn destroy(&self) {}
}
+#[cfg(not(test))]
const EINVAL: i32 = 22;
// used by libunwind port
+#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return 0;
}
+#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
if p.is_null() {
(*p).write();
return 0;
}
+#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
if p.is_null() {
// the following functions are also used by the libunwind port. They're
// included here to make sure parallel codegen and LTO don't mess things up.
+#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
if s < 0 {
}
}
+#[cfg(not(test))]
#[no_mangle]
// NB. used by both libunwind and libpanic_abort
pub unsafe extern "C" fn __rust_abort() {
crate::sys::abort_internal();
}
+#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
alloc::alloc(Layout::from_size_align_unchecked(size, align))
}
+#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
#[cfg(test)]
mod tests {
-
use super::*;
use core::array::FixedSizeArray;
- use crate::mem::MaybeUninit;
- use crate::{mem, ptr};
+ use crate::mem::{self, MaybeUninit};
- // The below test verifies that the bytes of initialized RWLock are the ones
- // we use in libunwind.
- // If they change we need to update src/UnwindRustSgx.h in libunwind.
+ // Verify that the bytes of initialized RWLock are the same as in
+ // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to
+ // be changed too.
#[test]
fn test_c_rwlock_initializer() {
const RWLOCK_INIT: &[u8] = &[
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
- let mut init = MaybeUninit::<RWLock>::zeroed();
- init.set(RWLock::new());
- assert_eq!(
- mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(),
- RWLOCK_INIT
- );
+ #[inline(never)]
+ fn zero_stack() {
+ test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed());
+ }
+
+ #[inline(never)]
+ unsafe fn rwlock_new(init: &mut MaybeUninit<RWLock>) {
+ init.set(RWLock::new());
+ }
+
+ unsafe {
+ // try hard to make sure that the padding/unused bytes in RWLock
+ // get initialized as 0. If the assertion below fails, that might
+ // just be an issue with the test code and not with the value of
+ // RWLOCK_INIT.
+ zero_stack();
+ let mut init = MaybeUninit::<RWLock>::zeroed();
+ rwlock_new(&mut init);
+ assert_eq!(
+ mem::transmute::<_, [u8; 128]>(init.into_initialized()).as_slice(),
+ RWLOCK_INIT
+ )
+ };
}
}
}
}
+#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init() {
}
+#![cfg_attr(test, allow(dead_code))] // why is this necessary?
use crate::boxed::FnBox;
use crate::ffi::CStr;
use crate::io;
}
}
+ #[cfg_attr(test, linkage = "available_externally")]
+ #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
static TASK_QUEUE_INIT: Once = Once::new();
+ #[cfg_attr(test, linkage = "available_externally")]
+ #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
Instant(usercalls::insecure_time())
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
- self.0 - other.0
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+ self.0.checked_sub(other.0)
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
use super::*;
use crate::sync::Arc;
use crate::thread;
+ use crate::time::{SystemTime, Duration};
#[test]
fn sleep() {
let t1 = thread::spawn(move || {
*mutex2.lock() = 1;
});
- thread::sleep_ms(50);
+
+ // "sleep" for 50ms
+ // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+ let start = SystemTime::now();
+ let max = Duration::from_millis(50);
+ while start.elapsed().unwrap() < max {}
+
assert_eq!(*guard, 0);
drop(guard);
t1.join().unwrap();
let locked = wq.lock();
let t1 = thread::spawn(move || {
- assert!(WaitQueue::notify_one(wq2.lock()).is_none())
+ // if we obtain the lock, the main thread should be waiting
+ assert!(WaitQueue::notify_one(wq2.lock()).is_ok());
});
WaitQueue::wait(locked);
true
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+ let diff = self.t.checked_sub(other.t)?;
let info = info();
- let diff = self.t.checked_sub(other.t)
- .expect("second instant is later than self");
let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
- Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
+ Some(Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32))
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
false // last clause, used so `||` is always trailing above
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
- self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
- panic!("specified instant was later than self")
- })
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+ self.t.sub_timespec(&other.t).ok()
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
false
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
- self.0 - other.0
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+ self.0.checked_sub(other.0)
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Instant { t: Duration::from_secs(0) }
}
- pub fn sub_instant(&self, other: &Instant) -> Duration {
+ pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
// On windows there's a threshold below which we consider two timestamps
// equivalent due to measurement error. For more details + doc link,
// check the docs on epsilon.
let epsilon =
perf_counter::PerformanceCounterInstant::epsilon();
if other.t > self.t && other.t - self.t <= epsilon {
- return Duration::new(0, 0)
+ Some(Duration::new(0, 0))
+ } else {
+ self.t.checked_sub(other.t)
}
- self.t.checked_sub(other.t)
- .expect("specified instant was later than self")
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
thread::spawn(|| {
assert!(FOO.try_with(|_| ()).is_ok());
- }).join().ok().unwrap();
+ }).join().ok().expect("thread panicked");
}
#[test]
thread::spawn(move|| {
drop(S1);
- }).join().ok().unwrap();
+ }).join().ok().expect("thread panicked");
}
#[test]
thread::spawn(move|| unsafe {
K1.with(|s| *s.get() = Some(S1));
- }).join().ok().unwrap();
+ }).join().ok().expect("thread panicked");
}
// Note that this test will deadlock if TLS destructors aren't run (this
fn test_unnamed_thread() {
thread::spawn(move|| {
assert!(thread::current().name().is_none());
- }).join().ok().unwrap();
+ }).join().ok().expect("thread panicked");
}
#[test]
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn test_park_timeout_unpark_not_called() {
for _ in 0..10 {
thread::park_timeout(Duration::from_millis(10));
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn test_park_timeout_unpark_called_other_thread() {
for _ in 0..10 {
let th = thread::current();
}
#[test]
+ #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn sleep_ms_smoke() {
thread::sleep(Duration::from_millis(2));
}
/// ```
#[stable(feature = "time2", since = "1.8.0")]
pub fn duration_since(&self, earlier: Instant) -> Duration {
- self.0.sub_instant(&earlier.0)
+ self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self")
}
/// Returns the amount of time elapsed from another instant to this one,
/// ```
#[unstable(feature = "checked_duration_since", issue = "58402")]
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
- if self >= &earlier {
- Some(self.0.sub_instant(&earlier.0))
- } else {
- None
- }
+ self.0.checked_sub_instant(&earlier.0)
}
/// Returns the amount of time elapsed from another instant to this one,
#[test]
#[should_panic]
- fn instant_duration_panic() {
+ fn instant_duration_since_panic() {
let a = Instant::now();
(a - Duration::new(1, 0)).duration_since(a);
}
#[test]
- fn checked_instant_duration_nopanic() {
- let a = Instant::now();
- let ret = (a - Duration::new(1, 0)).checked_duration_since(a);
- assert_eq!(ret, None);
+ fn instant_checked_duration_since_nopanic() {
+ let now = Instant::now();
+ let earlier = now - Duration::new(1, 0);
+ let later = now + Duration::new(1, 0);
+ assert_eq!(earlier.checked_duration_since(now), None);
+ assert_eq!(later.checked_duration_since(now), Some(Duration::new(1, 0)));
+ assert_eq!(now.checked_duration_since(now), Some(Duration::new(0, 0)));
}
#[test]
- fn saturating_instant_duration_nopanic() {
+ fn instant_saturating_duration_since_nopanic() {
let a = Instant::now();
let ret = (a - Duration::new(1, 0)).saturating_duration_since(a);
assert_eq!(ret, Duration::new(0,0));
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Variant_ {
+ /// Name of the variant.
pub ident: Ident,
+ /// Attributes of the variant.
pub attrs: Vec<Attribute>,
+ /// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
+ pub id: NodeId,
+ /// Fields and constructor id of the variant.
pub data: VariantData,
/// Explicit discriminant, e.g., `Foo = 1`.
pub disr_expr: Option<AnonConst>,
pub attrs: Vec<Attribute>,
}
-/// Fields and Ids of enum variants and structs
-///
-/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all
-/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants).
-/// One shared Id can be successfully used for these two purposes.
-/// Id of the whole enum lives in `Item`.
-///
-/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
-/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of
-/// the variant itself" from enum variants.
-/// Id of the whole struct lives in `Item`.
+/// Fields and constructor ids of enum variants and structs.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum VariantData {
/// Struct variant.
///
/// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
- Struct(Vec<StructField>, NodeId, bool),
+ Struct(Vec<StructField>, bool),
/// Tuple variant.
///
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
}
impl VariantData {
+ /// Return the fields of this variant.
pub fn fields(&self) -> &[StructField] {
match *self {
VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields,
_ => &[],
}
}
- pub fn id(&self) -> NodeId {
+
+ /// Return the `NodeId` of this variant's constructor, if it has one.
+ pub fn ctor_id(&self) -> Option<NodeId> {
match *self {
- VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
- }
- }
- pub fn is_struct(&self) -> bool {
- if let VariantData::Struct(..) = *self {
- true
- } else {
- false
- }
- }
- pub fn is_tuple(&self) -> bool {
- if let VariantData::Tuple(..) = *self {
- true
- } else {
- false
- }
- }
- pub fn is_unit(&self) -> bool {
- if let VariantData::Unit(..) = *self {
- true
- } else {
- false
+ VariantData::Struct(..) => None,
+ VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
}
}
}
)+
for meta in metas {
if let Some(mi) = meta.meta_item() {
- match mi.ident_str() {
+ match mi.name_or_empty().get() {
$(
- Some(stringify!($name))
+ stringify!($name)
=> if !get(mi, &mut $name) { continue 'outer },
)+
_ => {
}
}
- match meta.ident_str().expect("not a stability level") {
+ match meta.name_or_empty().get() {
"rustc_deprecated" => {
if rustc_depr.is_some() {
span_err!(diagnostic, item_sp, E0540,
let mut issue = None;
for meta in metas {
if let Some(mi) = meta.meta_item() {
- match mi.ident_str() {
- Some("feature") => if !get(mi, &mut feature) { continue 'outer },
- Some("reason") => if !get(mi, &mut reason) { continue 'outer },
- Some("issue") => if !get(mi, &mut issue) { continue 'outer },
+ match mi.name_or_empty().get() {
+ "feature" => if !get(mi, &mut feature) { continue 'outer },
+ "reason" => if !get(mi, &mut reason) { continue 'outer },
+ "issue" => if !get(mi, &mut issue) { continue 'outer },
_ => {
handle_errors(
sess,
for meta in metas {
match meta {
NestedMetaItem::MetaItem(mi) => {
- match mi.ident_str() {
- Some("feature") =>
+ match mi.name_or_empty().get() {
+ "feature" =>
if !get(mi, &mut feature) { continue 'outer },
- Some("since") =>
+ "since" =>
if !get(mi, &mut since) { continue 'outer },
_ => {
handle_errors(
// The unwraps below may look dangerous, but we've already asserted
// that they won't fail with the loop above.
- match cfg.ident_str() {
- Some("any") => mis.iter().any(|mi| {
+ match cfg.name_or_empty().get() {
+ "any" => mis.iter().any(|mi| {
eval_condition(mi.meta_item().unwrap(), sess, eval)
}),
- Some("all") => mis.iter().all(|mi| {
+ "all" => mis.iter().all(|mi| {
eval_condition(mi.meta_item().unwrap(), sess, eval)
}),
- Some("not") => {
+ "not" => {
if mis.len() != 1 {
span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
return false;
for meta in list {
match meta {
NestedMetaItem::MetaItem(mi) => {
- match mi.ident_str() {
- Some("since") => if !get(mi, &mut since) { continue 'outer },
- Some("note") => if !get(mi, &mut note) { continue 'outer },
+ match mi.name_or_empty().get() {
+ "since" => if !get(mi, &mut since) { continue 'outer },
+ "note" => if !get(mi, &mut note) { continue 'outer },
_ => {
handle_errors(
sess,
let mut recognised = false;
if item.is_word() {
- let hint = match item.ident_str() {
- Some("C") => Some(ReprC),
- Some("packed") => Some(ReprPacked(1)),
- Some("simd") => Some(ReprSimd),
- Some("transparent") => Some(ReprTransparent),
- name => name.and_then(|name| int_type_of_word(name)).map(ReprInt),
+ let hint = match item.name_or_empty().get() {
+ "C" => Some(ReprC),
+ "packed" => Some(ReprPacked(1)),
+ "simd" => Some(ReprSimd),
+ "transparent" => Some(ReprTransparent),
+ name => int_type_of_word(name).map(ReprInt),
};
if let Some(h) = hint {
use crate::parse::{self, ParseSess, PResult};
use crate::parse::token::{self, Token};
use crate::ptr::P;
-use crate::symbol::Symbol;
+use crate::symbol::{keywords, LocalInternedString, Symbol};
use crate::ThinVec;
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
use crate::GLOBALS;
pub fn ident(&self) -> Option<Ident> {
self.meta_item().and_then(|meta_item| meta_item.ident())
}
- pub fn ident_str(&self) -> Option<&str> {
- self.ident().map(|name| name.as_str().get())
+ pub fn name_or_empty(&self) -> LocalInternedString {
+ self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
}
/// Gets the string value if self is a MetaItem and the MetaItem is a
None
}
}
- pub fn ident_str(&self) -> Option<&str> {
- self.ident().map(|name| name.as_str().get())
+ pub fn name_or_empty(&self) -> LocalInternedString {
+ self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
}
pub fn value_str(&self) -> Option<Symbol> {
None
}
}
- pub fn ident_str(&self) -> Option<&str> {
- self.ident().map(|name| name.as_str().get())
+ pub fn name_or_empty(&self) -> LocalInternedString {
+ self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
}
// #[attribute(name = "value")]
fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
match vdata {
- ast::VariantData::Struct(fields, _id, _) |
- ast::VariantData::Tuple(fields, _id) =>
+ ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) =>
fields.flat_map_in_place(|field| self.configure(field)),
- ast::VariantData::Unit(_id) => {}
+ ast::VariantData::Unit(_) => {}
}
}
respan(span,
ast::Variant_ {
ident,
+ id: ast::DUMMY_NODE_ID,
attrs: Vec::new(),
data: vdata,
disr_expr: None,
impl<'a> Context<'a> {
fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
debug!("check_attribute(attr = {:?})", attr);
- let name = attr.ident_str();
+ let name = attr.name_or_empty();
for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES {
- if name == Some(n) {
+ if name == n {
if let Gated(_, name, desc, ref has_feature) = *gateage {
if !attr.span.allows_unstable(name) {
gate_feature_fn!(
}
}
if !attr::is_known(attr) {
- if name.map_or(false, |name| name.starts_with("rustc_")) {
+ if name.starts_with("rustc_") {
let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
are reserved for internal compiler diagnostics";
gate_feature!(self, rustc_attrs, attr.span, msg);
gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
}
ast::ExprKind::Type(..) => {
- gate_feature_post!(&self, type_ascription, e.span,
- "type ascription is experimental");
+ // To avoid noise about type ascription in common syntax errors, only emit if it
+ // is the *only* error.
+ if self.context.parse_sess.span_diagnostic.err_count() == 0 {
+ gate_feature_post!(&self, type_ascription, e.span,
+ "type ascription is experimental");
+ }
}
ast::ExprKind::ObsoleteInPlace(..) => {
// these get a hard error in ast-validation
};
for mi in list {
- let name = match mi.ident_str() {
- Some(name) if mi.is_word() => name,
- _ => continue,
- };
+ if !mi.is_word() {
+ continue;
+ }
- if incomplete_features.iter().any(|f| *f == name) {
+ let name = mi.name_or_empty();
+ if incomplete_features.iter().any(|f| name == *f) {
span_handler.struct_span_warn(
mi.span(),
&format!(
}
pub fn noop_visit_variant<T: MutVisitor>(variant: &mut Variant, vis: &mut T) {
- let Spanned { node: Variant_ { ident, attrs, data, disr_expr }, span } = variant;
+ let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant;
vis.visit_ident(ident);
visit_attrs(attrs, vis);
+ vis.visit_id(id);
vis.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr));
vis.visit_span(span);
pub fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T) {
match vdata {
- VariantData::Struct(fields, id, _) |
+ VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)),
VariantData::Tuple(fields, id) => {
visit_vec(fields, |field| vis.visit_struct_field(field));
vis.visit_id(id);
- }
+ },
VariantData::Unit(id) => vis.visit_id(id),
}
}
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
continue
} else if op == AssocOp::Colon {
+ let maybe_path = self.could_ascription_be_path(&lhs.node);
+ let next_sp = self.span;
+
lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) {
Ok(lhs) => lhs,
Err(mut err) => {
- err.span_label(self.span,
- "expecting a type here because of type ascription");
- let cm = self.sess.source_map();
- let cur_pos = cm.lookup_char_pos(self.span.lo());
- let op_pos = cm.lookup_char_pos(cur_op_span.hi());
- if cur_pos.line != op_pos.line {
- err.span_suggestion(
- cur_op_span,
- "try using a semicolon",
- ";".to_string(),
- Applicability::MaybeIncorrect // speculative
- );
- }
+ self.bad_type_ascription(
+ &mut err,
+ lhs_span,
+ cur_op_span,
+ next_sp,
+ maybe_path,
+ );
return Err(err);
}
};
Ok(lhs)
}
+ fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
+ self.token.is_ident() &&
+ if let ast::ExprKind::Path(..) = node { true } else { false } &&
+ !self.token.is_reserved_ident() && // v `foo:bar(baz)`
+ self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
+ self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar<baz`
+ self.look_ahead(2, |t| t.is_ident()) ||
+ self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz`
+ self.look_ahead(2, |t| t.is_ident()) ||
+ self.look_ahead(1, |t| t == &token::ModSep) && // `foo:bar::baz`
+ self.look_ahead(2, |t| t.is_ident())
+ }
+
+ fn bad_type_ascription(
+ &self,
+ err: &mut DiagnosticBuilder<'a>,
+ lhs_span: Span,
+ cur_op_span: Span,
+ next_sp: Span,
+ maybe_path: bool,
+ ) {
+ err.span_label(self.span, "expecting a type here because of type ascription");
+ let cm = self.sess.source_map();
+ let next_pos = cm.lookup_char_pos(next_sp.lo());
+ let op_pos = cm.lookup_char_pos(cur_op_span.hi());
+ if op_pos.line != next_pos.line {
+ err.span_suggestion(
+ cur_op_span,
+ "try using a semicolon",
+ ";".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ if maybe_path {
+ err.span_suggestion(
+ cur_op_span,
+ "maybe you meant to write a path separator here",
+ "::".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.note("type ascription is a nightly-only feature that lets \
+ you annotate an expression with a type: `<expr>: <type>`");
+ err.span_note(
+ lhs_span,
+ "this expression expects an ascribed type after the colon",
+ );
+ err.help("this might be indicative of a syntax error elsewhere");
+ }
+ }
+ }
+
fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span,
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind)
-> PResult<'a, P<Expr>> {
} else {
// If we see: `struct Foo<T> where T: Copy { ... }`
let (fields, recovered) = self.parse_record_struct_body()?;
- VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+ VariantData::Struct(fields, recovered)
}
// No `where` so: `struct Foo<T>;`
} else if self.eat(&token::Semi) {
// Record-style struct definition
} else if self.token == token::OpenDelim(token::Brace) {
let (fields, recovered) = self.parse_record_struct_body()?;
- VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+ VariantData::Struct(fields, recovered)
// Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(token::Paren) {
let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
let vdata = if self.token.is_keyword(keywords::Where) {
generics.where_clause = self.parse_where_clause()?;
let (fields, recovered) = self.parse_record_struct_body()?;
- VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+ VariantData::Struct(fields, recovered)
} else if self.token == token::OpenDelim(token::Brace) {
let (fields, recovered) = self.parse_record_struct_body()?;
- VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+ VariantData::Struct(fields, recovered)
} else {
let token_str = self.this_token_descr();
let mut err = self.fatal(&format!(
// Parse a struct variant.
all_nullary = false;
let (fields, recovered) = self.parse_record_struct_body()?;
- struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered);
+ struct_def = VariantData::Struct(fields, recovered);
} else if self.check(&token::OpenDelim(token::Paren)) {
all_nullary = false;
struct_def = VariantData::Tuple(
let vr = ast::Variant_ {
ident,
+ id: ast::DUMMY_NODE_ID,
attrs: variant_attrs,
data: struct_def,
disr_expr,
print_finalizer: bool) -> io::Result<()> {
self.print_ident(ident)?;
self.print_generic_params(&generics.params)?;
- if !struct_def.is_struct() {
- if struct_def.is_tuple() {
- self.popen()?;
- self.commasep(
- Inconsistent, struct_def.fields(),
- |s, field| {
- s.maybe_print_comment(field.span.lo())?;
- s.print_outer_attributes(&field.attrs)?;
- s.print_visibility(&field.vis)?;
- s.print_type(&field.ty)
- }
- )?;
- self.pclose()?;
- }
- self.print_where_clause(&generics.where_clause)?;
- if print_finalizer {
- self.s.word(";")?;
+ match struct_def {
+ ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+ if let ast::VariantData::Tuple(..) = struct_def {
+ self.popen()?;
+ self.commasep(
+ Inconsistent, struct_def.fields(),
+ |s, field| {
+ s.maybe_print_comment(field.span.lo())?;
+ s.print_outer_attributes(&field.attrs)?;
+ s.print_visibility(&field.vis)?;
+ s.print_type(&field.ty)
+ }
+ )?;
+ self.pclose()?;
+ }
+ self.print_where_clause(&generics.where_clause)?;
+ if print_finalizer {
+ self.s.word(";")?;
+ }
+ self.end()?;
+ self.end() // close the outer-box
}
- self.end()?;
- self.end() // close the outer-box
- } else {
- self.print_where_clause(&generics.where_clause)?;
- self.nbsp()?;
- self.bopen()?;
- self.hardbreak_if_not_bol()?;
-
- for field in struct_def.fields() {
+ ast::VariantData::Struct(..) => {
+ self.print_where_clause(&generics.where_clause)?;
+ self.nbsp()?;
+ self.bopen()?;
self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(field.span.lo())?;
- self.print_outer_attributes(&field.attrs)?;
- self.print_visibility(&field.vis)?;
- self.print_ident(field.ident.unwrap())?;
- self.word_nbsp(":")?;
- self.print_type(&field.ty)?;
- self.s.word(",")?;
- }
- self.bclose(span)
+ for field in struct_def.fields() {
+ self.hardbreak_if_not_bol()?;
+ self.maybe_print_comment(field.span.lo())?;
+ self.print_outer_attributes(&field.attrs)?;
+ self.print_visibility(&field.vis)?;
+ self.print_ident(field.ident.unwrap())?;
+ self.word_nbsp(":")?;
+ self.print_type(&field.ty)?;
+ self.s.word(",")?;
+ }
+
+ self.bclose(span)
+ }
}
}
let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
ident,
attrs: Vec::new(),
+ id: ast::DUMMY_NODE_ID,
// making this up as I go.... ?
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
disr_expr: None,
// build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
// or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
// based on the "shape".
- let (ident, is_struct) = match *substr.fields {
- Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
- EnumMatching(_, _, v, _) => (v.node.ident, v.node.data.is_struct()),
+ let (ident, vdata, fields) = match substr.fields {
+ Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
+ EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields),
EnumNonMatchingCollapsed(..) |
StaticStruct(..) |
StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
let fmt = substr.nonself_args[0].clone();
- let mut stmts = match *substr.fields {
- Struct(_, ref fields) |
- EnumMatching(.., ref fields) => {
- let mut stmts = vec![];
- if !is_struct {
- // tuple struct/"normal" variant
- let expr =
- cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
- stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
-
- for field in fields {
- // Use double indirection to make sure this works for unsized types
- let field = cx.expr_addr_of(field.span, field.self_.clone());
- let field = cx.expr_addr_of(field.span, field);
-
- let expr = cx.expr_method_call(span,
- builder_expr.clone(),
- Ident::from_str("field"),
- vec![field]);
-
- // Use `let _ = expr;` to avoid triggering the
- // unused_results lint.
- stmts.push(stmt_let_undescore(cx, span, expr));
- }
- } else {
- // normal struct/struct variant
- let expr =
- cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
- stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
-
- for field in fields {
- let name = cx.expr_lit(field.span,
- ast::LitKind::Str(field.name.unwrap().name,
- ast::StrStyle::Cooked));
-
- // Use double indirection to make sure this works for unsized types
- let field = cx.expr_addr_of(field.span, field.self_.clone());
- let field = cx.expr_addr_of(field.span, field);
- let expr = cx.expr_method_call(span,
- builder_expr.clone(),
- Ident::from_str("field"),
- vec![name, field]);
- stmts.push(stmt_let_undescore(cx, span, expr));
- }
+ let mut stmts = vec![];
+ match vdata {
+ ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+ // tuple struct/"normal" variant
+ let expr =
+ cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
+ stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
+
+ for field in fields {
+ // Use double indirection to make sure this works for unsized types
+ let field = cx.expr_addr_of(field.span, field.self_.clone());
+ let field = cx.expr_addr_of(field.span, field);
+
+ let expr = cx.expr_method_call(span,
+ builder_expr.clone(),
+ Ident::from_str("field"),
+ vec![field]);
+
+ // Use `let _ = expr;` to avoid triggering the
+ // unused_results lint.
+ stmts.push(stmt_let_undescore(cx, span, expr));
}
- stmts
}
- _ => unreachable!(),
- };
+ ast::VariantData::Struct(..) => {
+ // normal struct/struct variant
+ let expr =
+ cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
+ stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
+
+ for field in fields {
+ let name = cx.expr_lit(field.span,
+ ast::LitKind::Str(field.name.unwrap().name,
+ ast::StrStyle::Cooked));
+
+ // Use double indirection to make sure this works for unsized types
+ let field = cx.expr_addr_of(field.span, field.self_.clone());
+ let field = cx.expr_addr_of(field.span, field);
+ let expr = cx.expr_method_call(span,
+ builder_expr.clone(),
+ Ident::from_str("field"),
+ vec![name, field]);
+ stmts.push(stmt_let_undescore(cx, span, expr));
+ }
+ }
+ }
let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);
let mut attrs = newitem.attrs.clone();
attrs.extend(item.attrs
.iter()
- .filter(|a| a.ident_str().map_or(false, |name| {
- ["allow", "warn", "deny", "forbid", "stable", "unstable"].contains(&name)
- }))
+ .filter(|a| {
+ ["allow", "warn", "deny", "forbid", "stable", "unstable"]
+ .contains(&a.name_or_empty().get())
+ })
.cloned());
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
}
}
}
+ let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false };
match (just_spans.is_empty(), named_idents.is_empty()) {
(false, false) => {
cx.span_bug(self.span,
}
// named fields
(_, false) => Named(named_idents),
- // empty structs
- _ if struct_def.is_struct() => Named(named_idents),
- _ => Unnamed(just_spans, struct_def.is_tuple()),
+ // unnamed fields
+ (false, _) => Unnamed(just_spans, is_tuple),
+ // empty
+ _ => Named(Vec::new()),
}
}
#![feature(rustc_attrs)]
#![feature(specialization)]
#![feature(step_trait)]
-#![cfg_attr(not(stage0), feature(stdsimd))]
use serialize::{Encodable, Decodable, Encoder, Decoder};
with_interner(|interner| interner.gensymed(self))
}
+ pub fn is_gensymed(self) -> bool {
+ with_interner(|interner| interner.is_gensymed(self))
+ }
+
pub fn as_str(self) -> LocalInternedString {
with_interner(|interner| unsafe {
LocalInternedString {
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.
-date: 2019-02-27
+date: 2019-03-20
rustc: beta
cargo: beta
// ignore-tidy-linelength
// ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
// compile-flags: -g -C no-prepopulate-passes
// ignore-tidy-linelength
// ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
// compile-flags: -g -C no-prepopulate-passes
// ignore-tidy-linelength
// ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
// compile-flags: -g -C no-prepopulate-passes
// ignore-tidy-linelength
// ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
// compile-flags: -g -C no-prepopulate-passes
--- /dev/null
+// compile-flags: -Z chalk
+
+#![feature(trivial_bounds)]
+
+trait Bar {
+ fn foo();
+}
+trait Foo: Bar { }
+
+struct S where S: Foo;
+
+impl Foo for S {
+}
+
+fn bar<T: Bar>() {
+ T::foo();
+}
+
+fn foo<T: Foo>() {
+ bar::<T>()
+}
+
+fn main() {
+ // For some reason, the error is duplicated...
+
+ foo::<S>() //~ ERROR the type `S` is not well-formed (chalk)
+ //~^ ERROR the type `S` is not well-formed (chalk)
+}
// ignore-tidy-linelength
// Require LLVM with DW_TAG_variant_part and a gdb or lldb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// rust-lldb
// min-lldb-version: 310
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// compile-flags:-g
// min-lldb-version: 310
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// compile-flags:-g
// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
// read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// rust-lldb
// ignore-lldb
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// compile-flags:-g
// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
// read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// rust-lldb
// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
// read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// rust-lldb
// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
// read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
// min-gdb-version: 8.2
// rust-lldb
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_callee_function() {
callee2(1, 2)
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_argument_function() {
callee1(1, 3)
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_callee_method() {
let s = Struct;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_argument_method() {
let s = Struct;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_ufcs_callee_method() {
let s = Struct;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_argument_method_ufcs() {
let s = Struct;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
// One might think this would be expanded in the HirBody/Mir, but it actually
// results in slightly different Hir/Mir.
#[cfg(not(cfail1))]
use super::Struct2 as Struct;
- #[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_parameter() {
let x = 0u32;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_parameter_pattern() {
let _ = |&x: &u32| x;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_type_ascription_to_parameter() {
let closure = |x: u32| x + 1u32;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_parameter_type() {
let closure = |x: u16| (x as u64) + 1;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_field_value_struct_like() -> Enum {
Enum::Struct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_path_struct_like() {
let _ = Enum2::Struct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_variant_struct_like() {
let _ = Enum2::Struct2 {
#[rustc_clean(
cfg="cfail2",
- except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,\
+ except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
#[cfg(not(cfail1))]
use super::Enum2::Struct2 as Variant;
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn function() -> Enum2 {
Variant {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_field_value_tuple_like() -> Enum {
Enum::Tuple(0, 1, 3)
#[cfg(not(cfail1))]
#[rustc_clean(
cfg="cfail2",
- except="HirBody,MirOptimized,MirBuilt,TypeckTables"
+ except="HirBody,optimized_mir,mir_built,TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_path_tuple_like() {
#[cfg(not(cfail1))]
#[rustc_clean(
cfg="cfail2",
- except="HirBody,MirOptimized,MirBuilt,TypeckTables"
+ except="HirBody,optimized_mir,mir_built,TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_variant_tuple_like() {
#[rustc_clean(
cfg="cfail2",
- except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,\
+ except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
#[cfg(not(cfail1))]
use super::Enum2::Tuple2 as Variant;
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn function() -> Enum2 {
Variant(0, 1, 2)
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_path_c_like() {
let _ = Clike2::B;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_variant_c_like() {
let _ = Clike::C;
#[rustc_clean(
cfg="cfail2",
- except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,\
+ except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
#[cfg(not(cfail1))]
use super::Clike::B as Variant;
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn function() -> Clike {
Variant
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn body_not_exported_to_metadata() -> u32 {
2
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[inline]
pub fn body_exported_to_metadata_because_of_inline() -> u32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[inline]
pub fn body_exported_to_metadata_because_of_generic() -> u32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_iteration_variable_name() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_iteration_variable_pattern() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_iterable() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_break() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_break_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_to_break() {
let mut _x = 0;
#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn add_parameter(p: i32) {}
#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn type_of_parameter(p: i64) {}
#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn type_of_parameter_ref(p: &mut i32) {}
#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn order_of_parameters(p2: i64, p1: i32) {}
#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub unsafe fn make_unsafe() {}
pub fn make_extern() {}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, MirBuilt, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, mir_built, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub extern "C" fn make_extern() {}
use super::ReferencedType2 as ReturnType;
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn indirect_return_type() -> ReturnType {
ReturnType {}
use super::ReferencedType2 as ParameterType;
#[rustc_clean(cfg = "cfail2",
- except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+ except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn indirect_parameter_type(p: ParameterType) {}
}
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_condition(x: bool) -> u32 {
if !x {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_then_branch(x: bool) -> u32 {
if x {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_else_branch(x: bool) -> u32 {
if x {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
if let Some(_) = x {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
if let Some(x) = x {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
if let Some(x) = x {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
impl Foo {
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn method_body() {
println!("Hello, world!");
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
impl Foo {
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[inline]
pub fn method_body_inlined() {
impl Foo {
#[rustc_clean(
cfg="cfail2",
- except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirBuilt"
+ except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
)]
#[rustc_clean(cfg="cfail3")]
pub fn method_selfmutness(&mut self) { }
impl Foo {
#[rustc_clean(
cfg="cfail2",
- except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirBuilt"
+ except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
)]
#[rustc_clean(cfg="cfail3")]
pub fn add_method_parameter(&self, _: i32) { }
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
impl Foo {
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_method_parameter_name(&self, b: i64) { }
}
impl Foo {
#[rustc_clean(
cfg="cfail2",
- except="Hir,HirBody,FnSignature,MirOptimized,MirBuilt,TypeckTables")]
+ except="Hir,HirBody,FnSignature,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_method_return_type(&self) -> u8 { 0 }
}
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
impl Foo {
- #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+ #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
}
impl Foo {
#[rustc_clean(
cfg="cfail2",
- except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirBuilt"
+ except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
)]
#[rustc_clean(cfg="cfail3")]
pub unsafe fn make_method_unsafe(&self) { }
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
impl Foo {
- #[rustc_clean(cfg="cfail2", except="Hir,HirBody,MirBuilt,FnSignature,TypeckTables")]
+ #[rustc_clean(cfg="cfail2", except="Hir,HirBody,mir_built,FnSignature,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub extern fn make_method_extern(&self) { }
}
impl<T> Bar<T> {
#[rustc_clean(
cfg="cfail2",
- except="generics_of,FnSignature,TypeckTables,type_of,MirOptimized,MirBuilt"
+ except="generics_of,FnSignature,TypeckTables,type_of,optimized_mir,mir_built"
)]
#[rustc_clean(cfg="cfail3")]
pub fn add_type_parameter_to_impl(&self) { }
#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
#[rustc_clean(cfg="cfail3")]
impl Bar<u64> {
- #[rustc_clean(cfg="cfail2", except="FnSignature,MirOptimized,MirBuilt,TypeckTables")]
+ #[rustc_clean(cfg="cfail2", except="FnSignature,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_impl_self_type(&self) { }
}
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_template(a: i32) -> i32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_output(a: i32) -> i32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input(_a: i32, _b: i32) -> i32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_clobber(_a: i32) -> i32 {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_options(_a: i32) -> i32 {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name() {
let _y = 2u64;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn add_type() {
let _x: u32 = 2u32;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_type() {
let _x: u8 = 2;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_reference_type() {
let _x: &mut u64;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_slot() {
let _x: u64 = 0;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_simple_binding_to_pattern() {
let (_a, _b) = (0u8, 'x');
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name_in_pattern() {
let (_a, _c) = (1u8, 'y');
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn add_ref_in_pattern() {
let (ref _a, _b) = (1u8, 'y');
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn add_amp_in_pattern() {
let (&_a, _b) = (&1u8, 'y');
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_binding_in_pattern() {
let (mut _a, _b) = (99u8, 'q');
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+ except="HirBody,TypeckTables,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn add_initializer() {
let _x: i16 = 3i16;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_initializer() {
let _x = 5u16;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_break() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_break_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_to_break() {
let mut _x = 0;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_arm(x: u32) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_order_of_arms(x: u32) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_guard_clause(x: u32, y: bool) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_guard_clause(x: u32, y: bool) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_at_binding(x: u32) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name_of_at_binding(x: u32) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_simple_name_to_pattern(x: u32) -> u32 {
match (x, x & 1) {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
-except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
match (&x, x & 1) {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_rhs_of_arm(x: u32) -> u32 {
match x {
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+ except="HirBody,mir_built,optimized_mir,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_alternative_to_arm(x: u32) -> u32 {
match x {
// Indexing expression ---------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn indexing(slice: &[u8]) -> u8 {
#[cfg(cfail1)]
// Arithmetic overflow plus ----------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn arithmetic_overflow_plus(val: i32) -> i32 {
#[cfg(cfail1)]
// Arithmetic overflow minus ----------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn arithmetic_overflow_minus(val: i32) -> i32 {
#[cfg(cfail1)]
// Arithmetic overflow mult ----------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn arithmetic_overflow_mult(val: i32) -> i32 {
#[cfg(cfail1)]
// Arithmetic overflow negation ------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn arithmetic_overflow_negation(val: i32) -> i32 {
#[cfg(cfail1)]
// Division by zero ------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn division_by_zero(val: i32) -> i32 {
#[cfg(cfail1)]
}
// Division by zero ------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn mod_by_zero(val: i32) -> i32 {
#[cfg(cfail1)]
// shift left ------------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn shift_left(val: i32, shift: usize) -> i32 {
#[cfg(cfail1)]
// shift right ------------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn shift_right(val: i32, shift: usize) -> i32 {
#[cfg(cfail1)]
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_field_value_regular_struct() -> RegularStruct {
RegularStruct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_field_regular_struct() -> RegularStruct {
let struct1 = RegularStruct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_field_label_regular_struct() -> RegularStruct {
let struct1 = RegularStruct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_path_regular_struct() {
let _ = RegularStruct2 {
#[rustc_clean(
cfg="cfail2",
- except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,TypeckTables"
+ except="FnSignature,Hir,HirBody,optimized_mir,mir_built,TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
pub fn function() -> Struct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_field_value_tuple_struct() -> TupleStruct {
TupleStruct(0, 1, 3)
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_constructor_path_tuple_struct() {
let _ = TupleStruct2(0, 1, 2);
#[rustc_clean(
cfg="cfail2",
- except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,TypeckTables"
+ except="FnSignature,Hir,HirBody,optimized_mir,mir_built,TypeckTables"
)]
#[rustc_clean(cfg="cfail3")]
pub fn function() -> Struct {
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn const_negation() -> i32 {
-1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn const_bitwise_not() -> i32 {
!99
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn var_negation(x: i32, y: i32) -> i32 {
-y
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
!y
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt,TypeckTables", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built,TypeckTables", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn var_deref(x: &i32, y: &i32) -> i32 {
*y
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn first_const_add() -> i32 {
2 + 3
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn second_const_add() -> i32 {
1 + 3
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn first_var_add(a: i32, b: i32) -> i32 {
b + 2
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn second_var_add(a: i32, b: i32) -> i32 {
1 + b
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn plus_to_minus(a: i32) -> i32 {
1 - a
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn plus_to_mult(a: i32) -> i32 {
1 * a
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn plus_to_div(a: i32) -> i32 {
1 / a
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn plus_to_mod(a: i32) -> i32 {
1 % a
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn and_to_or(a: bool, b: bool) -> bool {
a || b
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
1 | a
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
1 ^ a
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn bitwise_and_to_lshift(a: i32) -> i32 {
a << 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn bitwise_and_to_rshift(a: i32) -> i32 {
a >> 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn eq_to_uneq(a: i32) -> bool {
a != 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn eq_to_lt(a: i32) -> bool {
a < 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn eq_to_gt(a: i32) -> bool {
a > 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn eq_to_le(a: i32) -> bool {
a <= 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn eq_to_ge(a: i32) -> bool {
a >= 1
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt,TypeckTables", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built,TypeckTables", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn type_cast(a: u8) -> u64 {
let b = a as u32;
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn value_cast(a: u32) -> i32 {
2 as i32
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn place() -> i32 {
let mut x = 10;
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn rvalue() -> i32 {
let mut x = 10;
}
#[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
s[j]
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_condition() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_break() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_break_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_to_break() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_condition() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
#[rustc_clean(cfg="cfail3")]
pub fn add_break() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_break_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_label() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_continue_to_break() {
let mut _x = 0;
}
#[cfg(rpass2)]
-#[rustc_dirty(label="MirOptimized", cfg="rpass2")]
+#[rustc_dirty(label="optimized_mir", cfg="rpass2")]
pub fn main() {
let _ = 0u8 + 1;
}
#[cfg(cfail2)]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
- #[rustc_dirty(label="MirOptimized", cfg="cfail2")]
+ #[rustc_dirty(label="optimized_mir", cfg="cfail2")]
pub fn x() {
println!("{}", "2");
}
use x;
#[rustc_clean(label="TypeckTables", cfg="cfail2")]
- #[rustc_clean(label="MirOptimized", cfg="cfail2")]
+ #[rustc_clean(label="optimized_mir", cfg="cfail2")]
pub fn y() {
x::x();
}
use y;
#[rustc_clean(label="TypeckTables", cfg="cfail2")]
- #[rustc_clean(label="MirOptimized", cfg="cfail2")]
+ #[rustc_clean(label="optimized_mir", cfg="cfail2")]
pub fn z() {
y::y();
}
--- /dev/null
+// Test graphviz output
+// compile-flags: -Z dump-mir-graphviz
+
+// ignore-tidy-linelength
+
+fn main() {}
+
+// END RUST SOURCE
+// START rustc.main.mir_map.0.dot
+// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier.
+// graph [fontname="monospace"];
+// node [fontname="monospace"];
+// edge [fontname="monospace"];
+// label=<fn main() -> ()<br align="left"/>>;
+// bb0 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = ()<br/></td></tr><tr><td align="left">goto</td></tr></table>
+// >];
+// bb1 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>
+// >];
+// bb2 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left">return</td></tr></table>
+// >];
+// bb0 -> bb2 [label=""];
+// }
+// END rustc.main.mir_map.0.dot
// }
// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
-// START rustc.Test-X.mir_map.0.mir
+// START rustc.Test-X-{{constructor}}.mir_map.0.mir
// fn Test::X(_1: usize) -> Test {
// let mut _0: Test;
//
// return;
// }
// }
-// END rustc.Test-X.mir_map.0.mir
+// END rustc.Test-X-{{constructor}}.mir_map.0.mir
|
= note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
= note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
- = note: forall<'a, T> { WellFormed(S<'a, T>) :- Implemented(T: Foo), TypeOutlives(T: 'a). }
+ = note: forall<'a, T> { WellFormed(S<'a, T>) :- WellFormed(T: Foo), TypeOutlives(T: 'a). }
error: program clause dump
--> $DIR/lower_env2.rs:11:1
LL | #[rustc_dump_env_program_clauses]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
= note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
error: program clause dump
LL | #[rustc_dump_env_program_clauses]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
= note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
= note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
= note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
= note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
= note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
= note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). }
- = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
+ = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- WellFormed(T: std::marker::Sized), WellFormed(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
error: aborting due to previous error
= note: forall<Self, S, T, ^3> { ProjectionEq(<Self as Foo<S, T>>::Assoc == ^3) :- Normalize(<Self as Foo<S, T>>::Assoc -> ^3). }
= note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
= note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
- = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>). }
+ = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- WellFormed(Self: Foo<S, T>). }
error: aborting due to 2 previous errors
--- /dev/null
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
+
+fn main() {}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/struct-with-invalid-const-param.rs:1:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
+error[E0573]: expected type, found const parameter `C`
+ --> $DIR/struct-with-invalid-const-param.rs:4:23
+ |
+LL | struct S<const C: u8>(C);
+ | ^ help: a struct with a similar name exists: `S`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
--> $DIR/atomic_initializers.rs:8:27
|
LL | static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^ help: replace the use of the deprecated item: `AtomicIsize::new(0)`
|
= note: #[warn(deprecated)] on by default
-help: use of deprecated item 'std::sync::atomic::ATOMIC_ISIZE_INIT': the `new` function is now preferred
- |
-LL | static FOO: AtomicIsize = AtomicIsize::new(0);
- | ^^^^^^^^^^^^^^^^^^^
--- /dev/null
+// run-rustfix
+
+#![feature(staged_api)]
+
+#![stable(since = "1.0.0", feature = "test")]
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+ #[rustc_deprecated(
+ since = "1.0.0",
+ reason = "replaced by `replacement`",
+ suggestion = "replacement",
+ )]
+ #[stable(since = "1.0.0", feature = "test")]
+ fn deprecated(&self) {}
+
+ fn replacement(&self) {}
+}
+
+fn main() {
+ let foo = Foo;
+
+ foo.replacement(); //~ ERROR use of deprecated
+}
--- /dev/null
+// run-rustfix
+
+#![feature(staged_api)]
+
+#![stable(since = "1.0.0", feature = "test")]
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+ #[rustc_deprecated(
+ since = "1.0.0",
+ reason = "replaced by `replacement`",
+ suggestion = "replacement",
+ )]
+ #[stable(since = "1.0.0", feature = "test")]
+ fn deprecated(&self) {}
+
+ fn replacement(&self) {}
+}
+
+fn main() {
+ let foo = Foo;
+
+ foo.deprecated(); //~ ERROR use of deprecated
+}
--- /dev/null
+error: use of deprecated item 'Foo::deprecated': replaced by `replacement`
+ --> $DIR/suggestion.rs:27:9
+ |
+LL | foo.deprecated();
+ | ^^^^^^^^^^ help: replace the use of the deprecated item: `replacement`
+ |
+note: lint level defined here
+ --> $DIR/suggestion.rs:7:9
+ |
+LL | #![deny(deprecated)]
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/E0423.rs:12:36
+ |
+LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected expression, found `==`
--> $DIR/E0423.rs:15:13
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/E0423.rs:21:32
+ |
+LL | for _ in std::ops::Range { start: 0, end: 10 } {}
+ | ^^^^^
+ = help: this might be indicative of a syntax error elsewhere
error[E0423]: expected function, found struct `Foo`
--> $DIR/E0423.rs:4:13
--- /dev/null
+// edition:2018
+
+mod std {}
--- /dev/null
+// compile-pass
+// edition:2018
+// aux-build:gensymed.rs
+
+extern crate gensymed;
+
+fn main() {}
--> $DIR/issue-17800.rs:8:28
|
LL | MyOption::MySome { x: 42 } => (),
- | ^^^^^
+ | ^
| |
| variant `MyOption::MySome` does not have this field
- | help: did you mean: `0`
+ | help: a field with a similar name exists: `0`
error: aborting due to previous error
|
LL | println!("{}", a: &mut 4);
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/issue-22644.rs:34:20
+ |
+LL | println!("{}", a: &mut 4);
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: aborting due to 9 previous errors
--- /dev/null
+#![feature(asm)]
+
+// only-x86_64
+
+fn main() {
+ unsafe {
+ asm!("int $3"); //~ ERROR too few operands for instruction
+ //~| ERROR invalid operand in inline asm
+ }
+}
--- /dev/null
+error: invalid operand in inline asm: 'int $3'
+ --> $DIR/issue-23458.rs:7:9
+ |
+LL | asm!("int $3");
+ | ^^^^^^^^^^^^^^^
+
+error: <inline asm>:1:2: error: too few operands for instruction
+ int
+ ^
+
+ --> $DIR/issue-23458.rs:7:9
+ |
+LL | asm!("int $3");
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+enum Test {
+ Drill {
+ field: i32,
+ }
+}
+
+fn main() {
+ Test::Drill(field: 42);
+ //~^ ERROR expected type, found
+}
--- /dev/null
+error: expected type, found `42`
+ --> $DIR/issue-34255-1.rs:8:24
+ |
+LL | Test::Drill(field: 42);
+ | ^^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/issue-34255-1.rs:8:17
+ |
+LL | Test::Drill(field: 42);
+ | ^^^^^
+ = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to previous error
+
--> $DIR/issue-51102.rs:13:17
|
LL | state: 0,
- | ^^^^^^^^ struct `SimpleStruct` does not have this field
+ | ^^^^^ struct `SimpleStruct` does not have this field
error[E0025]: field `no_state_here` bound multiple times in the pattern
--> $DIR/issue-51102.rs:24:17
--> $DIR/issue-51102.rs:33:17
|
LL | state: 0
- | ^^^^^^^^ variant `SimpleEnum::NoState` does not have this field
+ | ^^^^^ variant `SimpleEnum::NoState` does not have this field
error: aborting due to 3 previous errors
| ^^^
| |
| variant `A::A` does not have this field
- | help: did you mean: `foo`
+ | help: a field with a similar name exists: `foo`
error: aborting due to previous error
|
LL | loop { break 'label: loop { break 'label 42; }; }
| ^^^^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/lifetime_starts_expressions.rs:6:12
+ |
+LL | loop { break 'label: loop { break 'label 42; }; }
+ | ^^^^^^^^^^^^
+ = help: this might be indicative of a syntax error elsewhere
error: aborting due to 2 previous errors
--> $DIR/numeric-fields.rs:7:17
|
LL | S{0: a, 0x1: b, ..} => {}
- | ^^^^^^ struct `S` does not have this field
+ | ^^^ struct `S` does not have this field
error: aborting due to 2 previous errors
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/struct-literal-in-for.rs:13:9
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-in-for.rs:14:12
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/struct-literal-in-if.rs:13:9
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-in-if.rs:14:12
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/struct-literal-in-while.rs:13:9
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-in-while.rs:14:12
|
LL | x: 3
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/struct-literal-restrictions-in-lamda.rs:13:9
+ |
+LL | x: 3
+ | ^
+ = help: this might be indicative of a syntax error elsewhere
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/struct-literal-restrictions-in-lamda.rs:14:12
--> $DIR/resolve-error.rs:44:10
|
LL | #[derive(attr_proc_macra)]
- | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro`
+ | ^^^^^^^^^^^^^^^
error: cannot find macro `FooWithLongNama!` in this scope
--> $DIR/resolve-error.rs:49:5
LL | let _ = String.new();
| ^^^^^^----
| |
- | help: use `::` to access an associated function: `String::new`
+ | help: use the path separator to refer to an item: `String::new`
error: aborting due to previous error
--> $DIR/struct-field-cfg.rs:16:42
|
LL | let Foo { present: (), #[cfg(all())] absent: () } = foo;
- | ^^^^^^^^^^ struct `Foo` does not have this field
+ | ^^^^^^ struct `Foo` does not have this field
error: aborting due to 4 previous errors
--- /dev/null
+pub mod Mod {
+ pub struct Foo {}
+ impl Foo {
+ pub const BAR: usize = 42;
+ }
+}
+
+fn foo(_: usize) {}
+
+fn main() {
+ foo(Mod::Foo.Bar);
+ //~^ ERROR expected value, found
+}
--- /dev/null
+error[E0423]: expected value, found struct `Mod::Foo`
+ --> $DIR/assoc-const-as-field.rs:11:9
+ |
+LL | foo(Mod::Foo.Bar);
+ | ^^^^^^^^----
+ | |
+ | help: use the path separator to refer to an item: `Mod::Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
--- /dev/null
+//! Contains a struct with almost the same name as itself, to trigger Levenshtein suggestions.
+
+pub struct Foo;
--- /dev/null
+error[E0505]: cannot move out of `a` because it is borrowed
+ --> $DIR/borrow-for-loop-head.rs:4:18
+ |
+LL | for i in &a {
+ | --
+ | |
+ | borrow of `a` occurs here
+ | borrow later used here
+LL | for j in a {
+ | ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+ --> $DIR/borrow-for-loop-head.rs:4:18
+ |
+LL | let a = vec![1, 2, 3];
+ | - move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+LL | for i in &a {
+LL | for j in a {
+ | ^ value moved here, in previous iteration of loop
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
--- /dev/null
+fn main() {
+ let a = vec![1, 2, 3];
+ for i in &a {
+ for j in a {
+ //~^ ERROR cannot move out of `a` because it is borrowed
+ //~| ERROR use of moved value: `a`
+ println!("{} * {} = {}", i, j, i * j);
+ }
+ }
+}
--- /dev/null
+error[E0505]: cannot move out of `a` because it is borrowed
+ --> $DIR/borrow-for-loop-head.rs:4:18
+ |
+LL | for i in &a {
+ | - borrow of `a` occurs here
+LL | for j in a {
+ | ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+ --> $DIR/borrow-for-loop-head.rs:4:18
+ |
+LL | for j in a {
+ | ^ value moved here in previous iteration of loop
+ |
+ = note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+help: consider borrowing this to avoid moving it into the for loop
+ |
+LL | for j in &a {
+ | ^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
--- /dev/null
+// aux-build:foo.rs
+
+extern crate foo;
+
+type Output = Option<Foo>; //~ ERROR cannot find type `Foo`
+
+fn main() {}
--- /dev/null
+error[E0412]: cannot find type `Foo` in this scope
+ --> $DIR/no-extern-crate-in-type.rs:5:22
+ |
+LL | type Output = Option<Foo>;
+ | ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+ |
+LL | use foo::Foo;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
--- /dev/null
+fn fun(x: i32) -> i32 { x }
+
+fn main() {
+ let closure_annotated = |value: i32| -> i32 {
+ temp: i32 = fun(5i32);
+ //~^ ERROR cannot find value `temp` in this scope
+ temp + value + 1
+ //~^ ERROR cannot find value `temp` in this scope
+ };
+}
--- /dev/null
+error[E0425]: cannot find value `temp` in this scope
+ --> $DIR/type-ascription-instead-of-let.rs:5:9
+ |
+LL | temp: i32 = fun(5i32);
+ | ^^^^
+ | |
+ | not found in this scope
+ | help: maybe you meant to write an assignment here: `let temp`
+
+error[E0425]: cannot find value `temp` in this scope
+ --> $DIR/type-ascription-instead-of-let.rs:7:9
+ |
+LL | temp + value + 1
+ | ^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
--- /dev/null
+fn main() {
+ Box:new("foo".to_string())
+ //~^ ERROR expected type, found
+}
--- /dev/null
+error: expected type, found `"foo"`
+ --> $DIR/type-ascription-instead-of-method.rs:2:13
+ |
+LL | Box:new("foo".to_string())
+ | - ^^^^^ expecting a type here because of type ascription
+ | |
+ | help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
--- /dev/null
+fn main() {
+ std:io::stdin();
+ //~^ ERROR failed to resolve: use of undeclared type or module `io`
+ //~| ERROR expected value, found module
+}
--- /dev/null
+error[E0433]: failed to resolve: use of undeclared type or module `io`
+ --> $DIR/type-ascription-instead-of-path.rs:2:9
+ |
+LL | std:io::stdin();
+ | ^^ use of undeclared type or module `io`
+
+error[E0423]: expected value, found module `std`
+ --> $DIR/type-ascription-instead-of-path.rs:2:5
+ |
+LL | std:io::stdin();
+ | ^^^- help: maybe you meant to write a path separator here: `::`
+ | |
+ | not a value
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0433.
+For more information about an error, try `rustc --explain E0423`.
--- /dev/null
+fn main() {
+ let _ = Option:Some("");
+ //~^ ERROR expected type, found
+}
--- /dev/null
+error: expected type, found `""`
+ --> $DIR/type-ascription-instead-of-variant.rs:2:25
+ |
+LL | let _ = Option:Some("");
+ | - ^^ expecting a type here because of type ascription
+ | |
+ | help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
|
LL | println!("test"): 0;
| ^ expecting a type here because of type ascription
+ |
+ = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+ --> $DIR/type-ascription-instead-of-statement-end.rs:9:5
+ |
+LL | println!("test"): 0;
+ | ^^^^^^^^^^^^^^^^
+ = help: this might be indicative of a syntax error elsewhere
error: aborting due to 2 previous errors
Crate("fuchsia-zircon-sys"),
Crate("getopts"),
Crate("humantime"),
+ Crate("itertools"),
Crate("jobserver"),
Crate("kernel32-sys"),
Crate("lazy_static"),
"src/libstd/f64.rs",
// Integration test for platform-specific run-time feature detection:
"src/libstd/tests/run-time-detect.rs" ,
+ "src/libstd/net/test.rs",
"src/libstd/sys_common/mod.rs",
"src/libstd/sys_common/net.rs",
"src/libterm", // Not sure how to make this crate portable, but test crate needs it.