diff --git a/RELEASES.md b/RELEASES.md index c798c56cd6d03..57aacd8c5ecc4 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,439 @@ +Version 1.12.0 (2016-09-29) +=========================== + +Highlights +---------- + +* [`rustc` translates code to LLVM IR via its own "middle" IR (MIR)] + (https://github.com/rust-lang/rust/pull/34096). + This translation pass is far simpler than the previous AST->LLVM pass, and + creates opportunities to perform new optimizations directly on the MIR. It + was previously described [on the Rust blog] + (https://blog.rust-lang.org/2016/04/19/MIR.html). +* [`rustc` presents a new, more readable error format, along with + machine-readable JSON error output for use by IDEs] + (https://github.com/rust-lang/rust/pull/35401). + Most common editors supporting Rust have been updated to work with it. It was + previously described [on the Rust blog] + (https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html). + +Compiler +-------- + +* [`rustc` translates code to LLVM IR via its own "middle" IR (MIR)] + (https://github.com/rust-lang/rust/pull/34096). + This translation pass is far simpler than the previous AST->LLVM pass, and + creates opportunities to perform new optimizations directly on the MIR. It + was previously described [on the Rust blog] + (https://blog.rust-lang.org/2016/04/19/MIR.html). +* [Print the Rust target name, not the LLVM target name, with + `--print-target-list`] + (https://github.com/rust-lang/rust/pull/35489) +* [The computation of `TypeId` is correct in some cases where it was previously + producing inconsistent results] + (https://github.com/rust-lang/rust/pull/35267) +* [The `mips-unknown-linux-gnu` target uses hardware floating point by default] + (https://github.com/rust-lang/rust/pull/34910) +* [The `rustc` arguments, `--print target-cpus`, `--print target-features`, + `--print relocation-models`, and `--print code-models` print the available + options to the `-C target-cpu`, `-C target-feature`, `-C relocation-model` and + `-C code-model` code generation arguments] + (https://github.com/rust-lang/rust/pull/34845) +* [`rustc` supports three new MUSL targets on ARM: `arm-unknown-linux-musleabi`, + `arm-unknown-linux-musleabihf`, and `armv7-unknown-linux-musleabihf`] + (https://github.com/rust-lang/rust/pull/35060). + These targets produce statically-linked binaries. There are no binary release + builds yet though. + +Diagnostics +----------- + +* [`rustc` presents a new, more readable error format, along with + machine-readable JSON error output for use by IDEs] + (https://github.com/rust-lang/rust/pull/35401). + Most common editors supporting Rust have been updated to work with it. It was + previously described [on the Rust blog] + (https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html). +* [In error descriptions, references are now described in plain english, + instead of as "&-ptr"] + (https://github.com/rust-lang/rust/pull/35611) +* [In error type descriptions, unknown numeric types are named `{integer}` or + `{float}` instead of `_`] + (https://github.com/rust-lang/rust/pull/35080) +* [`rustc` emits a clearer error when inner attributes follow a doc comment] + (https://github.com/rust-lang/rust/pull/34676) + +Language +-------- + +* [`macro_rules!` invocations can be made within `macro_rules!` invocations] + (https://github.com/rust-lang/rust/pull/34925) +* [`macro_rules!` meta-variables are hygienic] + (https://github.com/rust-lang/rust/pull/35453) +* [`macro_rules!` `tt` matchers can be reparsed correctly, making them much more + useful] + (https://github.com/rust-lang/rust/pull/34908) +* [`macro_rules!` `stmt` matchers correctly consume the entire contents when + insider non-braces invocations] + (https://github.com/rust-lang/rust/pull/34886) +* [Semicolons are properly required as statement delimeters inside + `macro_rules!` invocations] + (https://github.com/rust-lang/rust/pull/34660) +* [`cfg_attr` works on `path` attributes] + (https://github.com/rust-lang/rust/pull/34546) + +Stabilized APIs +--------------- + +* [`Cell::as_ptr`] + (https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_ptr) +* [`RefCell::as_ptr`] + (https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.as_ptr) +* [`IpAddr::is_unspecified`] + (https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_unspecified) +* [`IpAddr::is_loopback`] + (https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_loopback) +* [`IpAddr::is_multicast`] + (https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_multicast) +* [`Ipv4Addr::is_unspecified`] + (https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html#method.is_unspecified) +* [`Ipv6Addr::octets`] + (https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html#method.octets) +* [`LinkedList::contains`] + (https://doc.rust-lang.org/std/collections/linked_list/struct.LinkedList.html#method.contains) +* [`VecDeque::contains`] + (https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.contains) +* [`ExitStatusExt::from_raw`] + (https://doc.rust-lang.org/std/os/unix/process/trait.ExitStatusExt.html#tymethod.from_raw). + Both on Unix and Windows. +* [`Receiver::recv_timeout`] + (https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html#method.recv_timeout) +* [`RecvTimeoutError`] + (https://doc.rust-lang.org/std/sync/mpsc/enum.RecvTimeoutError.html) +* [`BinaryHeap::peek_mut`] + (https://doc.rust-lang.org/std/collections/binary_heap/struct.BinaryHeap.html#method.peek_mut) +* [`PeekMut`] + (https://doc.rust-lang.org/std/collections/binary_heap/struct.PeekMut.html) +* [`iter::Product`] + (https://doc.rust-lang.org/std/iter/trait.Product.html) +* [`iter::Sum`] + (https://doc.rust-lang.org/std/iter/trait.Sum.html) +* [`OccupiedEntry::remove_entry`] + (https://doc.rust-lang.org/std/collections/btree_map/struct.OccupiedEntry.html#method.remove_entry) +* [`VacantEntry::into_key`] + (https://doc.rust-lang.org/std/collections/btree_map/struct.VacantEntry.html#method.into_key) + +Libraries +--------- + +* [The `format!` macro and friends now allow a single argument to be formatted + in multiple styles] + (https://github.com/rust-lang/rust/pull/33642) +* [The lifetime bounds on `[T]::binary_search_by` and + `[T]::binary_search_by_key` have been adjusted to be more flexible] + (https://github.com/rust-lang/rust/pull/34762) +* [`Option` implements `From` for its contained type] + (https://github.com/rust-lang/rust/pull/34828) +* [`Cell`, `RefCell` and `UnsafeCell` implement `From` for their contained type] + (https://github.com/rust-lang/rust/pull/35392) +* [`RwLock` panics if the reader count overflows] + (https://github.com/rust-lang/rust/pull/35378) +* [`vec_deque::Drain`, `hash_map::Drain` and `hash_set::Drain` are covariant] + (https://github.com/rust-lang/rust/pull/35354) +* [`vec::Drain` and `binary_heap::Drain` are covariant] + (https://github.com/rust-lang/rust/pull/34951) +* [`Cow` implements `FromIterator` for `char`, `&str` and `String`] + (https://github.com/rust-lang/rust/pull/35064) +* [Sockets on Linux are correctly closed in subprocesses via `SOCK_CLOEXEC`] + (https://github.com/rust-lang/rust/pull/34946) +* [`hash_map::Entry`, `hash_map::VacantEntry` and `hash_map::OccupiedEntry` + implement `Debug`] + (https://github.com/rust-lang/rust/pull/34946) +* [`btree_map::Entry`, `btree_map::VacantEntry` and `btree_map::OccupiedEntry` + implement `Debug`] + (https://github.com/rust-lang/rust/pull/34885) +* [`String` implements `AddAssign`] + (https://github.com/rust-lang/rust/pull/34890) +* [Variadic `extern fn` pointers implement the `Clone`, `PartialEq`, `Eq`, + `PartialOrd`, `Ord`, `Hash`, `fmt::Pointer`, and `fmt::Debug` traits] + (https://github.com/rust-lang/rust/pull/34879) +* [`FileType` implements `Debug`] + (https://github.com/rust-lang/rust/pull/34757) +* [References to `Mutex` and `RwLock` are unwind-safe] + (https://github.com/rust-lang/rust/pull/34756) +* [`mpsc::sync_channel` `Receiver`s return any available message before + reporting a disconnect] + (https://github.com/rust-lang/rust/pull/34731) +* [Unicode definitions have been updated to 9.0] + (https://github.com/rust-lang/rust/pull/34599) +* [`env` iterators implement `DoubleEndedIterator`] + (https://github.com/rust-lang/rust/pull/33312) + +Cargo +----- + +* [Support local mirrors of registries] + (https://github.com/rust-lang/cargo/pull/2857) +* [Add support for command aliases] + (https://github.com/rust-lang/cargo/pull/2679) +* [Allow `opt-level="s"` / `opt-level="z"` in profile overrides] + (https://github.com/rust-lang/cargo/pull/3007) +* [Make `cargo doc --open --target` work as expected] + (https://github.com/rust-lang/cargo/pull/2988) +* [Speed up noop registry updates] + (https://github.com/rust-lang/cargo/pull/2974) +* [Update OpenSSL] + (https://github.com/rust-lang/cargo/pull/2971) +* [Fix `--panic=abort` with plugins] + (https://github.com/rust-lang/cargo/pull/2954) +* [Always pass `-C metadata` to the compiler] + (https://github.com/rust-lang/cargo/pull/2946) +* [Fix depending on git repos with workspaces] + (https://github.com/rust-lang/cargo/pull/2938) +* [Add a `--lib` flag to `cargo new`] + (https://github.com/rust-lang/cargo/pull/2921) +* [Add `http.cainfo` for custom certs] + (https://github.com/rust-lang/cargo/pull/2917) +* [Indicate the compilation profile after compiling] + (https://github.com/rust-lang/cargo/pull/2909) +* [Allow enabling features for dependencies with `--features`] + (https://github.com/rust-lang/cargo/pull/2876) +* [Add `--jobs` flag to `cargo package`] + (https://github.com/rust-lang/cargo/pull/2867) +* [Add `--dry-run` to `cargo publish`] + (https://github.com/rust-lang/cargo/pull/2849) +* [Add support for `RUSTDOCFLAGS`] + (https://github.com/rust-lang/cargo/pull/2794) + +Performance +----------- + +* [`rustc` produces more compact code by more precisely identifying the live + ranges of variables] + (https://github.com/rust-lang/rust/pull/35409) +* [`panic::catch_unwind` is more optimized] + (https://github.com/rust-lang/rust/pull/35444) +* [`panic::catch_unwind` no longer accesses thread-local storage on entry] + (https://github.com/rust-lang/rust/pull/34866) + +Tooling +------- + +* [Test binaries now support a `--test-threads` argument to specify the number + of threads used to run tests, and which acts the same as the + `RUST_TEST_THREADS` environment variable] + (https://github.com/rust-lang/rust/pull/35414) +* [The test runner now emits a warning when tests run over 60 seconds] + (https://github.com/rust-lang/rust/pull/35405) +* [rustdoc: Fix methods in search results] + (https://github.com/rust-lang/rust/pull/34752) +* [`rust-lldb` warns about unsupported versions of LLDB] + (https://github.com/rust-lang/rust/pull/34646) +* [Rust releases now come with source packages that can be installed by rustup + via `rustup component add rust-src`] + (https://github.com/rust-lang/rust/pull/34366). + The resulting source code can be used by tools and IDES, located in the + sysroot under `lib/rustlib/src`. + +Misc +---- + +* [The compiler can now be built against LLVM 3.9] + (https://github.com/rust-lang/rust/pull/35594) +* Many minor improvements to the documentation. +* [The Rust exception handling "personality" routine is now written in Rust] + (https://github.com/rust-lang/rust/pull/34832) + +Compatibility Notes +------------------- + +* [When printing Windows `OsStr`s, unpaired surrogate codepoints are escaped + with the lowercase format instead of the uppercase] + (https://github.com/rust-lang/rust/pull/35084) +* [When formatting strings, if "precision" is specified, the "fill", + "align" and "width" specifiers are no longer ignored] + (https://github.com/rust-lang/rust/pull/34544) +* [The `Debug` impl for strings no longer escapes all non-ASCII characters] + (https://github.com/rust-lang/rust/pull/34485) + + +Version 1.11.0 (2016-08-18) +=========================== + +Language +-------- + +* [`cfg_attr` works on `path` attributes] + (https://github.com/rust-lang/rust/pull/34546) +* [Support nested `cfg_attr` attributes] + (https://github.com/rust-lang/rust/pull/34216) +* [Allow statement-generating braced macro invocations at the end of blocks] + (https://github.com/rust-lang/rust/pull/34436) +* [Macros can be expanded inside of trait definitions] + (https://github.com/rust-lang/rust/pull/34213) +* [`#[macro_use]` works properly when it is itself expanded from a macro] + (https://github.com/rust-lang/rust/pull/34032) + +Stabilized APIs +--------------- + +* [`BinaryHeap::append`] + (https://doc.rust-lang.org/std/collections/binary_heap/struct.BinaryHeap.html#method.append) +* [`BTreeMap::append`] + (https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.append) +* [`BTreeMap::split_off`] + (https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.split_off) +* [`BTreeSet::append`] + (https://doc.rust-lang.org/std/collections/btree_set/struct.BTreeSet.html#method.append) +* [`BTreeSet::split_off`] + (https://doc.rust-lang.org/std/collections/btree_set/struct.BTreeSet.html#method.split_off) +* [`f32::to_degrees`] + (https://doc.rust-lang.org/std/primitive.f32.html#method.to_degrees) + (in libcore - previously stabilized in libstd) +* [`f32::to_radians`] + (https://doc.rust-lang.org/std/primitive.f32.html#method.to_radians) + (in libcore - previously stabilized in libstd) +* [`f64::to_degrees`] + (https://doc.rust-lang.org/std/primitive.f64.html#method.to_degrees) + (in libcore - previously stabilized in libstd) +* [`f64::to_radians`] + (https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians) + (in libcore - previously stabilized in libstd) +* [`Iterator::sum`] + (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum) +* [`Iterator::product`] + (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum) +* [`Cell::get_mut`] + (https://doc.rust-lang.org/std/cell/struct.Cell.html#method.get_mut) +* [`RefCell::get_mut`] + (https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.get_mut) + +Libraries +--------- + +* [The `thread_local!` macro supports multiple definitions in a single + invocation, and can apply attributes] + (https://github.com/rust-lang/rust/pull/34077) +* [`Cow` implements `Default`] + (https://github.com/rust-lang/rust/pull/34305) +* [`Wrapping` implements binary, octal, lower-hex and upper-hex + `Display` formatting] + (https://github.com/rust-lang/rust/pull/34190) +* [The range types implement `Hash`] + (https://github.com/rust-lang/rust/pull/34180) +* [`lookup_host` ignores unknown address types] + (https://github.com/rust-lang/rust/pull/34067) +* [`assert_eq!` accepts a custom error message, like `assert!` does] + (https://github.com/rust-lang/rust/pull/33976) +* [The main thread is now called "main" instead of "<main>"] + (https://github.com/rust-lang/rust/pull/33803) + +Cargo +----- + +* [Disallow specifying features of transitive deps] + (https://github.com/rust-lang/cargo/pull/2821) +* [Add color support for Windows consoles] + (https://github.com/rust-lang/cargo/pull/2804) +* [Fix `harness = false` on `[lib]` sections] + (https://github.com/rust-lang/cargo/pull/2795) +* [Don't panic when `links` contains a '.'] + (https://github.com/rust-lang/cargo/pull/2787) +* [Build scripts can emit warnings] + (https://github.com/rust-lang/cargo/pull/2630), + and `-vv` prints warnings for all crates. +* [Ignore file locks on OS X NFS mounts] + (https://github.com/rust-lang/cargo/pull/2720) +* [Don't warn about `package.metadata` keys] + (https://github.com/rust-lang/cargo/pull/2668). + This provides room for expansion by arbitrary tools. +* [Add support for cdylib crate types] + (https://github.com/rust-lang/cargo/pull/2741) +* [Prevent publishing crates when files are dirty] + (https://github.com/rust-lang/cargo/pull/2781) +* [Don't fetch all crates on clean] + (https://github.com/rust-lang/cargo/pull/2704) +* [Propagate --color option to rustc] + (https://github.com/rust-lang/cargo/pull/2779) +* [Fix `cargo doc --open` on Windows] + (https://github.com/rust-lang/cargo/pull/2780) +* [Improve autocompletion] + (https://github.com/rust-lang/cargo/pull/2772) +* [Configure colors of stderr as well as stdout] + (https://github.com/rust-lang/cargo/pull/2739) + +Performance +----------- + +* [Caching projections speeds up type check dramatically for some + workloads] + (https://github.com/rust-lang/rust/pull/33816) +* [The default `HashMap` hasher is SipHash 1-3 instead of SipHash 2-4] + (https://github.com/rust-lang/rust/pull/33940) + This hasher is faster, but is believed to provide sufficient + protection from collision attacks. +* [Comparison of `Ipv4Addr` is 10x faster] + (https://github.com/rust-lang/rust/pull/33891) + +Rustdoc +------- + +* [Fix empty implementation section on some module pages] + (https://github.com/rust-lang/rust/pull/34536) +* [Fix inlined renamed reexports in import lists] + (https://github.com/rust-lang/rust/pull/34479) +* [Fix search result layout for enum variants and struct fields] + (https://github.com/rust-lang/rust/pull/34477) +* [Fix issues with source links to external crates] + (https://github.com/rust-lang/rust/pull/34387) +* [Fix redirect pages for renamed reexports] + (https://github.com/rust-lang/rust/pull/34245) + +Tooling +------- + +* [rustc is better at finding the MSVC toolchain] + (https://github.com/rust-lang/rust/pull/34492) +* [When emitting debug info, rustc emits frame pointers for closures, + shims and glue, as it does for all other functions] + (https://github.com/rust-lang/rust/pull/33909) +* [rust-lldb warns about unsupported versions of LLDB] + (https://github.com/rust-lang/rust/pull/34646) +* Many more errors have been given error codes and extended + explanations +* API documentation continues to be improved, with many new examples + +Misc +---- + +* [rustc no longer hangs when dependencies recursively re-export + submodules] + (https://github.com/rust-lang/rust/pull/34542) +* [rustc requires LLVM 3.7+] + (https://github.com/rust-lang/rust/pull/34104) +* [The 'How Safe and Unsafe Interact' chapter of The Rustonomicon was + rewritten] + (https://github.com/rust-lang/rust/pull/33895) +* [rustc support 16-bit pointer sizes] + (https://github.com/rust-lang/rust/pull/33460). + No targets use this yet, but it works toward AVR support. + +Compatibility Notes +------------------- + +* [`const`s and `static`s may not have unsized types] + (https://github.com/rust-lang/rust/pull/34443) +* [The new follow-set rules that place restrictions on `macro_rules!` + in order to ensure syntax forward-compatibility have been enabled] + (https://github.com/rust-lang/rust/pull/33982) + This was an [ammendment to RFC 550] + (https://github.com/rust-lang/rfcs/pull/1384), + and has been a warning since 1.10. +* [`cfg` attribute process has been refactored to fix various bugs] + (https://github.com/rust-lang/rust/pull/33706). + This causes breakage in some corner cases. + + Version 1.10.0 (2016-07-07) =========================== diff --git a/mk/main.mk b/mk/main.mk index c6c3e70abc37a..171ded4230370 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,12 +13,12 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.12.0 +CFG_RELEASE_NUM=1.12.1 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.1 +CFG_PRERELEASE_VERSION=.6 ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index b9f5c6fcab909..fe9b60c393f09 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -223,19 +223,19 @@ pub struct BinaryHeap { /// on `BinaryHeap`. See its documentation for details. /// /// [`peek_mut()`]: struct.BinaryHeap.html#method.peek_mut -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub struct PeekMut<'a, T: 'a + Ord> { heap: &'a mut BinaryHeap } -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> Drop for PeekMut<'a, T> { fn drop(&mut self) { self.heap.sift_down(0); } } -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> Deref for PeekMut<'a, T> { type Target = T; fn deref(&self) -> &T { @@ -243,7 +243,7 @@ impl<'a, T: Ord> Deref for PeekMut<'a, T> { } } -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> DerefMut for PeekMut<'a, T> { fn deref_mut(&mut self) -> &mut T { &mut self.heap.data[0] @@ -366,7 +366,6 @@ impl BinaryHeap { /// Basic usage: /// /// ``` - /// #![feature(binary_heap_peek_mut)] /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); /// assert!(heap.peek_mut().is_none()); @@ -380,7 +379,7 @@ impl BinaryHeap { /// } /// assert_eq!(heap.peek(), Some(&2)); /// ``` - #[unstable(feature = "binary_heap_peek_mut", issue = "34392")] + #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c3a7d4023754a..a2e2ad37acb84 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1981,8 +1981,6 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::BTreeMap; /// use std::collections::btree_map::Entry; /// @@ -1992,7 +1990,7 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// v.into_key(); /// } /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn into_key(self) -> K { self.key } @@ -2074,13 +2072,18 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { self.handle.reborrow().into_kv().0 } + /// Deprecated, renamed to `remove_entry` + #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to `remove_entry`")] + pub fn remove_pair(self) -> (K, V) { + self.remove_entry() + } + /// Take ownership of the key and value from the map. /// /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::BTreeMap; /// use std::collections::btree_map::Entry; /// @@ -2089,14 +2092,14 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// // We delete the entry from the map. - /// o.remove_pair(); + /// o.remove_entry(); /// } /// /// // If now try to get the value, it will panic: /// // println!("{}", map["poneyland"]); /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] - pub fn remove_pair(self) -> (K, V) { + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn remove_entry(self) -> (K, V) { self.remove_kv() } diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 6842f02e0e19b..73aa67849fd2a 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -379,8 +379,6 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(linked_list_contains)] - /// /// use std::collections::LinkedList; /// /// let mut list: LinkedList = LinkedList::new(); @@ -392,8 +390,7 @@ impl LinkedList { /// assert_eq!(list.contains(&0), true); /// assert_eq!(list.contains(&10), false); /// ``` - #[unstable(feature = "linked_list_contains", reason = "recently added", - issue = "32630")] + #[stable(feature = "linked_list_contains", since = "1.12.0")] pub fn contains(&self, x: &T) -> bool where T: PartialEq { diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 788c838cd3fc8..1ba0319f2d7d9 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1901,26 +1901,6 @@ impl Into> for String { } } -#[stable(feature = "stringfromchars", since = "1.12.0")] -impl<'a> From<&'a [char]> for String { - #[inline] - fn from(v: &'a [char]) -> String { - let mut s = String::with_capacity(v.len()); - for c in v { - s.push(*c); - } - s - } -} - -#[stable(feature = "stringfromchars", since = "1.12.0")] -impl From> for String { - #[inline] - fn from(v: Vec) -> String { - String::from(v.as_slice()) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { #[inline] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a6f817a89624c..3aefcc7d4cfa4 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1453,10 +1453,11 @@ impl IntoIterator for Vec { } else { begin.offset(self.len() as isize) as *const T }; - let buf = ptr::read(&self.buf); + let cap = self.buf.cap(); mem::forget(self); IntoIter { - _buf: buf, + buf: Shared::new(begin), + cap: cap, ptr: begin, end: end, } @@ -1708,8 +1709,9 @@ impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - _buf: RawVec, - ptr: *mut T, + buf: Shared, + cap: usize, + ptr: *const T, end: *const T, } @@ -1750,7 +1752,7 @@ impl IntoIter { #[unstable(feature = "vec_into_iter_as_slice", issue = "35601")] pub fn as_mut_slice(&self) -> &mut [T] { unsafe { - slice::from_raw_parts_mut(self.ptr, self.len()) + slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } } } @@ -1846,9 +1848,10 @@ impl Drop for IntoIter { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { // destroy the remaining elements - for _x in self {} + for _x in self.by_ref() {} // RawVec handles deallocation + let _ = unsafe { RawVec::from_raw_parts(*self.buf, self.cap) }; } } diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 9c3792afa2f1c..aa42daec4c2d1 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -938,8 +938,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vec_deque_contains)] - /// /// use std::collections::VecDeque; /// /// let mut vector: VecDeque = VecDeque::new(); @@ -950,8 +948,7 @@ impl VecDeque { /// assert_eq!(vector.contains(&1), true); /// assert_eq!(vector.contains(&10), false); /// ``` - #[unstable(feature = "vec_deque_contains", reason = "recently added", - issue = "32630")] + #[stable(feature = "vec_deque_contains", since = "1.12.0")] pub fn contains(&self, x: &T) -> bool where T: PartialEq { diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index ab3231b2b9955..f448fcf2dbf99 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -11,7 +11,6 @@ #![deny(warnings)] #![feature(binary_heap_extras)] -#![feature(binary_heap_peek_mut)] #![feature(box_syntax)] #![feature(btree_range)] #![feature(collections)] @@ -19,7 +18,6 @@ #![feature(const_fn)] #![feature(fn_traits)] #![feature(enumset)] -#![feature(linked_list_contains)] #![feature(pattern)] #![feature(rand)] #![feature(step_by)] @@ -27,7 +25,6 @@ #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] -#![feature(vec_deque_contains)] #![feature(vec_into_iter_as_slice)] extern crate collections; diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 9556174bd2294..537fabf8ab69b 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -11,7 +11,7 @@ use std::borrow::Cow; use std::iter::{FromIterator, repeat}; use std::mem::size_of; -use std::vec::Drain; +use std::vec::{Drain, IntoIter}; use test::Bencher; @@ -537,6 +537,7 @@ fn test_cow_from() { #[allow(dead_code)] fn assert_covariance() { fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d } + fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> { i } } #[bench] diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 17ec325e257b0..a388012e1daf2 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -233,10 +233,28 @@ impl Cell { /// ``` #[inline] #[unstable(feature = "as_unsafe_cell", issue = "27708")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to as_ptr")] pub fn as_unsafe_cell(&self) -> &UnsafeCell { &self.value } + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + pub fn as_ptr(&self) -> *mut T { + self.value.get() + } + /// Returns a mutable reference to the underlying data. /// /// This call borrows `Cell` mutably (at compile-time) which guarantees @@ -653,10 +671,28 @@ impl RefCell { /// ``` #[inline] #[unstable(feature = "as_unsafe_cell", issue = "27708")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to as_ptr")] pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell { &self.value } + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + pub fn as_ptr(&self) -> *mut T { + self.value.get() + } + /// Returns a mutable reference to the underlying data. /// /// This call borrows `RefCell` mutably (at compile-time) so there is no diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d2de0d46d746b..37baa0c40434a 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -301,7 +301,6 @@ use clone::Clone; use cmp; -use default::Default; use fmt; use iter_private::TrustedRandomAccess; use ops::FnMut; @@ -626,7 +625,9 @@ impl DoubleEndedIterator for Chain where pub struct Zip { a: A, b: B, - spec: <(A, B) as ZipImplData>::Data, + // index and len are only used by the specialized version of zip + index: usize, + len: usize, } #[stable(feature = "rust1", since = "1.0.0")] @@ -668,17 +669,6 @@ trait ZipImpl { B: DoubleEndedIterator + ExactSizeIterator; } -// Zip specialization data members -#[doc(hidden)] -trait ZipImplData { - type Data: 'static + Clone + Default + fmt::Debug; -} - -#[doc(hidden)] -impl ZipImplData for T { - default type Data = (); -} - // General Zip impl #[doc(hidden)] impl ZipImpl for Zip @@ -689,7 +679,8 @@ impl ZipImpl for Zip Zip { a: a, b: b, - spec: Default::default(), // unused + index: 0, // unused + len: 0, // unused } } @@ -742,20 +733,6 @@ impl ZipImpl for Zip } } -#[doc(hidden)] -#[derive(Default, Debug, Clone)] -struct ZipImplFields { - index: usize, - len: usize, -} - -#[doc(hidden)] -impl ZipImplData for (A, B) - where A: TrustedRandomAccess, B: TrustedRandomAccess -{ - type Data = ZipImplFields; -} - #[doc(hidden)] impl ZipImpl for Zip where A: TrustedRandomAccess, B: TrustedRandomAccess @@ -765,18 +742,16 @@ impl ZipImpl for Zip Zip { a: a, b: b, - spec: ZipImplFields { - index: 0, - len: len, - } + index: 0, + len: len, } } #[inline] fn next(&mut self) -> Option<(A::Item, B::Item)> { - if self.spec.index < self.spec.len { - let i = self.spec.index; - self.spec.index += 1; + if self.index < self.len { + let i = self.index; + self.index += 1; unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) } @@ -787,7 +762,7 @@ impl ZipImpl for Zip #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.spec.len - self.spec.index; + let len = self.len - self.index; (len, Some(len)) } @@ -796,9 +771,9 @@ impl ZipImpl for Zip where A: DoubleEndedIterator + ExactSizeIterator, B: DoubleEndedIterator + ExactSizeIterator { - if self.spec.index < self.spec.len { - self.spec.len -= 1; - let i = self.spec.len; + if self.index < self.len { + self.len -= 1; + let i = self.len; unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) } diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 4cbabe3f5edaf..cb509156e325e 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -563,10 +563,11 @@ impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I {} /// implement the trait can be generated by the `sum` method. Like /// `FromIterator` this trait should rarely be called directly and instead /// interacted with through `Iterator::sum`. -#[unstable(feature = "iter_arith_traits", issue = "34529")] +#[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// "summing up" the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] fn sum>(iter: I) -> Self; } @@ -577,16 +578,17 @@ pub trait Sum: Sized { /// which implement the trait can be generated by the `product` method. Like /// `FromIterator` this trait should rarely be called directly and instead /// interacted with through `Iterator::product`. -#[unstable(feature = "iter_arith_traits", issue = "34529")] +#[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// multiplying the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] fn product>(iter: I) -> Self; } macro_rules! integer_sum_product { ($($a:ident)*) => ($( - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold(0, |a, b| { @@ -595,7 +597,7 @@ macro_rules! integer_sum_product { } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { iter.fold(1, |a, b| { @@ -604,7 +606,7 @@ macro_rules! integer_sum_product { } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold(0, |a, b| { @@ -613,7 +615,7 @@ macro_rules! integer_sum_product { } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold(1, |a, b| { @@ -626,28 +628,28 @@ macro_rules! integer_sum_product { macro_rules! float_sum_product { ($($a:ident)*) => ($( - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold(0.0, |a, b| a + b) } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { iter.fold(1.0, |a, b| a * b) } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold(0.0, |a, b| a + *b) } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold(1.0, |a, b| a * *b) diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index a635620d12abd..a7c230ba979be 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -176,21 +176,21 @@ fn ref_mut_map_accessor() { } #[test] -fn as_unsafe_cell() { +fn as_ptr() { let c1: Cell = Cell::new(0); c1.set(1); - assert_eq!(1, unsafe { *c1.as_unsafe_cell().get() }); + assert_eq!(1, unsafe { *c1.as_ptr() }); let c2: Cell = Cell::new(0); - unsafe { *c2.as_unsafe_cell().get() = 1; } + unsafe { *c2.as_ptr() = 1; } assert_eq!(1, c2.get()); let r1: RefCell = RefCell::new(0); *r1.borrow_mut() = 1; - assert_eq!(1, unsafe { *r1.as_unsafe_cell().get() }); + assert_eq!(1, unsafe { *r1.as_ptr() }); let r2: RefCell = RefCell::new(0); - unsafe { *r2.as_unsafe_cell().get() = 1; } + unsafe { *r2.as_ptr() = 1; } assert_eq!(1, *r2.borrow()); } diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 9428b4096bfec..9116344c57938 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -10,7 +10,6 @@ #![deny(warnings)] -#![feature(as_unsafe_cell)] #![feature(borrow_state)] #![feature(box_syntax)] #![feature(cell_extras)] diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index fdae8f69a9c0e..bd0c2f5126d13 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -264,30 +264,6 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction { eh::find_eh_action(lsda, &eh_context) } -// *** Delete after a new snapshot *** -#[cfg(all(stage0, any(target_os = "ios", not(target_arch = "arm"))))] -#[lang = "eh_personality_catch"] -#[no_mangle] -pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code { - rust_eh_personality(version, actions, exception_class, ue_header, context) -} - -// *** Delete after a new snapshot *** -#[cfg(all(stage0, target_arch = "arm", not(target_os = "ios")))] -#[lang = "eh_personality_catch"] -#[no_mangle] -pub unsafe extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code { - rust_eh_personality(state, ue_header, context) -} - // See docs in the `unwind` module. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] #[lang = "eh_unwind_resume"] diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index 3642e2488958e..e6d3920b29cb0 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -81,21 +81,6 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { // This is considered acceptable, because the behavior of throwing exceptions // through a C ABI boundary is undefined. -// *** Delete after a new snapshot *** -#[cfg(stage0)] -#[lang = "eh_personality_catch"] -#[cfg(not(test))] -unsafe extern "C" fn rust_eh_personality_catch(exceptionRecord: *mut c::EXCEPTION_RECORD, - establisherFrame: c::LPVOID, - contextRecord: *mut c::CONTEXT, - dispatcherContext: *mut c::DISPATCHER_CONTEXT) - -> c::EXCEPTION_DISPOSITION { - rust_eh_personality(exceptionRecord, - establisherFrame, - contextRecord, - dispatcherContext) -} - #[lang = "eh_personality"] #[cfg(not(test))] unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut c::EXCEPTION_RECORD, diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index f0ddcdc07e120..3230a08c27630 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -114,7 +114,7 @@ declare_lint! { declare_lint! { pub PRIVATE_IN_PUBLIC, - Deny, + Warn, "detect private items in public interfaces not caught by the old implementation" } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 74d29b273ff2b..b83826de26dd6 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1479,7 +1479,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.tcx.region_maps.call_site_extent(id, body.id), &self.fn_ret(id)); - if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { + if fn_ret.is_never() { + // FIXME(durka) this rejects code like `fn foo(x: !) -> ! { x }` + if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() { + span_err!(self.ir.tcx.sess, sp, E0270, + "computation may converge in a function marked as diverging"); + } + } else if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env), diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0997d6c1a7562..a428c99119a38 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -107,6 +107,11 @@ impl FlagComputation { } &ty::TyProjection(ref data) => { + // currently we can't normalize projections that + // include bound regions, so track those separately. + if !data.has_escaping_regions() { + self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); + } self.add_flags(TypeFlags::HAS_PROJECTION); self.add_projection_ty(data); } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 3eeff6ee5792f..a8826f0b23ba6 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -105,7 +105,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_TY_INFER | TypeFlags::HAS_PARAMS | - TypeFlags::HAS_PROJECTION | + TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_TY_ERR | TypeFlags::HAS_SELF) } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8ddd8bef36a6f..5e4e7b342d631 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the def-id of `def_id`'s parent in the def tree. If /// this returns `None`, then `def_id` represents a crate root or /// inlined root. - fn parent_def_id(&self, def_id: DefId) -> Option { + pub fn parent_def_id(&self, def_id: DefId) -> Option { let key = self.def_key(def_id); key.parent.map(|index| DefId { krate: def_id.krate, index: index }) } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 195cece6bc4e0..7c944020e9352 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -803,10 +803,10 @@ impl<'a, 'gcx, 'tcx> Layout { ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) | ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let non_zero = !ty.is_unsafe_ptr(); + let pointee = normalize_associated_type(infcx, pointee); if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) { Scalar { value: Pointer, non_zero: non_zero } } else { - let pointee = normalize_associated_type(infcx, pointee); let unsized_part = tcx.struct_tail(pointee); let meta = match unsized_part.sty { ty::TySlice(_) | ty::TyStr => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cfc2e89f9d5a1..02be1573bf176 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -527,6 +527,10 @@ bitflags! { // Only set for TyInfer other than Fresh. const KEEP_IN_LOCAL_TCX = 1 << 11, + // Is there a projection that does not involve a bound region? + // Currently we can't normalize projections w/ bound regions. + const HAS_NORMALIZABLE_PROJECTION = 1 << 12, + const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_SELF.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6f57ae2941838..f9a5331926424 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1049,7 +1049,8 @@ fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec(f: F) { - const STACK_SIZE: usize = 8 * 1024 * 1024; // 8MB + // Temporarily have stack size set to 16MB to deal with nom-using crates failing + const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB struct Sink(Arc>>); impl Write for Sink { diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index ae5ccbfd82099..78330f0b9753b 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::LogicalOp { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } | + ExprKind::Use { .. } | ExprKind::NeverToAny { .. } | ExprKind::ReifyFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } | diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index dafc53d3c1542..3cd79ee1c5aa1 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -115,6 +115,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source = unpack!(block = this.as_operand(block, source)); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } + ExprKind::Use { source } => { + let source = unpack!(block = this.as_operand(block, source)); + block.and(Rvalue::Use(source)) + } ExprKind::ReifyFnPointer { source } => { let source = unpack!(block = this.as_operand(block, source)); block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty)) diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index c19ea0f445ac0..9671f80f48ba7 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -68,6 +68,7 @@ impl Category { ExprKind::Binary { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } | + ExprKind::Use { .. } | ExprKind::ReifyFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } | ExprKind::Unsize { .. } | diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index e5930f5a62df6..58265b5b0d36b 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -249,6 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Binary { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } | + ExprKind::Use { .. } | ExprKind::ReifyFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } | ExprKind::Unsize { .. } | diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index cae9e8379897c..dc1d63a291118 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -198,8 +198,11 @@ impl<'tcx> Scope<'tcx> { /// /// Should always be run for all inner scopes when a drop is pushed into some scope enclosing a /// larger extent of code. - fn invalidate_cache(&mut self) { - self.cached_exits = FnvHashMap(); + /// + /// `unwind` controls whether caches for the unwind branch are also invalidated. + fn invalidate_cache(&mut self, unwind: bool) { + self.cached_exits.clear(); + if !unwind { return; } for dropdata in &mut self.drops { if let DropKind::Value { ref mut cached_block } = dropdata.kind { *cached_block = None; @@ -455,25 +458,65 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; for scope in self.scopes.iter_mut().rev() { - if scope.extent == extent { + let this_scope = scope.extent == extent; + // When building drops, we try to cache chains of drops in such a way so these drops + // could be reused by the drops which would branch into the cached (already built) + // blocks. This, however, means that whenever we add a drop into a scope which already + // had some blocks built (and thus, cached) for it, we must invalidate all caches which + // might branch into the scope which had a drop just added to it. This is necessary, + // because otherwise some other code might use the cache to branch into already built + // chain of drops, essentially ignoring the newly added drop. + // + // For example consider there’s two scopes with a drop in each. These are built and + // thus the caches are filled: + // + // +--------------------------------------------------------+ + // | +---------------------------------+ | + // | | +--------+ +-------------+ | +---------------+ | + // | | | return | <-+ | drop(outer) | <-+ | drop(middle) | | + // | | +--------+ +-------------+ | +---------------+ | + // | +------------|outer_scope cache|--+ | + // +------------------------------|middle_scope cache|------+ + // + // Now, a new, inner-most scope is added along with a new drop into both inner-most and + // outer-most scopes: + // + // +------------------------------------------------------------+ + // | +----------------------------------+ | + // | | +--------+ +-------------+ | +---------------+ | +-------------+ + // | | | return | <+ | drop(new) | <-+ | drop(middle) | <--+| drop(inner) | + // | | +--------+ | | drop(outer) | | +---------------+ | +-------------+ + // | | +-+ +-------------+ | | + // | +---|invalid outer_scope cache|----+ | + // +----=----------------|invalid middle_scope cache|-----------+ + // + // If, when adding `drop(new)` we do not invalidate the cached blocks for both + // outer_scope and middle_scope, then, when building drops for the inner (right-most) + // scope, the old, cached blocks, without `drop(new)` will get used, producing the + // wrong results. + // + // The cache and its invalidation for unwind branch is somewhat special. The cache is + // per-drop, rather than per scope, which has a several different implications. Adding + // a new drop into a scope will not invalidate cached blocks of the prior drops in the + // scope. That is true, because none of the already existing drops will have an edge + // into a block with the newly added drop. + // + // Note that this code iterates scopes from the inner-most to the outer-most, + // invalidating caches of each scope visited. This way bare minimum of the + // caches gets invalidated. i.e. if a new drop is added into the middle scope, the + // cache of outer scpoe stays intact. + let invalidate_unwind = needs_drop && !this_scope; + scope.invalidate_cache(invalidate_unwind); + if this_scope { if let DropKind::Value { .. } = drop_kind { scope.needs_cleanup = true; } - - // No need to invalidate any caches here. The just-scheduled drop will branch into - // the drop that comes before it in the vector. scope.drops.push(DropData { span: span, location: lvalue.clone(), kind: drop_kind }); return; - } else { - // We must invalidate all the cached_blocks leading up to the scope we’re - // looking for, because all of the blocks in the chain will become incorrect. - if let DropKind::Value { .. } = drop_kind { - scope.invalidate_cache() - } } } span_bug!(span, "extent {:?} not in scope to drop {:?}", extent, lvalue); @@ -490,11 +533,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: &Lvalue<'tcx>, item_ty: Ty<'tcx>) { for scope in self.scopes.iter_mut().rev() { + // See the comment in schedule_drop above. The primary difference is that we invalidate + // the unwind blocks unconditionally. That’s because the box free may be considered + // outer-most cleanup within the scope. + scope.invalidate_cache(true); if scope.extent == extent { assert!(scope.free.is_none(), "scope already has a scheduled free!"); - // We also must invalidate the caches in the scope for which the free is scheduled - // because the drops must branch into the free we schedule here. - scope.invalidate_cache(); scope.needs_cleanup = true; scope.free = Some(FreeData { span: span, @@ -503,11 +547,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { cached_block: None }); return; - } else { - // We must invalidate all the cached_blocks leading up to the scope we’re looking - // for, because otherwise some/most of the blocks in the chain will become - // incorrect. - scope.invalidate_cache(); } } span_bug!(span, "extent {:?} not in scope to free {:?}", extent, value); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a61fdb79df822..605798ad44ce1 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -602,8 +602,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Check to see if this cast is a "coercion cast", where the cast is actually done // using a coercion (or is a no-op). if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) { - // Skip the actual cast itexpr, as it's now a no-op. - return source.make_mirror(cx); + // Convert the lexpr to a vexpr. + ExprKind::Use { source: source.to_ref() } } else { ExprKind::Cast { source: source.to_ref() } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 2a5b7d0fb2902..cc59346487e39 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> { Cast { source: ExprRef<'tcx>, }, + Use { + source: ExprRef<'tcx>, + }, // Use a lexpr to get a vexpr. NeverToAny { source: ExprRef<'tcx>, }, diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 891b6adea7893..66afe5835bf6f 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -17,6 +17,8 @@ A private trait was used on a public type parameter bound. Erroneous code examples: ```compile_fail,E0445 +#![deny(private_in_public)] + trait Foo { fn dummy(&self) { } } @@ -45,6 +47,8 @@ E0446: r##" A private type was used in a public type signature. Erroneous code example: ```compile_fail,E0446 +#![deny(private_in_public)] + mod Foo { struct Bar(u32); diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 23c4258caf7bd..5a88385a4635e 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -55,7 +55,7 @@ use syntax::attr; use syntax::attr::IntType; use _match; use abi::FAT_PTR_ADDR; -use base::InitAlloca; +use base::{self, InitAlloca}; use build::*; use cleanup; use cleanup::CleanupMethods; @@ -1023,16 +1023,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, Store(bcx, C_null(llptrty), val); } } - StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => { + StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull, .. } => { if discr != nndiscr { - let llptrptr = GEPi(bcx, val, &discrfield[..]); - let llptrty = val_ty(llptrptr).element_type(); - Store(bcx, C_null(llptrty), llptrptr); + if target_sets_discr_via_memset(bcx) { + // Issue #34427: As workaround for LLVM bug on + // ARM, use memset of 0 on whole struct rather + // than storing null to single target field. + let b = B(bcx); + let llptr = b.pointercast(val, Type::i8(b.ccx).ptr_to()); + let fill_byte = C_u8(b.ccx, 0); + let size = C_uint(b.ccx, nonnull.size); + let align = C_i32(b.ccx, nonnull.align as i32); + base::call_memset(&b, llptr, fill_byte, size, align, false); + } else { + let llptrptr = GEPi(bcx, val, &discrfield[..]); + let llptrty = val_ty(llptrptr).element_type(); + Store(bcx, C_null(llptrty), llptrptr); + } } } } } +fn target_sets_discr_via_memset<'blk, 'tcx>(bcx: Block<'blk, 'tcx>) -> bool { + bcx.sess().target.target.arch == "arm" || bcx.sess().target.target.arch == "aarch64" +} + fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) { match ity { attr::UnsignedInt(_) => { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c78cda75e820e..479a6a2cac3ed 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -320,7 +320,16 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => bug!("compare_scalar_types: must be a comparison operator"), } } - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => { + ty::TyBool => { + // FIXME(#36856) -- using `from_immediate` forces these booleans into `i8`, + // which works around some LLVM bugs + ICmp(bcx, + bin_op_to_icmp_predicate(op, false), + from_immediate(bcx, lhs), + from_immediate(bcx, rhs), + debug_loc) + } + ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyUint(_) | ty::TyChar => { ICmp(bcx, bin_op_to_icmp_predicate(op, false), lhs, diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 90f96af549691..8556e95903c18 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -22,6 +22,7 @@ use value::Value; use util::nodemap::FnvHashMap; use libc::{c_uint, c_char}; +use std::borrow::Cow; use std::ffi::CString; use std::ptr; use syntax_pos::Span; @@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .collect::>() .join(", ")); - check_call("invoke", llfn, args); - + let args = self.check_call("invoke", llfn, args); let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); unsafe { @@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); assert!(!self.llbuilder.is_null()); self.count_insn("store"); + let ptr = self.check_store(val, ptr); unsafe { llvm::LLVMBuildStore(self.llbuilder, val, ptr) } @@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); assert!(!self.llbuilder.is_null()); self.count_insn("store.volatile"); + let ptr = self.check_store(val, ptr); unsafe { let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr); llvm::LLVMSetVolatile(insn, llvm::True); @@ -562,6 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) { debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); self.count_insn("store.atomic"); + let ptr = self.check_store(val, ptr); unsafe { let ty = Type::from_ref(llvm::LLVMTypeOf(ptr)); let align = llalign_of_pref(self.ccx, ty.element_type()); @@ -857,8 +860,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .collect::>() .join(", ")); - check_call("call", llfn, args); - + let args = self.check_call("call", llfn, args); let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); unsafe { @@ -1100,10 +1102,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope); } } -} -fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) { - if cfg!(debug_assertions) { + /// Returns the ptr value that should be used for storing `val`. + fn check_store<'b>(&self, + val: ValueRef, + ptr: ValueRef) -> ValueRef { + let dest_ptr_ty = val_ty(ptr); + let stored_ty = val_ty(val); + let stored_ptr_ty = stored_ty.ptr_to(); + + assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer); + + if dest_ptr_ty == stored_ptr_ty { + ptr + } else { + debug!("Type mismatch in store. \ + Expected {:?}, got {:?}; inserting bitcast", + dest_ptr_ty, stored_ptr_ty); + self.bitcast(ptr, stored_ptr_ty) + } + } + + /// Returns the args that should be used for a call to `llfn`. + fn check_call<'b>(&self, + typ: &str, + llfn: ValueRef, + args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> { let mut fn_ty = val_ty(llfn); // Strip off pointers while fn_ty.kind() == llvm::TypeKind::Pointer { @@ -1115,16 +1139,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) { let param_tys = fn_ty.func_params(); - let iter = param_tys.into_iter() - .zip(args.iter().map(|&v| val_ty(v))); - for (i, (expected_ty, actual_ty)) in iter.enumerate() { - if expected_ty != actual_ty { - bug!("Type mismatch in function call of {:?}. \ - Expected {:?} for param {}, got {:?}", - Value(llfn), - expected_ty, i, actual_ty); + let all_args_match = param_tys.iter() + .zip(args.iter().map(|&v| val_ty(v))) + .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty); + + if all_args_match { + return Cow::Borrowed(args); + } + + let casted_args: Vec<_> = param_tys.into_iter() + .zip(args.iter()) + .enumerate() + .map(|(i, (expected_ty, &actual_val))| { + let actual_ty = val_ty(actual_val); + if expected_ty != actual_ty { + debug!("Type mismatch in function call of {:?}. \ + Expected {:?} for param {}, got {:?}; injecting bitcast", + Value(llfn), + expected_ty, i, actual_ty); + self.bitcast(actual_val, expected_ty) + } else { + actual_val + } + }) + .collect(); - } - } + return Cow::Owned(casted_args); } } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index acc302430aee6..fdd1ee1fba1d9 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1042,7 +1042,9 @@ fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let concrete_substs = monomorphize::apply_param_substs(tcx, param_substs, &fn_substs); - assert!(concrete_substs.is_normalized_for_trans()); + assert!(concrete_substs.is_normalized_for_trans(), + "concrete_substs not normalized for trans: {:?}", + concrete_substs); TransItem::Fn(Instance::new(def_id, concrete_substs)) } diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index e0d959f4774a6..66eb78aef07b4 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -48,6 +48,12 @@ pub fn lvalue_locals<'bcx, 'tcx>(bcx: Block<'bcx,'tcx>, common::type_is_fat_ptr(bcx.tcx(), ty)); } else if common::type_is_imm_pair(bcx.ccx(), ty) { // We allow pairs and uses of any of their 2 fields. + } else if !analyzer.seen_assigned.contains(index) { + // No assignment has been seen, which means that + // either the local has been marked as lvalue + // already, or there is no possible initialization + // for the local, making any reads invalid. + // This is useful in weeding out dead temps. } else { // These sorts of types require an alloca. Note that // type_is_immediate() may *still* be true, particularly diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 56d02fa1fac4f..6d03b44744b43 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -23,6 +23,7 @@ use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef}; use consts; use debuginfo::DebugLoc; use Disr; +use expr; use machine::{llalign_of_min, llbitsize_of_real}; use meth; use type_of; @@ -242,10 +243,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let lvalue = self.trans_lvalue(&bcx, location); let drop_fn = glue::get_drop_glue(bcx.ccx(), ty); let drop_ty = glue::get_drop_glue_type(bcx.tcx(), ty); - let llvalue = if drop_ty != ty { - bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to()) + let is_sized = common::type_is_sized(bcx.tcx(), ty); + let llvalue = if is_sized { + if drop_ty != ty { + bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to()) + } else { + lvalue.llval + } } else { - lvalue.llval + // FIXME(#36457) Currently drop glue takes sized + // values as a `*(data, meta)`, but elsewhere in + // MIR we pass `(data, meta)` as two separate + // arguments. It would be better to fix drop glue, + // but I am shooting for a quick fix to #35546 + // here that can be cleanly backported to beta, so + // I want to avoid touching all of trans. + bcx.with_block(|bcx| { + let scratch = base::alloc_ty(bcx, ty, "drop"); + base::call_lifetime_start(bcx, scratch); + build::Store(bcx, lvalue.llval, expr::get_dataptr(bcx, scratch)); + build::Store(bcx, lvalue.llextra, expr::get_meta(bcx, scratch)); + scratch + }) }; if let Some(unwind) = unwind { bcx.invoke(drop_fn, diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 31fee560fe369..2c83b7d07cc54 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -36,6 +36,7 @@ use value::Value; use syntax_pos::{Span, DUMMY_SP}; +use std::fmt; use std::ptr; use super::operand::{OperandRef, OperandValue}; @@ -147,6 +148,12 @@ impl<'tcx> Const<'tcx> { } } +impl<'tcx> fmt::Debug for Const<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Const({:?}: {:?})", Value(self.llval), self.ty) + } +} + #[derive(Copy, Clone)] enum Base { /// A constant value without an unique address. @@ -466,7 +473,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span) -> Result, ConstEvalFailure> { - match *operand { + debug!("const_operand({:?} @ {:?})", operand, span); + let result = match *operand { mir::Operand::Consume(ref lvalue) => { Ok(self.const_lvalue(lvalue, span)?.to_const(span)) } @@ -495,13 +503,33 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } } } - } + }; + debug!("const_operand({:?} @ {:?}) = {:?}", operand, span, + result.as_ref().ok()); + result + } + + fn const_array(&self, array_ty: Ty<'tcx>, fields: &[ValueRef]) + -> Const<'tcx> + { + let elem_ty = array_ty.builtin_index().unwrap_or_else(|| { + bug!("bad array type {:?}", array_ty) + }); + let llunitty = type_of::type_of(self.ccx, elem_ty); + // If the array contains enums, an LLVM array won't work. + let val = if fields.iter().all(|&f| val_ty(f) == llunitty) { + C_array(llunitty, fields) + } else { + C_struct(self.ccx, fields, false) + }; + Const::new(val, array_ty) } fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>, dest_ty: Ty<'tcx>, span: Span) -> Result, ConstEvalFailure> { let tcx = self.ccx.tcx(); + debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span); let val = match *rvalue { mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?, @@ -509,15 +537,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let elem = self.const_operand(elem, span)?; let size = count.value.as_u64(tcx.sess.target.uint_type); let fields = vec![elem.llval; size as usize]; - - let llunitty = type_of::type_of(self.ccx, elem.ty); - // If the array contains enums, an LLVM array won't work. - let val = if val_ty(elem.llval) == llunitty { - C_array(llunitty, &fields) - } else { - C_struct(self.ccx, &fields, false) - }; - Const::new(val, dest_ty) + self.const_array(dest_ty, &fields) } mir::Rvalue::Aggregate(ref kind, ref operands) => { @@ -541,22 +561,26 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { self.monomorphize(&substs)); } - let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind { - let repr = adt::represent_type(self.ccx, dest_ty); - let disr = Disr::from(adt_def.variants[index].disr_val); - adt::trans_const(self.ccx, &repr, disr, &fields) - } else if let ty::TyArray(elem_ty, _) = dest_ty.sty { - let llunitty = type_of::type_of(self.ccx, elem_ty); - // If the array contains enums, an LLVM array won't work. - if fields.iter().all(|&f| val_ty(f) == llunitty) { - C_array(llunitty, &fields) - } else { - C_struct(self.ccx, &fields, false) + match *kind { + mir::AggregateKind::Vec => { + self.const_array(dest_ty, &fields) } - } else { - C_struct(self.ccx, &fields, false) - }; - Const::new(val, dest_ty) + mir::AggregateKind::Adt(..) | + mir::AggregateKind::Closure(..) | + mir::AggregateKind::Tuple => { + let disr = match *kind { + mir::AggregateKind::Adt(adt_def, index, _) => { + Disr::from(adt_def.variants[index].disr_val) + } + _ => Disr(0) + }; + let repr = adt::represent_type(self.ccx, dest_ty); + Const::new( + adt::trans_const(self.ccx, &repr, disr, &fields), + dest_ty + ) + } + } } mir::Rvalue::Cast(ref kind, ref source, cast_ty) => { @@ -780,6 +804,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { _ => span_bug!(span, "{:?} in constant", rvalue) }; + debug!("const_rvalue({:?}: {:?} @ {:?}) = {:?}", rvalue, dest_ty, span, val); + Ok(val) } @@ -881,6 +907,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { constant: &mir::Constant<'tcx>) -> Const<'tcx> { + debug!("trans_constant({:?})", constant); let ty = bcx.monomorphize(&constant.ty); let result = match constant.literal.clone() { mir::Literal::Item { def_id, substs } => { @@ -905,7 +932,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } }; - match result { + let result = match result { Ok(v) => v, Err(ConstEvalFailure::Compiletime(_)) => { // We've errored, so we don't have to produce working code. @@ -917,7 +944,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { "MIR constant {:?} results in runtime panic: {:?}", constant, err.description()) } - } + }; + + debug!("trans_constant({:?}) = {:?}", constant, result); + result } } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 727b680541dd7..3b2059cd7ed18 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -22,7 +22,6 @@ use machine; use type_of; use syntax_pos::DUMMY_SP; -use syntax::parse::token::keywords; use std::ops::Deref; use std::rc::Rc; @@ -301,7 +300,6 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, _ => bug!("spread argument isn't a tuple?!") }; - let lltuplety = type_of::type_of(bcx.ccx(), arg_ty); let lltemp = bcx.with_block(|bcx| { base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) }); @@ -319,27 +317,20 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, } else { arg.store_fn_arg(bcx, &mut llarg_idx, dst); } - - bcx.with_block(|bcx| arg_scope.map(|scope| { - let byte_offset_of_var_in_tuple = - machine::llelement_offset(bcx.ccx(), lltuplety, i); - - let ops = unsafe { - [llvm::LLVMRustDIBuilderCreateOpDeref(), - llvm::LLVMRustDIBuilderCreateOpPlus(), - byte_offset_of_var_in_tuple as i64] - }; - - let variable_access = VariableAccess::IndirectVariable { - alloca: lltemp, - address_operations: &ops - }; - declare_local(bcx, keywords::Invalid.name(), - tupled_arg_ty, scope, variable_access, - VariableKind::ArgumentVariable(arg_index + i + 1), - bcx.fcx().span.unwrap_or(DUMMY_SP)); - })); } + + // Now that we have one alloca that contains the aggregate value, + // we can create one debuginfo entry for the argument. + bcx.with_block(|bcx| arg_scope.map(|scope| { + let variable_access = VariableAccess::DirectVariable { + alloca: lltemp + }; + declare_local(bcx, arg_decl.debug_name, + arg_ty, scope, variable_access, + VariableKind::ArgumentVariable(arg_index + 1), + bcx.fcx().span.unwrap_or(DUMMY_SP)); + })); + return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty))); } diff --git a/src/librustc_trans/tvec.rs b/src/librustc_trans/tvec.rs index 92a2d3787bfd6..11fe9c98d90aa 100644 --- a/src/librustc_trans/tvec.rs +++ b/src/librustc_trans/tvec.rs @@ -349,7 +349,7 @@ fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let plusone = Add(bcx, loop_counter, C_uint(bcx.ccx(), 1usize), DebugLoc::None); AddIncomingToPhi(loop_counter, plusone, bcx.llbb); - let cond_val = ICmp(bcx, llvm::IntULT, plusone, count, DebugLoc::None); + let cond_val = ICmp(bcx, llvm::IntNE, plusone, count, DebugLoc::None); CondBr(bcx, cond_val, loop_bcx.llbb, next_bcx.llbb, DebugLoc::None); next_bcx @@ -381,7 +381,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let data_ptr = Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]); let not_yet_at_end = - ICmp(header_bcx, llvm::IntULT, data_ptr, data_end_ptr, DebugLoc::None); + ICmp(header_bcx, llvm::IntNE, data_ptr, data_end_ptr, DebugLoc::None); let body_bcx = fcx.new_temp_block("iter_vec_loop_body"); let next_bcx = fcx.new_temp_block("iter_vec_next"); CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 04f22b195110f..c2fba80385784 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -535,13 +535,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { report_unexpected_def(); return; } - Def::Variant(..) | Def::Struct(..) => { + Def::Variant(..) => { let variant = tcx.expect_variant_def(def); if variant.kind != VariantKind::Unit { report_unexpected_def(); return; } } + Def::Struct(ctor_did) => { + let did = tcx.parent_def_id(ctor_did).expect("struct ctor has no parent"); + let variant = tcx.lookup_adt_def(did).struct_variant(); + if variant.kind != VariantKind::Unit { + report_unexpected_def(); + return; + } + } Def::Const(..) | Def::AssociatedConst(..) => {} // OK _ => bug!("unexpected pattern definition {:?}", def) } @@ -592,9 +600,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { report_unexpected_def(false); return; } - Def::Variant(..) | Def::Struct(..) => { + Def::Variant(..) => { tcx.expect_variant_def(def) } + Def::Struct(ctor_did) => { + let did = tcx.parent_def_id(ctor_did).expect("struct ctor has no parent"); + tcx.lookup_adt_def(did).struct_variant() + } _ => bug!("unexpected pattern definition {:?}", def) }; if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d985d3ccbea89..5dae28c12a028 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -709,7 +709,13 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig); - fcx.check_block_with_expected(body, ExpectHasType(fcx.ret_ty)); + // FIXME(aburka) do we need this special case? and should it be is_uninhabited? + let expected = if fcx.ret_ty.is_never() { + NoExpectation + } else { + ExpectHasType(fcx.ret_ty) + }; + fcx.check_block_with_expected(body, expected); fcx } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8039421ae7730..94710a9190f03 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1640,13 +1640,18 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { self.elem.read().0 } + /// Deprecated, renamed to `remove_entry` + #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to `remove_entry`")] + pub fn remove_pair(self) -> (K, V) { + self.remove_entry() + } + /// Take the ownership of the key and value from the map. /// /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// @@ -1655,13 +1660,13 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// // We delete the entry from the map. - /// o.remove_pair(); + /// o.remove_entry(); /// } /// /// assert_eq!(map.contains_key("poneyland"), false); /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] - pub fn remove_pair(self) -> (K, V) { + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn remove_entry(self) -> (K, V) { pop_internal(self.elem) } @@ -1808,8 +1813,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// @@ -1819,7 +1822,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// v.into_key(); /// } /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn into_key(self) -> K { self.key } diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs index a408b4378e19e..03f55f7ad6186 100644 --- a/src/libstd/memchr.rs +++ b/src/libstd/memchr.rs @@ -209,7 +209,7 @@ mod fallback { let end_align = (ptr as usize + len) & (usize_bytes - 1); let mut offset; if end_align > 0 { - offset = len - cmp::min(usize_bytes - end_align, len); + offset = if end_align >= len { 0 } else { len - end_align }; if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) { return Some(offset + index); } @@ -309,6 +309,17 @@ mod fallback { fn no_match_reversed() { assert_eq!(None, memrchr(b'a', b"xyz")); } + + #[test] + fn each_alignment_reversed() { + let mut data = [1u8; 64]; + let needle = 2; + let pos = 40; + data[pos] = needle; + for start in 0..16 { + assert_eq!(Some(pos - start), memrchr(needle, &data[start..])); + } + } } #[cfg(test)] @@ -385,4 +396,15 @@ mod tests { fn no_match_reversed() { assert_eq!(None, memrchr(b'a', b"xyz")); } + + #[test] + fn each_alignment() { + let mut data = [1u8; 64]; + let needle = 2; + let pos = 40; + data[pos] = needle; + for start in 0..16 { + assert_eq!(Some(pos - start), memchr(needle, &data[start..])); + } + } } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 2a8bd0c88beb6..4c3b993497cf5 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -63,8 +63,7 @@ impl IpAddr { /// Returns true for the special 'unspecified' address ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified - #[unstable(feature="ip", issue="27709", - reason="recently added and depends on unstable Ipv4Addr.is_unspecified()")] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_unspecified(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_unspecified(), @@ -75,7 +74,7 @@ impl IpAddr { /// Returns true if this is a loopback address ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback - #[unstable(feature="ip", reason="recently added", issue="27709")] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_loopback(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_loopback(), @@ -86,8 +85,6 @@ impl IpAddr { /// Returns true if the address appears to be globally routable ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global - #[unstable(feature="ip", issue="27709", - reason="recently added and depends on unstable Ip{v4,v6}Addr.is_global()")] pub fn is_global(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_global(), @@ -98,7 +95,7 @@ impl IpAddr { /// Returns true if this is a multicast address ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast - #[unstable(feature="ip", reason="recently added", issue="27709")] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_multicast(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_multicast(), @@ -109,8 +106,6 @@ impl IpAddr { /// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation - #[unstable(feature="ip", issue="27709", - reason="recently added and depends on unstable Ipv6Addr.is_documentation()")] pub fn is_documentation(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_documentation(), @@ -147,6 +142,7 @@ impl Ipv4Addr { /// This property is defined in _UNIX Network Programming, Second Edition_, /// W. Richard Stevens, p. 891; see also [ip7] /// [ip7][http://man7.org/linux/man-pages/man7/ip.7.html] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 } @@ -515,8 +511,7 @@ impl Ipv6Addr { } /// Returns the sixteen eight-bit integers the IPv6 address consists of. - #[unstable(feature = "ipv6_to_octets", reason = "needs some testing", - issue = "32313")] + #[stable(feature = "ipv6_to_octets", since = "1.12.0")] pub fn octets(&self) -> [u8; 16] { self.inner.s6_addr } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 11f785dffd16a..d8b8c6a77a266 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -394,13 +394,15 @@ pub enum TryRecvError { /// This enumeration is the list of possible errors that `recv_timeout` could /// not return data when called. #[derive(PartialEq, Eq, Clone, Copy, Debug)] -#[unstable(feature = "mpsc_recv_timeout", issue = "34029")] +#[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] pub enum RecvTimeoutError { /// This channel is currently empty, but the sender(s) have not yet /// disconnected, so data may yet become available. + #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] Timeout, /// This channel's sending half has become disconnected, and there will /// never be any more data received on this channel + #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] Disconnected, } @@ -912,8 +914,6 @@ impl Receiver { /// # Examples /// /// ```no_run - /// #![feature(mpsc_recv_timeout)] - /// /// use std::sync::mpsc::{self, RecvTimeoutError}; /// use std::time::Duration; /// @@ -922,7 +922,7 @@ impl Receiver { /// let timeout = Duration::from_millis(100); /// assert_eq!(Err(RecvTimeoutError::Timeout), recv.recv_timeout(timeout)); /// ``` - #[unstable(feature = "mpsc_recv_timeout", issue = "34029")] + #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] pub fn recv_timeout(&self, timeout: Duration) -> Result { // Do an optimistic try_recv to avoid the performance impact of // Instant::now() in the full-channel case. diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 430ec5f94a6f8..dd70ba2e490ad 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -114,7 +114,7 @@ impl CommandExt for process::Command { pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of /// a process. - #[unstable(feature = "exit_status_from", issue = "32713")] + #[stable(feature = "exit_status_from", since = "1.12.0")] fn from_raw(raw: i32) -> Self; /// If the process was terminated by a signal, returns that signal. diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 56c6a73d4f82b..98166bf8cda09 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -83,10 +83,11 @@ impl IntoRawHandle for process::ChildStderr { } /// Windows-specific extensions to `std::process::ExitStatus` -#[unstable(feature = "exit_status_from", issue = "32713")] +#[stable(feature = "exit_status_from", since = "1.12.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `u32` return value of /// a process. + #[stable(feature = "exit_status_from", since = "1.12.0")] fn from_raw(raw: u32) -> Self; } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 850127d9f2950..2b4193306ddf5 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -42,7 +42,6 @@ #![feature(staged_api)] #![feature(question_mark)] #![feature(panic_unwind)] -#![feature(mpsc_recv_timeout)] extern crate getopts; extern crate term; diff --git a/src/llvm b/src/llvm index 786aad117be48..ac1c94226e9fa 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 786aad117be48547f4ca50fae84c4879fa992d4d +Subproject commit ac1c94226e9fa17005ce7e2dd52dd6d1875f3137 diff --git a/src/rust-installer b/src/rust-installer index c37d3747da75c..755bc3db4ff79 160000 --- a/src/rust-installer +++ b/src/rust-installer @@ -1 +1 @@ -Subproject commit c37d3747da75c280237dc2d6b925078e69555499 +Subproject commit 755bc3db4ff795865ea31b5b4f38ac920d8acacb diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index 378810a8b89fc..b12e25bba694f 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2016-08-07 +2016-10-10 diff --git a/src/stage0.txt b/src/stage0.txt index aaf88a67d2749..b07347cfa685a 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,6 +12,6 @@ # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was # released on `$date` -rustc: beta-2016-07-06 -rustc_key: 411fd48b +rustc: 1.11.0-2016-08-16 +rustc_key: 39b92f95 cargo: nightly-2016-07-05 diff --git a/src/test/compile-fail/diverging-fn-tail-35849.rs b/src/test/compile-fail/diverging-fn-tail-35849.rs new file mode 100644 index 0000000000000..6dc447b4dc887 --- /dev/null +++ b/src/test/compile-fail/diverging-fn-tail-35849.rs @@ -0,0 +1,16 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn _converge() -> ! { //~ ERROR computation may converge + 42 +} + +fn main() { } + diff --git a/src/test/compile-fail/issue-28514.rs b/src/test/compile-fail/issue-28514.rs index 6ee375503c2af..fb25166531dcb 100644 --- a/src/test/compile-fail/issue-28514.rs +++ b/src/test/compile-fail/issue-28514.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(private_in_public)] + pub use inner::C; mod inner { diff --git a/src/test/compile-fail/issue-30079.rs b/src/test/compile-fail/issue-30079.rs index 55c58ed021b27..6a54e53f14638 100644 --- a/src/test/compile-fail/issue-30079.rs +++ b/src/test/compile-fail/issue-30079.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(private_in_public)] #![allow(unused)] struct SemiPriv; diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs index 6d6af77be92b0..455de37aee96f 100644 --- a/src/test/compile-fail/private-in-public-warn.rs +++ b/src/test/compile-fail/private-in-public-warn.rs @@ -13,8 +13,8 @@ #![feature(associated_consts)] #![feature(associated_type_defaults)] -#![allow(dead_code)] -#![allow(unused_variables)] +#![deny(private_in_public)] +#![allow(unused)] #![allow(improper_ctypes)] mod types { diff --git a/src/test/compile-fail/private-variant-and-crate-reexport.rs b/src/test/compile-fail/private-variant-and-crate-reexport.rs index ce029e7eff7fc..dce533e73feea 100644 --- a/src/test/compile-fail/private-variant-and-crate-reexport.rs +++ b/src/test/compile-fail/private-variant-and-crate-reexport.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(private_in_public)] #![allow(dead_code)] extern crate core; diff --git a/src/test/run-fail/call-fn-never-arg.rs b/src/test/run-fail/call-fn-never-arg.rs index 95101e70db951..b1aa76cd9bfe5 100644 --- a/src/test/run-fail/call-fn-never-arg.rs +++ b/src/test/run-fail/call-fn-never-arg.rs @@ -10,6 +10,7 @@ // Test that we can use a ! for an argument of type ! +// ignore-test FIXME(durka) can't be done with the current liveness code // error-pattern:wowzers! #![feature(never_type)] diff --git a/src/test/run-pass/diverging-fn-tail-35849.rs b/src/test/run-pass/diverging-fn-tail-35849.rs new file mode 100644 index 0000000000000..6c05a02e7183c --- /dev/null +++ b/src/test/run-pass/diverging-fn-tail-35849.rs @@ -0,0 +1,18 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn assert_sizeof() -> ! { + unsafe { + ::std::mem::transmute::(panic!()) + } +} + +fn main() { } + diff --git a/src/test/run-pass/issue-34427.rs b/src/test/run-pass/issue-34427.rs new file mode 100644 index 0000000000000..6bf8a2ac6a72d --- /dev/null +++ b/src/test/run-pass/issue-34427.rs @@ -0,0 +1,26 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #34427: On ARM, the code in `foo` at one time was generating +// a machine code instruction of the form: `str r0, [r0, rN]!` (for +// some N), which is not legal because the source register and base +// register cannot be identical in the preindexed form signalled by +// the `!`. +// +// See LLVM bug: https://llvm.org/bugs/show_bug.cgi?id=28809 + +#[inline(never)] +fn foo(n: usize) -> Vec> { + (0..n).map(|_| None).collect() +} + +fn main() { + let _ = (foo(10), foo(32)); +} diff --git a/src/test/run-pass/issue-35546.rs b/src/test/run-pass/issue-35546.rs new file mode 100644 index 0000000000000..e8d14f1d42146 --- /dev/null +++ b/src/test/run-pass/issue-35546.rs @@ -0,0 +1,28 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #35546. Check that we are able to codegen +// this. Before we had problems because of the drop glue signature +// around dropping a trait object (specifically, when dropping the +// `value` field of `Node`). + +struct Node { + next: Option>>, + value: T, +} + +fn clear(head: &mut Option>>) { + match head.take() { + Some(node) => *head = node.next, + None => (), + } +} + +fn main() {} diff --git a/src/test/run-pass/issue-36023.rs b/src/test/run-pass/issue-36023.rs new file mode 100644 index 0000000000000..f6c03b384f23d --- /dev/null +++ b/src/test/run-pass/issue-36023.rs @@ -0,0 +1,32 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +fn main() { + if env_var("FOOBAR").as_ref().map(Deref::deref).ok() == Some("yes") { + panic!() + } + + let env_home: Result = Ok("foo-bar-baz".to_string()); + let env_home = env_home.as_ref().map(Deref::deref).ok(); + + if env_home == Some("") { panic!() } +} + +#[inline(never)] +fn env_var(s: &str) -> Result { + Err(VarError::NotPresent) +} + +pub enum VarError { + NotPresent, + NotUnicode(String), +} diff --git a/src/test/run-pass/issue-36036-associated-type-layout.rs b/src/test/run-pass/issue-36036-associated-type-layout.rs new file mode 100644 index 0000000000000..4ee3be0eb7b81 --- /dev/null +++ b/src/test/run-pass/issue-36036-associated-type-layout.rs @@ -0,0 +1,36 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 36036: computing the layout of a type composed from another +// trait's associated type caused compiler to ICE when the associated +// type was allowed to be unsized, even though the known instantiated +// type is itself sized. + +#![allow(dead_code)] + +trait Context { + type Container: ?Sized; +} + +impl Context for u16 { + type Container = u8; +} + +struct Wrapper { + container: &'static C::Container +} + +fn foobar(_: Wrapper) {} + +static VALUE: u8 = 0; + +fn main() { + foobar(Wrapper { container: &VALUE }); +} diff --git a/src/test/run-pass/issue-36381.rs b/src/test/run-pass/issue-36381.rs new file mode 100644 index 0000000000000..6cd991bd942df --- /dev/null +++ b/src/test/run-pass/issue-36381.rs @@ -0,0 +1,34 @@ +// 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. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #36381. The trans collector was asserting that +// there are no projection types, but the `<&str as +// StreamOnce>::Position` projection contained a late-bound region, +// and we don't currently normalize in that case until the function is +// actually invoked. + +pub trait StreamOnce { + type Position; +} + +impl<'a> StreamOnce for &'a str { + type Position = usize; +} + +pub fn parser(_: F) { +} + +fn follow(_: &str) -> <&str as StreamOnce>::Position { + panic!() +} + +fn main() { + parser(follow); +} diff --git a/src/test/run-pass/issue-36401.rs b/src/test/run-pass/issue-36401.rs new file mode 100644 index 0000000000000..7b08eba9e4988 --- /dev/null +++ b/src/test/run-pass/issue-36401.rs @@ -0,0 +1,25 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Debug)] +pub enum Event { + Key(u8), + Resize, + Unknown(u16), +} + +static XTERM_SINGLE_BYTES : [(u8, Event); 1] = [(1, Event::Resize)]; + +fn main() { + match XTERM_SINGLE_BYTES[0] { + (1, Event::Resize) => {}, + ref bad => panic!("unexpected {:?}", bad) + } +} diff --git a/src/test/run-pass/issue-36474.rs b/src/test/run-pass/issue-36474.rs new file mode 100644 index 0000000000000..025244ca6648c --- /dev/null +++ b/src/test/run-pass/issue-36474.rs @@ -0,0 +1,40 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + remove_axis(&3, 0); +} + +trait Dimension { + fn slice(&self) -> &[usize]; +} + +impl Dimension for () { + fn slice(&self) -> &[usize] { &[] } +} + +impl Dimension for usize { + fn slice(&self) -> &[usize] { + unsafe { + ::std::slice::from_raw_parts(self, 1) + } + } +} + +fn remove_axis(value: &usize, axis: usize) -> () { + let tup = (); + let mut it = tup.slice().iter(); + for (i, _) in value.slice().iter().enumerate() { + if i == axis { + continue; + } + it.next(); + } +} diff --git a/src/test/run-pass/issue-36744-bitcast-args-if-needed.rs b/src/test/run-pass/issue-36744-bitcast-args-if-needed.rs new file mode 100644 index 0000000000000..1859cc9ca00b5 --- /dev/null +++ b/src/test/run-pass/issue-36744-bitcast-args-if-needed.rs @@ -0,0 +1,32 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This tests for an ICE (and, if ignored, subsequent LLVM abort) when +// a lifetime-parametric fn is passed into a context whose expected +// type has a differing lifetime parameterization. + +struct A<'a> { + _a: &'a i32, +} + +fn call(s: T, functions: &Vec fn(&'n T)>) { + for function in functions { + function(&s); + } +} + +fn f(a: &A) { println!("a holds {}", a._a); } + +fn main() { + let a = A { _a: &10 }; + + let vec: Vec fn(&'u A<'v>)> = vec![f]; + call(a, &vec); +} diff --git a/src/test/run-pass/issue-36744-without-calls.rs b/src/test/run-pass/issue-36744-without-calls.rs new file mode 100644 index 0000000000000..1766edb06b481 --- /dev/null +++ b/src/test/run-pass/issue-36744-without-calls.rs @@ -0,0 +1,22 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests for an LLVM abort when storing a lifetime-parametric fn into +// context that is expecting one that is not lifetime-parametric +// (i.e. has no `for <'_>`). + +pub struct A<'a>(&'a ()); +pub struct S(T); + +pub fn bad<'s>(v: &mut S)>, y: S fn(A<'b>)>) { + *v = y; +} + +fn main() {} diff --git a/src/test/run-pass/issue-36856.rs b/src/test/run-pass/issue-36856.rs new file mode 100644 index 0000000000000..91a0dadd65328 --- /dev/null +++ b/src/test/run-pass/issue-36856.rs @@ -0,0 +1,24 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #36856. + +// compile-flags:-g + +fn g() -> bool { + false +} + +pub fn main() { + let a = !g(); + if a != !g() { + panic!(); + } +} diff --git a/src/test/run-pass/issue-36936.rs b/src/test/run-pass/issue-36936.rs new file mode 100644 index 0000000000000..4216e2bb4fe6c --- /dev/null +++ b/src/test/run-pass/issue-36936.rs @@ -0,0 +1,35 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that casts are not being treated as lexprs. + +fn main() { + let mut a = 0i32; + let b = &(a as i32); + a = 1; + assert!((&a as *const i32) != (b as *const i32)); + assert_eq!(*b, 0); + + assert_eq!(issue_36936(), 1); +} + + +struct A(u32); + +impl Drop for A { + fn drop(&mut self) { + self.0 = 0; + } +} + +fn issue_36936() -> u32 { + let a = &(A(1) as A); + a.0 +} diff --git a/src/test/run-pass/mir_early_return_scope.rs b/src/test/run-pass/mir_early_return_scope.rs new file mode 100644 index 0000000000000..c27e57358b09b --- /dev/null +++ b/src/test/run-pass/mir_early_return_scope.rs @@ -0,0 +1,37 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut DROP: bool = false; + +struct ConnWrap(Conn); +impl ::std::ops::Deref for ConnWrap { + type Target=Conn; + fn deref(&self) -> &Conn { &self.0 } +} + +struct Conn; +impl Drop for Conn { + fn drop(&mut self) { unsafe { DROP = true; } } +} + +fn inner() { + let conn = &*match Some(ConnWrap(Conn)) { + Some(val) => val, + None => return, + }; + return; +} + +fn main() { + inner(); + unsafe { + assert_eq!(DROP, true); + } +} diff --git a/src/test/run-pass/mir_heavy_promoted.rs b/src/test/run-pass/mir_heavy_promoted.rs new file mode 100644 index 0000000000000..9e033421574b9 --- /dev/null +++ b/src/test/run-pass/mir_heavy_promoted.rs @@ -0,0 +1,18 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024]; + +// Check that the promoted copy of TEST_DATA doesn't +// leave an alloca from an unused temp behind, which, +// without optimizations, can still blow the stack. +fn main() { + println!("{}", TEST_DATA.len()); +} diff --git a/src/test/run-pass/variance-iterators-in-libcore.rs b/src/test/run-pass/variance-iterators-in-libcore.rs new file mode 100644 index 0000000000000..b9677d5ba8598 --- /dev/null +++ b/src/test/run-pass/variance-iterators-in-libcore.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(warnings)] + +use std::iter::Zip; + +fn zip_covariant<'a, A, B>(iter: Zip<&'static A, &'static B>) -> Zip<&'a A, &'a B> { iter } + +fn main() { }