diff options
| author | Axary <bastian_kauschke@hotmail.de> | 2018-11-11 10:41:49 +0100 |
|---|---|---|
| committer | Axary <bastian_kauschke@hotmail.de> | 2018-11-11 10:41:49 +0100 |
| commit | 50307942481ffd95e9eb616463363542bc79b14b (patch) | |
| tree | 4088a496090b024effdae0ed3beb24791225be46 /src | |
| parent | 852ff1fc7d74a7668441e0f354f8c477c95b676d (diff) | |
| parent | b76ee83254ec0398da554f25c2168d917ba60f1c (diff) | |
| download | rust-50307942481ffd95e9eb616463363542bc79b14b.tar.gz rust-50307942481ffd95e9eb616463363542bc79b14b.zip | |
Merge branch 'master' of https://github.com/rust-lang/rust
Diffstat (limited to 'src')
116 files changed, 1482 insertions, 892 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock index b4317864502..2ac51263cb5 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -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" diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 45f035ad04f..bb52d7990ff 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -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)); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 2c396b3b06b..b63b3684964 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -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)); diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 113a85abecb..58639808fae 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -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. diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 9176e0d32cb..0c870f9e404 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -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 diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index cceae9249e4..7ed6e4a8f51 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -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, diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1bbc7892c6b..c69d4441121 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -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 diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index a0c87f13e5d..c008b78e450 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -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 diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 1d0b194487e..8c4ff02aa14 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -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 { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c6cbeea5a0e..30b7b454684 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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)) + } } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 68de82d2945..308dd9c79fa 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -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, diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 62ccf6c865c..827e297c84d 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -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. /// /// ``` diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 1d21a5cf79d..96590c1fc72 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -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` diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index a2095ff40c0..f57e3ff913b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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), diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 49858972416..cc73dd63816 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -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) => { diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 523f03c2cfc..f2825887f36 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -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 diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index 88d45671b9a..a7a79dd2e65 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -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 diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 266b1c4d4a0..01d87bdbf63 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -301,12 +301,6 @@ declare_lint! { } declare_lint! { - pub DUPLICATE_ASSOCIATED_TYPE_BINDINGS, - Warn, - "warns about duplicate associated type bindings in generics" -} - -declare_lint! { pub DUPLICATE_MACRO_EXPORTS, Deny, "detects duplicate macro exports" @@ -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, diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 4b53235eab4..f773f46b6f5 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -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) } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index fe94b62ef19..efd7e8b610e 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -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 diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b7512790bfb..33b689c60a1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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)] diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 6b5eb4293e0..b59bd0e2388 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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()); diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 74f8d67ce04..3a882506b41 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -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>> { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 05d9d4bc37d..82095a2f5b0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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(_, _) => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c7c197d11c0..ef9b3e3efab 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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 } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 449730c9d06..7fac88a3d78 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -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))); } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 28b58d62175..a4130bf15cb 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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 => {} } } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index c1aed36c92d..b28e7c9fb19 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -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) diff --git a/src/librustc_apfloat/Cargo.toml b/src/librustc_apfloat/Cargo.toml index 735b74f1565..a8a5da90c7a 100644 --- a/src/librustc_apfloat/Cargo.toml +++ b/src/librustc_apfloat/Cargo.toml @@ -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"] } diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 87d59d2e763..4f405858e35 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -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); diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 6ea722ba769..69c9f385409 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -53,6 +53,7 @@ extern crate rustc_cratesio_shim; #[macro_use] extern crate bitflags; +extern crate smallvec; use std::cmp::Ordering; use std::fmt; diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index bd7a1c2c329..03b0b04d401 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -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, diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index ce4cb1ea3a0..54245a36017 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -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 } } } diff --git a/src/librustc_codegen_llvm/back/bytecode.rs b/src/librustc_codegen_llvm/back/bytecode.rs index 9a3dd9d2f88..0b264de18c1 100644 --- a/src/librustc_codegen_llvm/back/bytecode.rs +++ b/src/librustc_codegen_llvm/back/bytecode.rs @@ -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]; diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index dd95c3d9862..111637b6aa9 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -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 } } diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 3d96fef7c0d..76faffa2521 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -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)) } diff --git a/src/librustc_codegen_llvm/back/rpath.rs b/src/librustc_codegen_llvm/back/rpath.rs index 9609cb0c155..ee4a9b30a1a 100644 --- a/src/librustc_codegen_llvm/back/rpath.rs +++ b/src/librustc_codegen_llvm/back/rpath.rs @@ -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> { diff --git a/src/librustc_codegen_llvm/back/wasm.rs b/src/librustc_codegen_llvm/back/wasm.rs index f37854b7bca..7101255173c 100644 --- a/src/librustc_codegen_llvm/back/wasm.rs +++ b/src/librustc_codegen_llvm/back/wasm.rs @@ -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 } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 184be4b9eab..8973852caa8 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -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); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 555e4012c3a..81d615b5ad7 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -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}); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index ba1e3f5960c..00f06645930 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -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 diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index a4401cf96d9..a5f90149f4a 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -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 => { diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 0e8fb1c28a3..eaa599e0cd0 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -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(); } diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index d38f343d01f..0dc5a4ddde8 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -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); diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index a6e2ccf92e4..e5b25ea068b 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -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)), diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index 51a233d7916..6fb78fe4aa5 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -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) } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index b01d7e3a776..fea02edf7be 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -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) }; diff --git a/src/librustc_codegen_utils/linker.rs b/src/librustc_codegen_utils/linker.rs index c1f41fd509a..ae1d77f1521 100644 --- a/src/librustc_codegen_utils/linker.rs +++ b/src/librustc_codegen_utils/linker.rs @@ -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 diff --git a/src/librustc_codegen_utils/symbol_export.rs b/src/librustc_codegen_utils/symbol_export.rs index 6c40296b2ef..dff7e518630 100644 --- a/src/librustc_codegen_utils/symbol_export.rs +++ b/src/librustc_codegen_utils/symbol_export.rs @@ -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) } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index f289acc032b..8c0e9bd11a1 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -318,11 +318,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { 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>", edition: None, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 99372a511a9..a32fb0503a8 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -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 diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 734ddbc3ab9..a057f2f45c0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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 ( diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index cb2a750f4e3..3eb3d7600fd 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -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)?; } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 4d3b422ab28..98311444e28 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -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); } _ => {}, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 4f92ba40048..885d70dc430 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -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: \ diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2db3bbda323..1cce0de5152 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -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>) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ca9c4eb9b8b..03497be0308 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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" diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 43a5fdb7a02..db5b516e7b2 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -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()) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index c7d0469e556..15f61a03344 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -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")?, diff --git a/src/librustc_target/spec/wasm32_unknown_emscripten.rs b/src/librustc_target/spec/wasm32_unknown_emscripten.rs index b4c09f86b8a..2c80f3b4b3b 100644 --- a/src/librustc_target/spec/wasm32_unknown_emscripten.rs +++ b/src/librustc_target/spec/wasm32_unknown_emscripten.rs @@ -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, diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 7cc064f9c3d..7514c2c18e7 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -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() diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 2ed02a4cdab..e635bc9efc4 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -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, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 18f8473b5b5..572e79407a1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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() diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 4a300fe0921..a477df6ae2d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -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. // diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3156458b4aa..84967aaf72f 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -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" => diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 266b9e3c0ab..8574443190d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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] diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index be09cfce8ca..d5f5cbb562e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index c81aea2465b..a985c3e9fdf 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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 } diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index d748d93d898..6ed59837eb4 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -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: diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 903aafed641..7dafe67485a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -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() diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index efd71ad0763..f560350d510 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -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(); diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs new file mode 100644 index 00000000000..3baa082bd0e --- /dev/null +++ b/src/librustdoc/html/static_files.rs @@ -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"); +} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f0f36f0355e..4b043b26d86 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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; diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index dfec13cd2ec..87ffe0f15e4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -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. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f27beb0b46c..0829593505d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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. // diff --git a/src/test/mir-opt/inline-trait-method_2.rs b/src/test/mir-opt/inline-trait-method_2.rs new file mode 100644 index 00000000000..aa756f4a233 --- /dev/null +++ b/src/test/mir-opt/inline-trait-method_2.rs @@ -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 diff --git a/src/test/run-pass/associated-types/associated-types-from-supertrait.rs b/src/test/run-pass/associated-types/associated-types-from-supertrait.rs new file mode 100644 index 00000000000..e69c0af2be7 --- /dev/null +++ b/src/test/run-pass/associated-types/associated-types-from-supertrait.rs @@ -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; +} diff --git a/src/test/run-pass/issues/issue-24010.rs b/src/test/run-pass/issues/issue-24010.rs new file mode 100644 index 00000000000..cce8bb84837 --- /dev/null +++ b/src/test/run-pass/issues/issue-24010.rs @@ -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); +} diff --git a/src/test/run-pass/traits/trait-alias-object-type.rs b/src/test/run-pass/traits/trait-alias-object.rs index 17e30922b2c..adac28eeb12 100644 --- a/src/test/run-pass/traits/trait-alias-object-type.rs +++ b/src/test/run-pass/traits/trait-alias-object.rs @@ -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)); } diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs new file mode 100644 index 00000000000..8d91561b7d6 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs @@ -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(); +} diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr new file mode 100644 index 00000000000..536cd945083 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -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`. diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.rs b/src/test/ui/associated-types/associated-types-overridden-binding.rs new file mode 100644 index 00000000000..ed2211ecffd --- /dev/null +++ b/src/test/ui/associated-types/associated-types-overridden-binding.rs @@ -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>; +} diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr new file mode 100644 index 00000000000..216aa097db9 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -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`. diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr index 5bf1fc08178..95b26a5724a 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.stderr +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr @@ -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 diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr new file mode 100644 index 00000000000..171e992e8a6 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr @@ -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 + diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.rs b/src/test/ui/borrowck/borrowck-box-insensitivity.rs index eabb8d7bca3..2af97a9fc1d 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.rs +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.rs @@ -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) { } diff --git a/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs new file mode 100644 index 00000000000..6d91fd3508a --- /dev/null +++ b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs @@ -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); +} diff --git a/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs new file mode 100644 index 00000000000..f6bbcc60e4e --- /dev/null +++ b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs @@ -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 } +} diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs new file mode 100644 index 00000000000..13309f978b6 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice.rs @@ -0,0 +1,3 @@ +fn main() { + [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3 +} diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr new file mode 100644 index 00000000000..749ef952b5d --- /dev/null +++ b/src/test/ui/consts/const-prop-ice.stderr @@ -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 + diff --git a/src/test/ui/consts/const-prop-ice2.rs b/src/test/ui/consts/const-prop-ice2.rs new file mode 100644 index 00000000000..e5fd79f1167 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice2.rs @@ -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 +} diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr new file mode 100644 index 00000000000..4febd0ee1e3 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice2.stderr @@ -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 + diff --git a/src/test/ui/consts/promote_fn_calls.rs b/src/test/ui/consts/promote_fn_calls.rs new file mode 100644 index 00000000000..045322de347 --- /dev/null +++ b/src/test/ui/consts/promote_fn_calls.rs @@ -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(); +} diff --git a/src/test/ui/consts/promote_fn_calls_std.rs b/src/test/ui/consts/promote_fn_calls_std.rs new file mode 100644 index 00000000000..0350708d673 --- /dev/null +++ b/src/test/ui/consts/promote_fn_calls_std.rs @@ -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(); +} diff --git a/src/test/ui/error-codes/E0191.rs b/src/test/ui/error-codes/E0191.rs index 489ebb033f8..c35c7e10f5a 100644 --- a/src/test/ui/error-codes/E0191.rs +++ b/src/test/ui/error-codes/E0191.rs @@ -14,5 +14,4 @@ trait Trait { type Foo = Trait; //~ ERROR E0191 -fn main() { -} +fn main() {} diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.rs b/src/test/ui/error-codes/E0719.rs index 2c789a139cd..c7bfa85093f 100644 --- a/src/test/ui/lint/issue-50589-multiple-associated-types.rs +++ b/src/test/ui/error-codes/E0719.rs @@ -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(); } diff --git a/src/test/ui/error-codes/E0719.stderr b/src/test/ui/error-codes/E0719.stderr new file mode 100644 index 00000000000..3a908fceced --- /dev/null +++ b/src/test/ui/error-codes/E0719.stderr @@ -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`. diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs new file mode 100644 index 00000000000..3ad7435fecf --- /dev/null +++ b/src/test/ui/hygiene/no_implicit_prelude-2018.rs @@ -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() {} diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr new file mode 100644 index 00000000000..370fc9784ad --- /dev/null +++ b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr @@ -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 + diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs index bf07bc05491..5b6041945ab 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.rs +++ b/src/test/ui/hygiene/no_implicit_prelude.rs @@ -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() {} diff --git a/src/test/ui/issue-51947.rs b/src/test/ui/issue-51947.rs deleted file mode 100644 index 7b79807e4d7..00000000000 --- a/src/test/ui/issue-51947.rs +++ /dev/null @@ -1,17 +0,0 @@ -// compile-pass - -#![crate_type = "lib"] -#![feature(linkage)] - -// MergeFunctions will merge these via an anonymous internal -// backing function, which must be named if ThinLTO buffers are used - -#[linkage = "weak"] -pub fn fn1(a: u32, b: u32, c: u32) -> u32 { - a + b + c -} - -#[linkage = "weak"] -pub fn fn2(a: u32, b: u32, c: u32) -> u32 { - a + b + c -} diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index c43f8d77823..9620f893386 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,10 +1,11 @@ -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next` +error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized` --> $DIR/issue-23122-2.rs:17:15 | LL | impl<T: Next> Next for GetNext<T> { | ^^^^ | = help: consider adding a `#![recursion_limit="128"]` attribute to your crate + = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51947.rs b/src/test/ui/issues/issue-51947.rs new file mode 100644 index 00000000000..3e0c3c002f6 --- /dev/null +++ b/src/test/ui/issues/issue-51947.rs @@ -0,0 +1,27 @@ +// 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. + +// compile-pass + +#![crate_type = "lib"] +#![feature(linkage)] + +// MergeFunctions will merge these via an anonymous internal +// backing function, which must be named if ThinLTO buffers are used + +#[linkage = "weak"] +pub fn fn1(a: u32, b: u32, c: u32) -> u32 { + a + b + c +} + +#[linkage = "weak"] +pub fn fn2(a: u32, b: u32, c: u32) -> u32 { + a + b + c +} diff --git a/src/test/ui/issues/issue-55796.rs b/src/test/ui/issues/issue-55796.rs new file mode 100644 index 00000000000..b48d4a9c022 --- /dev/null +++ b/src/test/ui/issues/issue-55796.rs @@ -0,0 +1,22 @@ +pub trait EdgeTrait<N> { + fn target(&self) -> N; +} + +pub trait Graph<'a> { + type Node; + type Edge: EdgeTrait<Self::Node>; + type NodesIter: Iterator<Item = Self::Node> + 'a; + type EdgesIter: Iterator<Item = Self::Edge> + 'a; + + fn nodes(&'a self) -> Self::NodesIter; + fn out_edges(&'a self, u: &Self::Node) -> Self::EdgesIter; + fn in_edges(&'a self, u: &Self::Node) -> Self::EdgesIter; + + fn out_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> { + Box::new(self.out_edges(u).map(|e| e.target())) + } + + fn in_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> { + Box::new(self.in_edges(u).map(|e| e.target())) + } +} diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr new file mode 100644 index 00000000000..60ce8293a5c --- /dev/null +++ b/src/test/ui/issues/issue-55796.stderr @@ -0,0 +1,50 @@ +error[E0601]: `main` function not found in crate `issue_55796` + | + = note: consider adding a `main` function to `$DIR/issue-55796.rs` + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/issue-55796.rs:16:9 + | +LL | Box::new(self.out_edges(u).map(|e| e.target())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17... + --> $DIR/issue-55796.rs:5:17 + | +LL | pub trait Graph<'a> { + | ^^ +note: ...so that the type `std::iter::Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:16:40: 16:54]>` will meet its required lifetime bounds + --> $DIR/issue-55796.rs:16:9 + | +LL | Box::new(self.out_edges(u).map(|e| e.target())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: but, the lifetime must be valid for the static lifetime... + = note: ...so that the expression is assignable: + expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)> + found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>> + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/issue-55796.rs:20:9 + | +LL | Box::new(self.in_edges(u).map(|e| e.target())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17... + --> $DIR/issue-55796.rs:5:17 + | +LL | pub trait Graph<'a> { + | ^^ +note: ...so that the type `std::iter::Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:20:39: 20:53]>` will meet its required lifetime bounds + --> $DIR/issue-55796.rs:20:9 + | +LL | Box::new(self.in_edges(u).map(|e| e.target())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: but, the lifetime must be valid for the static lifetime... + = note: ...so that the expression is assignable: + expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)> + found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>> + +error: aborting due to 3 previous errors + +Some errors occurred: E0495, E0601. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.stderr b/src/test/ui/lint/issue-50589-multiple-associated-types.stderr deleted file mode 100644 index 7f0a1ee1f33..00000000000 --- a/src/test/ui/lint/issue-50589-multiple-associated-types.stderr +++ /dev/null @@ -1,23 +0,0 @@ -warning: associated type binding `Item` specified more than once - --> $DIR/issue-50589-multiple-associated-types.rs:17:39 - | -LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> { - | --------- ^^^^^^^^^^^ used more than once - | | - | first use of `Item` - | - = note: #[warn(duplicate_associated_type_bindings)] on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589> - -warning: associated type binding `Item` specified more than once - --> $DIR/issue-50589-multiple-associated-types.rs:17:39 - | -LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> { - | --------- ^^^^^^^^^^^ used more than once - | | - | first use of `Item` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589> - diff --git a/src/test/ui/lint/lint-unused-mut-variables.nll.stderr b/src/test/ui/lint/lint-unused-mut-variables.nll.stderr deleted file mode 100644 index 40f68c67827..00000000000 --- a/src/test/ui/lint/lint-unused-mut-variables.nll.stderr +++ /dev/null @@ -1,150 +0,0 @@ -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:59:14 - | -LL | let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - | -note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:19:9 - | -LL | #![deny(unused_mut)] - | ^^^^^^^^^^ - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:24:9 - | -LL | let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:26:9 - | -LL | let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:28:9 - | -LL | let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:30:9 - | -LL | let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:32:10 - | -LL | let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:34:9 - | -LL | let mut a; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:38:9 - | -LL | let mut b; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:47:9 - | -LL | mut x => {} //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:51:8 - | -LL | (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:64:9 - | -LL | let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:69:9 - | -LL | let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:72:9 - | -LL | let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:84:9 - | -LL | let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:61:13 - | -LL | fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable - | ----^^^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:79:20 - | -LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { - | ----^^^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:143:9 - | -LL | let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable - | ----^ - | | - | help: remove this `mut` - | -note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:139:8 - | -LL | #[deny(unused_mut)] - | ^^^^^^^^^^ - -error: aborting due to 17 previous errors - diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 14d836074dc..a2005ba9f72 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lexical nll -#![cfg_attr(nll, feature(nll))] + + // Exercise the unused_mut attribute in some positive and negative cases @@ -21,22 +21,22 @@ fn main() { // negative cases - let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable - let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable - let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable - let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable - let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable - let mut a; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + let mut a = 3; //~ ERROR: variable does not need to be mutable + + let mut a = 2; //~ ERROR: variable does not need to be mutable + + let mut b = 3; //~ ERROR: variable does not need to be mutable + + let mut a = vec![3]; //~ ERROR: variable does not need to be mutable + + let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable + + let mut a; //~ ERROR: variable does not need to be mutable + a = 3; - let mut b; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + let mut b; //~ ERROR: variable does not need to be mutable + if true { b = 3; } else { @@ -44,45 +44,45 @@ fn main() { } match 30 { - mut x => {} //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + mut x => {} //~ ERROR: variable does not need to be mutable + } match (30, 2) { - (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + (mut x, 1) | //~ ERROR: variable does not need to be mutable + (mut x, 2) | (mut x, 3) => { } _ => {} } - let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable - fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable + + fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable + + + let mut a = &mut 5; //~ ERROR: variable does not need to be mutable - let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable *a = 4; let mut a = 5; - let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable - *b.0 = 4; //[nll]~^ ERROR: variable does not need to be mutable + let mut b = (&mut a,); //~ ERROR: variable does not need to be mutable + *b.0 = 4; + + let mut x = &mut 1; //~ ERROR: variable does not need to be mutable - let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable let mut f = || { *x += 1; }; f(); fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { - &mut arg[..] //[lexical]~^ ERROR: variable does not need to be mutable - //[nll]~^^ ERROR: variable does not need to be mutable + &mut arg[..] //~^ ERROR: variable does not need to be mutable + } - let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable + v.push(()); // positive cases @@ -140,6 +140,6 @@ fn foo(mut a: isize) { fn bar() { #[allow(unused_mut)] let mut a = 3; - let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable - //[nll]~^ ERROR: variable does not need to be mutable + let mut b = vec![2]; //~ ERROR: variable does not need to be mutable + } diff --git a/src/test/ui/lint/lint-unused-mut-variables.lexical.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index 40f68c67827..60e8400c428 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.lexical.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -1,7 +1,7 @@ error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:59:14 | -LL | let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable +LL | let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -15,7 +15,7 @@ LL | #![deny(unused_mut)] error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:24:9 | -LL | let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut a = 3; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -23,7 +23,7 @@ LL | let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:26:9 | -LL | let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut a = 2; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -31,7 +31,7 @@ LL | let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:28:9 | -LL | let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut b = 3; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -39,7 +39,7 @@ LL | let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:30:9 | -LL | let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut a = vec![3]; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -47,7 +47,7 @@ LL | let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be m error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:32:10 | -LL | let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable +LL | let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -55,7 +55,7 @@ LL | let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:34:9 | -LL | let mut a; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut a; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -63,7 +63,7 @@ LL | let mut a; //[lexical]~ ERROR: variable does not need to be mutable error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:38:9 | -LL | let mut b; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut b; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -71,7 +71,7 @@ LL | let mut b; //[lexical]~ ERROR: variable does not need to be mutable error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:47:9 | -LL | mut x => {} //[lexical]~ ERROR: variable does not need to be mutable +LL | mut x => {} //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -79,7 +79,7 @@ LL | mut x => {} //[lexical]~ ERROR: variable does not need to be mutabl error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:51:8 | -LL | (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable +LL | (mut x, 1) | //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -87,7 +87,7 @@ LL | (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:64:9 | -LL | let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut a = &mut 5; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -95,7 +95,7 @@ LL | let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mu error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:69:9 | -LL | let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut b = (&mut a,); //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -103,7 +103,7 @@ LL | let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:72:9 | -LL | let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut x = &mut 1; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -111,7 +111,7 @@ LL | let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mu error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:84:9 | -LL | let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` @@ -119,7 +119,7 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable do error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:61:13 | -LL | fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable +LL | fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable | ----^^^ | | | help: remove this `mut` @@ -135,7 +135,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:143:9 | -LL | let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable +LL | let mut b = vec![2]; //~ ERROR: variable does not need to be mutable | ----^ | | | help: remove this `mut` diff --git a/src/test/ui/nll/issue-55394.rs b/src/test/ui/nll/issue-55394.rs new file mode 100644 index 00000000000..452fc88d1ec --- /dev/null +++ b/src/test/ui/nll/issue-55394.rs @@ -0,0 +1,25 @@ +// Copyright 2017 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(nll)] + +struct Bar; + +struct Foo<'s> { + bar: &'s mut Bar, +} + +impl Foo<'_> { + fn new(bar: &mut Bar) -> Self { + Foo { bar } + } +} + +fn main() { } diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr new file mode 100644 index 00000000000..284d7afa6fd --- /dev/null +++ b/src/test/ui/nll/issue-55394.stderr @@ -0,0 +1,12 @@ +error: unsatisfied lifetime constraints + --> $DIR/issue-55394.rs:21:9 + | +LL | fn new(bar: &mut Bar) -> Self { + | - ---- return type is Foo<'2> + | | + | let's call the lifetime of this reference `'1` +LL | Foo { bar } + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/src/test/ui/traits/trait-alias-objects.rs b/src/test/ui/traits/trait-alias-object.rs index 3adcd8436d8..3adcd8436d8 100644 --- a/src/test/ui/traits/trait-alias-objects.rs +++ b/src/test/ui/traits/trait-alias-object.rs diff --git a/src/test/ui/traits/trait-alias-objects.stderr b/src/test/ui/traits/trait-alias-object.stderr index 8f9681e898f..6b7b322a53d 100644 --- a/src/test/ui/traits/trait-alias-objects.stderr +++ b/src/test/ui/traits/trait-alias-object.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `EqAlias` cannot be made into an object - --> $DIR/trait-alias-objects.rs:17:13 + --> $DIR/trait-alias-object.rs:17:13 | LL | let _: &dyn EqAlias = &123; | ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object @@ -7,7 +7,7 @@ LL | let _: &dyn EqAlias = &123; = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified - --> $DIR/trait-alias-objects.rs:18:13 + --> $DIR/trait-alias-object.rs:18:13 | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); | ^^^^^^^^^^^^^^^^^ missing associated type `Item` value diff --git a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs new file mode 100644 index 00000000000..9eed80ad886 --- /dev/null +++ b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs @@ -0,0 +1,23 @@ +// compile-pass + +// rust-lang/rust#55810: types for a binding in a match arm can be +// inferred from arms that come later in the match. + +struct S; + +impl S { + fn method(&self) -> bool { + unimplemented!() + } +} + +fn get<T>() -> T { + unimplemented!() +} + +fn main() { + match get() { + x if x.method() => {} + &S => {} + } +} diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 1fa30882067703202d13ad0bd53d630bc2c1de6 +Subproject 241fac0e3933063fa48a1a01f5d577e40af12e4 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index ee14c62df30..f2b08f8e0bb 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -59,4 +59,4 @@ openssl = { version = "0.10.12", optional = true } [features] -all-static = ['openssl/vendored', 'curl-sys/static-curl'] +all-static = ['openssl/vendored', 'curl-sys/static-curl', 'curl-sys/force-system-lib-on-osx'] |
