mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Merge branch 'master' of https://github.com/rust-lang/rust
This commit is contained in:
commit
5030794248
@ -197,7 +197,8 @@ dependencies = [
|
||||
"crates-io 0.21.0",
|
||||
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -230,7 +231,7 @@ dependencies = [
|
||||
"serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -474,7 +475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "crates-io"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -561,10 +562,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.18"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -576,7 +577,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "curl-sys"
|
||||
version = "0.4.13"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -848,7 +849,7 @@ name = "git2-curl"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -966,7 +967,7 @@ dependencies = [
|
||||
"flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1088,7 +1089,7 @@ version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2095,6 +2096,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_cratesio_shim 0.0.0",
|
||||
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2838,7 +2840,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.16"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3210,8 +3212,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
|
||||
"checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
|
||||
"checksum curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a9e5285b49b44401518c947d3b808d14d99a538a6c9ffb3ec0205c11f9fc4389"
|
||||
"checksum curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08459503c415173da1ce6b41036a37b8bfdd86af46d45abb9964d4c61fe670ef"
|
||||
"checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16"
|
||||
"checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870"
|
||||
"checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142"
|
||||
"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
|
||||
"checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b"
|
||||
@ -3390,7 +3392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
|
||||
"checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a"
|
||||
"checksum tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "69e16840a1e0a1f1a880b739ef1cc6a4b85496c99b8aa786ccffce6e0c15624c"
|
||||
"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76"
|
||||
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
|
||||
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
||||
|
@ -672,14 +672,16 @@ impl<T: ?Sized> Rc<T> {
|
||||
// Previously, layout was calculated on the expression
|
||||
// `&*(ptr as *const RcBox<T>)`, but this created a misaligned
|
||||
// reference (see #54908).
|
||||
let (layout, _) = Layout::new::<RcBox<()>>()
|
||||
.extend(Layout::for_value(&*ptr)).unwrap();
|
||||
let layout = Layout::new::<RcBox<()>>()
|
||||
.extend(Layout::for_value(&*ptr)).unwrap().0
|
||||
.pad_to_align().unwrap();
|
||||
|
||||
let mem = Global.alloc(layout)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
|
||||
// Initialize the RcBox
|
||||
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
|
||||
debug_assert_eq!(Layout::for_value(&*inner), layout);
|
||||
|
||||
ptr::write(&mut (*inner).strong, Cell::new(1));
|
||||
ptr::write(&mut (*inner).weak, Cell::new(1));
|
||||
|
@ -575,14 +575,16 @@ impl<T: ?Sized> Arc<T> {
|
||||
// Previously, layout was calculated on the expression
|
||||
// `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
|
||||
// reference (see #54908).
|
||||
let (layout, _) = Layout::new::<ArcInner<()>>()
|
||||
.extend(Layout::for_value(&*ptr)).unwrap();
|
||||
let layout = Layout::new::<ArcInner<()>>()
|
||||
.extend(Layout::for_value(&*ptr)).unwrap().0
|
||||
.pad_to_align().unwrap();
|
||||
|
||||
let mem = Global.alloc(layout)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
|
||||
// Initialize the ArcInner
|
||||
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
|
||||
debug_assert_eq!(Layout::for_value(&*inner), layout);
|
||||
|
||||
ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
|
||||
ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
|
||||
|
@ -218,6 +218,23 @@ impl Layout {
|
||||
len_rounded_up.wrapping_sub(len)
|
||||
}
|
||||
|
||||
/// Creates a layout by rounding the size of this layout up to a multiple
|
||||
/// of the layout's alignment.
|
||||
///
|
||||
/// Returns `Err` if the padded size would overflow.
|
||||
///
|
||||
/// This is equivalent to adding the result of `padding_needed_for`
|
||||
/// to the layout's current size.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub fn pad_to_align(&self) -> Result<Layout, LayoutErr> {
|
||||
let pad = self.padding_needed_for(self.align());
|
||||
let new_size = self.size().checked_add(pad)
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
|
||||
Layout::from_size_align(new_size, self.align())
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `n` instances of
|
||||
/// `self`, with a suitable amount of padding between each to
|
||||
/// ensure that each instance is given its requested size and
|
||||
@ -506,7 +523,7 @@ pub unsafe trait GlobalAlloc {
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Shink or grow a block of memory to the given `new_size`.
|
||||
/// Shrink or grow a block of memory to the given `new_size`.
|
||||
/// The block is described by the given `ptr` pointer and `layout`.
|
||||
///
|
||||
/// If this returns a non-null pointer, then ownership of the memory block
|
||||
@ -757,7 +774,7 @@ pub unsafe trait Alloc {
|
||||
// realloc. alloc_excess, realloc_excess
|
||||
|
||||
/// Returns a pointer suitable for holding data described by
|
||||
/// a new layout with `layout`’s alginment and a size given
|
||||
/// a new layout with `layout`’s alignment and a size given
|
||||
/// by `new_size`. To
|
||||
/// accomplish this, this may extend or shrink the allocation
|
||||
/// referenced by `ptr` to fit the new layout.
|
||||
|
@ -17,7 +17,7 @@ use ops;
|
||||
use pin::Pin;
|
||||
use task::{Poll, LocalWaker};
|
||||
|
||||
/// A future represents an asychronous computation.
|
||||
/// A future represents an asynchronous computation.
|
||||
///
|
||||
/// A future is a value that may not have finished computing yet. This kind of
|
||||
/// "asynchronous value" makes it possible for a thread to continue doing useful
|
||||
|
@ -1465,6 +1465,20 @@ extern "rust-intrinsic" {
|
||||
/// y < 0 or y >= N, where N is the width of T in bits.
|
||||
pub fn unchecked_shr<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Performs rotate left.
|
||||
/// The stabilized versions of this intrinsic are available on the integer
|
||||
/// primitives via the `rotate_left` method. For example,
|
||||
/// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
|
||||
#[cfg(not(stage0))]
|
||||
pub fn rotate_left<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Performs rotate right.
|
||||
/// The stabilized versions of this intrinsic are available on the integer
|
||||
/// primitives via the `rotate_right` method. For example,
|
||||
/// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
|
||||
#[cfg(not(stage0))]
|
||||
pub fn rotate_right<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
|
||||
/// The stabilized versions of this intrinsic are available on the integer
|
||||
/// primitives via the `wrapping_add` method. For example,
|
||||
|
@ -228,7 +228,7 @@ mod nonzero;
|
||||
mod tuple;
|
||||
mod unit;
|
||||
|
||||
// Pull in the the `coresimd` crate directly into libcore. This is where all the
|
||||
// Pull in the `coresimd` crate directly into libcore. This is where all the
|
||||
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
|
||||
// things like SIMD and such. Note that the actual source for all this lies in a
|
||||
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
|
||||
|
@ -350,9 +350,8 @@ macro_rules! try {
|
||||
/// assert_eq!(v, b"s = \"abc 123\"");
|
||||
/// ```
|
||||
///
|
||||
/// Note: This macro can be used in `no_std` setups as well
|
||||
/// In a `no_std` setup you are responsible for the
|
||||
/// implementation details of the components.
|
||||
/// Note: This macro can be used in `no_std` setups as well.
|
||||
/// In a `no_std` setup you are responsible for the implementation details of the components.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # extern crate core;
|
||||
@ -440,7 +439,7 @@ macro_rules! writeln {
|
||||
///
|
||||
/// If the determination that the code is unreachable proves incorrect, the
|
||||
/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`],
|
||||
/// which belongs to the [`std::hint`] module, informs the compilier to
|
||||
/// which belongs to the [`std::hint`] module, informs the compiler to
|
||||
/// optimize the code out of the release version entirely.
|
||||
///
|
||||
/// [`panic!`]: ../std/macro.panic.html
|
||||
|
@ -202,7 +202,7 @@ pub fn forget<T>(t: T) {
|
||||
///
|
||||
/// ## Size of Enums
|
||||
///
|
||||
/// Enums that carry no data other than the descriminant have the same size as C enums
|
||||
/// Enums that carry no data other than the discriminant have the same size as C enums
|
||||
/// on the platform they are compiled for.
|
||||
///
|
||||
/// ## Size of Unions
|
||||
@ -1081,7 +1081,7 @@ impl<T> MaybeUninit<T> {
|
||||
///
|
||||
/// # Unsafety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
|
||||
/// state, otherwise this will immediately cause undefined behavior.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
pub unsafe fn into_inner(self) -> T {
|
||||
@ -1092,7 +1092,7 @@ impl<T> MaybeUninit<T> {
|
||||
///
|
||||
/// # Unsafety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
|
||||
/// state, otherwise this will immediately cause undefined behavior.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
pub unsafe fn get_ref(&self) -> &T {
|
||||
@ -1103,7 +1103,7 @@ impl<T> MaybeUninit<T> {
|
||||
///
|
||||
/// # Unsafety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
|
||||
/// state, otherwise this will immediately cause undefined behavior.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
pub unsafe fn get_mut(&mut self) -> &mut T {
|
||||
|
@ -2152,6 +2152,7 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(", stringify!($SelfT), "::min_value(), 0);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_promotable]
|
||||
#[inline]
|
||||
pub const fn min_value() -> Self { 0 }
|
||||
}
|
||||
@ -2168,6 +2169,7 @@ Basic usage:
|
||||
stringify!($MaxV), ");", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_promotable]
|
||||
#[inline]
|
||||
pub const fn max_value() -> Self { !0 }
|
||||
}
|
||||
@ -2301,7 +2303,12 @@ assert_eq!(n.rotate_left(", $rot, "), m);
|
||||
#[rustc_const_unstable(feature = "const_int_rotate")]
|
||||
#[inline]
|
||||
pub const fn rotate_left(self, n: u32) -> Self {
|
||||
(self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS))
|
||||
#[cfg(not(stage0))] {
|
||||
unsafe { intrinsics::rotate_left(self, n as $SelfT) }
|
||||
}
|
||||
#[cfg(stage0)] {
|
||||
(self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2326,7 +2333,12 @@ assert_eq!(n.rotate_right(", $rot, "), m);
|
||||
#[rustc_const_unstable(feature = "const_int_rotate")]
|
||||
#[inline]
|
||||
pub const fn rotate_right(self, n: u32) -> Self {
|
||||
(self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS))
|
||||
#[cfg(not(stage0))] {
|
||||
unsafe { intrinsics::rotate_right(self, n as $SelfT) }
|
||||
}
|
||||
#[cfg(stage0)] {
|
||||
(self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! It is sometimes useful to have objects that are guaranteed to not move,
|
||||
//! in the sense that their placement in memory does not change, and can thus be relied upon.
|
||||
//!
|
||||
//! A prime example of such a scenario would be building self-referencial structs,
|
||||
//! A prime example of such a scenario would be building self-referential structs,
|
||||
//! since moving an object with pointers to itself will invalidate them,
|
||||
//! which could cause undefined behavior.
|
||||
//!
|
||||
@ -39,7 +39,7 @@
|
||||
//! use std::marker::Pinned;
|
||||
//! use std::ptr::NonNull;
|
||||
//!
|
||||
//! // This is a self referencial struct since the slice field points to the data field.
|
||||
//! // This is a self-referential struct since the slice field points to the data field.
|
||||
//! // We cannot inform the compiler about that with a normal reference,
|
||||
//! // since this pattern cannot be described with the usual borrowing rules.
|
||||
//! // Instead we use a raw pointer, though one which is known to not be null,
|
||||
|
@ -120,7 +120,7 @@ pub use intrinsics::write_bytes;
|
||||
///
|
||||
/// Additionally, if `T` is not [`Copy`], using the pointed-to value after
|
||||
/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
|
||||
/// foo` counts as a use because it will cause the the value to be dropped
|
||||
/// foo` counts as a use because it will cause the value to be dropped
|
||||
/// again. [`write`] can be used to overwrite data without causing it to be
|
||||
/// dropped.
|
||||
///
|
||||
@ -371,7 +371,7 @@ pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
|
||||
#[inline]
|
||||
unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
|
||||
// The approach here is to utilize simd to swap x & y efficiently. Testing reveals
|
||||
// that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
|
||||
// that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
|
||||
// Haswell E processors. LLVM is more able to optimize if we give a struct a
|
||||
// #[repr(simd)], even if we don't actually use this struct directly.
|
||||
//
|
||||
@ -1005,7 +1005,7 @@ impl<T: ?Sized> *const T {
|
||||
/// # Null-unchecked version
|
||||
///
|
||||
/// If you are sure the pointer can never be null and are looking for some kind of
|
||||
/// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can
|
||||
/// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
|
||||
/// dereference the pointer directly.
|
||||
///
|
||||
/// ```
|
||||
@ -1625,7 +1625,7 @@ impl<T: ?Sized> *mut T {
|
||||
/// # Null-unchecked version
|
||||
///
|
||||
/// If you are sure the pointer can never be null and are looking for some kind of
|
||||
/// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can
|
||||
/// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
|
||||
/// dereference the pointer directly.
|
||||
///
|
||||
/// ```
|
||||
|
@ -2134,7 +2134,7 @@ static X: u32 = 42;
|
||||
|
||||
|
||||
register_diagnostics! {
|
||||
// E0006 // merged with E0005
|
||||
// E0006, // merged with E0005
|
||||
// E0101, // replaced with E0282
|
||||
// E0102, // replaced with E0282
|
||||
// E0134,
|
||||
@ -2183,9 +2183,7 @@ register_diagnostics! {
|
||||
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
|
||||
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
|
||||
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
|
||||
|
||||
E0697, // closures cannot be static
|
||||
|
||||
E0707, // multiple elided lifetimes used in arguments of `async fn`
|
||||
E0708, // `async` non-`move` closures with arguments are not currently supported
|
||||
E0709, // multiple different lifetimes used in arguments of `async fn`
|
||||
|
@ -506,9 +506,9 @@ pub enum TraitBoundModifier {
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Sync.
|
||||
/// `typeck::collect::compute_bounds` matches these against
|
||||
/// the "special" built-in traits (see `middle::lang_items`) and
|
||||
/// detects `Copy`, `Send` and `Sync`.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifier),
|
||||
|
@ -366,7 +366,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
let mut types = vec![concrete_ty];
|
||||
let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r);
|
||||
while let Some(ty) = types.pop() {
|
||||
let mut components = self.tcx.outlives_components(ty);
|
||||
let mut components = smallvec![];
|
||||
self.tcx.push_outlives_components(ty, &mut components);
|
||||
while let Some(component) = components.pop() {
|
||||
match component {
|
||||
Component::Region(r) => {
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Code that handles "type-outlives" constraints like `T: 'a`. This
|
||||
//! is based on the `outlives_components` function defined on the tcx,
|
||||
//! is based on the `push_outlives_components` function defined on the tcx,
|
||||
//! but it adds a bit of heuristics on top, in particular to deal with
|
||||
//! associated types and projections.
|
||||
//!
|
||||
@ -307,17 +307,18 @@ where
|
||||
|
||||
assert!(!ty.has_escaping_bound_vars());
|
||||
|
||||
let components = self.tcx.outlives_components(ty);
|
||||
self.components_must_outlive(origin, components, region);
|
||||
let mut components = smallvec![];
|
||||
self.tcx.push_outlives_components(ty, &mut components);
|
||||
self.components_must_outlive(origin, &components, region);
|
||||
}
|
||||
|
||||
fn components_must_outlive(
|
||||
&mut self,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
components: Vec<Component<'tcx>>,
|
||||
components: &[Component<'tcx>],
|
||||
region: ty::Region<'tcx>,
|
||||
) {
|
||||
for component in components {
|
||||
for component in components.iter() {
|
||||
let origin = origin.clone();
|
||||
match component {
|
||||
Component::Region(region1) => {
|
||||
@ -325,13 +326,13 @@ where
|
||||
.push_sub_region_constraint(origin, region, region1);
|
||||
}
|
||||
Component::Param(param_ty) => {
|
||||
self.param_ty_must_outlive(origin, region, param_ty);
|
||||
self.param_ty_must_outlive(origin, region, *param_ty);
|
||||
}
|
||||
Component::Projection(projection_ty) => {
|
||||
self.projection_must_outlive(origin, region, projection_ty);
|
||||
self.projection_must_outlive(origin, region, *projection_ty);
|
||||
}
|
||||
Component::EscapingProjection(subcomponents) => {
|
||||
self.components_must_outlive(origin, subcomponents, region);
|
||||
self.components_must_outlive(origin, &subcomponents, region);
|
||||
}
|
||||
Component::UnresolvedInferenceVariable(v) => {
|
||||
// ignore this, we presume it will yield an error
|
||||
|
@ -155,7 +155,8 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
|
||||
.map(|subty| self.type_bound(subty))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut regions = ty.regions();
|
||||
let mut regions = smallvec![];
|
||||
ty.push_regions(&mut regions);
|
||||
regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
|
||||
bounds.push(VerifyBound::AllBounds(
|
||||
regions
|
||||
|
@ -300,12 +300,6 @@ declare_lint! {
|
||||
"detects labels that are never used"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
Warn,
|
||||
"warns about duplicate associated type bindings in generics"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DUPLICATE_MACRO_EXPORTS,
|
||||
Deny,
|
||||
@ -418,7 +412,6 @@ impl LintPass for HardwiredLints {
|
||||
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
UNSTABLE_NAME_COLLISIONS,
|
||||
IRREFUTABLE_LET_PATTERNS,
|
||||
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
DUPLICATE_MACRO_EXPORTS,
|
||||
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
||||
MISSING_DOC_CODE_EXAMPLES,
|
||||
|
@ -80,7 +80,8 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||
elem: &PlaceElem<'tcx>)
|
||||
-> PlaceTy<'tcx>
|
||||
{
|
||||
self.projection_ty_core(tcx, elem, |_, _, ty| ty)
|
||||
self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
||||
@ -88,11 +89,12 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||
/// `Ty` or downcast variant corresponding to that projection.
|
||||
/// The `handle_field` callback must map a `Field` to its `Ty`,
|
||||
/// (which should be trivial when `T` = `Ty`).
|
||||
pub fn projection_ty_core<V, T>(self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
elem: &ProjectionElem<'tcx, V, T>,
|
||||
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
|
||||
-> PlaceTy<'tcx>
|
||||
pub fn projection_ty_core<V, T, E>(
|
||||
self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
elem: &ProjectionElem<'tcx, V, T>,
|
||||
mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
|
||||
-> Result<PlaceTy<'tcx>, E>
|
||||
where
|
||||
V: ::std::fmt::Debug, T: ::std::fmt::Debug
|
||||
{
|
||||
@ -142,10 +144,11 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||
bug!("cannot downcast non-ADT type: `{:?}`", self)
|
||||
}
|
||||
},
|
||||
ProjectionElem::Field(ref f, ref fty) => PlaceTy::Ty { ty: handle_field(&self, f, fty) }
|
||||
ProjectionElem::Field(ref f, ref fty) =>
|
||||
PlaceTy::Ty { ty: handle_field(&self, f, fty)? },
|
||||
};
|
||||
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
|
||||
answer
|
||||
Ok(answer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -963,6 +963,10 @@ impl Session {
|
||||
self.opts.debugging_opts.teach && self.diagnostic().must_teach(code)
|
||||
}
|
||||
|
||||
pub fn rust_2015(&self) -> bool {
|
||||
self.opts.edition == Edition::Edition2015
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 edition?
|
||||
pub fn rust_2018(&self) -> bool {
|
||||
self.opts.edition >= Edition::Edition2018
|
||||
|
@ -50,11 +50,8 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError
|
||||
pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
|
||||
pub use self::specialize::find_associated_item;
|
||||
pub use self::engine::{TraitEngine, TraitEngineExt};
|
||||
pub use self::util::elaborate_predicates;
|
||||
pub use self::util::supertraits;
|
||||
pub use self::util::Supertraits;
|
||||
pub use self::util::supertrait_def_ids;
|
||||
pub use self::util::SupertraitDefIds;
|
||||
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
|
||||
pub use self::util::{supertraits, supertrait_def_ids, Supertraits, SupertraitDefIds};
|
||||
pub use self::util::transitive_bounds;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -885,7 +885,7 @@ fn project_type<'cx, 'gcx, 'tcx>(
|
||||
let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
|
||||
if obligation.recursion_depth >= recursion_limit {
|
||||
debug!("project: overflow!");
|
||||
selcx.infcx().report_overflow_error(&obligation, true);
|
||||
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
|
||||
}
|
||||
|
||||
let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
|
||||
|
@ -200,8 +200,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
let visited = &mut self.visited;
|
||||
let mut components = smallvec![];
|
||||
tcx.push_outlives_components(ty_max, &mut components);
|
||||
self.stack.extend(
|
||||
tcx.outlives_components(ty_max)
|
||||
components
|
||||
.into_iter()
|
||||
.filter_map(|component| match component {
|
||||
Component::Region(r) => if r.is_late_bound() {
|
||||
@ -333,7 +335,7 @@ impl<I> FilterToTraits<I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,I:Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||
impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||
type Item = ty::PolyTraitRef<'tcx>;
|
||||
|
||||
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
|
||||
|
@ -17,7 +17,7 @@ use session::Session;
|
||||
use session::config::{BorrowckMode, OutputFilenames};
|
||||
use session::config::CrateType;
|
||||
use middle;
|
||||
use hir::{TraitCandidate, HirId, ItemLocalId, Node};
|
||||
use hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node};
|
||||
use hir::def::{Def, Export};
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
||||
use hir::map as hir_map;
|
||||
@ -1602,6 +1602,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
&self,
|
||||
scope_def_id: DefId,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
// HACK: `type_of_def_id()` will fail on these (#55796), so return None
|
||||
let node_id = self.hir.as_local_node_id(scope_def_id).unwrap();
|
||||
match self.hir.get(node_id) {
|
||||
Node::Item(item) => {
|
||||
match item.node {
|
||||
ItemKind::Fn(..) => { /* type_of_def_id() will work */ }
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => { /* type_of_def_id() will work or panic */ }
|
||||
}
|
||||
|
||||
let ret_ty = self.type_of(scope_def_id);
|
||||
match ret_ty.sty {
|
||||
ty::FnDef(_, _) => {
|
||||
|
@ -294,7 +294,7 @@ impl Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if an item with this visibility is accessible from the given block.
|
||||
/// Returns `true` if an item with this visibility is accessible from the given block.
|
||||
pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
|
||||
let restriction = match self {
|
||||
// Public items are visible everywhere.
|
||||
@ -309,7 +309,7 @@ impl Visibility {
|
||||
tree.is_descendant_of(module, restriction)
|
||||
}
|
||||
|
||||
/// Returns true if this visibility is at least as accessible as the given visibility
|
||||
/// Returns `true` if this visibility is at least as accessible as the given visibility
|
||||
pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
|
||||
let vis_restriction = match vis {
|
||||
Visibility::Public => return self == Visibility::Public,
|
||||
@ -320,7 +320,7 @@ impl Visibility {
|
||||
self.is_accessible_from(vis_restriction, tree)
|
||||
}
|
||||
|
||||
// Returns true if this item is visible anywhere in the local crate.
|
||||
// Returns `true` if this item is visible anywhere in the local crate.
|
||||
pub fn is_visible_locally(self) -> bool {
|
||||
match self {
|
||||
Visibility::Public => true,
|
||||
@ -451,7 +451,7 @@ bitflags! {
|
||||
// FIXME: Rename this to the actual property since it's used for generators too
|
||||
const HAS_TY_CLOSURE = 1 << 9;
|
||||
|
||||
// true if there are "names" of types and regions and so forth
|
||||
// `true` if there are "names" of types and regions and so forth
|
||||
// that are local to a particular fn
|
||||
const HAS_FREE_LOCAL_NAMES = 1 << 10;
|
||||
|
||||
@ -544,14 +544,14 @@ impl<'tcx> TyS<'tcx> {
|
||||
pub fn is_primitive_ty(&self) -> bool {
|
||||
match self.sty {
|
||||
TyKind::Bool |
|
||||
TyKind::Char |
|
||||
TyKind::Int(_) |
|
||||
TyKind::Uint(_) |
|
||||
TyKind::Float(_) |
|
||||
TyKind::Infer(InferTy::IntVar(_)) |
|
||||
TyKind::Infer(InferTy::FloatVar(_)) |
|
||||
TyKind::Infer(InferTy::FreshIntTy(_)) |
|
||||
TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
|
||||
TyKind::Char |
|
||||
TyKind::Int(_) |
|
||||
TyKind::Uint(_) |
|
||||
TyKind::Float(_) |
|
||||
TyKind::Infer(InferTy::IntVar(_)) |
|
||||
TyKind::Infer(InferTy::FloatVar(_)) |
|
||||
TyKind::Infer(InferTy::FreshIntTy(_)) |
|
||||
TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
|
||||
TyKind::Ref(_, x, _) => x.is_primitive_ty(),
|
||||
_ => false,
|
||||
}
|
||||
@ -953,7 +953,7 @@ impl<'a, 'gcx, 'tcx> Generics {
|
||||
_ => bug!("expected lifetime parameter, but found another generic parameter")
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.region_param(param, tcx)
|
||||
}
|
||||
}
|
||||
@ -970,7 +970,7 @@ impl<'a, 'gcx, 'tcx> Generics {
|
||||
_ => bug!("expected type parameter, but found another generic parameter")
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.type_param(param, tcx)
|
||||
}
|
||||
}
|
||||
@ -993,6 +993,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
|
||||
self.instantiate_into(tcx, &mut instantiated, substs);
|
||||
instantiated
|
||||
}
|
||||
|
||||
pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
|
||||
-> InstantiatedPredicates<'tcx> {
|
||||
InstantiatedPredicates {
|
||||
@ -1041,15 +1042,15 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum Predicate<'tcx> {
|
||||
/// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
|
||||
/// Corresponds to `where Foo: Bar<A,B,C>`. `Foo` here would be
|
||||
/// the `Self` type of the trait reference and `A`, `B`, and `C`
|
||||
/// would be the type parameters.
|
||||
Trait(PolyTraitPredicate<'tcx>),
|
||||
|
||||
/// where `'a : 'b`
|
||||
/// where `'a: 'b`
|
||||
RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
|
||||
|
||||
/// where `T : 'a`
|
||||
/// where `T: 'a`
|
||||
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
|
||||
|
||||
/// where `<T as TraitRef>::Name == X`, approximately.
|
||||
@ -1062,7 +1063,7 @@ pub enum Predicate<'tcx> {
|
||||
/// trait must be object-safe
|
||||
ObjectSafe(DefId),
|
||||
|
||||
/// No direct syntax. May be thought of as `where T : FnFoo<...>`
|
||||
/// No direct syntax. May be thought of as `where T: FnFoo<...>`
|
||||
/// for some substitutions `...` and `T` being a closure type.
|
||||
/// Satisfied (or refuted) once we know the closure's kind.
|
||||
ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
|
||||
@ -1111,11 +1112,11 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
//
|
||||
// Let's start with an easy case. Consider two traits:
|
||||
//
|
||||
// trait Foo<'a> : Bar<'a,'a> { }
|
||||
// trait Foo<'a>: Bar<'a,'a> { }
|
||||
// trait Bar<'b,'c> { }
|
||||
//
|
||||
// Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
|
||||
// we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
|
||||
// Now, if we have a trait reference `for<'x> T: Foo<'x>`, then
|
||||
// we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
|
||||
// knew that `Foo<'x>` (for any 'x) then we also know that
|
||||
// `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
|
||||
// normal substitution.
|
||||
@ -1128,21 +1129,21 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
//
|
||||
// Another example to be careful of is this:
|
||||
//
|
||||
// trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
|
||||
// trait Foo1<'a>: for<'b> Bar1<'a,'b> { }
|
||||
// trait Bar1<'b,'c> { }
|
||||
//
|
||||
// Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
|
||||
// The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
|
||||
// Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
|
||||
// The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
|
||||
// reason is similar to the previous example: any impl of
|
||||
// `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So
|
||||
// `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
|
||||
// basically we would want to collapse the bound lifetimes from
|
||||
// the input (`trait_ref`) and the supertraits.
|
||||
//
|
||||
// To achieve this in practice is fairly straightforward. Let's
|
||||
// consider the more complicated scenario:
|
||||
//
|
||||
// - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
|
||||
// has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
|
||||
// - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
|
||||
// has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
|
||||
// where both `'x` and `'b` would have a DB index of 1.
|
||||
// The substitution from the input trait-ref is therefore going to be
|
||||
// `'a => 'x` (where `'x` has a DB index of 1).
|
||||
@ -1194,6 +1195,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
pub struct TraitPredicate<'tcx> {
|
||||
pub trait_ref: TraitRef<'tcx>
|
||||
}
|
||||
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> TraitPredicate<'tcx> {
|
||||
@ -1218,7 +1220,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
|
||||
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A: B`
|
||||
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
|
||||
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>,
|
||||
ty::Region<'tcx>>;
|
||||
@ -1238,11 +1240,11 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
|
||||
/// This kind of predicate has no *direct* correspondent in the
|
||||
/// syntax, but it roughly corresponds to the syntactic forms:
|
||||
///
|
||||
/// 1. `T : TraitRef<..., Item=Type>`
|
||||
/// 1. `T: TraitRef<..., Item=Type>`
|
||||
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
|
||||
///
|
||||
/// In particular, form #1 is "desugared" to the combination of a
|
||||
/// normal trait predicate (`T : TraitRef<...>`) and one of these
|
||||
/// normal trait predicate (`T: TraitRef<...>`) and one of these
|
||||
/// predicates. Form #2 is a broader form in that it also permits
|
||||
/// equality between arbitrary types. Processing an instance of
|
||||
/// Form #2 eventually yields one of these `ProjectionPredicate`
|
||||
@ -1256,14 +1258,14 @@ pub struct ProjectionPredicate<'tcx> {
|
||||
pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
/// Returns the def-id of the associated item being projected.
|
||||
/// Returns the `DefId` of the associated item being projected.
|
||||
pub fn item_def_id(&self) -> DefId {
|
||||
self.skip_binder().projection_ty.item_def_id
|
||||
}
|
||||
|
||||
pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'_, '_, '_>) -> PolyTraitRef<'tcx> {
|
||||
// Note: unlike with TraitRef::to_poly_trait_ref(),
|
||||
// self.0.trait_ref is permitted to have escaping regions.
|
||||
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
|
||||
// `self.0.trait_ref` is permitted to have escaping regions.
|
||||
// This is because here `self` has a `Binder` and so does our
|
||||
// return value, so we are preserving the number of binding
|
||||
// levels.
|
||||
@ -1274,12 +1276,12 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
self.map_bound(|predicate| predicate.ty)
|
||||
}
|
||||
|
||||
/// The DefId of the TraitItem for the associated type.
|
||||
/// The `DefId` of the `TraitItem` for the associated type.
|
||||
///
|
||||
/// Note that this is not the DefId of the TraitRef containing this
|
||||
/// associated type, which is in tcx.associated_item(projection_def_id()).container.
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
|
||||
pub fn projection_def_id(&self) -> DefId {
|
||||
// ok to skip binder since trait def-id does not care about regions
|
||||
// okay to skip binder since trait def-id does not care about regions
|
||||
self.skip_binder().projection_ty.item_def_id
|
||||
}
|
||||
}
|
||||
@ -1515,14 +1517,14 @@ impl UniverseIndex {
|
||||
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
|
||||
}
|
||||
|
||||
/// True if `self` can name a name from `other` -- in other words,
|
||||
/// Returns `true` if `self` can name a name from `other` -- in other words,
|
||||
/// if the set of names in `self` is a superset of those in
|
||||
/// `other` (`self >= other`).
|
||||
pub fn can_name(self, other: UniverseIndex) -> bool {
|
||||
self.private >= other.private
|
||||
}
|
||||
|
||||
/// True if `self` cannot name some names from `other` -- in other
|
||||
/// Returns `true` if `self` cannot name some names from `other` -- in other
|
||||
/// words, if the set of names in `self` is a strict subset of
|
||||
/// those in `other` (`self < other`).
|
||||
pub fn cannot_name(self, other: UniverseIndex) -> bool {
|
||||
@ -1574,7 +1576,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
||||
/// are revealed. This is suitable for monomorphized, post-typeck
|
||||
/// environments like codegen or doing optimizations.
|
||||
///
|
||||
/// NB. If you want to have predicates in scope, use `ParamEnv::new`,
|
||||
/// N.B. If you want to have predicates in scope, use `ParamEnv::new`,
|
||||
/// or invoke `param_env.with_reveal_all()`.
|
||||
pub fn reveal_all() -> Self {
|
||||
Self::new(List::empty(), Reveal::All)
|
||||
@ -1979,14 +1981,14 @@ impl ReprOptions {
|
||||
self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
|
||||
}
|
||||
|
||||
/// Returns true if this `#[repr()]` should inhabit "smart enum
|
||||
/// Returns `true` if this `#[repr()]` should inhabit "smart enum
|
||||
/// layout" optimizations, such as representing `Foo<&T>` as a
|
||||
/// single pointer.
|
||||
pub fn inhibit_enum_layout_opt(&self) -> bool {
|
||||
self.c() || self.int.is_some()
|
||||
}
|
||||
|
||||
/// Returns true if this `#[repr()]` should inhibit struct field reordering
|
||||
/// Returns `true` if this `#[repr()]` should inhibit struct field reordering
|
||||
/// optimizations, such as with repr(C) or repr(packed(1)).
|
||||
pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
|
||||
!(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
|
||||
@ -2089,7 +2091,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
|
||||
}
|
||||
|
||||
/// Returns true if this is PhantomData<T>.
|
||||
/// Returns `true` if this is PhantomData<T>.
|
||||
#[inline]
|
||||
pub fn is_phantom_data(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
|
||||
@ -2105,7 +2107,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
self.flags.intersects(AdtFlags::IS_RC)
|
||||
}
|
||||
|
||||
/// Returns true if this is Box<T>.
|
||||
/// Returns `true` if this is Box<T>.
|
||||
#[inline]
|
||||
pub fn is_box(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_BOX)
|
||||
@ -2422,7 +2424,7 @@ impl<'a, 'tcx> ClosureKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// True if this a type that impls this closure kind
|
||||
/// Returns `true` if this a type that impls this closure kind
|
||||
/// must also implement `other`.
|
||||
pub fn extends(self, other: ty::ClosureKind) -> bool {
|
||||
match (self, other) {
|
||||
@ -2475,7 +2477,7 @@ impl<'tcx> TyS<'tcx> {
|
||||
///
|
||||
/// Note: prefer `ty.walk()` where possible.
|
||||
pub fn maybe_walk<F>(&'tcx self, mut f: F)
|
||||
where F : FnMut(Ty<'tcx>) -> bool
|
||||
where F: FnMut(Ty<'tcx>) -> bool
|
||||
{
|
||||
let mut walker = self.walk();
|
||||
while let Some(ty) = walker.next() {
|
||||
@ -2678,7 +2680,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
as Box<dyn Iterator<Item = AssociatedItem> + 'a>
|
||||
}
|
||||
|
||||
/// Returns true if the impls are the same polarity and the trait either
|
||||
/// Returns `true` if the impls are the same polarity and the trait either
|
||||
/// has no items or is annotated #[marker] and prevents item overrides.
|
||||
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
|
||||
if self.features().overlapping_marker_traits {
|
||||
@ -2802,7 +2804,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
attr::contains_name(&self.get_attrs(did), attr)
|
||||
}
|
||||
|
||||
/// Returns true if this is an `auto trait`.
|
||||
/// Returns `true` if this is an `auto trait`.
|
||||
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
|
||||
self.trait_def(trait_def_id).has_auto_impl
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
|
||||
// RFC for reference.
|
||||
|
||||
use smallvec::SmallVec;
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -55,17 +56,15 @@ pub enum Component<'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// Returns all the things that must outlive `'a` for the condition
|
||||
/// Push onto `out` all the things that must outlive `'a` for the condition
|
||||
/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
|
||||
pub fn outlives_components(&self, ty0: Ty<'tcx>)
|
||||
-> Vec<Component<'tcx>> {
|
||||
let mut components = vec![];
|
||||
self.compute_components(ty0, &mut components);
|
||||
debug!("components({:?}) = {:?}", ty0, components);
|
||||
components
|
||||
pub fn push_outlives_components(&self, ty0: Ty<'tcx>,
|
||||
out: &mut SmallVec<[Component<'tcx>; 4]>) {
|
||||
self.compute_components(ty0, out);
|
||||
debug!("components({:?}) = {:?}", ty0, out);
|
||||
}
|
||||
|
||||
fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
|
||||
fn compute_components(&self, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
|
||||
// Descend through the types, looking for the various "base"
|
||||
// components and collecting them into `out`. This is not written
|
||||
// with `collect()` because of the need to sometimes skip subtrees
|
||||
@ -164,7 +163,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// list is maintained explicitly, because bound regions
|
||||
// themselves can be readily identified.
|
||||
|
||||
push_region_constraints(out, ty.regions());
|
||||
push_region_constraints(ty, out);
|
||||
for subty in ty.walk_shallow() {
|
||||
self.compute_components(subty, out);
|
||||
}
|
||||
@ -173,15 +172,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
|
||||
let mut temp = vec![];
|
||||
push_region_constraints(&mut temp, ty.regions());
|
||||
let mut temp = smallvec![];
|
||||
push_region_constraints(ty, &mut temp);
|
||||
for subty in ty.walk_shallow() {
|
||||
self.compute_components(subty, &mut temp);
|
||||
}
|
||||
temp
|
||||
temp.into_iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
|
||||
fn push_region_constraints<'tcx>(ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
|
||||
let mut regions = smallvec![];
|
||||
ty.push_regions(&mut regions);
|
||||
out.extend(regions.iter().filter(|&r| !r.is_late_bound()).map(|r| Component::Region(r)));
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use ty::{List, TyS, ParamEnvAnd, ParamEnv};
|
||||
use util::captures::Captures;
|
||||
use mir::interpret::{Scalar, Pointer};
|
||||
|
||||
use smallvec::SmallVec;
|
||||
use std::iter;
|
||||
use std::cmp::Ordering;
|
||||
use rustc_target::spec::abi;
|
||||
@ -627,7 +628,7 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where clause:
|
||||
///
|
||||
/// T : Foo<U>
|
||||
/// T: Foo<U>
|
||||
///
|
||||
/// This would be represented by a trait-reference where the def-id is the
|
||||
/// def-id for the trait `Foo` and the substs define `T` as parameter 0,
|
||||
@ -637,8 +638,8 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
||||
/// that case the `Self` parameter is absent from the substitutions.
|
||||
///
|
||||
/// Note that a `TraitRef` introduces a level of region binding, to
|
||||
/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
|
||||
/// U>` or higher-ranked object types.
|
||||
/// account for higher-ranked trait bounds like `T: for<'a> Foo<&'a U>`
|
||||
/// or higher-ranked object types.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct TraitRef<'tcx> {
|
||||
pub def_id: DefId,
|
||||
@ -663,7 +664,7 @@ impl<'tcx> TraitRef<'tcx> {
|
||||
self.substs.type_at(0)
|
||||
}
|
||||
|
||||
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
|
||||
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
|
||||
// Select only the "input types" from a trait-reference. For
|
||||
// now this is all the types that appear in the
|
||||
// trait-reference, but it should eventually exclude
|
||||
@ -886,16 +887,16 @@ pub struct ProjectionTy<'tcx> {
|
||||
/// The parameters of the associated item.
|
||||
pub substs: &'tcx Substs<'tcx>,
|
||||
|
||||
/// The DefId of the TraitItem for the associated type N.
|
||||
/// The `DefId` of the `TraitItem` for the associated type `N`.
|
||||
///
|
||||
/// Note that this is not the DefId of the TraitRef containing this
|
||||
/// associated type, which is in tcx.associated_item(item_def_id).container.
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(item_def_id).container`.
|
||||
pub item_def_id: DefId,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ProjectionTy<'tcx> {
|
||||
/// Construct a ProjectionTy by searching the trait from trait_ref for the
|
||||
/// associated item named item_name.
|
||||
/// Construct a `ProjectionTy` by searching the trait from `trait_ref` for the
|
||||
/// associated item named `item_name`.
|
||||
pub fn from_ref_and_name(
|
||||
tcx: TyCtxt<'_, '_, '_>, trait_ref: ty::TraitRef<'tcx>, item_name: Ident
|
||||
) -> ProjectionTy<'tcx> {
|
||||
@ -1846,28 +1847,27 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the regions directly referenced from this type (but
|
||||
/// not types reachable from this type via `walk_tys`). This
|
||||
/// ignores late-bound regions binders.
|
||||
pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
|
||||
/// Push onto `out` the regions directly referenced from this type (but not
|
||||
/// types reachable from this type via `walk_tys`). This ignores late-bound
|
||||
/// regions binders.
|
||||
pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
|
||||
match self.sty {
|
||||
Ref(region, _, _) => {
|
||||
vec![region]
|
||||
out.push(region);
|
||||
}
|
||||
Dynamic(ref obj, region) => {
|
||||
let mut v = vec![region];
|
||||
v.extend(obj.principal().skip_binder().substs.regions());
|
||||
v
|
||||
out.push(region);
|
||||
out.extend(obj.principal().skip_binder().substs.regions());
|
||||
}
|
||||
Adt(_, substs) | Opaque(_, substs) => {
|
||||
substs.regions().collect()
|
||||
out.extend(substs.regions())
|
||||
}
|
||||
Closure(_, ClosureSubsts { ref substs }) |
|
||||
Generator(_, GeneratorSubsts { ref substs }, _) => {
|
||||
substs.regions().collect()
|
||||
out.extend(substs.regions())
|
||||
}
|
||||
Projection(ref data) | UnnormalizedProjection(ref data) => {
|
||||
data.substs.regions().collect()
|
||||
out.extend(data.substs.regions())
|
||||
}
|
||||
FnDef(..) |
|
||||
FnPtr(_) |
|
||||
@ -1887,9 +1887,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
Param(_) |
|
||||
Bound(..) |
|
||||
Infer(_) |
|
||||
Error => {
|
||||
vec![]
|
||||
}
|
||||
Error => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
/// An entity in the Rust typesystem, which can be one of
|
||||
/// An entity in the Rust type system, which can be one of
|
||||
/// several kinds (only types and lifetimes for now).
|
||||
/// To reduce memory usage, a `Kind` is a interned pointer,
|
||||
/// with the lowest 2 bits being reserved for a tag to
|
||||
@ -171,7 +171,7 @@ impl<'tcx> Decodable for Kind<'tcx> {
|
||||
pub type Substs<'tcx> = List<Kind<'tcx>>;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
/// Creates a Substs that maps each generic parameter to itself.
|
||||
/// Creates a `Substs` that maps each generic parameter to itself.
|
||||
pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
Substs::for_item(tcx, def_id, |param, _| {
|
||||
@ -179,9 +179,9 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a Substs for generic parameter definitions,
|
||||
/// Creates a `Substs` for generic parameter definitions,
|
||||
/// by calling closures to obtain each kind.
|
||||
/// The closures get to observe the Substs as they're
|
||||
/// The closures get to observe the `Substs` as they're
|
||||
/// being built, which can be used to correctly
|
||||
/// substitute defaults of generic parameters.
|
||||
pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
|
||||
pub fn types(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
|
||||
self.iter().filter_map(|k| {
|
||||
if let UnpackedKind::Type(ty) = k.unpack() {
|
||||
Some(ty)
|
||||
@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regions(&'a self) -> impl DoubleEndedIterator<Item=ty::Region<'tcx>> + 'a {
|
||||
pub fn regions(&'a self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'a {
|
||||
self.iter().filter_map(|k| {
|
||||
if let UnpackedKind::Lifetime(lt) = k.unpack() {
|
||||
Some(lt)
|
||||
@ -332,7 +332,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
|
||||
// `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
|
||||
// there is more information available (for better errors).
|
||||
|
||||
pub trait Subst<'tcx> : Sized {
|
||||
pub trait Subst<'tcx>: Sized {
|
||||
fn subst<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
substs: &[Kind<'tcx>]) -> Self {
|
||||
self.subst_spanned(tcx, substs, None)
|
||||
|
@ -10,3 +10,4 @@ path = "lib.rs"
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
|
||||
smallvec = { version = "0.6.5", features = ["union"] }
|
||||
|
@ -11,6 +11,7 @@
|
||||
use {Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO};
|
||||
use {Float, FloatConvert, ParseError, Round, Status, StatusAnd};
|
||||
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use std::cmp::{self, Ordering};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Write};
|
||||
@ -1962,7 +1963,7 @@ impl<S: Semantics> IeeeFloat<S> {
|
||||
// to hold the full significand, and an extra limb required by
|
||||
// tcMultiplyPart.
|
||||
let max_limbs = limbs_for_bits(1 + 196 * significand_digits / 59);
|
||||
let mut dec_sig = Vec::with_capacity(max_limbs);
|
||||
let mut dec_sig: SmallVec<[Limb; 1]> = SmallVec::with_capacity(max_limbs);
|
||||
|
||||
// Convert to binary efficiently - we do almost all multiplication
|
||||
// in a Limb. When this would overflow do we do a single
|
||||
@ -2021,11 +2022,11 @@ impl<S: Semantics> IeeeFloat<S> {
|
||||
|
||||
const FIRST_EIGHT_POWERS: [Limb; 8] = [1, 5, 25, 125, 625, 3125, 15625, 78125];
|
||||
|
||||
let mut p5_scratch = vec![];
|
||||
let mut p5 = vec![FIRST_EIGHT_POWERS[4]];
|
||||
let mut p5_scratch = smallvec![];
|
||||
let mut p5: SmallVec<[Limb; 1]> = smallvec![FIRST_EIGHT_POWERS[4]];
|
||||
|
||||
let mut r_scratch = vec![];
|
||||
let mut r = vec![FIRST_EIGHT_POWERS[power & 7]];
|
||||
let mut r_scratch = smallvec![];
|
||||
let mut r: SmallVec<[Limb; 1]> = smallvec![FIRST_EIGHT_POWERS[power & 7]];
|
||||
power >>= 3;
|
||||
|
||||
while power > 0 {
|
||||
@ -2064,7 +2065,7 @@ impl<S: Semantics> IeeeFloat<S> {
|
||||
let calc_precision = (LIMB_BITS << attempt) - 1;
|
||||
attempt += 1;
|
||||
|
||||
let calc_normal_from_limbs = |sig: &mut Vec<Limb>,
|
||||
let calc_normal_from_limbs = |sig: &mut SmallVec<[Limb; 1]>,
|
||||
limbs: &[Limb]|
|
||||
-> StatusAnd<ExpInt> {
|
||||
sig.resize(limbs_for_bits(calc_precision), 0);
|
||||
|
@ -53,6 +53,7 @@ extern crate rustc_cratesio_shim;
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate smallvec;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
|
@ -19,7 +19,7 @@ use type_::Type;
|
||||
use type_of::{LayoutLlvmExt, PointerKind};
|
||||
use value::Value;
|
||||
|
||||
use rustc_target::abi::{LayoutOf, Size, TyLayout, Abi as LayoutAbi};
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout;
|
||||
|
||||
@ -277,6 +277,7 @@ pub trait FnTypeExt<'tcx> {
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
abi: Abi);
|
||||
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
||||
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
||||
fn llvm_cconv(&self) -> llvm::CallConv;
|
||||
fn apply_attrs_llfn(&self, llfn: &'ll Value);
|
||||
fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
|
||||
@ -658,6 +659,13 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMPointerType(self.llvm_type(cx),
|
||||
cx.data_layout().instruction_address_space as c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
fn llvm_cconv(&self) -> llvm::CallConv {
|
||||
match self.conv {
|
||||
Conv::C => llvm::CCallConv,
|
||||
|
@ -83,15 +83,16 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
if self.src_archive().is_none() {
|
||||
return Vec::new()
|
||||
}
|
||||
|
||||
let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
|
||||
let ret = archive.iter()
|
||||
.filter_map(|child| child.ok())
|
||||
.filter(is_relevant_child)
|
||||
.filter_map(|child| child.name())
|
||||
.filter(|name| !self.removals.iter().any(|x| x == name))
|
||||
.map(|name| name.to_string())
|
||||
.collect();
|
||||
return ret;
|
||||
|
||||
archive.iter()
|
||||
.filter_map(|child| child.ok())
|
||||
.filter(is_relevant_child)
|
||||
.filter_map(|child| child.name())
|
||||
.filter(|name| !self.removals.iter().any(|x| x == name))
|
||||
.map(|name| name.to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn src_archive(&mut self) -> Option<&ArchiveRO> {
|
||||
@ -171,7 +172,7 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
let name = file.file_name().unwrap().to_str().unwrap();
|
||||
self.additions.push(Addition::File {
|
||||
path: file.to_path_buf(),
|
||||
name_in_archive: name.to_string(),
|
||||
name_in_archive: name.to_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -184,13 +185,8 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
/// Combine the provided files, rlibs, and native libraries into a single
|
||||
/// `Archive`.
|
||||
pub fn build(&mut self) {
|
||||
let kind = match self.llvm_archive_kind() {
|
||||
Ok(kind) => kind,
|
||||
Err(kind) => {
|
||||
self.config.sess.fatal(&format!("Don't know how to build archive of type: {}",
|
||||
kind));
|
||||
}
|
||||
};
|
||||
let kind = self.llvm_archive_kind().unwrap_or_else(|kind|
|
||||
self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)));
|
||||
|
||||
if let Err(e) = self.build_with_llvm(kind) {
|
||||
self.config.sess.fatal(&format!("failed to build archive: {}", e));
|
||||
@ -281,10 +277,9 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
let ret = if r.into_result().is_err() {
|
||||
let err = llvm::LLVMRustGetLastError();
|
||||
let msg = if err.is_null() {
|
||||
"failed to write archive".to_string()
|
||||
"failed to write archive".into()
|
||||
} else {
|
||||
String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
|
||||
.into_owned()
|
||||
};
|
||||
Err(io::Error::new(io::ErrorKind::Other, msg))
|
||||
} else {
|
||||
@ -293,7 +288,7 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
for member in members {
|
||||
llvm::LLVMRustArchiveMemberFree(member);
|
||||
}
|
||||
return ret
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ use flate2::write::DeflateEncoder;
|
||||
|
||||
// This is the "magic number" expected at the beginning of a LLVM bytecode
|
||||
// object in an rlib.
|
||||
pub const RLIB_BYTECODE_OBJECT_MAGIC: &'static [u8] = b"RUST_OBJECT";
|
||||
pub const RLIB_BYTECODE_OBJECT_MAGIC: &[u8] = b"RUST_OBJECT";
|
||||
|
||||
// The version number this compiler will write to bytecode objects in rlibs
|
||||
pub const RLIB_BYTECODE_OBJECT_VERSION: u8 = 2;
|
||||
@ -106,39 +106,39 @@ pub struct DecodedBytecode<'a> {
|
||||
}
|
||||
|
||||
impl<'a> DecodedBytecode<'a> {
|
||||
pub fn new(data: &'a [u8]) -> Result<DecodedBytecode<'a>, String> {
|
||||
pub fn new(data: &'a [u8]) -> Result<DecodedBytecode<'a>, &'static str> {
|
||||
if !data.starts_with(RLIB_BYTECODE_OBJECT_MAGIC) {
|
||||
return Err("magic bytecode prefix not found".to_string())
|
||||
return Err("magic bytecode prefix not found")
|
||||
}
|
||||
let data = &data[RLIB_BYTECODE_OBJECT_MAGIC.len()..];
|
||||
if !data.starts_with(&[RLIB_BYTECODE_OBJECT_VERSION, 0, 0, 0]) {
|
||||
return Err("wrong version prefix found in bytecode".to_string())
|
||||
return Err("wrong version prefix found in bytecode")
|
||||
}
|
||||
let data = &data[4..];
|
||||
if data.len() < 4 {
|
||||
return Err("bytecode corrupted".to_string())
|
||||
return Err("bytecode corrupted")
|
||||
}
|
||||
let identifier_len = unsafe {
|
||||
u32::from_le(ptr::read_unaligned(data.as_ptr() as *const u32)) as usize
|
||||
};
|
||||
let data = &data[4..];
|
||||
if data.len() < identifier_len {
|
||||
return Err("bytecode corrupted".to_string())
|
||||
return Err("bytecode corrupted")
|
||||
}
|
||||
let identifier = match str::from_utf8(&data[..identifier_len]) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return Err("bytecode corrupted".to_string())
|
||||
Err(_) => return Err("bytecode corrupted")
|
||||
};
|
||||
let data = &data[identifier_len..];
|
||||
if data.len() < 8 {
|
||||
return Err("bytecode corrupted".to_string())
|
||||
return Err("bytecode corrupted")
|
||||
}
|
||||
let bytecode_len = unsafe {
|
||||
u64::from_le(ptr::read_unaligned(data.as_ptr() as *const u64)) as usize
|
||||
};
|
||||
let data = &data[8..];
|
||||
if data.len() < bytecode_len {
|
||||
return Err("bytecode corrupted".to_string())
|
||||
return Err("bytecode corrupted")
|
||||
}
|
||||
let encoded_bytecode = &data[..bytecode_len];
|
||||
|
||||
|
@ -47,8 +47,8 @@ use std::str;
|
||||
use syntax::attr;
|
||||
|
||||
pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
|
||||
invalid_output_for_target, out_filename, check_file_is_writeable,
|
||||
filename_for_metadata};
|
||||
invalid_output_for_target, filename_for_metadata,
|
||||
out_filename, check_file_is_writeable};
|
||||
|
||||
// The third parameter is for env vars, used on windows to set up the
|
||||
// path for MSVC to find its DLLs, and gcc to find its bundled
|
||||
@ -107,13 +107,10 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB
|
||||
}
|
||||
|
||||
pub fn remove(sess: &Session, path: &Path) {
|
||||
match fs::remove_file(path) {
|
||||
Ok(..) => {}
|
||||
Err(e) => {
|
||||
sess.err(&format!("failed to remove {}: {}",
|
||||
path.display(),
|
||||
e));
|
||||
}
|
||||
if let Err(e) = fs::remove_file(path) {
|
||||
sess.err(&format!("failed to remove {}: {}",
|
||||
path.display(),
|
||||
e));
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,9 +144,7 @@ pub(crate) fn link_binary(sess: &Session,
|
||||
|
||||
// Remove the temporary object file and metadata if we aren't saving temps
|
||||
if !sess.opts.cg.save_temps {
|
||||
if sess.opts.output_types.should_codegen() &&
|
||||
!preserve_objects_for_their_debuginfo(sess)
|
||||
{
|
||||
if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) {
|
||||
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
|
||||
remove(sess, obj);
|
||||
}
|
||||
@ -186,7 +181,7 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
|
||||
// the objects as they're losslessly contained inside the archives.
|
||||
let output_linked = sess.crate_types.borrow()
|
||||
.iter()
|
||||
.any(|x| *x != config::CrateType::Rlib && *x != config::CrateType::Staticlib);
|
||||
.any(|&x| x != config::CrateType::Rlib && x != config::CrateType::Staticlib);
|
||||
if !output_linked {
|
||||
return false
|
||||
}
|
||||
@ -270,7 +265,7 @@ pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum)
|
||||
// crates providing these functions don't participate in LTO (e.g.
|
||||
// no_builtins or compiler builtins crates).
|
||||
!sess.target.target.options.no_builtins &&
|
||||
(info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum))
|
||||
(info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
|
||||
}
|
||||
|
||||
fn link_binary_output(sess: &Session,
|
||||
@ -291,13 +286,10 @@ fn link_binary_output(sess: &Session,
|
||||
// final destination, with a `fs::rename` call. In order for the rename to
|
||||
// always succeed, the temporary file needs to be on the same filesystem,
|
||||
// which is why we create it inside the output directory specifically.
|
||||
let metadata_tmpdir = match TempFileBuilder::new()
|
||||
let metadata_tmpdir = TempFileBuilder::new()
|
||||
.prefix("rmeta")
|
||||
.tempdir_in(out_filename.parent().unwrap())
|
||||
{
|
||||
Ok(tmpdir) => tmpdir,
|
||||
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
||||
};
|
||||
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||
let metadata = emit_metadata(sess, codegen_results, &metadata_tmpdir);
|
||||
if let Err(e) = fs::rename(metadata, &out_filename) {
|
||||
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
||||
@ -305,10 +297,8 @@ fn link_binary_output(sess: &Session,
|
||||
out_filenames.push(out_filename);
|
||||
}
|
||||
|
||||
let tmpdir = match TempFileBuilder::new().prefix("rustc").tempdir() {
|
||||
Ok(tmpdir) => tmpdir,
|
||||
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
||||
};
|
||||
let tmpdir = TempFileBuilder::new().prefix("rustc").tempdir().unwrap_or_else(|err|
|
||||
sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||
|
||||
if outputs.outputs.should_codegen() {
|
||||
let out_filename = out_filename(sess, crate_type, outputs, crate_name);
|
||||
@ -342,7 +332,8 @@ fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
|
||||
sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| {
|
||||
search.push(path.to_path_buf());
|
||||
});
|
||||
return search;
|
||||
|
||||
search
|
||||
}
|
||||
|
||||
fn archive_config<'a>(sess: &'a Session,
|
||||
@ -814,8 +805,8 @@ fn link_natively(sess: &Session,
|
||||
.unwrap_or_else(|_| {
|
||||
let mut x = "Non-UTF-8 output: ".to_string();
|
||||
x.extend(s.iter()
|
||||
.flat_map(|&b| ascii::escape_default(b))
|
||||
.map(|b| char::from_u32(b as u32).unwrap()));
|
||||
.flat_map(|&b| ascii::escape_default(b))
|
||||
.map(char::from));
|
||||
x
|
||||
})
|
||||
}
|
||||
@ -870,9 +861,8 @@ fn link_natively(sess: &Session,
|
||||
sess.opts.debuginfo != DebugInfo::None &&
|
||||
!preserve_objects_for_their_debuginfo(sess)
|
||||
{
|
||||
match Command::new("dsymutil").arg(out_filename).output() {
|
||||
Ok(..) => {}
|
||||
Err(e) => sess.fatal(&format!("failed to run dsymutil: {}", e)),
|
||||
if let Err(e) = Command::new("dsymutil").arg(out_filename).output() {
|
||||
sess.fatal(&format!("failed to run dsymutil: {}", e))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1012,8 +1002,7 @@ fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: &
|
||||
// ensure the line is interpreted as one whole argument.
|
||||
for c in self.arg.chars() {
|
||||
match c {
|
||||
'\\' |
|
||||
' ' => write!(f, "\\{}", c)?,
|
||||
'\\' | ' ' => write!(f, "\\{}", c)?,
|
||||
c => write!(f, "{}", c)?,
|
||||
}
|
||||
}
|
||||
@ -1426,7 +1415,6 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
|
||||
for f in archive.src_files() {
|
||||
if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME {
|
||||
archive.remove_file(&f);
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,11 +205,11 @@ pub(crate) fn run(cgcx: &CodegenContext,
|
||||
Lto::Fat => {
|
||||
assert!(cached_modules.is_empty());
|
||||
let opt_jobs = fat_lto(cgcx,
|
||||
&diag_handler,
|
||||
modules,
|
||||
upstream_modules,
|
||||
&symbol_white_list,
|
||||
timeline);
|
||||
&diag_handler,
|
||||
modules,
|
||||
upstream_modules,
|
||||
&symbol_white_list,
|
||||
timeline);
|
||||
opt_jobs.map(|opt_jobs| (opt_jobs, vec![]))
|
||||
}
|
||||
Lto::Thin |
|
||||
@ -296,7 +296,7 @@ fn fat_lto(cgcx: &CodegenContext,
|
||||
let data = bc_decoded.data();
|
||||
linker.add(&data).map_err(|()| {
|
||||
let msg = format!("failed to load bc of {:?}", name);
|
||||
write::llvm_err(&diag_handler, msg)
|
||||
write::llvm_err(&diag_handler, &msg)
|
||||
})
|
||||
})?;
|
||||
timeline.record(&format!("link {:?}", name));
|
||||
@ -310,8 +310,8 @@ fn fat_lto(cgcx: &CodegenContext,
|
||||
unsafe {
|
||||
let ptr = symbol_white_list.as_ptr();
|
||||
llvm::LLVMRustRunRestrictionPass(llmod,
|
||||
ptr as *const *const libc::c_char,
|
||||
symbol_white_list.len() as libc::size_t);
|
||||
ptr as *const *const libc::c_char,
|
||||
symbol_white_list.len() as libc::size_t);
|
||||
cgcx.save_temp_bitcode(&module, "lto.after-restriction");
|
||||
}
|
||||
|
||||
@ -490,7 +490,7 @@ fn thin_lto(cgcx: &CodegenContext,
|
||||
symbol_white_list.as_ptr(),
|
||||
symbol_white_list.len() as u32,
|
||||
).ok_or_else(|| {
|
||||
write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
|
||||
write::llvm_err(&diag_handler, "failed to prepare thin LTO context")
|
||||
})?;
|
||||
|
||||
info!("thin LTO data created");
|
||||
@ -617,8 +617,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
time_ext(cgcx.time_passes, None, "LTO passes", ||
|
||||
llvm::LLVMRunPassManager(pm, llmod));
|
||||
time_ext(cgcx.time_passes, None, "LTO passes", || llvm::LLVMRunPassManager(pm, llmod));
|
||||
|
||||
llvm::LLVMDisposePassManager(pm);
|
||||
}
|
||||
@ -747,7 +746,7 @@ impl ThinModule {
|
||||
{
|
||||
let diag_handler = cgcx.create_diag_handler();
|
||||
let tm = (cgcx.tm_factory)().map_err(|e| {
|
||||
write::llvm_err(&diag_handler, e)
|
||||
write::llvm_err(&diag_handler, &e)
|
||||
})?;
|
||||
|
||||
// Right now the implementation we've got only works over serialized
|
||||
@ -762,7 +761,7 @@ impl ThinModule {
|
||||
self.data().len(),
|
||||
self.shared.module_names[self.idx].as_ptr(),
|
||||
).ok_or_else(|| {
|
||||
let msg = "failed to parse bitcode for thin LTO module".to_string();
|
||||
let msg = "failed to parse bitcode for thin LTO module";
|
||||
write::llvm_err(&diag_handler, msg)
|
||||
})? as *const _;
|
||||
let module = ModuleCodegen {
|
||||
@ -786,7 +785,7 @@ impl ThinModule {
|
||||
let mut cu2 = ptr::null_mut();
|
||||
llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
|
||||
if !cu2.is_null() {
|
||||
let msg = "multiple source DICompileUnits found".to_string();
|
||||
let msg = "multiple source DICompileUnits found";
|
||||
return Err(write::llvm_err(&diag_handler, msg))
|
||||
}
|
||||
|
||||
@ -807,25 +806,25 @@ impl ThinModule {
|
||||
// You can find some more comments about these functions in the LLVM
|
||||
// bindings we've got (currently `PassWrapper.cpp`)
|
||||
if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
|
||||
let msg = "failed to prepare thin LTO module".to_string();
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg))
|
||||
}
|
||||
cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
|
||||
timeline.record("rename");
|
||||
if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
|
||||
let msg = "failed to prepare thin LTO module".to_string();
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg))
|
||||
}
|
||||
cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
|
||||
timeline.record("resolve");
|
||||
if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
|
||||
let msg = "failed to prepare thin LTO module".to_string();
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg))
|
||||
}
|
||||
cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
|
||||
timeline.record("internalize");
|
||||
if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
|
||||
let msg = "failed to prepare thin LTO module".to_string();
|
||||
let msg = "failed to prepare thin LTO module";
|
||||
return Err(write::llvm_err(&diag_handler, msg))
|
||||
}
|
||||
cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
|
||||
@ -920,12 +919,6 @@ impl ThinLTOImports {
|
||||
}
|
||||
|
||||
fn module_name_to_str(c_str: &CStr) -> &str {
|
||||
match c_str.to_str() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
bug!("Encountered non-utf8 LLVM module name `{}`: {}",
|
||||
c_str.to_string_lossy(),
|
||||
e)
|
||||
}
|
||||
}
|
||||
c_str.to_str().unwrap_or_else(|e|
|
||||
bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e))
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
|
||||
|
||||
// Use DT_RUNPATH instead of DT_RPATH if available
|
||||
if config.linker_is_gnu {
|
||||
flags.push("-Wl,--enable-new-dtags".to_string());
|
||||
flags.push("-Wl,--enable-new-dtags".to_owned());
|
||||
}
|
||||
|
||||
flags
|
||||
@ -59,7 +59,8 @@ fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
|
||||
ret.push(format!("-Wl,-rpath,{}", &(*rpath)));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec<String> {
|
||||
@ -92,7 +93,8 @@ fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec<String> {
|
||||
|
||||
// Remove duplicates
|
||||
let rpaths = minimize_rpaths(&rpaths);
|
||||
return rpaths;
|
||||
|
||||
rpaths
|
||||
}
|
||||
|
||||
fn get_rpaths_relative_to_output(config: &mut RPathConfig,
|
||||
@ -117,8 +119,7 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
|
||||
let relative = path_relative_from(&lib, &output).unwrap_or_else(||
|
||||
panic!("couldn't create relative path from {:?} to {:?}", output, lib));
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
format!("{}/{}", prefix,
|
||||
relative.to_str().expect("non-utf8 component in path"))
|
||||
format!("{}/{}", prefix, relative.to_str().expect("non-utf8 component in path"))
|
||||
}
|
||||
|
||||
// This routine is adapted from the *old* Path's `path_relative_from`
|
||||
@ -168,7 +169,7 @@ fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
|
||||
let path = (config.get_install_prefix_lib_path)();
|
||||
let path = env::current_dir().unwrap().join(&path);
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
path.to_str().expect("non-utf8 component in rpath").to_string()
|
||||
path.to_str().expect("non-utf8 component in rpath").to_owned()
|
||||
}
|
||||
|
||||
fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
|
||||
|
@ -42,7 +42,7 @@ const WASM_EXTERNAL_KIND_GLOBAL: u8 = 3;
|
||||
/// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
|
||||
/// needs to be added, tracked at https://bugs.llvm.org/show_bug.cgi?id=37168
|
||||
pub fn rewrite_imports(path: &Path, import_map: &FxHashMap<String, String>) {
|
||||
if import_map.len() == 0 {
|
||||
if import_map.is_empty() {
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ impl<'a> Iterator for WasmSections<'a> {
|
||||
type Item = (u8, &'a [u8]);
|
||||
|
||||
fn next(&mut self) -> Option<(u8, &'a [u8])> {
|
||||
if self.0.data.len() == 0 {
|
||||
if self.0.data.is_empty() {
|
||||
return None
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ use std::time::Instant;
|
||||
use std::thread;
|
||||
use libc::{c_uint, c_void, c_char, size_t};
|
||||
|
||||
pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
|
||||
pub const RELOC_MODEL_ARGS : [(&str, llvm::RelocMode); 7] = [
|
||||
("pic", llvm::RelocMode::PIC),
|
||||
("static", llvm::RelocMode::Static),
|
||||
("default", llvm::RelocMode::Default),
|
||||
@ -81,7 +81,7 @@ pub const CODE_GEN_MODEL_ARGS: &[(&str, llvm::CodeModel)] = &[
|
||||
("large", llvm::CodeModel::Large),
|
||||
];
|
||||
|
||||
pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
|
||||
pub const TLS_MODEL_ARGS : [(&str, llvm::ThreadLocalMode); 4] = [
|
||||
("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic),
|
||||
("local-dynamic", llvm::ThreadLocalMode::LocalDynamic),
|
||||
("initial-exec", llvm::ThreadLocalMode::InitialExec),
|
||||
@ -90,7 +90,7 @@ pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
|
||||
|
||||
const PRE_THIN_LTO_BC_EXT: &str = "pre-thin-lto.bc";
|
||||
|
||||
pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
|
||||
pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError {
|
||||
match llvm::last_error() {
|
||||
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
|
||||
None => handler.fatal(&msg),
|
||||
@ -106,11 +106,10 @@ pub fn write_output_file(
|
||||
file_type: llvm::FileType) -> Result<(), FatalError> {
|
||||
unsafe {
|
||||
let output_c = path2cstr(output);
|
||||
let result = llvm::LLVMRustWriteOutputFile(
|
||||
target, pm, m, output_c.as_ptr(), file_type);
|
||||
let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type);
|
||||
if result.into_result().is_err() {
|
||||
let msg = format!("could not write output to {}", output.display());
|
||||
Err(llvm_err(handler, msg))
|
||||
Err(llvm_err(handler, &msg))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -140,7 +139,7 @@ pub fn create_target_machine(
|
||||
find_features: bool,
|
||||
) -> &'static mut llvm::TargetMachine {
|
||||
target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
|
||||
llvm_err(sess.diagnostic(), err).raise()
|
||||
llvm_err(sess.diagnostic(), &err).raise()
|
||||
})
|
||||
}
|
||||
|
||||
@ -456,7 +455,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
|
||||
unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext,
|
||||
msg: &'b str,
|
||||
cookie: c_uint) {
|
||||
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string());
|
||||
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
|
||||
}
|
||||
|
||||
unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic,
|
||||
@ -590,8 +589,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
||||
|
||||
for pass in &config.passes {
|
||||
if !addpass(pass) {
|
||||
diag_handler.warn(&format!("unknown pass `{}`, ignoring",
|
||||
pass));
|
||||
diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass));
|
||||
}
|
||||
if pass == "name-anon-globals" {
|
||||
have_name_anon_globals_pass = true;
|
||||
@ -601,8 +599,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
||||
for pass in &cgcx.plugin_passes {
|
||||
if !addpass(pass) {
|
||||
diag_handler.err(&format!("a plugin asked for LLVM pass \
|
||||
`{}` but LLVM does not \
|
||||
recognize it", pass));
|
||||
`{}` but LLVM does not \
|
||||
recognize it", pass));
|
||||
}
|
||||
if pass == "name-anon-globals" {
|
||||
have_name_anon_globals_pass = true;
|
||||
@ -613,12 +611,12 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
||||
// As described above, this will probably cause an error in LLVM
|
||||
if config.no_prepopulate_passes {
|
||||
diag_handler.err("The current compilation is going to use thin LTO buffers \
|
||||
without running LLVM's NameAnonGlobals pass. \
|
||||
This will likely cause errors in LLVM. Consider adding \
|
||||
-C passes=name-anon-globals to the compiler command line.");
|
||||
without running LLVM's NameAnonGlobals pass. \
|
||||
This will likely cause errors in LLVM. Consider adding \
|
||||
-C passes=name-anon-globals to the compiler command line.");
|
||||
} else {
|
||||
bug!("We are using thin LTO buffers without running the NameAnonGlobals pass. \
|
||||
This will likely cause errors in LLVM and should never happen.");
|
||||
This will likely cause errors in LLVM and should never happen.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -704,9 +702,9 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
||||
// escape the closure itself, and the manager should only be
|
||||
// used once.
|
||||
unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine,
|
||||
llmod: &'ll llvm::Module,
|
||||
no_builtins: bool,
|
||||
f: F) -> R
|
||||
llmod: &'ll llvm::Module,
|
||||
no_builtins: bool,
|
||||
f: F) -> R
|
||||
where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
|
||||
{
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
@ -818,7 +816,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
||||
};
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(diag_handler, tm, cpm, llmod, &path,
|
||||
llvm::FileType::AssemblyFile)
|
||||
llvm::FileType::AssemblyFile)
|
||||
})?;
|
||||
timeline.record("asm");
|
||||
}
|
||||
@ -826,7 +824,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
||||
if write_obj {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
|
||||
llvm::FileType::ObjectFile)
|
||||
llvm::FileType::ObjectFile)
|
||||
})?;
|
||||
timeline.record("obj");
|
||||
} else if asm_to_obj {
|
||||
@ -947,11 +945,11 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
|
||||
}
|
||||
|
||||
pub fn start_async_codegen(tcx: TyCtxt,
|
||||
time_graph: Option<TimeGraph>,
|
||||
metadata: EncodedMetadata,
|
||||
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
||||
total_cgus: usize)
|
||||
-> OngoingCodegen {
|
||||
time_graph: Option<TimeGraph>,
|
||||
metadata: EncodedMetadata,
|
||||
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
||||
total_cgus: usize)
|
||||
-> OngoingCodegen {
|
||||
let sess = tcx.sess;
|
||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
|
||||
@ -1116,7 +1114,8 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
|
||||
}
|
||||
|
||||
if let Some((id, product)) =
|
||||
copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) {
|
||||
copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files)
|
||||
{
|
||||
work_products.insert(id, product);
|
||||
}
|
||||
}
|
||||
@ -1441,15 +1440,12 @@ fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
|
||||
module.name,
|
||||
source_file,
|
||||
obj_out.display());
|
||||
match link_or_copy(&source_file, &obj_out) {
|
||||
Ok(_) => { }
|
||||
Err(err) => {
|
||||
let diag_handler = cgcx.create_diag_handler();
|
||||
diag_handler.err(&format!("unable to copy {} to {}: {}",
|
||||
source_file.display(),
|
||||
obj_out.display(),
|
||||
err));
|
||||
}
|
||||
if let Err(err) = link_or_copy(&source_file, &obj_out) {
|
||||
let diag_handler = cgcx.create_diag_handler();
|
||||
diag_handler.err(&format!("unable to copy {} to {}: {}",
|
||||
source_file.display(),
|
||||
obj_out.display(),
|
||||
err));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1584,10 +1580,8 @@ fn start_executing_work(tcx: TyCtxt,
|
||||
|
||||
let (name, mut cmd) = get_linker(sess, &linker, flavor);
|
||||
cmd.args(&sess.target.target.options.asm_args);
|
||||
Some(Arc::new(AssemblerCommand {
|
||||
name,
|
||||
cmd,
|
||||
}))
|
||||
|
||||
Some(Arc::new(AssemblerCommand { name, cmd }))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -2186,9 +2180,9 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
|
||||
handler.struct_err(&format!("linking with `{}` failed: {}",
|
||||
pname.display(),
|
||||
prog.status))
|
||||
.note(&format!("{:?}", &cmd))
|
||||
.note(str::from_utf8(¬e[..]).unwrap())
|
||||
.emit();
|
||||
.note(&format!("{:?}", &cmd))
|
||||
.note(str::from_utf8(¬e[..]).unwrap())
|
||||
.emit();
|
||||
handler.abort_if_errors();
|
||||
}
|
||||
},
|
||||
@ -2450,8 +2444,8 @@ impl OngoingCodegen {
|
||||
}
|
||||
|
||||
pub(crate) fn submit_pre_codegened_module_to_llvm(&self,
|
||||
tcx: TyCtxt,
|
||||
module: ModuleCodegen) {
|
||||
tcx: TyCtxt,
|
||||
module: ModuleCodegen) {
|
||||
self.wait_for_signal_to_codegen_item();
|
||||
self.check_for_errors(tcx.sess);
|
||||
|
||||
|
@ -720,6 +720,18 @@ fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> {
|
||||
ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64);
|
||||
ifn!("llvm.bitreverse.i128", fn(t_i128) -> t_i128);
|
||||
|
||||
ifn!("llvm.fshl.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
|
||||
ifn!("llvm.fshl.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
|
||||
ifn!("llvm.fshl.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
|
||||
ifn!("llvm.fshl.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
|
||||
ifn!("llvm.fshl.i128", fn(t_i128, t_i128, t_i128) -> t_i128);
|
||||
|
||||
ifn!("llvm.fshr.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
|
||||
ifn!("llvm.fshr.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
|
||||
ifn!("llvm.fshr.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
|
||||
ifn!("llvm.fshr.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
|
||||
ifn!("llvm.fshr.i128", fn(t_i128, t_i128, t_i128) -> t_i128);
|
||||
|
||||
ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
|
||||
ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
|
||||
ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
|
||||
|
@ -23,6 +23,7 @@ use value::Value;
|
||||
use llvm;
|
||||
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
|
||||
DICompositeType, DILexicalBlock, DIFlags};
|
||||
use llvm_util;
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc::hir::CodegenFnAttrFlags;
|
||||
@ -1169,9 +1170,8 @@ fn prepare_union_metadata(
|
||||
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.
|
||||
return cx.sess().target.target.options.is_like_msvc || unsafe {
|
||||
llvm::LLVMRustVersionMajor() < 7
|
||||
};
|
||||
return cx.sess().target.target.options.is_like_msvc
|
||||
|| llvm_util::get_major_version() < 7;
|
||||
}
|
||||
|
||||
// Describes the members of an enum value: An enum is described as a union of
|
||||
|
@ -13,6 +13,7 @@
|
||||
use attributes;
|
||||
use intrinsics::{self, Intrinsic};
|
||||
use llvm::{self, TypeKind};
|
||||
use llvm_util;
|
||||
use abi::{Abi, FnType, LlvmType, PassMode};
|
||||
use mir::place::PlaceRef;
|
||||
use mir::operand::{OperandRef, OperandValue};
|
||||
@ -284,7 +285,8 @@ pub fn codegen_intrinsic_call(
|
||||
"ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
|
||||
"bitreverse" | "add_with_overflow" | "sub_with_overflow" |
|
||||
"mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
|
||||
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" => {
|
||||
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" |
|
||||
"rotate_left" | "rotate_right" => {
|
||||
let ty = arg_tys[0];
|
||||
match int_type_width_signed(ty, cx) {
|
||||
Some((width, signed)) =>
|
||||
@ -363,6 +365,27 @@ pub fn codegen_intrinsic_call(
|
||||
} else {
|
||||
bx.lshr(args[0].immediate(), args[1].immediate())
|
||||
},
|
||||
"rotate_left" | "rotate_right" => {
|
||||
let is_left = name == "rotate_left";
|
||||
let val = args[0].immediate();
|
||||
let raw_shift = args[1].immediate();
|
||||
if llvm_util::get_major_version() >= 7 {
|
||||
// rotate = funnel shift with first two args the same
|
||||
let llvm_name = &format!("llvm.fsh{}.i{}",
|
||||
if is_left { 'l' } else { 'r' }, width);
|
||||
let llfn = cx.get_intrinsic(llvm_name);
|
||||
bx.call(llfn, &[val, val, raw_shift], None)
|
||||
} else {
|
||||
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
|
||||
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
|
||||
let width = C_uint(Type::ix(cx, width), width);
|
||||
let shift = bx.urem(raw_shift, width);
|
||||
let inv_shift = bx.urem(bx.sub(width, raw_shift), width);
|
||||
let shift1 = bx.shl(val, if is_left { shift } else { inv_shift });
|
||||
let shift2 = bx.lshr(val, if !is_left { shift } else { inv_shift });
|
||||
bx.or(shift1, shift2)
|
||||
}
|
||||
},
|
||||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
|
@ -257,6 +257,10 @@ pub fn print_version() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_major_version() -> u32 {
|
||||
unsafe { llvm::LLVMRustVersionMajor() }
|
||||
}
|
||||
|
||||
pub fn print_passes() {
|
||||
// Can be called without initializing LLVM
|
||||
unsafe { llvm::LLVMRustPrintPasses(); }
|
||||
|
@ -39,7 +39,7 @@ impl<'a, 'tcx> VirtualIndex {
|
||||
// Load the data pointer from the object.
|
||||
debug!("get_fn({:?}, {:?})", llvtable, self);
|
||||
|
||||
let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
|
||||
let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx).ptr_to());
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align;
|
||||
let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align);
|
||||
bx.nonnull_metadata(ptr);
|
||||
|
@ -12,6 +12,7 @@ use common::{C_i32, C_null};
|
||||
use libc::c_uint;
|
||||
use llvm::{self, BasicBlock};
|
||||
use llvm::debuginfo::DIScope;
|
||||
use llvm_util;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
|
||||
use rustc::ty::layout::{LayoutOf, TyLayout};
|
||||
use rustc::mir::{self, Mir};
|
||||
@ -612,7 +613,7 @@ fn arg_local_refs(
|
||||
// doesn't actually strip the offset when splitting the closure
|
||||
// environment into its components so it ends up out of bounds.
|
||||
// (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
|
||||
let env_alloca = !env_ref && unsafe { llvm::LLVMRustVersionMajor() < 6 };
|
||||
let env_alloca = !env_ref && llvm_util::get_major_version() < 6;
|
||||
let env_ptr = if env_alloca {
|
||||
let scratch = PlaceRef::alloca(bx,
|
||||
bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
|
||||
|
@ -234,6 +234,8 @@ impl Type {
|
||||
}
|
||||
|
||||
pub fn ptr_to(&self) -> &Type {
|
||||
assert_ne!(self.kind(), TypeKind::Function,
|
||||
"don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
|
||||
unsafe {
|
||||
llvm::LLVMPointerType(self, 0)
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
|
||||
ty::ParamEnv::reveal_all(),
|
||||
&sig,
|
||||
);
|
||||
FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
|
||||
FnType::new(cx, sig, &[]).ptr_to_llvm_type(cx)
|
||||
}
|
||||
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO)
|
||||
};
|
||||
|
@ -224,9 +224,9 @@ impl<'a> GccLinker<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Linker for GccLinker<'a> {
|
||||
fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}",lib)); }
|
||||
fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}", lib)); }
|
||||
fn link_staticlib(&mut self, lib: &str) {
|
||||
self.hint_static(); self.cmd.arg(format!("-l{}",lib));
|
||||
self.hint_static(); self.cmd.arg(format!("-l{}", lib));
|
||||
}
|
||||
fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
|
||||
fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
|
||||
@ -243,7 +243,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
|
||||
self.hint_dynamic();
|
||||
self.cmd.arg(format!("-l{}",lib));
|
||||
self.cmd.arg(format!("-l{}", lib));
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, framework: &str) {
|
||||
@ -261,7 +261,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
self.hint_static();
|
||||
let target = &self.sess.target.target;
|
||||
if !target.options.is_like_osx {
|
||||
self.linker_arg("--whole-archive").cmd.arg(format!("-l{}",lib));
|
||||
self.linker_arg("--whole-archive").cmd.arg(format!("-l{}", lib));
|
||||
self.linker_arg("--no-whole-archive");
|
||||
} else {
|
||||
// -force_load is the macOS equivalent of --whole-archive, but it
|
||||
@ -343,17 +343,13 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
}
|
||||
|
||||
fn debuginfo(&mut self) {
|
||||
match self.sess.opts.debuginfo {
|
||||
DebugInfo::None => {
|
||||
// If we are building without debuginfo enabled and we were called with
|
||||
// `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
|
||||
// found when linking to get rid of symbols from libstd.
|
||||
match self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
|
||||
Some(true) => { self.linker_arg("-S"); },
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
if let DebugInfo::None = self.sess.opts.debuginfo {
|
||||
// If we are building without debuginfo enabled and we were called with
|
||||
// `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
|
||||
// found when linking to get rid of symbols from libstd.
|
||||
if let Some(true) = self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
|
||||
self.linker_arg("-S");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -373,8 +369,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
// purely to support rustbuild right now, we should get a more
|
||||
// principled solution at some point to force the compiler to pass
|
||||
// the right `-Wl,-install_name` with an `@rpath` in it.
|
||||
if self.sess.opts.cg.rpath ||
|
||||
self.sess.opts.debugging_opts.osx_rpath_install_name {
|
||||
if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
|
||||
self.linker_arg("-install_name");
|
||||
let mut v = OsString::from("@rpath/");
|
||||
v.push(out_filename.file_name().unwrap());
|
||||
@ -461,9 +456,8 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
|
||||
fn finalize(&mut self) -> Command {
|
||||
self.hint_dynamic(); // Reset to default before returning the composed command line.
|
||||
let mut cmd = Command::new("");
|
||||
::std::mem::swap(&mut cmd, &mut self.cmd);
|
||||
cmd
|
||||
|
||||
::std::mem::replace(&mut self.cmd, Command::new(""))
|
||||
}
|
||||
|
||||
fn group_start(&mut self) {
|
||||
@ -715,9 +709,7 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||
}
|
||||
|
||||
fn finalize(&mut self) -> Command {
|
||||
let mut cmd = Command::new("");
|
||||
::std::mem::swap(&mut cmd, &mut self.cmd);
|
||||
cmd
|
||||
::std::mem::replace(&mut self.cmd, Command::new(""))
|
||||
}
|
||||
|
||||
// MSVC doesn't need group indicators
|
||||
@ -865,7 +857,7 @@ impl<'a> Linker for EmLinker<'a> {
|
||||
let res = encoder.emit_seq(symbols.len(), |encoder| {
|
||||
for (i, sym) in symbols.iter().enumerate() {
|
||||
encoder.emit_seq_elt(i, |encoder| {
|
||||
encoder.emit_str(&("_".to_string() + sym))
|
||||
encoder.emit_str(&("_".to_owned() + sym))
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
@ -885,9 +877,7 @@ impl<'a> Linker for EmLinker<'a> {
|
||||
}
|
||||
|
||||
fn finalize(&mut self) -> Command {
|
||||
let mut cmd = Command::new("");
|
||||
::std::mem::swap(&mut cmd, &mut self.cmd);
|
||||
cmd
|
||||
::std::mem::replace(&mut self.cmd, Command::new(""))
|
||||
}
|
||||
|
||||
// Appears not necessary on Emscripten
|
||||
@ -1085,9 +1075,7 @@ impl<'a> Linker for WasmLd<'a> {
|
||||
// indicative of bugs, let's prevent them.
|
||||
self.cmd.arg("--fatal-warnings");
|
||||
|
||||
let mut cmd = Command::new("");
|
||||
::std::mem::swap(&mut cmd, &mut self.cmd);
|
||||
cmd
|
||||
::std::mem::replace(&mut self.cmd, Command::new(""))
|
||||
}
|
||||
|
||||
// Not needed for now with LLD
|
||||
|
@ -47,11 +47,10 @@ fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn crates_export_threshold(crate_types: &[config::CrateType])
|
||||
-> SymbolExportLevel {
|
||||
if crate_types.iter().any(|&crate_type| {
|
||||
crate_export_threshold(crate_type) == SymbolExportLevel::Rust
|
||||
}) {
|
||||
pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExportLevel {
|
||||
if crate_types.iter().any(|&crate_type|
|
||||
crate_export_threshold(crate_type) == SymbolExportLevel::Rust)
|
||||
{
|
||||
SymbolExportLevel::Rust
|
||||
} else {
|
||||
SymbolExportLevel::C
|
||||
@ -359,7 +358,7 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt, def_id: DefId) -> bool
|
||||
!tcx.reachable_set(LOCAL_CRATE).0.contains(&node_id)
|
||||
} else {
|
||||
bug!("is_unreachable_local_definition called with non-local DefId: {:?}",
|
||||
def_id)
|
||||
def_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,11 +317,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(DUPLICATE_ASSOCIATED_TYPE_BINDINGS),
|
||||
reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK),
|
||||
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
|
||||
|
@ -687,22 +687,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir");
|
||||
|
||||
let (return_span, mir_description) =
|
||||
if let hir::ExprKind::Closure(_, _, _, span, gen_move) =
|
||||
tcx.hir.expect_expr(mir_node_id).node
|
||||
{
|
||||
(
|
||||
tcx.sess.source_map().end_point(span),
|
||||
if gen_move.is_some() {
|
||||
" of generator"
|
||||
} else {
|
||||
" of closure"
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// unreachable?
|
||||
(mir.span, "")
|
||||
};
|
||||
let (return_span, mir_description) = match tcx.hir.get(mir_node_id) {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
node: hir::ExprKind::Closure(_, _, _, span, gen_move),
|
||||
..
|
||||
}) => (
|
||||
tcx.sess.source_map().end_point(*span),
|
||||
if gen_move.is_some() {
|
||||
" of generator"
|
||||
} else {
|
||||
" of closure"
|
||||
},
|
||||
),
|
||||
hir::Node::ImplItem(hir::ImplItem {
|
||||
node: hir::ImplItemKind::Method(method_sig, _),
|
||||
..
|
||||
}) => (method_sig.decl.output.span(), ""),
|
||||
_ => (mir.span, ""),
|
||||
};
|
||||
|
||||
Some(RegionName {
|
||||
// This counter value will already have been used, so this function will increment it
|
||||
|
@ -1021,20 +1021,39 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
let v1 = ty::Contravariant.xform(v);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
let mut projected_ty = PlaceTy::from_ty(ty);
|
||||
let ty = self.normalize(ty, locations);
|
||||
|
||||
// We need to follow any provided projetions into the type.
|
||||
//
|
||||
// if we hit a ty var as we descend, then just skip the
|
||||
// attempt to relate the mir local with any type.
|
||||
#[derive(Debug)] struct HitTyVar;
|
||||
let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
|
||||
|
||||
curr_projected_ty = Ok(PlaceTy::from_ty(ty));
|
||||
for proj in &user_ty.projs {
|
||||
projected_ty = projected_ty.projection_ty_core(
|
||||
let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
|
||||
projected_ty
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
curr_projected_ty = projected_ty.projection_ty_core(
|
||||
tcx, proj, |this, field, &()| {
|
||||
let ty = this.field_ty(tcx, field);
|
||||
self.normalize(ty, locations)
|
||||
if this.to_ty(tcx).is_ty_var() {
|
||||
Err(HitTyVar)
|
||||
} else {
|
||||
let ty = this.field_ty(tcx, field);
|
||||
Ok(self.normalize(ty, locations))
|
||||
}
|
||||
});
|
||||
}
|
||||
debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
|
||||
user_ty.base, ty, user_ty.projs, projected_ty);
|
||||
user_ty.base, ty, user_ty.projs, curr_projected_ty);
|
||||
|
||||
let ty = projected_ty.to_ty(tcx);
|
||||
|
||||
self.relate_types(ty, v1, a, locations, category)?;
|
||||
if let Ok(projected_ty) = curr_projected_ty {
|
||||
let ty = projected_ty.to_ty(tcx);
|
||||
self.relate_types(ty, v1, a, locations, category)?;
|
||||
}
|
||||
}
|
||||
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
|
||||
let (
|
||||
|
@ -150,6 +150,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||
}
|
||||
self.write_scalar(val, dest)?;
|
||||
}
|
||||
"rotate_left" | "rotate_right" => {
|
||||
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
|
||||
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
|
||||
let layout = self.layout_of(substs.type_at(0))?;
|
||||
let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?;
|
||||
let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?;
|
||||
let width_bits = layout.size.bits() as u128;
|
||||
let shift_bits = raw_shift_bits % width_bits;
|
||||
let inv_shift_bits = (width_bits - raw_shift_bits) % width_bits;
|
||||
let result_bits = if intrinsic_name == "rotate_left" {
|
||||
(val_bits << shift_bits) | (val_bits >> inv_shift_bits)
|
||||
} else {
|
||||
(val_bits >> shift_bits) | (val_bits << inv_shift_bits)
|
||||
};
|
||||
let truncated_bits = self.truncate(result_bits, layout);
|
||||
let result = Scalar::from_uint(truncated_bits, layout.size);
|
||||
self.write_scalar(result, dest)?;
|
||||
}
|
||||
"transmute" => {
|
||||
self.copy_op_transmute(args[0], dest)?;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place};
|
||||
use rustc::mir::{Rvalue, Statement, StatementKind};
|
||||
use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
|
||||
use rustc::ty::{Ty, RegionKind, TyCtxt};
|
||||
use smallvec::smallvec;
|
||||
use transform::{MirPass, MirSource};
|
||||
|
||||
pub struct CleanEndRegions;
|
||||
@ -80,7 +81,11 @@ impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions {
|
||||
|
||||
fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
|
||||
// Gather regions that occur in types
|
||||
for re in ty.walk().flat_map(|t| t.regions()) {
|
||||
let mut regions = smallvec![];
|
||||
for t in ty.walk() {
|
||||
t.push_regions(&mut regions);
|
||||
}
|
||||
for re in regions {
|
||||
match *re {
|
||||
RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); }
|
||||
_ => {},
|
||||
|
@ -591,8 +591,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
||||
if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
|
||||
if let Some(value) = self.eval_operand(cond, source_info) {
|
||||
trace!("assertion on {:?} should be {:?}", value, expected);
|
||||
let expected = Immediate::Scalar(Scalar::from_bool(*expected).into());
|
||||
if expected != value.0.to_immediate() {
|
||||
let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
|
||||
if expected != self.ecx.read_scalar(value.0).unwrap() {
|
||||
// poison all places this operand references so that further code
|
||||
// doesn't use the invalid value
|
||||
match cond {
|
||||
@ -628,20 +628,20 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
||||
let len = self
|
||||
.eval_operand(len, source_info)
|
||||
.expect("len must be const");
|
||||
let len = match len.0.to_immediate() {
|
||||
Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
|
||||
let len = match self.ecx.read_scalar(len.0) {
|
||||
Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
|
||||
bits, ..
|
||||
})) => bits,
|
||||
_ => bug!("const len not primitive: {:?}", len),
|
||||
other => bug!("const len not primitive: {:?}", other),
|
||||
};
|
||||
let index = self
|
||||
.eval_operand(index, source_info)
|
||||
.expect("index must be const");
|
||||
let index = match index.0.to_immediate() {
|
||||
Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
|
||||
let index = match self.ecx.read_scalar(index.0) {
|
||||
Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
|
||||
bits, ..
|
||||
})) => bits,
|
||||
_ => bug!("const index not primitive: {:?}", index),
|
||||
other => bug!("const index not primitive: {:?}", other),
|
||||
};
|
||||
format!(
|
||||
"index out of bounds: \
|
||||
|
@ -19,7 +19,7 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::*;
|
||||
use rustc::ty::{self, Instance, InstanceDef, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
|
||||
use rustc::ty::subst::{Subst,Substs};
|
||||
|
||||
use std::collections::VecDeque;
|
||||
@ -85,39 +85,16 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||
// Only do inlining into fn bodies.
|
||||
let id = self.tcx.hir.as_local_node_id(self.source.def_id).unwrap();
|
||||
let body_owner_kind = self.tcx.hir.body_owner_kind(id);
|
||||
|
||||
if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) {
|
||||
|
||||
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
|
||||
// Don't inline calls that are in cleanup blocks.
|
||||
if bb_data.is_cleanup { continue; }
|
||||
|
||||
// Only consider direct calls to functions
|
||||
let terminator = bb_data.terminator();
|
||||
if let TerminatorKind::Call {
|
||||
func: ref op, .. } = terminator.kind {
|
||||
if let ty::FnDef(callee_def_id, substs) = op.ty(caller_mir, self.tcx).sty {
|
||||
if let Some(instance) = Instance::resolve(self.tcx,
|
||||
param_env,
|
||||
callee_def_id,
|
||||
substs) {
|
||||
let is_virtual =
|
||||
if let InstanceDef::Virtual(..) = instance.def {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if !is_virtual {
|
||||
callsites.push_back(CallSite {
|
||||
callee: instance.def_id(),
|
||||
substs: instance.substs,
|
||||
bb,
|
||||
location: terminator.source_info
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(callsite) = self.get_valid_function_call(bb,
|
||||
bb_data,
|
||||
caller_mir,
|
||||
param_env) {
|
||||
callsites.push_back(callsite);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
@ -163,20 +140,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||
|
||||
// Add callsites from inlined function
|
||||
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
|
||||
// Only consider direct calls to functions
|
||||
let terminator = bb_data.terminator();
|
||||
if let TerminatorKind::Call {
|
||||
func: Operand::Constant(ref f), .. } = terminator.kind {
|
||||
if let ty::FnDef(callee_def_id, substs) = f.ty.sty {
|
||||
// Don't inline the same function multiple times.
|
||||
if callsite.callee != callee_def_id {
|
||||
callsites.push_back(CallSite {
|
||||
callee: callee_def_id,
|
||||
substs,
|
||||
bb,
|
||||
location: terminator.source_info
|
||||
});
|
||||
}
|
||||
if let Some(new_callsite) = self.get_valid_function_call(bb,
|
||||
bb_data,
|
||||
caller_mir,
|
||||
param_env) {
|
||||
// Don't inline the same function multiple times.
|
||||
if callsite.callee != new_callsite.callee {
|
||||
callsites.push_back(new_callsite);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,6 +168,40 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_valid_function_call(&self,
|
||||
bb: BasicBlock,
|
||||
bb_data: &BasicBlockData<'tcx>,
|
||||
caller_mir: &Mir<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
) -> Option<CallSite<'tcx>> {
|
||||
// Don't inline calls that are in cleanup blocks.
|
||||
if bb_data.is_cleanup { return None; }
|
||||
|
||||
// Only consider direct calls to functions
|
||||
let terminator = bb_data.terminator();
|
||||
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
|
||||
if let ty::FnDef(callee_def_id, substs) = op.ty(caller_mir, self.tcx).sty {
|
||||
let instance = Instance::resolve(self.tcx,
|
||||
param_env,
|
||||
callee_def_id,
|
||||
substs)?;
|
||||
|
||||
if let InstanceDef::Virtual(..) = instance.def {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some(CallSite {
|
||||
callee: instance.def_id(),
|
||||
substs: instance.substs,
|
||||
bb,
|
||||
location: terminator.source_info
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn consider_optimizing(&self,
|
||||
callsite: CallSite<'tcx>,
|
||||
callee_mir: &Mir<'tcx>)
|
||||
|
@ -869,6 +869,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
| "overflowing_mul"
|
||||
| "unchecked_shl"
|
||||
| "unchecked_shr"
|
||||
| "rotate_left"
|
||||
| "rotate_right"
|
||||
| "add_with_overflow"
|
||||
| "sub_with_overflow"
|
||||
| "mul_with_overflow"
|
||||
|
@ -663,10 +663,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
binding.map(|binding| (binding, Flags::MODULE, Flags::empty()))
|
||||
}
|
||||
WhereToResolve::MacroUsePrelude => {
|
||||
match self.macro_use_prelude.get(&ident.name).cloned() {
|
||||
Some(binding) => Ok((binding, Flags::PRELUDE, Flags::empty())),
|
||||
None => Err(Determinacy::Determined),
|
||||
let mut result = Err(Determinacy::Determined);
|
||||
if use_prelude || self.session.rust_2015() {
|
||||
if let Some(binding) = self.macro_use_prelude.get(&ident.name).cloned() {
|
||||
result = Ok((binding, Flags::PRELUDE, Flags::empty()));
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
WhereToResolve::BuiltinMacros => {
|
||||
match self.builtin_macros.get(&ident.name).cloned() {
|
||||
@ -685,7 +688,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
}
|
||||
}
|
||||
WhereToResolve::LegacyPluginHelpers => {
|
||||
if self.session.plugin_attributes.borrow().iter()
|
||||
if (use_prelude || self.session.rust_2015()) &&
|
||||
self.session.plugin_attributes.borrow().iter()
|
||||
.any(|(name, _)| ident.name == &**name) {
|
||||
let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
|
||||
ty::Visibility::Public, ident.span, Mark::root())
|
||||
|
@ -35,7 +35,8 @@ pub struct TargetDataLayout {
|
||||
pub aggregate_align: Align,
|
||||
|
||||
/// Alignments for vector types.
|
||||
pub vector_align: Vec<(Size, Align)>
|
||||
pub vector_align: Vec<(Size, Align)>,
|
||||
pub instruction_address_space: u32,
|
||||
}
|
||||
|
||||
impl Default for TargetDataLayout {
|
||||
@ -57,13 +58,22 @@ impl Default for TargetDataLayout {
|
||||
vector_align: vec![
|
||||
(Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
|
||||
(Size::from_bits(128), Align::from_bits(128, 128).unwrap())
|
||||
]
|
||||
],
|
||||
instruction_address_space: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetDataLayout {
|
||||
pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
|
||||
// Parse an address space index from a string.
|
||||
let parse_address_space = |s: &str, cause: &str| {
|
||||
s.parse::<u32>().map_err(|err| {
|
||||
format!("invalid address space `{}` for `{}` in \"data-layout\": {}",
|
||||
s, cause, err)
|
||||
})
|
||||
};
|
||||
|
||||
// Parse a bit count from a string.
|
||||
let parse_bits = |s: &str, kind: &str, cause: &str| {
|
||||
s.parse::<u64>().map_err(|err| {
|
||||
@ -96,6 +106,9 @@ impl TargetDataLayout {
|
||||
match spec.split(':').collect::<Vec<_>>()[..] {
|
||||
["e"] => dl.endian = Endian::Little,
|
||||
["E"] => dl.endian = Endian::Big,
|
||||
[p] if p.starts_with("P") => {
|
||||
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
|
||||
}
|
||||
["a", ref a..] => dl.aggregate_align = align(a, "a")?,
|
||||
["f32", ref a..] => dl.f32_align = align(a, "f32")?,
|
||||
["f64", ref a..] => dl.f64_align = align(a, "f64")?,
|
||||
|
@ -11,12 +11,18 @@
|
||||
use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
// FIXME(nikic) BINARYEN_TRAP_MODE=clamp is needed to avoid trapping in our
|
||||
// -Zsaturating-float-casts implementation. This can be dropped if/when
|
||||
// we have native fpto[su]i.sat intrinsics, or the implementation otherwise
|
||||
// stops relying on non-trapping fpto[su]i.
|
||||
let mut post_link_args = LinkArgs::new();
|
||||
post_link_args.insert(LinkerFlavor::Em,
|
||||
vec!["-s".to_string(),
|
||||
"BINARYEN=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
|
||||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"BINARYEN_TRAP_MODE='clamp'".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
dynamic_linking: false,
|
||||
|
@ -20,6 +20,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::outlives::Component;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::wf;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use syntax::ast::DUMMY_NODE_ID;
|
||||
use syntax::source_map::DUMMY_SP;
|
||||
use rustc::traits::FulfillmentContext;
|
||||
@ -133,7 +134,8 @@ fn compute_implied_outlives_bounds<'tcx>(
|
||||
None => vec![],
|
||||
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
|
||||
let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
|
||||
let components = tcx.outlives_components(ty_a);
|
||||
let mut components = smallvec![];
|
||||
tcx.push_outlives_components(ty_a, &mut components);
|
||||
implied_bounds_from_components(r_b, components)
|
||||
}
|
||||
},
|
||||
@ -155,7 +157,7 @@ fn compute_implied_outlives_bounds<'tcx>(
|
||||
/// those relationships.
|
||||
fn implied_bounds_from_components(
|
||||
sub_region: ty::Region<'tcx>,
|
||||
sup_components: Vec<Component<'tcx>>,
|
||||
sup_components: SmallVec<[Component<'tcx>; 4]>,
|
||||
) -> Vec<OutlivesBound<'tcx>> {
|
||||
sup_components
|
||||
.into_iter()
|
||||
|
@ -151,17 +151,35 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
||||
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
|
||||
let ty = self.normalize(ty);
|
||||
|
||||
let mut projected_ty = PlaceTy::from_ty(ty);
|
||||
// We need to follow any provided projetions into the type.
|
||||
//
|
||||
// if we hit a ty var as we descend, then just skip the
|
||||
// attempt to relate the mir local with any type.
|
||||
|
||||
struct HitTyVar;
|
||||
let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
|
||||
curr_projected_ty = Ok(PlaceTy::from_ty(ty));
|
||||
for proj in projs {
|
||||
projected_ty = projected_ty.projection_ty_core(
|
||||
let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
|
||||
projected_ty
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
curr_projected_ty = projected_ty.projection_ty_core(
|
||||
tcx, proj, |this, field, &()| {
|
||||
let ty = this.field_ty(tcx, field);
|
||||
self.normalize(ty)
|
||||
if this.to_ty(tcx).is_ty_var() {
|
||||
Err(HitTyVar)
|
||||
} else {
|
||||
let ty = this.field_ty(tcx, field);
|
||||
Ok(self.normalize(ty))
|
||||
}
|
||||
});
|
||||
}
|
||||
let ty = projected_ty.to_ty(tcx);
|
||||
|
||||
self.relate(mir_ty, variance, ty)?;
|
||||
if let Ok(projected_ty) = curr_projected_ty {
|
||||
let ty = projected_ty.to_ty(tcx);
|
||||
self.relate(mir_ty, variance, ty)?;
|
||||
}
|
||||
|
||||
if let Some(UserSelfTy {
|
||||
impl_def_id,
|
||||
|
@ -37,7 +37,7 @@ use std::iter;
|
||||
use syntax::ast;
|
||||
use syntax::ptr::P;
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax_pos::{Span, MultiSpan};
|
||||
use syntax_pos::{DUMMY_SP, Span, MultiSpan};
|
||||
|
||||
pub trait AstConv<'gcx, 'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
|
||||
@ -451,7 +451,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
|
||||
// We manually build up the substitution, rather than using convenience
|
||||
// methods in subst.rs so that we can iterate over the arguments and
|
||||
// methods in `subst.rs` so that we can iterate over the arguments and
|
||||
// parameters in lock-step linearly, rather than trying to match each pair.
|
||||
let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count);
|
||||
|
||||
@ -469,7 +469,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
|
||||
// (Unless it's been handled in `parent_substs`) `Self` is handled first.
|
||||
// `Self` is handled first, unless it's been handled in `parent_substs`.
|
||||
if has_self {
|
||||
if let Some(¶m) = params.peek() {
|
||||
if param.index == 0 {
|
||||
@ -698,7 +698,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
trait_ref.path.segments.last().unwrap())
|
||||
}
|
||||
|
||||
/// Get the DefId of the given trait ref. It _must_ actually be a trait.
|
||||
/// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
|
||||
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
|
||||
let path = &trait_ref.path;
|
||||
match path.def {
|
||||
@ -711,7 +711,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
|
||||
/// The given `trait_ref` must actually be trait.
|
||||
/// The given trait ref must actually be a trait.
|
||||
pub(super) fn instantiate_poly_trait_ref_inner(&self,
|
||||
trait_ref: &hir::TraitRef,
|
||||
self_ty: Ty<'tcx>,
|
||||
@ -738,7 +738,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
let predicate: Result<_, ErrorReported> =
|
||||
self.ast_type_binding_to_poly_projection_predicate(
|
||||
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
|
||||
// ok to ignore Err because ErrorReported (see above)
|
||||
// okay to ignore Err because of ErrorReported (see above)
|
||||
Some((predicate.ok()?, binding.span))
|
||||
}));
|
||||
|
||||
@ -831,7 +831,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if !speculative {
|
||||
// Given something like `U : SomeTrait<T=X>`, we want to produce a
|
||||
// Given something like `U: SomeTrait<T = X>`, we want to produce a
|
||||
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
||||
// subtle in the event that `T` is defined in a supertrait of
|
||||
// `SomeTrait`, because in that case we need to upcast.
|
||||
@ -839,7 +839,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
// That is, consider this case:
|
||||
//
|
||||
// ```
|
||||
// trait SubTrait : SuperTrait<int> { }
|
||||
// trait SubTrait: SuperTrait<int> { }
|
||||
// trait SuperTrait<A> { type T; }
|
||||
//
|
||||
// ... B : SubTrait<T=foo> ...
|
||||
@ -908,16 +908,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
if !speculative {
|
||||
dup_bindings.entry(assoc_ty.def_id)
|
||||
.and_modify(|prev_span| {
|
||||
let mut err = self.tcx().struct_span_lint_node(
|
||||
::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
ref_id,
|
||||
binding.span,
|
||||
&format!("associated type binding `{}` specified more than once",
|
||||
binding.item_name)
|
||||
);
|
||||
err.span_label(binding.span, "used more than once");
|
||||
err.span_label(*prev_span, format!("first use of `{}`", binding.item_name));
|
||||
err.emit();
|
||||
struct_span_err!(self.tcx().sess, binding.span, E0719,
|
||||
"the value of the associated type `{}` (from the trait `{}`) \
|
||||
is already specified",
|
||||
binding.item_name,
|
||||
tcx.item_path_str(assoc_ty.container.id()))
|
||||
.span_label(binding.span, "re-bound here")
|
||||
.span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
|
||||
.emit();
|
||||
})
|
||||
.or_insert(binding.span);
|
||||
}
|
||||
@ -969,7 +967,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
return tcx.types.err;
|
||||
}
|
||||
|
||||
let mut projection_bounds = vec![];
|
||||
let mut projection_bounds = Vec::new();
|
||||
let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
|
||||
let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
|
||||
dummy_self,
|
||||
@ -994,23 +992,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above.
|
||||
let existential_principal = principal.map_bound(|trait_ref| {
|
||||
self.trait_ref_to_existential(trait_ref)
|
||||
});
|
||||
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|b| {
|
||||
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
|
||||
ty::ExistentialProjection {
|
||||
ty: b.ty,
|
||||
item_def_id: b.projection_ty.item_def_id,
|
||||
substs: trait_ref.substs,
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Check that there are no gross object safety violations;
|
||||
// most importantly, that the supertraits don't contain Self,
|
||||
// most importantly, that the supertraits don't contain `Self`,
|
||||
// to avoid ICEs.
|
||||
let object_safety_violations =
|
||||
tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
|
||||
@ -1021,13 +1004,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
return tcx.types.err;
|
||||
}
|
||||
|
||||
// Use a BTreeSet to keep output in a more consistent order.
|
||||
// Use a `BTreeSet` to keep output in a more consistent order.
|
||||
let mut associated_types = BTreeSet::default();
|
||||
|
||||
for tr in traits::supertraits(tcx, principal) {
|
||||
associated_types.extend(tcx.associated_items(tr.def_id())
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Type)
|
||||
.map(|item| item.def_id));
|
||||
for tr in traits::elaborate_trait_ref(tcx, principal) {
|
||||
match tr {
|
||||
ty::Predicate::Trait(pred) => {
|
||||
associated_types.extend(tcx.associated_items(pred.def_id())
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Type)
|
||||
.map(|item| item.def_id));
|
||||
}
|
||||
ty::Predicate::Projection(pred) => {
|
||||
// Include projections defined on supertraits.
|
||||
projection_bounds.push((pred, DUMMY_SP))
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
for (projection_bound, _) in &projection_bounds {
|
||||
@ -1046,11 +1038,26 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
|
||||
let existential_principal = principal.map_bound(|trait_ref| {
|
||||
self.trait_ref_to_existential(trait_ref)
|
||||
});
|
||||
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|b| {
|
||||
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
|
||||
ty::ExistentialProjection {
|
||||
ty: b.ty,
|
||||
item_def_id: b.projection_ty.item_def_id,
|
||||
substs: trait_ref.substs,
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
|
||||
auto_traits.sort();
|
||||
auto_traits.dedup();
|
||||
|
||||
// skip_binder is okay, because the predicates are re-bound.
|
||||
// Calling `skip_binder` is okay, because the predicates are re-bound.
|
||||
let mut v =
|
||||
iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
|
||||
.chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
|
||||
@ -1128,8 +1135,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
span)
|
||||
}
|
||||
|
||||
|
||||
// Checks that bounds contains exactly one element and reports appropriate
|
||||
// Checks that `bounds` contains exactly one element and reports appropriate
|
||||
// errors otherwise.
|
||||
fn one_bound_for_assoc_type<I>(&self,
|
||||
mut bounds: I,
|
||||
@ -1186,11 +1192,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
|
||||
// Create a type from a path to an associated type.
|
||||
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
|
||||
// and item_segment is the path segment for D. We return a type and a def for
|
||||
// For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C`
|
||||
// and item_segment is the path segment for `D`. We return a type and a def for
|
||||
// the whole path.
|
||||
// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
|
||||
// parameter or Self.
|
||||
// Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type
|
||||
// parameter or `Self`.
|
||||
pub fn associated_path_def_to_ty(&self,
|
||||
ref_id: ast::NodeId,
|
||||
span: Span,
|
||||
@ -1210,7 +1216,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
// item is declared.
|
||||
let bound = match (&ty.sty, ty_path_def) {
|
||||
(_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
|
||||
// `Self` in an impl of a trait - we have a concrete self type and a
|
||||
// `Self` in an impl of a trait - we have a concrete `self` type and a
|
||||
// trait reference.
|
||||
let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
|
||||
Some(trait_ref) => trait_ref,
|
||||
@ -1361,7 +1367,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
let span = path.span;
|
||||
match path.def {
|
||||
Def::Existential(did) => {
|
||||
// check for desugared impl trait
|
||||
// Check for desugared impl trait.
|
||||
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
|
||||
let item_segment = path.segments.split_last().unwrap();
|
||||
self.prohibit_generics(item_segment.1);
|
||||
@ -1398,7 +1404,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str())
|
||||
}
|
||||
Def::SelfTy(_, Some(def_id)) => {
|
||||
// Self in impl (we know the concrete type).
|
||||
// `Self` in impl (we know the concrete type)
|
||||
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_generics(&path.segments);
|
||||
@ -1406,7 +1412,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
tcx.at(span).type_of(def_id)
|
||||
}
|
||||
Def::SelfTy(Some(_), None) => {
|
||||
// Self in trait.
|
||||
// `Self` in trait
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_generics(&path.segments);
|
||||
tcx.mk_self_type()
|
||||
|
@ -626,9 +626,9 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
||||
let discrim_diverges = self.diverges.get();
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
|
||||
// Typecheck the patterns first, so that we get types for all the
|
||||
// bindings.
|
||||
let all_arm_pats_diverge = arms.iter().map(|arm| {
|
||||
// rust-lang/rust#55810: Typecheck patterns first (via eager
|
||||
// collection into `Vec`), so we get types for all bindings.
|
||||
let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
|
||||
let mut all_pats_diverge = Diverges::WarnedAlways;
|
||||
for p in &arm.pats {
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
@ -644,7 +644,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
||||
Diverges::Maybe => Diverges::Maybe,
|
||||
Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
|
||||
}
|
||||
});
|
||||
}).collect();
|
||||
|
||||
// Now typecheck the blocks.
|
||||
//
|
||||
|
@ -292,7 +292,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
"unchecked_div" | "unchecked_rem" | "exact_div" =>
|
||||
(1, vec![param(0), param(0)], param(0)),
|
||||
"unchecked_shl" | "unchecked_shr" =>
|
||||
"unchecked_shl" | "unchecked_shr" |
|
||||
"rotate_left" | "rotate_right" =>
|
||||
(1, vec![param(0), param(0)], param(0)),
|
||||
|
||||
"overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
|
||||
|
@ -28,9 +28,9 @@ use errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir;
|
||||
|
||||
/// Helper type of a temporary returned by .for_item(...).
|
||||
/// Helper type of a temporary returned by `.for_item(...)`.
|
||||
/// Necessary because we can't write the following bound:
|
||||
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
|
||||
/// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`.
|
||||
struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
|
||||
id: ast::NodeId,
|
||||
@ -186,6 +186,8 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
item_id: ast::NodeId,
|
||||
span: Span,
|
||||
sig_if_method: Option<&hir::MethodSig>) {
|
||||
debug!("check_associated_item: {:?}", item_id);
|
||||
|
||||
let code = ObligationCauseCode::MiscObligation;
|
||||
for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
|
||||
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
|
||||
@ -311,6 +313,8 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
|
||||
debug!("check_trait: {:?}", item.id);
|
||||
|
||||
let trait_def_id = tcx.hir.local_def_id(item.id);
|
||||
|
||||
let trait_def = tcx.trait_def(trait_def_id);
|
||||
@ -1012,7 +1016,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
None => {
|
||||
// Inherent impl: take implied bounds from the self type.
|
||||
// Inherent impl: take implied bounds from the `self` type.
|
||||
let self_ty = self.tcx.type_of(impl_def_id);
|
||||
let self_ty = self.normalize_associated_types_in(span, &self_ty);
|
||||
vec![self_ty]
|
||||
|
@ -1978,9 +1978,9 @@ pub enum SizedByDefault {
|
||||
No,
|
||||
}
|
||||
|
||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
|
||||
/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
|
||||
/// built-in trait (formerly known as kind): Send.
|
||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped `Ty`
|
||||
/// or a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
|
||||
/// built-in trait `Send`.
|
||||
pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
||||
astconv: &dyn AstConv<'gcx, 'tcx>,
|
||||
param_ty: Ty<'tcx>,
|
||||
@ -1988,8 +1988,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span,
|
||||
) -> Bounds<'tcx> {
|
||||
let mut region_bounds = vec![];
|
||||
let mut trait_bounds = vec![];
|
||||
let mut region_bounds = Vec::new();
|
||||
let mut trait_bounds = Vec::new();
|
||||
|
||||
for ast_bound in ast_bounds {
|
||||
match *ast_bound {
|
||||
@ -1999,7 +1999,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
let mut projection_bounds = vec![];
|
||||
let mut projection_bounds = Vec::new();
|
||||
|
||||
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
|
||||
(astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)
|
||||
|
@ -4909,4 +4909,5 @@ register_diagnostics! {
|
||||
E0641, // cannot cast to/from a pointer with an unknown kind
|
||||
E0645, // trait aliases not finished
|
||||
E0698, // type inside generator must be known in this context
|
||||
E0719, // duplicate values for associated type binding
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
use rustc::ty::outlives::Component;
|
||||
use rustc::ty::subst::{Kind, UnpackedKind};
|
||||
use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
|
||||
use smallvec::smallvec;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
|
||||
@ -40,7 +41,9 @@ pub fn insert_outlives_predicate<'tcx>(
|
||||
//
|
||||
// Or if within `struct Foo<U>` you had `T = Vec<U>`, then
|
||||
// we would want to add `U: 'outlived_region`
|
||||
for component in tcx.outlives_components(ty) {
|
||||
let mut components = smallvec![];
|
||||
tcx.push_outlives_components(ty, &mut components);
|
||||
for component in components {
|
||||
match component {
|
||||
Component::Region(r) => {
|
||||
// This would arise from something like:
|
||||
|
@ -29,6 +29,7 @@ use core::new_handler;
|
||||
use externalfiles::ExternalHtml;
|
||||
use html;
|
||||
use html::markdown::IdMap;
|
||||
use html::static_files;
|
||||
use opts;
|
||||
use passes::{self, DefaultPassOption};
|
||||
use theme;
|
||||
@ -261,7 +262,7 @@ impl Options {
|
||||
|
||||
let to_check = matches.opt_strs("theme-checker");
|
||||
if !to_check.is_empty() {
|
||||
let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css"));
|
||||
let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
|
||||
let mut errors = 0;
|
||||
|
||||
println!("rustdoc: [theme-checker] Starting tests!");
|
||||
@ -338,7 +339,7 @@ impl Options {
|
||||
|
||||
let mut themes = Vec::new();
|
||||
if matches.opt_present("themes") {
|
||||
let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css"));
|
||||
let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
|
||||
|
||||
for (theme_file, theme_s) in matches.opt_strs("themes")
|
||||
.iter()
|
||||
|
@ -76,7 +76,7 @@ use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
|
||||
use html::format::fmt_impl_for_trait_page;
|
||||
use html::item_type::ItemType;
|
||||
use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap};
|
||||
use html::{highlight, layout};
|
||||
use html::{highlight, layout, static_files};
|
||||
|
||||
use minifier;
|
||||
|
||||
@ -767,10 +767,10 @@ fn write_shared(
|
||||
// overwrite them anyway to make sure that they're fresh and up-to-date.
|
||||
|
||||
write_minify(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
|
||||
include_str!("static/rustdoc.css"),
|
||||
static_files::RUSTDOC_CSS,
|
||||
options.enable_minification)?;
|
||||
write_minify(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
|
||||
include_str!("static/settings.css"),
|
||||
static_files::SETTINGS_CSS,
|
||||
options.enable_minification)?;
|
||||
|
||||
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
|
||||
@ -790,15 +790,15 @@ fn write_shared(
|
||||
}
|
||||
|
||||
write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/brush.svg"))?;
|
||||
static_files::BRUSH_SVG)?;
|
||||
write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/wheel.svg"))?;
|
||||
static_files::WHEEL_SVG)?;
|
||||
write_minify(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
|
||||
include_str!("static/themes/light.css"),
|
||||
static_files::themes::LIGHT,
|
||||
options.enable_minification)?;
|
||||
themes.insert("light".to_owned());
|
||||
write_minify(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
|
||||
include_str!("static/themes/dark.css"),
|
||||
static_files::themes::DARK,
|
||||
options.enable_minification)?;
|
||||
themes.insert("dark".to_owned());
|
||||
|
||||
@ -854,16 +854,16 @@ themePicker.onblur = handleThemeButtonsBlur;
|
||||
)?;
|
||||
|
||||
write_minify(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)),
|
||||
include_str!("static/main.js"),
|
||||
static_files::MAIN_JS,
|
||||
options.enable_minification)?;
|
||||
write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
|
||||
include_str!("static/settings.js"),
|
||||
static_files::SETTINGS_JS,
|
||||
options.enable_minification)?;
|
||||
|
||||
{
|
||||
let mut data = format!("var resourcesSuffix = \"{}\";\n",
|
||||
cx.shared.resource_suffix);
|
||||
data.push_str(include_str!("static/storage.js"));
|
||||
data.push_str(static_files::STORAGE_JS);
|
||||
write_minify(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)),
|
||||
&data,
|
||||
options.enable_minification)?;
|
||||
@ -882,36 +882,36 @@ themePicker.onblur = handleThemeButtonsBlur;
|
||||
}
|
||||
}
|
||||
write_minify(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
|
||||
include_str!("static/normalize.css"),
|
||||
static_files::NORMALIZE_CSS,
|
||||
options.enable_minification)?;
|
||||
write(cx.dst.join("FiraSans-Regular.woff"),
|
||||
include_bytes!("static/FiraSans-Regular.woff"))?;
|
||||
static_files::fira_sans::REGULAR)?;
|
||||
write(cx.dst.join("FiraSans-Medium.woff"),
|
||||
include_bytes!("static/FiraSans-Medium.woff"))?;
|
||||
static_files::fira_sans::MEDIUM)?;
|
||||
write(cx.dst.join("FiraSans-LICENSE.txt"),
|
||||
include_bytes!("static/FiraSans-LICENSE.txt"))?;
|
||||
static_files::fira_sans::LICENSE)?;
|
||||
write(cx.dst.join("Heuristica-Italic.woff"),
|
||||
include_bytes!("static/Heuristica-Italic.woff"))?;
|
||||
static_files::heuristica::ITALIC)?;
|
||||
write(cx.dst.join("Heuristica-LICENSE.txt"),
|
||||
include_bytes!("static/Heuristica-LICENSE.txt"))?;
|
||||
static_files::heuristica::LICENSE)?;
|
||||
write(cx.dst.join("SourceSerifPro-Regular.woff"),
|
||||
include_bytes!("static/SourceSerifPro-Regular.woff"))?;
|
||||
static_files::source_serif_pro::REGULAR)?;
|
||||
write(cx.dst.join("SourceSerifPro-Bold.woff"),
|
||||
include_bytes!("static/SourceSerifPro-Bold.woff"))?;
|
||||
static_files::source_serif_pro::BOLD)?;
|
||||
write(cx.dst.join("SourceSerifPro-LICENSE.txt"),
|
||||
include_bytes!("static/SourceSerifPro-LICENSE.txt"))?;
|
||||
static_files::source_serif_pro::LICENSE)?;
|
||||
write(cx.dst.join("SourceCodePro-Regular.woff"),
|
||||
include_bytes!("static/SourceCodePro-Regular.woff"))?;
|
||||
static_files::source_code_pro::REGULAR)?;
|
||||
write(cx.dst.join("SourceCodePro-Semibold.woff"),
|
||||
include_bytes!("static/SourceCodePro-Semibold.woff"))?;
|
||||
static_files::source_code_pro::SEMIBOLD)?;
|
||||
write(cx.dst.join("SourceCodePro-LICENSE.txt"),
|
||||
include_bytes!("static/SourceCodePro-LICENSE.txt"))?;
|
||||
static_files::source_code_pro::LICENSE)?;
|
||||
write(cx.dst.join("LICENSE-MIT.txt"),
|
||||
include_bytes!("static/LICENSE-MIT.txt"))?;
|
||||
static_files::LICENSE_MIT)?;
|
||||
write(cx.dst.join("LICENSE-APACHE.txt"),
|
||||
include_bytes!("static/LICENSE-APACHE.txt"))?;
|
||||
static_files::LICENSE_APACHE)?;
|
||||
write(cx.dst.join("COPYRIGHT.txt"),
|
||||
include_bytes!("static/COPYRIGHT.txt"))?;
|
||||
static_files::COPYRIGHT)?;
|
||||
|
||||
fn collect(path: &Path, krate: &str, key: &str) -> io::Result<(Vec<String>, Vec<String>)> {
|
||||
let mut ret = Vec::new();
|
||||
|
111
src/librustdoc/html/static_files.rs
Normal file
111
src/librustdoc/html/static_files.rs
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Static files bundled with documentation output.
|
||||
//!
|
||||
//! All the static files are included here for centralized access in case anything other than the
|
||||
//! HTML rendering code (say, the theme checker) needs to access one of these files.
|
||||
//!
|
||||
//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the
|
||||
//! minifier to run on them. All other files are included as `&'static [u8]` so they can be
|
||||
//! directly written to a `Write` handle.
|
||||
|
||||
/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
|
||||
pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css");
|
||||
|
||||
/// The file contents of `settings.css`, responsible for the items on the settings page.
|
||||
pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css");
|
||||
|
||||
/// The file contents of `normalize.css`, included to even out standard elements between browser
|
||||
/// implementations.
|
||||
pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css");
|
||||
|
||||
/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
|
||||
/// including search behavior and docblock folding, among others.
|
||||
pub static MAIN_JS: &'static str = include_str!("static/main.js");
|
||||
|
||||
/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
|
||||
/// page.
|
||||
pub static SETTINGS_JS: &'static str = include_str!("static/settings.js");
|
||||
|
||||
/// The file contents of `storage.js`, which contains functionality related to browser Local
|
||||
/// Storage, used to store documentation settings.
|
||||
pub static STORAGE_JS: &'static str = include_str!("static/storage.js");
|
||||
|
||||
/// The file contents of `brush.svg`, the icon used for the theme-switch button.
|
||||
pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg");
|
||||
|
||||
/// The file contents of `wheel.svg`, the icon used for the settings button.
|
||||
pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg");
|
||||
|
||||
/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
|
||||
/// output.
|
||||
pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt");
|
||||
|
||||
/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
|
||||
pub static LICENSE_APACHE: &'static [u8] = include_bytes!("static/LICENSE-APACHE.txt");
|
||||
|
||||
/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
|
||||
pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
|
||||
|
||||
/// The built-in themes given to every documentation site.
|
||||
pub mod themes {
|
||||
/// The "light" theme, selected by default when no setting is available. Used as the basis for
|
||||
/// the `--theme-checker` functionality.
|
||||
pub static LIGHT: &'static str = include_str!("static/themes/light.css");
|
||||
|
||||
/// The "dark" theme.
|
||||
pub static DARK: &'static str = include_str!("static/themes/dark.css");
|
||||
}
|
||||
|
||||
/// Files related to the Fira Sans font.
|
||||
pub mod fira_sans {
|
||||
/// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
|
||||
pub static REGULAR: &'static [u8] = include_bytes!("static/FiraSans-Regular.woff");
|
||||
|
||||
/// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
|
||||
pub static MEDIUM: &'static [u8] = include_bytes!("static/FiraSans-Medium.woff");
|
||||
|
||||
/// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt");
|
||||
}
|
||||
|
||||
/// Files related to the Heuristica font.
|
||||
pub mod heuristica {
|
||||
/// The file `Heuristica-Italic.woff`, the Italic variant of the Heuristica font.
|
||||
pub static ITALIC: &'static [u8] = include_bytes!("static/Heuristica-Italic.woff");
|
||||
|
||||
/// The file `Heuristica-LICENSE.txt`, the license text for the Heuristica font.
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/Heuristica-LICENSE.txt");
|
||||
}
|
||||
|
||||
/// Files related to the Source Serif Pro font.
|
||||
pub mod source_serif_pro {
|
||||
/// The file `SourceSerifPro-Regular.woff`, the Regular variant of the Source Serif Pro font.
|
||||
pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.woff");
|
||||
|
||||
/// The file `SourceSerifPro-Bold.woff`, the Bold variant of the Source Serif Pro font.
|
||||
pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.woff");
|
||||
|
||||
/// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font.
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.txt");
|
||||
}
|
||||
|
||||
/// Files related to the Source Code Pro font.
|
||||
pub mod source_code_pro {
|
||||
/// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font.
|
||||
pub static REGULAR: &'static [u8] = include_bytes!("static/SourceCodePro-Regular.woff");
|
||||
|
||||
/// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font.
|
||||
pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
|
||||
|
||||
/// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
|
||||
}
|
@ -78,6 +78,7 @@ pub mod html {
|
||||
crate mod layout;
|
||||
pub mod markdown;
|
||||
crate mod render;
|
||||
crate mod static_files;
|
||||
crate mod toc;
|
||||
}
|
||||
mod markdown;
|
||||
|
@ -1178,7 +1178,7 @@ impl CStr {
|
||||
///
|
||||
/// If the contents of the `CStr` are valid UTF-8 data, this
|
||||
/// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
|
||||
/// with the the corresponding [`&str`] slice. Otherwise, it will
|
||||
/// with the corresponding [`&str`] slice. Otherwise, it will
|
||||
/// replace any invalid UTF-8 sequences with
|
||||
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
|
||||
/// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
|
||||
|
@ -495,7 +495,7 @@ mod memchr;
|
||||
// compiler
|
||||
pub mod rt;
|
||||
|
||||
// Pull in the the `stdsimd` crate directly into libstd. This is the same as
|
||||
// Pull in the `stdsimd` crate directly into libstd. This is the same as
|
||||
// libcore's arch/simd modules where the source of truth here is in a different
|
||||
// repository, but we pull things in here manually to get it into libstd.
|
||||
//
|
||||
|
36
src/test/mir-opt/inline-trait-method_2.rs
Normal file
36
src/test/mir-opt/inline-trait-method_2.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// compile-flags: -Z span_free_formats -Z mir-opt-level=3
|
||||
|
||||
#[inline]
|
||||
fn test(x: &dyn X) -> bool {
|
||||
x.y()
|
||||
}
|
||||
|
||||
fn test2(x: &dyn X) -> bool {
|
||||
test(x)
|
||||
}
|
||||
|
||||
trait X {
|
||||
fn y(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl X for () {
|
||||
fn y(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Should be true: {}", test2(&()));
|
||||
}
|
||||
|
||||
// END RUST SOURCE
|
||||
// START rustc.test2.Inline.after.mir
|
||||
// ...
|
||||
// bb0: {
|
||||
// ...
|
||||
// _0 = const X::y(move _2) -> bb1;
|
||||
// }
|
||||
// ...
|
||||
// END rustc.test2.Inline.after.mir
|
@ -0,0 +1,16 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Foo: Iterator<Item = i32> {}
|
||||
trait Bar: Foo {}
|
||||
|
||||
fn main() {
|
||||
let _: &dyn Bar;
|
||||
}
|
22
src/test/run-pass/issues/issue-24010.rs
Normal file
22
src/test/run-pass/issues/issue-24010.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Foo: Fn(i32) -> i32 + Send {}
|
||||
|
||||
impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
|
||||
|
||||
fn wants_foo(f: Box<Foo>) -> i32 {
|
||||
f(42)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let f = Box::new(|x| x);
|
||||
assert_eq!(wants_foo(f), 42);
|
||||
}
|
@ -21,7 +21,6 @@ pub fn main() {
|
||||
let b = Box::new(456) as Box<dyn Foo>;
|
||||
assert!(*b == 456);
|
||||
|
||||
// FIXME(alexreg): associated type should be gotten from trait alias definition
|
||||
// let c: &dyn I32Iterator = &vec![123].into_iter();
|
||||
// assert_eq!(c.next(), Some(123));
|
||||
let c: &mut dyn I32Iterator = &mut vec![123].into_iter();
|
||||
assert_eq!(c.next(), Some(123));
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait I32Iterator = Iterator<Item = i32>;
|
||||
|
||||
fn main() {
|
||||
let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
|
||||
--> $DIR/associated-types-overridden-binding-2.rs:16:39
|
||||
|
|
||||
LL | let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `i32`
|
||||
= note: required for the cast to the object type `dyn I32Iterator<Item=u32, Item=i32>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -0,0 +1,21 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Foo: Iterator<Item = i32> {}
|
||||
trait Bar: Foo<Item = u32> {}
|
||||
|
||||
trait I32Iterator = Iterator<Item = i32>;
|
||||
trait U32Iterator = I32Iterator<Item = u32>;
|
||||
|
||||
fn main() {
|
||||
let _: &I32Iterator<Item = u32>;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
|
||||
--> $DIR/associated-types-overridden-binding.rs:14:1
|
||||
|
|
||||
LL | trait Bar: Foo<Item = u32> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by `Foo`
|
||||
--> $DIR/associated-types-overridden-binding.rs:13:1
|
||||
|
|
||||
LL | trait Foo: Iterator<Item = i32> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
@ -3,8 +3,8 @@ error[E0382]: use of moved value: `a`
|
||||
|
|
||||
LL | let _x = a.x;
|
||||
| -- value moved here
|
||||
LL | //~^ value moved here
|
||||
LL | let _y = a.y; //~ ERROR use of moved
|
||||
LL | //[ast]~^ value moved here
|
||||
LL | let _y = a.y; //[ast]~ ERROR use of moved
|
||||
| ^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
|
||||
@ -14,8 +14,8 @@ error[E0382]: use of moved value: `a`
|
||||
|
|
||||
LL | let _x = a.x;
|
||||
| -- value moved here
|
||||
LL | //~^ value moved here
|
||||
LL | let _y = a.y; //~ ERROR use of moved
|
||||
LL | //[ast]~^ value moved here
|
||||
LL | let _y = a.y; //[ast]~ ERROR use of moved
|
||||
| ^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
|
||||
@ -25,8 +25,8 @@ error[E0382]: use of moved value: `a`
|
||||
|
|
||||
LL | let _x = a.x;
|
||||
| -- value moved here
|
||||
LL | //~^ value moved here
|
||||
LL | let _y = &a.y; //~ ERROR use of moved
|
||||
LL | //[ast]~^ value moved here
|
||||
LL | let _y = &a.y; //[ast]~ ERROR use of moved
|
||||
| ^^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
|
||||
@ -44,7 +44,7 @@ error[E0503]: cannot use `a.y` because it was mutably borrowed
|
||||
|
|
||||
LL | let _x = &mut a.x;
|
||||
| --- borrow of `a.x` occurs here
|
||||
LL | let _y = a.y; //~ ERROR cannot use
|
||||
LL | let _y = a.y; //[ast]~ ERROR cannot use
|
||||
| ^^ use of borrowed `a.x`
|
||||
|
||||
error[E0505]: cannot move out of `a.y` because it is borrowed
|
||||
@ -60,9 +60,9 @@ error[E0502]: cannot borrow `a` (via `a.y`) as immutable because `a` is also bor
|
||||
|
|
||||
LL | let _x = &mut a.x;
|
||||
| --- mutable borrow occurs here (via `a.x`)
|
||||
LL | let _y = &a.y; //~ ERROR cannot borrow
|
||||
LL | let _y = &a.y; //[ast]~ ERROR cannot borrow
|
||||
| ^^^ immutable borrow occurs here (via `a.y`)
|
||||
LL | //~^ immutable borrow occurs here (via `a.y`)
|
||||
...
|
||||
LL | }
|
||||
| - mutable borrow ends here
|
||||
|
||||
@ -71,9 +71,9 @@ error[E0502]: cannot borrow `a` (via `a.y`) as mutable because `a` is also borro
|
||||
|
|
||||
LL | let _x = &a.x;
|
||||
| --- immutable borrow occurs here (via `a.x`)
|
||||
LL | let _y = &mut a.y; //~ ERROR cannot borrow
|
||||
LL | let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
||||
| ^^^ mutable borrow occurs here (via `a.y`)
|
||||
LL | //~^ mutable borrow occurs here (via `a.y`)
|
||||
...
|
||||
LL | }
|
||||
| - immutable borrow ends here
|
||||
|
||||
@ -82,8 +82,8 @@ error[E0382]: use of collaterally moved value: `a.y`
|
||||
|
|
||||
LL | let _x = a.x.x;
|
||||
| -- value moved here
|
||||
LL | //~^ value moved here
|
||||
LL | let _y = a.y; //~ ERROR use of collaterally moved
|
||||
LL | //[ast]~^ value moved here
|
||||
LL | let _y = a.y; //[ast]~ ERROR use of collaterally moved
|
||||
| ^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
|
||||
@ -93,8 +93,8 @@ error[E0382]: use of collaterally moved value: `a.y`
|
||||
|
|
||||
LL | let _x = a.x.x;
|
||||
| -- value moved here
|
||||
LL | //~^ value moved here
|
||||
LL | let _y = a.y; //~ ERROR use of collaterally moved
|
||||
LL | //[ast]~^ value moved here
|
||||
LL | let _y = a.y; //[ast]~ ERROR use of collaterally moved
|
||||
| ^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
|
||||
@ -104,8 +104,8 @@ error[E0382]: use of collaterally moved value: `a.y`
|
||||
|
|
||||
LL | let _x = a.x.x;
|
||||
| -- value moved here
|
||||
LL | //~^ value moved here
|
||||
LL | let _y = &a.y; //~ ERROR use of collaterally moved
|
||||
LL | //[ast]~^ value moved here
|
||||
LL | let _y = &a.y; //[ast]~ ERROR use of collaterally moved
|
||||
| ^^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
|
||||
@ -115,7 +115,7 @@ error[E0505]: cannot move out of `a.y` because it is borrowed
|
||||
|
|
||||
LL | let _x = &a.x.x;
|
||||
| ----- borrow of `a.x.x` occurs here
|
||||
LL | //~^ borrow of `a.x.x` occurs here
|
||||
LL | //[ast]~^ borrow of `a.x.x` occurs here
|
||||
LL | let _y = a.y;
|
||||
| ^^ move out of `a.y` occurs here
|
||||
|
||||
@ -124,7 +124,7 @@ error[E0503]: cannot use `a.y` because it was mutably borrowed
|
||||
|
|
||||
LL | let _x = &mut a.x.x;
|
||||
| ----- borrow of `a.x.x` occurs here
|
||||
LL | let _y = a.y; //~ ERROR cannot use
|
||||
LL | let _y = a.y; //[ast]~ ERROR cannot use
|
||||
| ^^ use of borrowed `a.x.x`
|
||||
|
||||
error[E0505]: cannot move out of `a.y` because it is borrowed
|
||||
@ -140,10 +140,10 @@ error[E0502]: cannot borrow `a.y` as immutable because `a.x.x` is also borrowed
|
||||
|
|
||||
LL | let _x = &mut a.x.x;
|
||||
| ----- mutable borrow occurs here
|
||||
LL | //~^ mutable borrow occurs here
|
||||
LL | let _y = &a.y; //~ ERROR cannot borrow
|
||||
LL | //[ast]~^ mutable borrow occurs here
|
||||
LL | let _y = &a.y; //[ast]~ ERROR cannot borrow
|
||||
| ^^^ immutable borrow occurs here
|
||||
LL | //~^ immutable borrow occurs here
|
||||
...
|
||||
LL | }
|
||||
| - mutable borrow ends here
|
||||
|
||||
@ -152,10 +152,10 @@ error[E0502]: cannot borrow `a.y` as mutable because `a.x.x` is also borrowed as
|
||||
|
|
||||
LL | let _x = &a.x.x;
|
||||
| ----- immutable borrow occurs here
|
||||
LL | //~^ immutable borrow occurs here
|
||||
LL | let _y = &mut a.y; //~ ERROR cannot borrow
|
||||
LL | //[ast]~^ immutable borrow occurs here
|
||||
LL | let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
||||
| ^^^ mutable borrow occurs here
|
||||
LL | //~^ mutable borrow occurs here
|
||||
...
|
||||
LL | }
|
||||
| - immutable borrow ends here
|
||||
|
14
src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
Normal file
14
src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: compilation successful
|
||||
--> $DIR/borrowck-box-insensitivity.rs:160:1
|
||||
|
|
||||
LL | / fn main() { //[mir]~ ERROR compilation successful
|
||||
LL | | copy_after_move();
|
||||
LL | | move_after_move();
|
||||
LL | | borrow_after_move();
|
||||
... |
|
||||
LL | | mut_borrow_after_borrow_nested();
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
// This test is an artifact of the old policy that `Box<T>` should not
|
||||
// be treated specially by the AST-borrowck.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
// NLL goes back to treating `Box<T>` specially (namely, knowing that
|
||||
// it uniquely owns the data it holds). See rust-lang/rfcs#130.
|
||||
|
||||
// revisions: ast mir
|
||||
//[ast] compile-flags: -Z borrowck=ast
|
||||
//[mir] compile-flags: -Z borrowck=mir
|
||||
// ignore-compare-mode-nll
|
||||
#![feature(box_syntax, rustc_attrs)]
|
||||
|
||||
struct A {
|
||||
@ -33,131 +33,131 @@ struct D {
|
||||
fn copy_after_move() {
|
||||
let a: Box<_> = box A { x: box 0, y: 1 };
|
||||
let _x = a.x;
|
||||
//~^ value moved here
|
||||
let _y = a.y; //~ ERROR use of moved
|
||||
//~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
|
||||
//~| value used here after move
|
||||
//[ast]~^ value moved here
|
||||
let _y = a.y; //[ast]~ ERROR use of moved
|
||||
//[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
|
||||
//[ast]~| value used here after move
|
||||
}
|
||||
|
||||
fn move_after_move() {
|
||||
let a: Box<_> = box B { x: box 0, y: box 1 };
|
||||
let _x = a.x;
|
||||
//~^ value moved here
|
||||
let _y = a.y; //~ ERROR use of moved
|
||||
//~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
|
||||
//~| value used here after move
|
||||
//[ast]~^ value moved here
|
||||
let _y = a.y; //[ast]~ ERROR use of moved
|
||||
//[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
|
||||
//[ast]~| value used here after move
|
||||
}
|
||||
|
||||
fn borrow_after_move() {
|
||||
let a: Box<_> = box A { x: box 0, y: 1 };
|
||||
let _x = a.x;
|
||||
//~^ value moved here
|
||||
let _y = &a.y; //~ ERROR use of moved
|
||||
//~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
|
||||
//~| value used here after move
|
||||
//[ast]~^ value moved here
|
||||
let _y = &a.y; //[ast]~ ERROR use of moved
|
||||
//[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
|
||||
//[ast]~| value used here after move
|
||||
}
|
||||
|
||||
fn move_after_borrow() {
|
||||
let a: Box<_> = box B { x: box 0, y: box 1 };
|
||||
let _x = &a.x;
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
//[ast]~^ ERROR cannot move
|
||||
//[ast]~| move out of
|
||||
use_imm(_x);
|
||||
}
|
||||
|
||||
fn copy_after_mut_borrow() {
|
||||
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
||||
let _x = &mut a.x;
|
||||
let _y = a.y; //~ ERROR cannot use
|
||||
let _y = a.y; //[ast]~ ERROR cannot use
|
||||
use_mut(_x);
|
||||
}
|
||||
|
||||
fn move_after_mut_borrow() {
|
||||
let mut a: Box<_> = box B { x: box 0, y: box 1 };
|
||||
let _x = &mut a.x;
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
//[ast]~^ ERROR cannot move
|
||||
//[ast]~| move out of
|
||||
use_mut(_x);
|
||||
}
|
||||
|
||||
fn borrow_after_mut_borrow() {
|
||||
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
||||
let _x = &mut a.x;
|
||||
let _y = &a.y; //~ ERROR cannot borrow
|
||||
//~^ immutable borrow occurs here (via `a.y`)
|
||||
let _y = &a.y; //[ast]~ ERROR cannot borrow
|
||||
//[ast]~^ immutable borrow occurs here (via `a.y`)
|
||||
use_mut(_x);
|
||||
}
|
||||
|
||||
fn mut_borrow_after_borrow() {
|
||||
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
||||
let _x = &a.x;
|
||||
let _y = &mut a.y; //~ ERROR cannot borrow
|
||||
//~^ mutable borrow occurs here (via `a.y`)
|
||||
let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
||||
//[ast]~^ mutable borrow occurs here (via `a.y`)
|
||||
use_imm(_x);
|
||||
}
|
||||
|
||||
fn copy_after_move_nested() {
|
||||
let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = a.x.x;
|
||||
//~^ value moved here
|
||||
let _y = a.y; //~ ERROR use of collaterally moved
|
||||
//~| value used here after move
|
||||
//[ast]~^ value moved here
|
||||
let _y = a.y; //[ast]~ ERROR use of collaterally moved
|
||||
//[ast]~| value used here after move
|
||||
}
|
||||
|
||||
fn move_after_move_nested() {
|
||||
let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
|
||||
let _x = a.x.x;
|
||||
//~^ value moved here
|
||||
let _y = a.y; //~ ERROR use of collaterally moved
|
||||
//~| value used here after move
|
||||
//[ast]~^ value moved here
|
||||
let _y = a.y; //[ast]~ ERROR use of collaterally moved
|
||||
//[ast]~| value used here after move
|
||||
}
|
||||
|
||||
fn borrow_after_move_nested() {
|
||||
let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = a.x.x;
|
||||
//~^ value moved here
|
||||
let _y = &a.y; //~ ERROR use of collaterally moved
|
||||
//~| value used here after move
|
||||
//[ast]~^ value moved here
|
||||
let _y = &a.y; //[ast]~ ERROR use of collaterally moved
|
||||
//[ast]~| value used here after move
|
||||
}
|
||||
|
||||
fn move_after_borrow_nested() {
|
||||
let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
|
||||
let _x = &a.x.x;
|
||||
//~^ borrow of `a.x.x` occurs here
|
||||
//[ast]~^ borrow of `a.x.x` occurs here
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
//[ast]~^ ERROR cannot move
|
||||
//[ast]~| move out of
|
||||
use_imm(_x);
|
||||
}
|
||||
|
||||
fn copy_after_mut_borrow_nested() {
|
||||
let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = &mut a.x.x;
|
||||
let _y = a.y; //~ ERROR cannot use
|
||||
let _y = a.y; //[ast]~ ERROR cannot use
|
||||
use_mut(_x);
|
||||
}
|
||||
|
||||
fn move_after_mut_borrow_nested() {
|
||||
let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
|
||||
let _x = &mut a.x.x;
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
//[ast]~^ ERROR cannot move
|
||||
//[ast]~| move out of
|
||||
use_mut(_x);
|
||||
}
|
||||
|
||||
fn borrow_after_mut_borrow_nested() {
|
||||
let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = &mut a.x.x;
|
||||
//~^ mutable borrow occurs here
|
||||
let _y = &a.y; //~ ERROR cannot borrow
|
||||
//~^ immutable borrow occurs here
|
||||
//[ast]~^ mutable borrow occurs here
|
||||
let _y = &a.y; //[ast]~ ERROR cannot borrow
|
||||
//[ast]~^ immutable borrow occurs here
|
||||
use_mut(_x);
|
||||
}
|
||||
|
||||
fn mut_borrow_after_borrow_nested() {
|
||||
let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = &a.x.x;
|
||||
//~^ immutable borrow occurs here
|
||||
let _y = &mut a.y; //~ ERROR cannot borrow
|
||||
//~^ mutable borrow occurs here
|
||||
//[ast]~^ immutable borrow occurs here
|
||||
let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
||||
//[ast]~^ mutable borrow occurs here
|
||||
use_imm(_x);
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() {
|
||||
fn main() { //[mir]~ ERROR compilation successful
|
||||
copy_after_move();
|
||||
move_after_move();
|
||||
borrow_after_move();
|
||||
@ -180,3 +180,6 @@ fn main() {
|
||||
borrow_after_mut_borrow_nested();
|
||||
mut_borrow_after_borrow_nested();
|
||||
}
|
||||
|
||||
fn use_mut<T>(_: &mut T) { }
|
||||
fn use_imm<T>(_: &T) { }
|
||||
|
@ -0,0 +1,31 @@
|
||||
// compile-pass
|
||||
|
||||
// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
|
||||
// (for ensuring that NLL respects user-provided lifetime annotations)
|
||||
// did not handle the case where the ascribed type has some expliit
|
||||
// wildcards (`_`) mixed in, and it caused an internal compiler error
|
||||
// (ICE).
|
||||
//
|
||||
// This test is just checking that we do not ICE when such things
|
||||
// occur.
|
||||
|
||||
struct X;
|
||||
struct Y;
|
||||
struct Z;
|
||||
|
||||
struct Pair { x: X, y: Y }
|
||||
|
||||
pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
|
||||
where A: FnOnce() -> RA + Send,
|
||||
B: FnOnce() -> RB + Send,
|
||||
RA: Send,
|
||||
RB: Send
|
||||
{
|
||||
(oper_a(), oper_b())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ((_x, _y), _z): (_, Z) = join(|| (X, Y), || Z);
|
||||
|
||||
let (Pair { x: _x, y: _y }, Z): (_, Z) = join(|| Pair { x: X, y: Y }, || Z);
|
||||
}
|
31
src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs
Normal file
31
src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Crate that exports a const fn. Used for testing cross-crate.
|
||||
|
||||
#![feature(staged_api, rustc_attrs)]
|
||||
#![stable(since="1.0.0", feature = "mep")]
|
||||
|
||||
#![crate_type="rlib"]
|
||||
|
||||
#[rustc_promotable]
|
||||
#[stable(since="1.0.0", feature = "mep")]
|
||||
#[inline]
|
||||
pub const fn foo() -> usize { 22 }
|
||||
|
||||
#[stable(since="1.0.0", feature = "mep")]
|
||||
pub struct Foo(usize);
|
||||
|
||||
impl Foo {
|
||||
#[stable(since="1.0.0", feature = "mep")]
|
||||
#[inline]
|
||||
#[rustc_promotable]
|
||||
pub const fn foo() -> usize { 22 }
|
||||
}
|
3
src/test/ui/consts/const-prop-ice.rs
Normal file
3
src/test/ui/consts/const-prop-ice.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
[0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
|
||||
}
|
10
src/test/ui/consts/const-prop-ice.stderr
Normal file
10
src/test/ui/consts/const-prop-ice.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: index out of bounds: the len is 3 but the index is 3
|
||||
--> $DIR/const-prop-ice.rs:2:5
|
||||
|
|
||||
LL | [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: #[deny(const_err)] on by default
|
||||
|
||||
error: aborting due to previous error
|
||||
|
5
src/test/ui/consts/const-prop-ice2.rs
Normal file
5
src/test/ui/consts/const-prop-ice2.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
enum Enum { One=1 }
|
||||
let xs=[0;1 as usize];
|
||||
println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1
|
||||
}
|
10
src/test/ui/consts/const-prop-ice2.stderr
Normal file
10
src/test/ui/consts/const-prop-ice2.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: index out of bounds: the len is 1 but the index is 1
|
||||
--> $DIR/const-prop-ice2.rs:4:20
|
||||
|
|
||||
LL | println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: #[deny(const_err)] on by default
|
||||
|
||||
error: aborting due to previous error
|
||||
|
13
src/test/ui/consts/promote_fn_calls.rs
Normal file
13
src/test/ui/consts/promote_fn_calls.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// compile-pass
|
||||
// aux-build:promotable_const_fn_lib.rs
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
extern crate promotable_const_fn_lib;
|
||||
|
||||
use promotable_const_fn_lib::{foo, Foo};
|
||||
|
||||
fn main() {
|
||||
let x: &'static usize = &foo();
|
||||
let x: &'static usize = &Foo::foo();
|
||||
}
|
30
src/test/ui/consts/promote_fn_calls_std.rs
Normal file
30
src/test/ui/consts/promote_fn_calls_std.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// compile-pass
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
fn main() {
|
||||
let x: &'static u8 = &u8::max_value();
|
||||
let x: &'static u16 = &u16::max_value();
|
||||
let x: &'static u32 = &u32::max_value();
|
||||
let x: &'static u64 = &u64::max_value();
|
||||
let x: &'static u128 = &u128::max_value();
|
||||
let x: &'static usize = &usize::max_value();
|
||||
let x: &'static u8 = &u8::min_value();
|
||||
let x: &'static u16 = &u16::min_value();
|
||||
let x: &'static u32 = &u32::min_value();
|
||||
let x: &'static u64 = &u64::min_value();
|
||||
let x: &'static u128 = &u128::min_value();
|
||||
let x: &'static usize = &usize::min_value();
|
||||
let x: &'static i8 = &i8::max_value();
|
||||
let x: &'static i16 = &i16::max_value();
|
||||
let x: &'static i32 = &i32::max_value();
|
||||
let x: &'static i64 = &i64::max_value();
|
||||
let x: &'static i128 = &i128::max_value();
|
||||
let x: &'static isize = &isize::max_value();
|
||||
let x: &'static i8 = &i8::min_value();
|
||||
let x: &'static i16 = &i16::min_value();
|
||||
let x: &'static i32 = &i32::min_value();
|
||||
let x: &'static i64 = &i64::min_value();
|
||||
let x: &'static i128 = &i128::min_value();
|
||||
let x: &'static isize = &isize::min_value();
|
||||
}
|
@ -14,5 +14,4 @@ trait Trait {
|
||||
|
||||
type Foo = Trait; //~ ERROR E0191
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -8,16 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
use std::iter::Iterator;
|
||||
trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
|
||||
type Unit = ();
|
||||
|
||||
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
Box::new(None.into_iter())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: &Iterator<Item = i32, Item = i32>;
|
||||
test();
|
||||
}
|
19
src/test/ui/error-codes/E0719.stderr
Normal file
19
src/test/ui/error-codes/E0719.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
|
||||
--> $DIR/E0719.rs:11:33
|
||||
|
|
||||
LL | trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
|
||||
--> $DIR/E0719.rs:15:38
|
||||
|
|
||||
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
|
||||
| --------- ^^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0719`.
|
11
src/test/ui/hygiene/no_implicit_prelude-2018.rs
Normal file
11
src/test/ui/hygiene/no_implicit_prelude-2018.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// edition:2018
|
||||
|
||||
#[no_implicit_prelude]
|
||||
mod bar {
|
||||
fn f() {
|
||||
::std::print!(""); // OK
|
||||
print!(); //~ ERROR cannot find macro `print!` in this scope
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
10
src/test/ui/hygiene/no_implicit_prelude-2018.stderr
Normal file
10
src/test/ui/hygiene/no_implicit_prelude-2018.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: cannot find macro `print!` in this scope
|
||||
--> $DIR/no_implicit_prelude-2018.rs:7:9
|
||||
|
|
||||
LL | print!(); //~ ERROR cannot find macro `print!` in this scope
|
||||
| ^^^^^
|
||||
|
|
||||
= help: have you added the `#[macro_use]` on the module/import?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -21,7 +21,10 @@ mod bar {
|
||||
Vec::new(); //~ ERROR failed to resolve
|
||||
().clone() //~ ERROR no method named `clone` found
|
||||
}
|
||||
fn f() { ::foo::m!(); }
|
||||
fn f() {
|
||||
::foo::m!();
|
||||
println!(); // OK on 2015 edition (at least for now)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user