]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #31089 - fhahn:macro-ice, r=pnkfelix
authorbors <bors@rust-lang.org>
Wed, 27 Jan 2016 12:12:52 +0000 (12:12 +0000)
committerbors <bors@rust-lang.org>
Wed, 27 Jan 2016 12:12:52 +0000 (12:12 +0000)
This is a  work in progress PR that potentially should fix #29084, #28308, #25385, #28288, #31011. I think this may also adresse parts of  #2887.

The problem in this issues seems to be that when transcribing macro arguments, we just clone the argument Nonterminal, which still has to original spans. This leads to the unprintable spans. One solution would be to update the spans of the inserted argument to match the argument in the macro definition. So for [this testcase](https://github.com/rust-lang/rust/compare/master...fhahn:macro-ice?expand=1#diff-f7def7420c51621640707b6337726876R2) the error message would be displayed in the macro definition:

    src/test/compile-fail/issue-31011.rs:4:12: 4:22 error: attempted access of field `trace` on type `&T`, but no field with that name was found
    src/test/compile-fail/issue-31011.rs:4         if $ctx.trace {

Currently I've added a very simple `update_span` function, which updates the span of the outer-most expression of a `NtExpr`, but this `update_span` function should be updated to handle all Nonterminals. But I'm pretty new to the macro system and would like to check if this approach makes sense, before doing that.

107 files changed:
mk/target.mk
src/doc/book/error-handling.md
src/doc/book/getting-started.md
src/doc/book/learn-rust.md [deleted file]
src/doc/book/loops.md
src/liballoc/boxed_test.rs
src/liballoc/lib.rs
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libarena/lib.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollectionstest/slice.rs
src/libcore/cell.rs
src/libcore/hash/mod.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/libgraphviz/lib.rs
src/liblog/lib.rs
src/librand/lib.rs
src/librbml/lib.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/middle/check_match.rs
src/librustc/middle/implicator.rs [deleted file]
src/librustc/session/mod.rs
src/librustc/util/common.rs
src/librustc_back/lib.rs
src/librustc_back/target/dragonfly_base.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/netbsd_base.rs
src/librustc_back/target/openbsd_base.rs
src/librustc_bitflags/lib.rs
src/librustc_borrowck/lib.rs
src/librustc_data_structures/fnv.rs
src/librustc_data_structures/lib.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_front/lib.rs
src/librustc_front/print/pprust.rs
src/librustc_lint/lib.rs
src/librustc_llvm/lib.rs
src/librustc_metadata/lib.rs
src/librustc_mir/lib.rs
src/librustc_passes/lib.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_plugin/lib.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_trans/lib.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/lib.rs
src/librustc_unicode/lib.rs
src/librustdoc/core.rs
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/libserialize/collection_impls.rs
src/libserialize/json.rs
src/libserialize/lib.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/state.rs
src/libstd/collections/hash/table.rs
src/libstd/collections/mod.rs
src/libstd/dynamic_lib.rs
src/libstd/io/buffered.rs
src/libstd/io/stdio.rs
src/libstd/lib.rs
src/libstd/os/raw.rs
src/libstd/panicking.rs
src/libstd/path.rs
src/libstd/process.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/semaphore.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/process.rs
src/libstd/sys/windows/stack_overflow.rs
src/libstd/sys/windows/thread.rs
src/libsyntax/errors/emitter.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/lib.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax_ext/lib.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/test/compile-fail/macro-follow.rs [new file with mode: 0644]
src/test/compile-fail/non-exhaustive-pattern-witness.rs
src/test/pretty/issue-31073.pp [new file with mode: 0644]
src/test/pretty/issue-31073.rs [new file with mode: 0644]
src/test/run-fail-fulldeps/qquote.rs
src/test/run-make/execution-engine/test.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-pass/lexical-scoping.rs [new file with mode: 0644]
src/test/run-pass/lint-expr-stmt-attrs-for-early-lints.rs [new file with mode: 0644]
src/test/run-pass/macro-follow.rs [new file with mode: 0644]
src/test/run-pass/multi-panic.rs [new file with mode: 0644]
src/test/run-pass/no-stdio.rs [new file with mode: 0644]

index f90b09479c9858c338c7264be72f3773a0380285..32a3eb5c20d2840c3f7e16772a83bfc3b4a417c9 100644 (file)
@@ -17,14 +17,6 @@ export CFG_COMPILER_HOST_TRIPLE
 export CFG_DEFAULT_LINKER
 export CFG_DEFAULT_AR
 
-# The standard libraries should be held up to a higher standard than any old
-# code, make sure that these common warnings are denied by default. These can
-# be overridden during development temporarily. For stage0, we allow warnings
-# which may be bugs in stage0 (should be fixed in stage1+)
-RUST_LIB_FLAGS_ST0 += -W warnings
-RUST_LIB_FLAGS_ST1 += -D warnings
-RUST_LIB_FLAGS_ST2 += -D warnings
-
 # Macro that generates the full list of dependencies for a crate at a particular
 # stage/target/host tuple.
 #
index 9b1d16170b97f1c879e6c6c85169f8f6f807d761..40891dbe191e9ca9a40346b64238a63340304518 100644 (file)
@@ -1512,7 +1512,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
 
 We're not going to spend a lot of time on setting up a project with
 Cargo because it is already covered well in [the Cargo
-section](../book/hello-cargo.html) and [Cargo's documentation][14].
+section](getting-started.html#hello-cargo) and [Cargo's documentation][14].
 
 To get started from scratch, run `cargo new --bin city-pop` and make sure your
 `Cargo.toml` looks something like this:
index 77d468254b6c5d1ffba9fbe2b9e28f8033c6475b..d7b6e15794ef4f9f831c1700a847b8438016183f 100644 (file)
@@ -167,6 +167,10 @@ variable. If it isn't, run the installer again, select "Change" on the "Change,
 repair, or remove installation" page and ensure "Add to PATH" is installed on
 the local hard drive.
 
+Rust does not do its own linking, and so you’ll need to have a linker
+installed. Doing so will depend on your specific system, consult its
+documentation for more details.
+
 If not, there are a number of places where we can get help. The easiest is
 [the #rust IRC channel on irc.mozilla.org][irc], which we can access through
 [Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans
@@ -604,11 +608,11 @@ This chapter covered the basics that will serve you well through the rest of
 this book, and the rest of your time with Rust. Now that you’ve got the tools
 down, we'll cover more about the Rust language itself.
 
-You have two options: Dive into a project with â€˜[Learn Rust][learnrust]’, or
+You have two options: Dive into a project with â€˜[Tutorial: Guessing Game][guessinggame]’, or
 start from the bottom and work your way up with â€˜[Syntax and
 Semantics][syntax]’. More experienced systems programmers will probably prefer
-‘Learn Rust’, while those from dynamic backgrounds may enjoy either. Different
+‘Tutorial: Guessing Game’, while those from dynamic backgrounds may enjoy either. Different
 people learn differently! Choose whatever’s right for you.
 
-[learnrust]: learn-rust.html
+[guessinggame]: guessing-game.html
 [syntax]: syntax-and-semantics.html
diff --git a/src/doc/book/learn-rust.md b/src/doc/book/learn-rust.md
deleted file mode 100644 (file)
index 7be7fa4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-% Learn Rust
-
-Welcome! This chapter has a few tutorials that teach you Rust through building
-projects. You’ll get a high-level overview, but we’ll skim over the details.
-
-If you’d prefer a more â€˜from the ground up’-style experience, check
-out [Syntax and Semantics][ss].
-
-[ss]: syntax-and-semantics.html
index 68bb49d2c296698ec71a86bf3eff018e48f31762..5b08c2fb04dbde49616e5a5fc74a835cf1f112d9 100644 (file)
@@ -195,7 +195,7 @@ for x in 0..10 {
 You may also encounter situations where you have nested loops and need to
 specify which one your `break` or `continue` statement is for. Like most
 other languages, by default a `break` or `continue` will apply to innermost
-loop. In a situation where you would like to `break` or `continue` for one
+loop. In a situation where you would like to `break` or `continue` for one
 of the outer loops, you can use labels to specify which loop the `break` or
  `continue` statement applies to. This will only print when both `x` and `y` are
  odd:
index e7da6d04d3f8fce438f9832dd03401b51136c585..120301afa449f910f2201e5ec16ed2f07bb65a39 100644 (file)
@@ -15,7 +15,6 @@
 use core::result::Result::{Ok, Err};
 use core::clone::Clone;
 
-use std::boxed;
 use std::boxed::Box;
 
 #[test]
index 0a232ed0620d4a25106e5679b7c20e2462ab55a8..1438103d7f6d4ef2566b47c9b0422dd0f3ed7515 100644 (file)
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
 #![no_std]
 #![needs_allocator]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(allocator)]
 #![feature(box_syntax)]
 #![feature(coerce_unsized)]
+#![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
+#![feature(drop_in_place)]
+#![feature(dropck_parametricity)]
 #![feature(fundamental)]
 #![feature(lang_items)]
+#![feature(needs_allocator)]
 #![feature(optin_builtin_traits)]
 #![feature(placement_in_syntax)]
-#![feature(placement_new_protocol)]
-#![feature(raw)]
 #![feature(shared)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
-#![feature(dropck_parametricity)]
 #![feature(unsize)]
-#![feature(drop_in_place)]
-#![feature(fn_traits)]
-#![feature(const_fn)]
-
-#![feature(needs_allocator)]
 
 // Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
 // might be unavailable or disabled
 #![cfg_attr(stage0, feature(alloc_system))]
 
+#![cfg_attr(not(test), feature(raw, fn_traits, placement_new_protocol))]
 #![cfg_attr(test, feature(test, rustc_private, box_heap))]
 
 #[cfg(stage0)]
index 91d229b819df197b84987f7f0b2002cfb8a05c00..b009dfd8c751cc8fd30d1dda213d275bdacb9f35 100644 (file)
@@ -16,6 +16,7 @@
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
             issue = "27783")]
+#![cfg_attr(not(stage0), deny(warnings))]
 #![feature(allocator)]
 #![feature(libc)]
 #![feature(staged_api)]
index ffb6999d6e3fef7ef932832ecbb65f219cdcd8bd..8a9e32daa728aa28ecca791f9db78b1d9f3967ca 100644 (file)
@@ -12,6 +12,7 @@
 #![crate_type = "rlib"]
 #![no_std]
 #![allocator]
+#![cfg_attr(not(stage0), deny(warnings))]
 #![unstable(feature = "alloc_system",
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
index cd2093984e618ef785f7ee748351f5a06f3c5aed..46a63390c835264c26e765f6b49a8917a881d9c9 100644 (file)
@@ -27,6 +27,7 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(no_crate_inject, attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
index 6077a4c01045b5b9842f11694e3055f5e09dce88..4958f75016651c647a47d0052c91c961e391416e 100644 (file)
@@ -28,6 +28,7 @@
 
 #![allow(trivial_casts)]
 #![cfg_attr(test, allow(deprecated))] // rand
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(alloc)]
 #![feature(box_patterns)]
@@ -55,7 +56,7 @@
 #![feature(unicode)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag)]
-#![cfg_attr(test, feature(clone_from_slice, rand, test))]
+#![cfg_attr(test, feature(rand, test))]
 
 #![no_std]
 
index 8b4497e6f037e2ee3216073e1f952f73c3696e4c..6252e4888eb3ca71f6d37e9e2a9df764d443607b 100644 (file)
 
 // Many of the usings in this module are only used in the test configuration.
 // It's cleaner to just turn off the unused_imports warning than to fix them.
-#![allow(unused_imports)]
+#![cfg_attr(test, allow(unused_imports, dead_code))]
 
 use alloc::boxed::Box;
-use core::clone::Clone;
 use core::cmp::Ordering::{self, Greater, Less};
-use core::cmp::{self, Ord, PartialEq};
-use core::iter::Iterator;
-use core::marker::Sized;
+use core::cmp;
 use core::mem::size_of;
 use core::mem;
-use core::ops::FnMut;
-use core::option::Option::{self, Some, None};
 use core::ptr;
-use core::result::Result;
 use core::slice as core_slice;
 
 use borrow::{Borrow, BorrowMut, ToOwned};
 // `test_permutations` test
 mod hack {
     use alloc::boxed::Box;
-    use core::clone::Clone;
-    #[cfg(test)]
-    use core::iter::Iterator;
     use core::mem;
-    #[cfg(test)]
-    use core::option::Option::{Some, None};
 
     #[cfg(test)]
     use string::ToString;
index 9ce1a111cf83a18f36f31dd8543450abb5237101..094b7f1d034536494d7e8554f22886582451306c 100644 (file)
 // It's cleaner to just turn off the unused_imports warning than to fix them.
 #![allow(unused_imports)]
 
-use core::clone::Clone;
-use core::iter::{Iterator, Extend};
-use core::option::Option::{self, Some, None};
-use core::result::Result;
 use core::str as core_str;
 use core::str::pattern::Pattern;
 use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
index 80dcd48fbfaa9e953b84f104595d95f8c3ee271e..e5e15025625b5e23847f516bfa10d8a2d9ed23c5 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::cmp::Ordering::{Equal, Greater, Less};
-use std::default::Default;
 use std::mem;
 use std::__rand::{Rng, thread_rng};
 use std::rc::Rc;
index 789b75836d0a70a43db847db7014d03f804e5c92..6041355e9dbc0d861d8a3584038e509725ac7e2b 100644 (file)
@@ -414,7 +414,9 @@ pub fn borrow(&self) -> Ref<T> {
     ///
     /// let c = RefCell::new(5);
     ///
-    /// let borrowed_five = c.borrow_mut();
+    /// *c.borrow_mut() = 7;
+    ///
+    /// assert_eq!(*c.borrow(), 7);
     /// ```
     ///
     /// An example of panic:
index 0781dd3b7742f9d54611f78aae1705a83e65e8da..9ab55620e0aece5ebad170eb205792215975639e 100644 (file)
@@ -73,6 +73,7 @@
 
 use prelude::v1::*;
 
+use marker;
 use mem;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -190,6 +191,77 @@ fn write_isize(&mut self, i: isize) {
     }
 }
 
+/// A `BuildHasher` is typically used as a factory for instances of `Hasher`
+/// which a `HashMap` can then use to hash keys independently.
+///
+/// Note that for each instance of `BuildHasher` the create hashers should be
+/// identical. That is if the same stream of bytes is fed into each hasher the
+/// same output will also be generated.
+#[stable(since = "1.7.0", feature = "build_hasher")]
+pub trait BuildHasher {
+    /// Type of the hasher that will be created.
+    #[stable(since = "1.7.0", feature = "build_hasher")]
+    type Hasher: Hasher;
+
+    /// Creates a new hasher.
+    #[stable(since = "1.7.0", feature = "build_hasher")]
+    fn build_hasher(&self) -> Self::Hasher;
+}
+
+/// A structure which implements `BuildHasher` for all `Hasher` types which also
+/// implement `Default`.
+///
+/// This struct is 0-sized and does not need construction.
+#[stable(since = "1.7.0", feature = "build_hasher")]
+pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
+
+#[stable(since = "1.7.0", feature = "build_hasher")]
+impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> {
+    type Hasher = H;
+
+    fn build_hasher(&self) -> H {
+        H::default()
+    }
+}
+
+#[stable(since = "1.7.0", feature = "build_hasher")]
+impl<H> Clone for BuildHasherDefault<H> {
+    fn clone(&self) -> BuildHasherDefault<H> {
+        BuildHasherDefault(marker::PhantomData)
+    }
+}
+
+#[stable(since = "1.7.0", feature = "build_hasher")]
+impl<H> Default for BuildHasherDefault<H> {
+    fn default() -> BuildHasherDefault<H> {
+        BuildHasherDefault(marker::PhantomData)
+    }
+}
+
+// The HashState trait is super deprecated, but it's here to have the blanket
+// impl that goes from HashState -> BuildHasher
+
+/// Deprecated, renamed to `BuildHasher`
+#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+           issue = "27713")]
+#[rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash and \
+                                              renamed to BuildHasher")]
+pub trait HashState {
+    /// Type of the hasher that will be created.
+    type Hasher: Hasher;
+
+    /// Creates a new hasher based on the given state of this object.
+    fn hasher(&self) -> Self::Hasher;
+}
+
+#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+           issue = "27713")]
+#[allow(deprecated)]
+impl<T: HashState> BuildHasher for T {
+    type Hasher = T::Hasher;
+    fn build_hasher(&self) -> T::Hasher { self.hasher() }
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 mod impls {
index e3e783329ec812e003d8d6cd915648eac8c86c86..3f1c0f6a5492a1cc8ff81ec1c4511873f3fbea76 100644 (file)
@@ -2740,7 +2740,13 @@ pub trait Extend<A> {
 /// It is important to note that both back and forth work on the same range,
 /// and do not cross: iteration is over when they meet in the middle.
 ///
+/// In a similar fashion to the [`Iterator`] protocol, once a
+/// `DoubleEndedIterator` returns `None` from a `next_back()`, calling it again
+/// may or may not ever return `Some` again. `next()` and `next_back()` are
+/// interchangable for this purpose.
+///
 /// [`Iterator`]: trait.Iterator.html
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -4246,13 +4252,15 @@ impl<A: Step> RangeFrom<A> {
     ///
     /// # Examples
     ///
-    /// ```ignore
-    /// for i in (0u8..).step_by(2) {
+    /// ```
+    /// # #![feature(step_by)]
+    ///
+    /// for i in (0u8..).step_by(2).take(10) {
     ///     println!("{}", i);
     /// }
     /// ```
     ///
-    /// This prints all even `u8` values.
+    /// This prints the first ten even natural integers (0 to 18).
     #[unstable(feature = "step_by", reason = "recent addition",
                issue = "27741")]
     pub fn step_by(self, by: A) -> StepBy<A, Self> {
index e8803976937d2d7ea43f49c71d55c6ddfe9fe04e..f76b8655ad1ed1389f555999bee3c4d63b95f395 100644 (file)
@@ -56,6 +56,7 @@
 
 #![no_core]
 #![deny(missing_docs)]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(allow_internal_unstable)]
 #![feature(associated_type_defaults)]
index a60a1c67e175d2165d27aaeaf474c018bec53cc0..f316250d96d710c3eb296784f48fcaab0f7df703 100644 (file)
@@ -22,6 +22,7 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(libc)]
 #![feature(staged_api)]
index 7a229ad522227a7229e34958f013f91f82097466..07d26cddfdb87ee818d762a511fb5a35040afdd0 100644 (file)
@@ -23,6 +23,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(staged_api)]
 #![feature(unicode)]
index 38b45ec0feaedacbcd9294e710b36d20b66d4e0c..2e26cc1b2660ad951b1dec5e4c5cf4a3395a8ffd 100644 (file)
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(allow(unused_variables), deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(str_escape)]
 
index dbd553acd68fc9f361793f3f65b10948921ec75a..011f5a744dc844d429e8b684747aa77f6df40314 100644 (file)
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
 #![deny(missing_docs)]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_syntax)]
 #![feature(const_fn)]
index 06f4c8dfd20a82b65dff234a0dc8c09302274a34..531be63b7bb73468615480b4f3b75a5bb12a0bed 100644 (file)
@@ -23,6 +23,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 #![no_std]
 #![unstable(feature = "rand",
             reason = "use `rand` from crates.io",
@@ -35,7 +36,7 @@
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 
-#![cfg_attr(test, feature(test, rand, rustc_private, iter_order_deprecated))]
+#![cfg_attr(test, feature(test, rand, rustc_private))]
 
 #![allow(deprecated)]
 
index 913314c4899a2260c69eb34c8cd5bb3c07440fb0..8404026df143e13535553c20927e63b0c542f27d 100644 (file)
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(rustc_private)]
 #![feature(staged_api)]
index 4d772de7835941b1c65cd1564908624739f1db19..54c12b67970b1c8c57cda3c21f6c01fff55d6f06 100644 (file)
@@ -19,8 +19,9 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
@@ -29,7 +30,6 @@
 #![feature(collections)]
 #![feature(const_fn)]
 #![feature(enumset)]
-#![feature(hashmap_hasher)]
 #![feature(iter_arith)]
 #![feature(libc)]
 #![feature(nonzero)]
@@ -108,7 +108,6 @@ pub mod middle {
     pub mod free_region;
     pub mod intrinsicck;
     pub mod infer;
-    pub mod implicator;
     pub mod lang_items;
     pub mod liveness;
     pub mod mem_categorization;
index c41a361fcc309338ea1b2c3c332636038372baa7..55782041be68712aa804847461db3f0400572064 100644 (file)
@@ -735,7 +735,7 @@ fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> {
     }
 
     fn enter_attrs(&mut self, attrs: &[ast::Attribute]) {
-        debug!("early context: exit_attrs({:?})", attrs);
+        debug!("early context: enter_attrs({:?})", attrs);
         run_lints!(self, enter_lint_attrs, early_passes, attrs);
     }
 
@@ -934,8 +934,10 @@ fn visit_pat(&mut self, p: &ast::Pat) {
     }
 
     fn visit_expr(&mut self, e: &ast::Expr) {
-        run_lints!(self, check_expr, early_passes, e);
-        ast_visit::walk_expr(self, e);
+        self.with_lint_attrs(e.attrs.as_attr_slice(), |cx| {
+            run_lints!(cx, check_expr, early_passes, e);
+            ast_visit::walk_expr(cx, e);
+        })
     }
 
     fn visit_stmt(&mut self, s: &ast::Stmt) {
@@ -990,8 +992,10 @@ fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) {
     }
 
     fn visit_local(&mut self, l: &ast::Local) {
-        run_lints!(self, check_local, early_passes, l);
-        ast_visit::walk_local(self, l);
+        self.with_lint_attrs(l.attrs.as_attr_slice(), |cx| {
+            run_lints!(cx, check_local, early_passes, l);
+            ast_visit::walk_local(cx, l);
+        })
     }
 
     fn visit_block(&mut self, b: &ast::Block) {
index d52089dbeab5680b1a57567eac5150d9b3e5dd95..fa09c9d2bb6bade3d241b48a14bd8ca306c19b3e 100644 (file)
@@ -368,31 +368,46 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
 fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir::MatchSource) {
     match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
-            let witness = match &pats[..] {
-                [ref witness] => &**witness,
-                [] => DUMMY_WILD_PAT,
-                _ => unreachable!()
+            let witnesses = if pats.is_empty() {
+                vec![DUMMY_WILD_PAT]
+            } else {
+                pats.iter().map(|w| &**w ).collect()
             };
             match source {
                 hir::MatchSource::ForLoopDesugar => {
-                    // `witness` has the form `Some(<head>)`, peel off the `Some`
-                    let witness = match witness.node {
+                    // `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
+                    let witness = match witnesses[0].node {
                         hir::PatEnum(_, Some(ref pats)) => match &pats[..] {
                             [ref pat] => &**pat,
                             _ => unreachable!(),
                         },
                         _ => unreachable!(),
                     };
-
                     span_err!(cx.tcx.sess, sp, E0297,
                         "refutable pattern in `for` loop binding: \
                                 `{}` not covered",
                                 pat_to_string(witness));
                 },
                 _ => {
+                    let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
+                        pat_to_string(w)
+                    }).collect();
+                    const LIMIT: usize = 3;
+                    let joined_patterns = match pattern_strings.len() {
+                        0 => unreachable!(),
+                        1 => format!("`{}`", pattern_strings[0]),
+                        2...LIMIT => {
+                            let (tail, head) = pattern_strings.split_last().unwrap();
+                            format!("`{}`", head.join("`, `") + "` and `" + tail)
+                        },
+                        _ => {
+                            let (head, tail) = pattern_strings.split_at(LIMIT);
+                            format!("`{}` and {} more", head.join("`, `"), tail.len())
+                        }
+                    };
                     span_err!(cx.tcx.sess, sp, E0004,
-                        "non-exhaustive patterns: `{}` not covered",
-                        pat_to_string(witness)
+                        "non-exhaustive patterns: {} not covered",
+                        joined_patterns
                     );
                 },
             }
@@ -594,14 +609,15 @@ fn variant_of_ctor(&self,
     }
 }
 
-fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
-                       left_ty: Ty, max_slice_length: usize) -> Option<Constructor> {
+fn missing_constructors(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
+                       left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
     let used_constructors: Vec<Constructor> = rows.iter()
         .flat_map(|row| pat_constructors(cx, row[0], left_ty, max_slice_length))
         .collect();
     all_constructors(cx, left_ty, max_slice_length)
         .into_iter()
-        .find(|c| !used_constructors.contains(c))
+        .filter(|c| !used_constructors.contains(c))
+        .collect()
 }
 
 /// This determines the set of all possible constructors of a pattern matching
@@ -680,46 +696,44 @@ fn is_useful(cx: &MatchCheckCtxt,
 
     let constructors = pat_constructors(cx, v[0], left_ty, max_slice_length);
     if constructors.is_empty() {
-        match missing_constructor(cx, matrix, left_ty, max_slice_length) {
-            None => {
-                all_constructors(cx, left_ty, max_slice_length).into_iter().map(|c| {
-                    match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
-                        UsefulWithWitness(pats) => UsefulWithWitness({
-                            let arity = constructor_arity(cx, &c, left_ty);
-                            let mut result = {
-                                let pat_slice = &pats[..];
-                                let subpats: Vec<_> = (0..arity).map(|i| {
-                                    pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
-                                }).collect();
-                                vec![construct_witness(cx, &c, subpats, left_ty)]
-                            };
-                            result.extend(pats.into_iter().skip(arity));
-                            result
-                        }),
-                        result => result
-                    }
-                }).find(|result| result != &NotUseful).unwrap_or(NotUseful)
-            },
-
-            Some(constructor) => {
-                let matrix = rows.iter().filter_map(|r| {
-                    if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) {
-                        Some(r[1..].to_vec())
-                    } else {
-                        None
-                    }
-                }).collect();
-                match is_useful(cx, &matrix, &v[1..], witness) {
-                    UsefulWithWitness(pats) => {
-                        let arity = constructor_arity(cx, &constructor, left_ty);
-                        let wild_pats = vec![DUMMY_WILD_PAT; arity];
-                        let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
-                        let mut new_pats = vec![enum_pat];
-                        new_pats.extend(pats);
-                        UsefulWithWitness(new_pats)
-                    },
+        let constructors = missing_constructors(cx, matrix, left_ty, max_slice_length);
+        if constructors.is_empty() {
+            all_constructors(cx, left_ty, max_slice_length).into_iter().map(|c| {
+                match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
+                    UsefulWithWitness(pats) => UsefulWithWitness({
+                        let arity = constructor_arity(cx, &c, left_ty);
+                        let mut result = {
+                            let pat_slice = &pats[..];
+                            let subpats: Vec<_> = (0..arity).map(|i| {
+                                pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
+                            }).collect();
+                            vec![construct_witness(cx, &c, subpats, left_ty)]
+                        };
+                        result.extend(pats.into_iter().skip(arity));
+                        result
+                    }),
                     result => result
                 }
+            }).find(|result| result != &NotUseful).unwrap_or(NotUseful)
+        } else {
+            let matrix = rows.iter().filter_map(|r| {
+                if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) {
+                    Some(r[1..].to_vec())
+                } else {
+                    None
+                }
+            }).collect();
+            match is_useful(cx, &matrix, &v[1..], witness) {
+                UsefulWithWitness(pats) => {
+                    let mut new_pats: Vec<_> = constructors.into_iter().map(|constructor| {
+                        let arity = constructor_arity(cx, &constructor, left_ty);
+                        let wild_pats = vec![DUMMY_WILD_PAT; arity];
+                        construct_witness(cx, &constructor, wild_pats, left_ty)
+                    }).collect();
+                    new_pats.extend(pats);
+                    UsefulWithWitness(new_pats)
+                },
+                result => result
             }
         }
     } else {
diff --git a/src/librustc/middle/implicator.rs b/src/librustc/middle/implicator.rs
deleted file mode 100644 (file)
index d25084b..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// #![warn(deprecated_mode)]
-
-use middle::def_id::DefId;
-use middle::infer::{InferCtxt, GenericKind};
-use middle::subst::Substs;
-use middle::traits;
-use middle::ty::{self, ToPredicate, Ty};
-use middle::ty::fold::{TypeFoldable, TypeFolder};
-
-use syntax::ast;
-use syntax::codemap::Span;
-
-use util::common::ErrorReported;
-use util::nodemap::FnvHashSet;
-
-// Helper functions related to manipulating region types.
-
-#[derive(Debug)]
-pub enum Implication<'tcx> {
-    RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
-    RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
-    Predicate(DefId, ty::Predicate<'tcx>),
-}
-
-struct Implicator<'a, 'tcx: 'a> {
-    infcx: &'a InferCtxt<'a,'tcx>,
-    body_id: ast::NodeId,
-    stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
-    span: Span,
-    out: Vec<Implication<'tcx>>,
-    visited: FnvHashSet<Ty<'tcx>>,
-}
-
-/// This routine computes the well-formedness constraints that must hold for the type `ty` to
-/// appear in a context with lifetime `outer_region`
-pub fn implications<'a,'tcx>(
-    infcx: &'a InferCtxt<'a,'tcx>,
-    body_id: ast::NodeId,
-    ty: Ty<'tcx>,
-    outer_region: ty::Region,
-    span: Span)
-    -> Vec<Implication<'tcx>>
-{
-    debug!("implications(body_id={}, ty={:?}, outer_region={:?})",
-           body_id,
-           ty,
-           outer_region);
-
-    let mut stack = Vec::new();
-    stack.push((outer_region, None));
-    let mut wf = Implicator { infcx: infcx,
-                              body_id: body_id,
-                              span: span,
-                              stack: stack,
-                              out: Vec::new(),
-                              visited: FnvHashSet() };
-    wf.accumulate_from_ty(ty);
-    debug!("implications: out={:?}", wf.out);
-    wf.out
-}
-
-impl<'a, 'tcx> Implicator<'a, 'tcx> {
-    fn tcx(&self) -> &'a ty::ctxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
-        debug!("accumulate_from_ty(ty={:?})",
-               ty);
-
-        // When expanding out associated types, we can visit a cyclic
-        // set of types. Issue #23003.
-        if !self.visited.insert(ty) {
-            return;
-        }
-
-        match ty.sty {
-            ty::TyBool |
-            ty::TyChar |
-            ty::TyInt(..) |
-            ty::TyUint(..) |
-            ty::TyFloat(..) |
-            ty::TyBareFn(..) |
-            ty::TyError |
-            ty::TyStr => {
-                // No borrowed content reachable here.
-            }
-
-            ty::TyClosure(_, ref substs) => {
-                // FIXME(#27086). We do not accumulate from substs, since they
-                // don't represent reachable data. This means that, in
-                // practice, some of the lifetime parameters might not
-                // be in scope when the body runs, so long as there is
-                // no reachable data with that lifetime. For better or
-                // worse, this is consistent with fn types, however,
-                // which can also encapsulate data in this fashion
-                // (though it's somewhat harder, and typically
-                // requires virtual dispatch).
-                //
-                // Note that changing this (in a naive way, at least)
-                // causes regressions for what appears to be perfectly
-                // reasonable code like this:
-                //
-                // ```
-                // fn foo<'a>(p: &Data<'a>) {
-                //    bar(|q: &mut Parser| q.read_addr())
-                // }
-                // fn bar(p: Box<FnMut(&mut Parser)+'static>) {
-                // }
-                // ```
-                //
-                // Note that `p` (and `'a`) are not used in the
-                // closure at all, but to meet the requirement that
-                // the closure type `C: 'static` (so it can be coerced
-                // to the object type), we get the requirement that
-                // `'a: 'static` since `'a` appears in the closure
-                // type `C`.
-                //
-                // A smarter fix might "prune" unused `func_substs` --
-                // this would avoid breaking simple examples like
-                // this, but would still break others (which might
-                // indeed be invalid, depending on your POV). Pruning
-                // would be a subtle process, since we have to see
-                // what func/type parameters are used and unused,
-                // taking into consideration UFCS and so forth.
-
-                for &upvar_ty in &substs.upvar_tys {
-                    self.accumulate_from_ty(upvar_ty);
-                }
-            }
-
-            ty::TyTrait(ref t) => {
-                let required_region_bounds =
-                    object_region_bounds(self.tcx(), &t.principal, t.bounds.builtin_bounds);
-                self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
-            }
-
-            ty::TyEnum(def, substs) |
-            ty::TyStruct(def, substs) => {
-                let item_scheme = def.type_scheme(self.tcx());
-                self.accumulate_from_adt(ty, def.did, &item_scheme.generics, substs)
-            }
-
-            ty::TyArray(t, _) |
-            ty::TySlice(t) |
-            ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) |
-            ty::TyBox(t) => {
-                self.accumulate_from_ty(t)
-            }
-
-            ty::TyRef(r_b, mt) => {
-                self.accumulate_from_rptr(ty, *r_b, mt.ty);
-            }
-
-            ty::TyParam(p) => {
-                self.push_param_constraint_from_top(p);
-            }
-
-            ty::TyProjection(ref data) => {
-                // `<T as TraitRef<..>>::Name`
-
-                self.push_projection_constraint_from_top(data);
-            }
-
-            ty::TyTuple(ref tuptys) => {
-                for &tupty in tuptys {
-                    self.accumulate_from_ty(tupty);
-                }
-            }
-
-            ty::TyInfer(_) => {
-                // This should not happen, BUT:
-                //
-                //   Currently we uncover region relationships on
-                //   entering the fn check. We should do this after
-                //   the fn check, then we can call this case a bug().
-            }
-        }
-    }
-
-    fn accumulate_from_rptr(&mut self,
-                            ty: Ty<'tcx>,
-                            r_b: ty::Region,
-                            ty_b: Ty<'tcx>) {
-        // We are walking down a type like this, and current
-        // position is indicated by caret:
-        //
-        //     &'a &'b ty_b
-        //         ^
-        //
-        // At this point, top of stack will be `'a`. We must
-        // require that `'a <= 'b`.
-
-        self.push_region_constraint_from_top(r_b);
-
-        // Now we push `'b` onto the stack, because it must
-        // constrain any borrowed content we find within `T`.
-
-        self.stack.push((r_b, Some(ty)));
-        self.accumulate_from_ty(ty_b);
-        self.stack.pop().unwrap();
-    }
-
-    /// Pushes a constraint that `r_b` must outlive the top region on the stack.
-    fn push_region_constraint_from_top(&mut self,
-                                       r_b: ty::Region) {
-
-        // Indicates that we have found borrowed content with a lifetime
-        // of at least `r_b`. This adds a constraint that `r_b` must
-        // outlive the region `r_a` on top of the stack.
-        //
-        // As an example, imagine walking a type like:
-        //
-        //     &'a &'b T
-        //         ^
-        //
-        // when we hit the inner pointer (indicated by caret), `'a` will
-        // be on top of stack and `'b` will be the lifetime of the content
-        // we just found. So we add constraint that `'a <= 'b`.
-
-        let &(r_a, opt_ty) = self.stack.last().unwrap();
-        self.push_sub_region_constraint(opt_ty, r_a, r_b);
-    }
-
-    /// Pushes a constraint that `r_a <= r_b`, due to `opt_ty`
-    fn push_sub_region_constraint(&mut self,
-                                  opt_ty: Option<Ty<'tcx>>,
-                                  r_a: ty::Region,
-                                  r_b: ty::Region) {
-        self.out.push(Implication::RegionSubRegion(opt_ty, r_a, r_b));
-    }
-
-    /// Pushes a constraint that `param_ty` must outlive the top region on the stack.
-    fn push_param_constraint_from_top(&mut self,
-                                      param_ty: ty::ParamTy) {
-        let &(region, opt_ty) = self.stack.last().unwrap();
-        self.push_param_constraint(region, opt_ty, param_ty);
-    }
-
-    /// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
-    fn push_projection_constraint_from_top(&mut self,
-                                           projection_ty: &ty::ProjectionTy<'tcx>) {
-        let &(region, opt_ty) = self.stack.last().unwrap();
-        self.out.push(Implication::RegionSubGeneric(
-            opt_ty, region, GenericKind::Projection(projection_ty.clone())));
-    }
-
-    /// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
-    fn push_param_constraint(&mut self,
-                             region: ty::Region,
-                             opt_ty: Option<Ty<'tcx>>,
-                             param_ty: ty::ParamTy) {
-        self.out.push(Implication::RegionSubGeneric(
-            opt_ty, region, GenericKind::Param(param_ty)));
-    }
-
-    fn accumulate_from_adt(&mut self,
-                           ty: Ty<'tcx>,
-                           def_id: DefId,
-                           _generics: &ty::Generics<'tcx>,
-                           substs: &Substs<'tcx>)
-    {
-        let predicates =
-            self.tcx().lookup_predicates(def_id).instantiate(self.tcx(), substs);
-        let predicates = match self.fully_normalize(&predicates) {
-            Ok(predicates) => predicates,
-            Err(ErrorReported) => { return; }
-        };
-
-        for predicate in predicates.predicates.as_slice() {
-            match *predicate {
-                ty::Predicate::Trait(..) => { }
-                ty::Predicate::Equate(..) => { }
-                ty::Predicate::Projection(..) => { }
-                ty::Predicate::RegionOutlives(ref data) => {
-                    match self.tcx().no_late_bound_regions(data) {
-                        None => { }
-                        Some(ty::OutlivesPredicate(r_a, r_b)) => {
-                            self.push_sub_region_constraint(Some(ty), r_b, r_a);
-                        }
-                    }
-                }
-                ty::Predicate::TypeOutlives(ref data) => {
-                    match self.tcx().no_late_bound_regions(data) {
-                        None => { }
-                        Some(ty::OutlivesPredicate(ty_a, r_b)) => {
-                            self.stack.push((r_b, Some(ty)));
-                            self.accumulate_from_ty(ty_a);
-                            self.stack.pop().unwrap();
-                        }
-                    }
-                }
-                ty::Predicate::ObjectSafe(_) |
-                ty::Predicate::WellFormed(_) => {
-                }
-            }
-        }
-
-        let obligations = predicates.predicates
-                                    .into_iter()
-                                    .map(|pred| Implication::Predicate(def_id, pred));
-        self.out.extend(obligations);
-
-        let variances = self.tcx().item_variances(def_id);
-        self.accumulate_from_substs(substs, Some(&variances));
-    }
-
-    fn accumulate_from_substs(&mut self,
-                              substs: &Substs<'tcx>,
-                              variances: Option<&ty::ItemVariances>)
-    {
-        let mut tmp_variances = None;
-        let variances = variances.unwrap_or_else(|| {
-            tmp_variances = Some(ty::ItemVariances {
-                types: substs.types.map(|_| ty::Variance::Invariant),
-                regions: substs.regions().map(|_| ty::Variance::Invariant),
-            });
-            tmp_variances.as_ref().unwrap()
-        });
-
-        for (&region, &variance) in substs.regions().iter().zip(&variances.regions) {
-            match variance {
-                ty::Contravariant | ty::Invariant => {
-                    // If any data with this lifetime is reachable
-                    // within, it must be at least contravariant.
-                    self.push_region_constraint_from_top(region)
-                }
-                ty::Covariant | ty::Bivariant => { }
-            }
-        }
-
-        for (&ty, &variance) in substs.types.iter().zip(&variances.types) {
-            match variance {
-                ty::Covariant | ty::Invariant => {
-                    // If any data of this type is reachable within,
-                    // it must be at least covariant.
-                    self.accumulate_from_ty(ty);
-                }
-                ty::Contravariant | ty::Bivariant => { }
-            }
-        }
-    }
-
-    fn accumulate_from_object_ty(&mut self,
-                                 ty: Ty<'tcx>,
-                                 region_bound: ty::Region,
-                                 required_region_bounds: Vec<ty::Region>)
-    {
-        // Imagine a type like this:
-        //
-        //     trait Foo { }
-        //     trait Bar<'c> : 'c { }
-        //
-        //     &'b (Foo+'c+Bar<'d>)
-        //         ^
-        //
-        // In this case, the following relationships must hold:
-        //
-        //     'b <= 'c
-        //     'd <= 'c
-        //
-        // The first conditions is due to the normal region pointer
-        // rules, which say that a reference cannot outlive its
-        // referent.
-        //
-        // The final condition may be a bit surprising. In particular,
-        // you may expect that it would have been `'c <= 'd`, since
-        // usually lifetimes of outer things are conservative
-        // approximations for inner things. However, it works somewhat
-        // differently with trait objects: here the idea is that if the
-        // user specifies a region bound (`'c`, in this case) it is the
-        // "master bound" that *implies* that bounds from other traits are
-        // all met. (Remember that *all bounds* in a type like
-        // `Foo+Bar+Zed` must be met, not just one, hence if we write
-        // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
-        // 'y.)
-        //
-        // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
-        // am looking forward to the future here.
-
-        // The content of this object type must outlive
-        // `bounds.region_bound`:
-        let r_c = region_bound;
-        self.push_region_constraint_from_top(r_c);
-
-        // And then, in turn, to be well-formed, the
-        // `region_bound` that user specified must imply the
-        // region bounds required from all of the trait types:
-        for &r_d in &required_region_bounds {
-            // Each of these is an instance of the `'c <= 'b`
-            // constraint above
-            self.out.push(Implication::RegionSubRegion(Some(ty), r_d, r_c));
-        }
-    }
-
-    fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
-        where T : TypeFoldable<'tcx>
-    {
-        let value =
-            traits::fully_normalize(self.infcx,
-                                    traits::ObligationCause::misc(self.span, self.body_id),
-                                    value);
-        match value {
-            Ok(value) => Ok(value),
-            Err(errors) => {
-                // I don't like reporting these errors here, but I
-                // don't know where else to report them just now. And
-                // I don't really expect errors to arise here
-                // frequently. I guess the best option would be to
-                // propagate them out.
-                traits::report_fulfillment_errors(self.infcx, &errors);
-                Err(ErrorReported)
-            }
-        }
-    }
-}
-
-/// Given an object type like `SomeTrait+Send`, computes the lifetime
-/// bounds that must hold on the elided self type. These are derived
-/// from the declarations of `SomeTrait`, `Send`, and friends -- if
-/// they declare `trait SomeTrait : 'static`, for example, then
-/// `'static` would appear in the list. The hard work is done by
-/// `ty::required_region_bounds`, see that for more information.
-pub fn object_region_bounds<'tcx>(
-    tcx: &ty::ctxt<'tcx>,
-    principal: &ty::PolyTraitRef<'tcx>,
-    others: ty::BuiltinBounds)
-    -> Vec<ty::Region>
-{
-    // Since we don't actually *know* the self type for an object,
-    // this "open(err)" serves as a kind of dummy standin -- basically
-    // a skolemized type.
-    let open_ty = tcx.mk_infer(ty::FreshTy(0));
-
-    // Note that we preserve the overall binding levels here.
-    assert!(!open_ty.has_escaping_regions());
-    let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
-    let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs)));
-
-    let mut predicates = others.to_predicates(tcx, open_ty);
-    predicates.extend(trait_refs.iter().map(|t| t.to_predicate()));
-
-    tcx.required_region_bounds(open_ty, predicates)
-}
index 975ec0e709b7d272605e9c31b6f9c2fe057c6511..fbfdbd15116c9b9fbc6bfc5d0b67e5aaa511f06f 100644 (file)
@@ -176,15 +176,28 @@ pub fn has_errors(&self) -> bool {
     pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
-    pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
+    pub fn track_errors<F, T>(&self, f: F) -> Result<T, usize>
         where F: FnOnce() -> T
     {
-        let count = self.err_count();
+        let mut count = self.err_count();
         let result = f();
-        if self.err_count() > count {
-            self.abort_if_errors();
+        count -= self.err_count();
+        if count == 0 {
+            Ok(result)
+        } else {
+            Err(count)
+        }
+    }
+    pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
+        where F: FnOnce() -> T
+    {
+        match self.track_errors(f) {
+            Ok(result) => result,
+            Err(_) => {
+                self.abort_if_errors();
+                unreachable!();
+            }
         }
-        result
     }
     pub fn span_warn(&self, sp: Span, msg: &str) {
         self.diagnostic().span_warn(sp, msg)
index 2481cab78b4d6f15bdf37bf15d65c19a557cd38c..9441e34cb9b1fad3b011d6ede0475f96bf2fc14a 100644 (file)
 
 use std::cell::{RefCell, Cell};
 use std::collections::HashMap;
-use std::collections::hash_state::HashState;
 use std::ffi::CString;
 use std::fmt::Debug;
-use std::hash::Hash;
+use std::hash::{Hash, BuildHasher};
 use std::iter::repeat;
 use std::path::Path;
 use std::time::Instant;
@@ -217,7 +216,7 @@ fn memoize<OP>(&self, key: Self::Key, op: OP) -> Self::Value
 }
 
 impl<K, V, S> MemoizationMap for RefCell<HashMap<K,V,S>>
-    where K: Hash+Eq+Clone, V: Clone, S: HashState
+    where K: Hash+Eq+Clone, V: Clone, S: BuildHasher
 {
     type Key = K;
     type Value = V;
index 746d3ba07d6011383da92eaa73e3b22fad55fe60..4d8cfc23804203b786a0c98534233d63cfa5236f 100644 (file)
@@ -28,6 +28,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_syntax)]
 #![feature(libc)]
index b78fdc9f59ba1103063cb2863e1ab87efaf5fa80..ead16f957079c1996b17bdd9171e202c68fe43a4 100644 (file)
@@ -24,6 +24,9 @@ pub fn opts() -> TargetOptions {
             // libraries which follow this flag.  Thus, use it before
             // specifying libraries to link to.
             "-Wl,--as-needed".to_string(),
+
+            // Always enable NX protection when it is available
+            "-Wl,-z,noexecstack".to_string(),
         ),
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
index e955f8c302bd64977a0b8c84e0d17c49bd153963..946e529502e7d6ebb144fb86e51182a841faced3 100644 (file)
@@ -17,6 +17,10 @@ pub fn opts() -> TargetOptions {
         dynamic_linking: true,
         executables: true,
         has_rpath: true,
+        pre_link_args: vec![
+            // Always enable NX protection when it is available
+            "-Wl,-z,noexecstack".to_string(),
+        ],
         archive_format: "gnu".to_string(),
         exe_allocation_crate: super::maybe_jemalloc(),
 
index 0efcf73ee86808ecff5243e64d199410ffc996a1..20aae113f7bb34f4026e78672804b99b82e9cb0e 100644 (file)
@@ -26,6 +26,9 @@ pub fn opts() -> TargetOptions {
             // following libraries so we're sure to pass it as one of the first
             // arguments.
             "-Wl,--as-needed".to_string(),
+
+            // Always enable NX protection when it is available
+            "-Wl,-z,noexecstack".to_string(),
         ],
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
index 361f71f69959197ddf580c0a6a64a6508c688571..ead8a7259f03b0a1f8906f877f96cf9f16eaf8da 100644 (file)
@@ -24,6 +24,9 @@ pub fn opts() -> TargetOptions {
             // libraries which follow this flag.  Thus, use it before
             // specifying libraries to link to.
             "-Wl,--as-needed".to_string(),
+
+            // Always enable NX protection when it is available
+            "-Wl,-z,noexecstack".to_string(),
         ),
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
index 2e4aa27cf889d22659b909e2221c5e5e6d9d8182..e0c2d062949d877a25883e334fc54011e368425b 100644 (file)
@@ -24,6 +24,9 @@ pub fn opts() -> TargetOptions {
             // libraries which follow this flag.  Thus, use it before
             // specifying libraries to link to.
             "-Wl,--as-needed".to_string(),
+
+            // Always enable NX protection when it is available
+            "-Wl,-z,noexecstack".to_string(),
         ),
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
index e2a929f58e14da0b2fe0aa723a9c1c052d8e31d9..e2025eaa8ee06d6537c264631f4b59c213066a2e 100644 (file)
@@ -15,6 +15,7 @@
 #![crate_type = "rlib"]
 #![no_std]
 #![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 //! A typesafe bitmask flag generator.
 
index d730b383a80499d7e52f05a8fe2c17f2a144b19d..e7f5fddc7bbf2b18a97ad34e02a49d10d538c76a 100644 (file)
@@ -15,6 +15,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![allow(non_camel_case_types)]
 
index 77baa84c0236d020e2d7ab133575d68b2f9cded7..6f4dc28e12221c13c423f67e9b6904dde5c029a8 100644 (file)
@@ -9,21 +9,20 @@
 // except according to those terms.
 
 use std::collections::{HashMap, HashSet};
-use std::collections::hash_state::DefaultState;
 use std::default::Default;
-use std::hash::{Hasher, Hash};
+use std::hash::{Hasher, Hash, BuildHasherDefault};
 
-pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
-pub type FnvHashSet<V> = HashSet<V, DefaultState<FnvHasher>>;
+pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FnvHasher>>;
+pub type FnvHashSet<V> = HashSet<V, BuildHasherDefault<FnvHasher>>;
 
 #[allow(non_snake_case)]
 pub fn FnvHashMap<K: Hash + Eq, V>() -> FnvHashMap<K, V> {
-    Default::default()
+    HashMap::default()
 }
 
 #[allow(non_snake_case)]
 pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
-    Default::default()
+    HashSet::default()
 }
 
 /// A speedy hash algorithm for node ids and def ids. The hashmap in
index 1fbbdf17455b27872b1297bc3b8982348e92ff01..e4b13ff548a4538df0efda70e71bfd671132f2ec 100644 (file)
@@ -23,8 +23,8 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
-#![feature(hashmap_hasher)]
 #![feature(nonzero)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
index 36074a7ae0225369e4de694b829eecc00b7389a0..6189416dd578a7596d8c9f59172a5502d2713f50 100644 (file)
@@ -35,7 +35,7 @@
 use rustc_front::hir;
 use rustc_front::lowering::{lower_crate, LoweringContext};
 use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion};
-use super::Compilation;
+use super::{Compilation, CompileResult, compile_result_from_err_count};
 
 use serialize::json;
 
 use syntax;
 use syntax_ext;
 
-pub fn compile_input(sess: Session,
+macro_rules! throw_if_errors {
+    ($tsess: expr) => {{
+        let err_count = $tsess.err_count();
+        if err_count > 0 {
+            return Err(err_count);
+        }
+    }}
+}
+
+pub fn compile_input(sess: &Session,
                      cstore: &CStore,
                      cfg: ast::CrateConfig,
                      input: &Input,
                      outdir: &Option<PathBuf>,
                      output: &Option<PathBuf>,
                      addl_plugins: Option<Vec<String>>,
-                     control: CompileController) {
+                     control: CompileController) -> CompileResult {
     macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: expr) => ({
         let state = $make_state;
         (control.$point.callback)(state);
 
         if control.$point.stop == Compilation::Stop {
-            $tsess.abort_if_errors();
-            return;
+            return compile_result_from_err_count($tsess.err_count());
         }
     })}
 
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let result = {
+    let (outputs, trans) = {
         let (outputs, expanded_crate, id) = {
-            let krate = phase_1_parse_input(&sess, cfg, input);
+            let krate = phase_1_parse_input(sess, cfg, input);
 
             controller_entry_point!(after_parse,
                                     sess,
-                                    CompileState::state_after_parse(input, &sess, outdir, &krate));
-
-            let outputs = build_output_filenames(input, outdir, output, &krate.attrs, &sess);
-            let id = link::find_crate_name(Some(&sess), &krate.attrs, input);
-            let expanded_crate = match phase_2_configure_and_expand(&sess,
-                                                                    &cstore,
-                                                                    krate,
-                                                                    &id[..],
-                                                                    addl_plugins) {
-                None => return,
-                Some(k) => k,
-            };
+                                    CompileState::state_after_parse(input, sess, outdir, &krate));
+
+            let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
+            let id = link::find_crate_name(Some(sess), &krate.attrs, input);
+            let expanded_crate = try!(phase_2_configure_and_expand(sess,
+                                                                   &cstore,
+                                                                   krate,
+                                                                   &id[..],
+                                                                   addl_plugins));
 
             (outputs, expanded_crate, id)
         };
@@ -103,14 +108,14 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
         controller_entry_point!(after_expand,
                                 sess,
                                 CompileState::state_after_expand(input,
-                                                                 &sess,
+                                                                 sess,
                                                                  outdir,
                                                                  &expanded_crate,
                                                                  &id[..]));
 
-        let expanded_crate = assign_node_ids(&sess, expanded_crate);
+        let expanded_crate = assign_node_ids(sess, expanded_crate);
         // Lower ast -> hir.
-        let lcx = LoweringContext::new(&sess, Some(&expanded_crate));
+        let lcx = LoweringContext::new(sess, Some(&expanded_crate));
         let mut hir_forest = time(sess.time_passes(),
                                   "lowering ast -> hir",
                                   || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
@@ -122,14 +127,14 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
         }
 
         let arenas = ty::CtxtArenas::new();
-        let hir_map = make_map(&sess, &mut hir_forest);
+        let hir_map = make_map(sess, &mut hir_forest);
 
-        write_out_deps(&sess, &outputs, &id);
+        write_out_deps(sess, &outputs, &id);
 
         controller_entry_point!(after_write_deps,
                                 sess,
                                 CompileState::state_after_write_deps(input,
-                                                                     &sess,
+                                                                     sess,
                                                                      outdir,
                                                                      &hir_map,
                                                                      &expanded_crate,
@@ -138,12 +143,12 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
                                                                      &lcx));
 
         time(sess.time_passes(), "attribute checking", || {
-            front::check_attr::check_crate(&sess, &expanded_crate);
+            front::check_attr::check_crate(sess, &expanded_crate);
         });
 
         time(sess.time_passes(),
              "early lint checks",
-             || lint::check_ast_crate(&sess, &expanded_crate));
+             || lint::check_ast_crate(sess, &expanded_crate));
 
         let opt_crate = if sess.opts.debugging_opts.keep_ast ||
                            sess.opts.debugging_opts.save_analysis {
@@ -153,67 +158,62 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
             None
         };
 
-        phase_3_run_analysis_passes(&sess,
-                                    &cstore,
-                                    hir_map,
-                                    &arenas,
-                                    &id,
-                                    control.make_glob_map,
-                                    |tcx, mir_map, analysis| {
-
-                                        {
-                                            let state =
-                                                CompileState::state_after_analysis(input,
-                                                                                   &tcx.sess,
-                                                                                   outdir,
-                                                                                   opt_crate,
-                                                                                   tcx.map.krate(),
-                                                                                   &analysis,
-                                                                                   &mir_map,
-                                                                                   tcx,
-                                                                                   &lcx,
-                                                                                   &id);
-                                            (control.after_analysis.callback)(state);
-
-                                            tcx.sess.abort_if_errors();
-                                            if control.after_analysis.stop == Compilation::Stop {
-                                                return Err(());
-                                            }
-                                        }
-
-                                        if log_enabled!(::log::INFO) {
-                                            println!("Pre-trans");
-                                            tcx.print_debug_stats();
-                                        }
-                                        let trans = phase_4_translate_to_llvm(tcx,
-                                                                              mir_map,
-                                                                              analysis);
-
-                                        if log_enabled!(::log::INFO) {
-                                            println!("Post-trans");
-                                            tcx.print_debug_stats();
-                                        }
-
-                                        // Discard interned strings as they are no longer required.
-                                        token::get_ident_interner().clear();
-
-                                        Ok((outputs, trans))
-                                    })
-    };
+        try!(try!(phase_3_run_analysis_passes(sess,
+                                         &cstore,
+                                         hir_map,
+                                         &arenas,
+                                         &id,
+                                         control.make_glob_map,
+                                         |tcx, mir_map, analysis| {
+            {
+                let state =
+                    CompileState::state_after_analysis(input,
+                                                       &tcx.sess,
+                                                       outdir,
+                                                       opt_crate,
+                                                       tcx.map.krate(),
+                                                       &analysis,
+                                                       &mir_map,
+                                                       tcx,
+                                                       &lcx,
+                                                       &id);
+                (control.after_analysis.callback)(state);
+
+                throw_if_errors!(tcx.sess);
+                if control.after_analysis.stop == Compilation::Stop {
+                    return Err(0usize);
+                }
+            }
 
-    let (outputs, trans) = if let Ok(out) = result {
-        out
-    } else {
-        return;
+            if log_enabled!(::log::INFO) {
+                println!("Pre-trans");
+                tcx.print_debug_stats();
+            }
+            let trans = phase_4_translate_to_llvm(tcx,
+                                                  mir_map,
+                                                  analysis);
+
+            if log_enabled!(::log::INFO) {
+                println!("Post-trans");
+                tcx.print_debug_stats();
+            }
+
+            // Discard interned strings as they are no longer required.
+            token::get_ident_interner().clear();
+
+            Ok((outputs, trans))
+        })))
     };
 
-    phase_5_run_llvm_passes(&sess, &trans, &outputs);
+    try!(phase_5_run_llvm_passes(sess, &trans, &outputs));
 
     controller_entry_point!(after_llvm,
                             sess,
-                            CompileState::state_after_llvm(input, &sess, outdir, &trans));
+                            CompileState::state_after_llvm(input, sess, outdir, &trans));
+
+    phase_6_link_output(sess, &trans, &outputs);
 
-    phase_6_link_output(&sess, &trans, &outputs);
+    Ok(())
 }
 
 /// The name used for source code that doesn't originate in a file
@@ -457,7 +457,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
                                     mut krate: ast::Crate,
                                     crate_name: &str,
                                     addl_plugins: Option<Vec<String>>)
-                                    -> Option<ast::Crate> {
+                                    -> Result<ast::Crate, usize> {
     let time_passes = sess.time_passes();
 
     // strip before anything else because crate metadata may use #[cfg_attr]
@@ -469,13 +469,13 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     // baz! should not use this definition unless foo is enabled.
 
     let mut feature_gated_cfgs = vec![];
-    krate = time(time_passes, "configuration 1", || {
-        sess.abort_if_new_errors(|| {
+    krate = try!(time(time_passes, "configuration 1", || {
+        sess.track_errors(|| {
             syntax::config::strip_unconfigured_items(sess.diagnostic(),
                                                      krate,
                                                      &mut feature_gated_cfgs)
         })
-    });
+    }));
 
     *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
     *sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs);
@@ -484,8 +484,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         middle::recursion_limit::update_recursion_limit(sess, &krate);
     });
 
-    time(time_passes, "gated macro checking", || {
-        sess.abort_if_new_errors(|| {
+    try!(time(time_passes, "gated macro checking", || {
+        sess.track_errors(|| {
             let features =
               syntax::feature_gate::check_crate_macros(sess.codemap(),
                                                        &sess.parse_sess.span_diagnostic,
@@ -493,8 +493,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
             // these need to be set "early" so that expansion sees `quote` if enabled.
             *sess.features.borrow_mut() = features;
-        });
-    });
+        })
+    }));
 
 
     krate = time(time_passes, "crate injection", || {
@@ -531,7 +531,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
                    llvm_passes, attributes, .. } = registry;
 
-    sess.abort_if_new_errors(|| {
+    try!(sess.track_errors(|| {
         let mut ls = sess.lint_store.borrow_mut();
         for pass in early_lint_passes {
             ls.register_early_pass(Some(sess), true, pass);
@@ -546,14 +546,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
         *sess.plugin_attributes.borrow_mut() = attributes.clone();
-    });
+    }));
 
     // Lint plugins are registered; now we can process command line flags.
     if sess.opts.describe_lints {
         super::describe_lints(&*sess.lint_store.borrow(), true);
-        return None;
+        return Err(0);
     }
-    sess.abort_if_new_errors(|| sess.lint_store.borrow_mut().process_command_line(sess));
+    try!(sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess)));
 
     krate = time(time_passes, "expansion", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
@@ -596,21 +596,21 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     // of macro expansion.  This runs before #[cfg] to try to catch as
     // much as possible (e.g. help the programmer avoid platform
     // specific differences)
-    time(time_passes, "complete gated feature checking 1", || {
-        sess.abort_if_new_errors(|| {
+    try!(time(time_passes, "complete gated feature checking 1", || {
+        sess.track_errors(|| {
             let features = syntax::feature_gate::check_crate(sess.codemap(),
                                                              &sess.parse_sess.span_diagnostic,
                                                              &krate,
                                                              &attributes,
                                                              sess.opts.unstable_features);
             *sess.features.borrow_mut() = features;
-        });
-    });
+        })
+    }));
 
     // JBC: make CFG processing part of expansion to avoid this problem:
 
     // strip again, in case expansion added anything with a #[cfg].
-    krate = sess.abort_if_new_errors(|| {
+    krate = try!(sess.track_errors(|| {
         let krate = time(time_passes, "configuration 2", || {
             syntax::config::strip_unconfigured_items(sess.diagnostic(),
                                                      krate,
@@ -627,7 +627,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         });
 
         krate
-    });
+    }));
 
     krate = time(time_passes, "maybe building test harness", || {
         syntax::test::modify_for_testing(&sess.parse_sess, &sess.opts.cfg, krate, sess.diagnostic())
@@ -648,16 +648,16 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     // One final feature gating of the true AST that gets compiled
     // later, to make sure we've got everything (e.g. configuration
     // can insert new attributes via `cfg_attr`)
-    time(time_passes, "complete gated feature checking 2", || {
-        sess.abort_if_new_errors(|| {
+    try!(time(time_passes, "complete gated feature checking 2", || {
+        sess.track_errors(|| {
             let features = syntax::feature_gate::check_crate(sess.codemap(),
                                                              &sess.parse_sess.span_diagnostic,
                                                              &krate,
                                                              &attributes,
                                                              sess.opts.unstable_features);
             *sess.features.borrow_mut() = features;
-        });
-    });
+        })
+    }));
 
     time(time_passes,
          "const fn bodies and arguments",
@@ -667,7 +667,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         println!("Post-expansion node count: {}", count_nodes(&krate));
     }
 
-    Some(krate)
+    Ok(krate)
 }
 
 pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
@@ -712,7 +712,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                name: &str,
                                                make_glob_map: resolve::MakeGlobMap,
                                                f: F)
-                                               -> R
+                                               -> Result<R, usize>
     where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R
 {
     let time_passes = sess.time_passes();
@@ -722,11 +722,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
          "external crate/lib resolution",
          || LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate));
 
-    let lang_items = time(time_passes, "language item collection", || {
-        sess.abort_if_new_errors(|| {
+    let lang_items = try!(time(time_passes, "language item collection", || {
+        sess.track_errors(|| {
             middle::lang_items::collect_language_items(&sess, &hir_map)
         })
-    });
+    }));
 
     let resolve::CrateMap {
         def_map,
@@ -773,98 +773,98 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                lang_items,
                                stability::Index::new(krate),
                                |tcx| {
-                                   // passes are timed inside typeck
-                                   typeck::check_crate(tcx, trait_map);
-
-                                   time(time_passes,
-                                        "const checking",
-                                        || consts::check_crate(tcx));
-
-                                   let access_levels =
-                                       time(time_passes, "privacy checking", || {
-                                           rustc_privacy::check_crate(tcx,
-                                                                      &export_map,
-                                                                      external_exports)
-                                       });
-
-                                   // Do not move this check past lint
-                                   time(time_passes, "stability index", || {
-                                       tcx.stability.borrow_mut().build(tcx, krate, &access_levels)
-                                   });
-
-                                   time(time_passes,
-                                        "intrinsic checking",
-                                        || middle::intrinsicck::check_crate(tcx));
-
-                                   time(time_passes,
-                                        "effect checking",
-                                        || middle::effect::check_crate(tcx));
-
-                                   time(time_passes,
-                                        "match checking",
-                                        || middle::check_match::check_crate(tcx));
-
-                                   let mir_map =
-                                       time(time_passes,
-                                            "MIR dump",
-                                            || mir::mir_map::build_mir_for_crate(tcx));
-
-                                   time(time_passes,
-                                        "liveness checking",
-                                        || middle::liveness::check_crate(tcx));
-
-                                   time(time_passes,
-                                        "borrow checking",
-                                        || borrowck::check_crate(tcx));
-
-                                   time(time_passes,
-                                        "rvalue checking",
-                                        || rvalues::check_crate(tcx));
-
-                                   // Avoid overwhelming user with errors if type checking failed.
-                                   // I'm not sure how helpful this is, to be honest, but it avoids
-                                   // a
-                                   // lot of annoying errors in the compile-fail tests (basically,
-                                   // lint warnings and so on -- kindck used to do this abort, but
-                                   // kindck is gone now). -nmatsakis
-                                   tcx.sess.abort_if_errors();
-
-                                   let reachable_map =
-                                       time(time_passes,
-                                            "reachability checking",
-                                            || reachable::find_reachable(tcx, &access_levels));
-
-                                   time(time_passes, "death checking", || {
-                                       middle::dead::check_crate(tcx, &access_levels);
-                                   });
-
-                                   let ref lib_features_used =
-                                       time(time_passes,
-                                            "stability checking",
-                                            || stability::check_unstable_api_usage(tcx));
-
-                                   time(time_passes, "unused lib feature checking", || {
-                                       stability::check_unused_or_stable_features(&tcx.sess,
-                                                                                  lib_features_used)
-                                   });
-
-                                   time(time_passes,
-                                        "lint checking",
-                                        || lint::check_crate(tcx, &access_levels));
-
-                                   // The above three passes generate errors w/o aborting
-                                   tcx.sess.abort_if_errors();
-
-                                   f(tcx,
-                                     mir_map,
-                                     ty::CrateAnalysis {
-                                         export_map: export_map,
-                                         access_levels: access_levels,
-                                         reachable: reachable_map,
-                                         name: name,
-                                         glob_map: glob_map,
-                                     })
-                               })
+        // passes are timed inside typeck
+        typeck::check_crate(tcx, trait_map);
+
+        time(time_passes,
+             "const checking",
+             || consts::check_crate(tcx));
+
+        let access_levels =
+            time(time_passes, "privacy checking", || {
+                rustc_privacy::check_crate(tcx,
+                                           &export_map,
+                                           external_exports)
+            });
+
+        // Do not move this check past lint
+        time(time_passes, "stability index", || {
+            tcx.stability.borrow_mut().build(tcx, krate, &access_levels)
+        });
+
+        time(time_passes,
+             "intrinsic checking",
+             || middle::intrinsicck::check_crate(tcx));
+
+        time(time_passes,
+             "effect checking",
+             || middle::effect::check_crate(tcx));
+
+        time(time_passes,
+             "match checking",
+             || middle::check_match::check_crate(tcx));
+
+        let mir_map =
+            time(time_passes,
+                 "MIR dump",
+                 || mir::mir_map::build_mir_for_crate(tcx));
+
+        time(time_passes,
+             "liveness checking",
+             || middle::liveness::check_crate(tcx));
+
+        time(time_passes,
+             "borrow checking",
+             || borrowck::check_crate(tcx));
+
+        time(time_passes,
+             "rvalue checking",
+             || rvalues::check_crate(tcx));
+
+        // Avoid overwhelming user with errors if type checking failed.
+        // I'm not sure how helpful this is, to be honest, but it avoids
+        // a
+        // lot of annoying errors in the compile-fail tests (basically,
+        // lint warnings and so on -- kindck used to do this abort, but
+        // kindck is gone now). -nmatsakis
+        throw_if_errors!(tcx.sess);
+
+        let reachable_map =
+            time(time_passes,
+                 "reachability checking",
+                 || reachable::find_reachable(tcx, &access_levels));
+
+        time(time_passes, "death checking", || {
+            middle::dead::check_crate(tcx, &access_levels);
+        });
+
+        let ref lib_features_used =
+            time(time_passes,
+                 "stability checking",
+                 || stability::check_unstable_api_usage(tcx));
+
+        time(time_passes, "unused lib feature checking", || {
+            stability::check_unused_or_stable_features(&tcx.sess,
+                                                       lib_features_used)
+        });
+
+        time(time_passes,
+             "lint checking",
+             || lint::check_crate(tcx, &access_levels));
+
+        // The above three passes generate errors w/o aborting
+        throw_if_errors!(tcx.sess);
+
+        Ok(f(tcx,
+          mir_map,
+          ty::CrateAnalysis {
+              export_map: export_map,
+              access_levels: access_levels,
+              reachable: reachable_map,
+              name: name,
+              glob_map: glob_map,
+          }))
+    })
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
@@ -893,7 +893,7 @@ pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>,
 /// as a side effect.
 pub fn phase_5_run_llvm_passes(sess: &Session,
                                trans: &trans::CrateTranslation,
-                               outputs: &OutputFilenames) {
+                               outputs: &OutputFilenames) -> CompileResult {
     if sess.opts.cg.no_integrated_as {
         let mut map = HashMap::new();
         map.insert(OutputType::Assembly, None);
@@ -913,7 +913,8 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
              || write::run_passes(sess, trans, &sess.opts.output_types, outputs));
     }
 
-    sess.abort_if_errors();
+    throw_if_errors!(sess);
+    Ok(())
 }
 
 /// Run the linker on any artifacts that resulted from the LLVM run.
index 31151e10a5a55c9d2b8be45aaf6e097047ae20db..97256a1a3fd0f060d71d7e2aac26b37f11399b45 100644 (file)
@@ -21,6 +21,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_syntax)]
 #![feature(libc)]
 const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                                       md#bug-reports";
 
+// Err(0) means compilation was stopped, but no errors were found.
+// This would be better as a dedicated enum, but using try! is so convenient.
+pub type CompileResult = Result<(), usize>;
+
+pub fn compile_result_from_err_count(err_count: usize) -> CompileResult {
+    if err_count == 0 {
+        Ok(())
+    } else {
+        Err(err_count)
+    }
+}
+
+#[inline]
+fn abort_msg(err_count: usize) -> String {
+    match err_count {
+        0 => "aborting with no errors (maybe a bug?)".to_owned(),
+        1 => "aborting due to previous error".to_owned(),
+        e => format!("aborting due to {} previous errors", e),
+    }
+}
+
+pub fn abort_on_err<T>(result: Result<T, usize>, sess: &Session) -> T {
+    match result {
+        Err(err_count) => {
+            sess.fatal(&abort_msg(err_count));
+        }
+        Ok(x) => x,
+    }
+}
+
 pub fn run(args: Vec<String>) -> isize {
-    monitor(move || run_compiler(&args, &mut RustcDefaultCalls));
+    monitor(move || {
+        let (result, session) = run_compiler(&args, &mut RustcDefaultCalls);
+        if let Err(err_count) = result {
+            if err_count > 0 {
+                match session {
+                    Some(sess) => sess.fatal(&abort_msg(err_count)),
+                    None => {
+                        let mut emitter =
+                            errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
+                        emitter.emit(None, &abort_msg(err_count), None, errors::Level::Fatal);
+                        panic!(errors::FatalError);
+                    }
+                }
+            }
+        }
+    });
     0
 }
 
 // Parse args and run the compiler. This is the primary entry point for rustc.
 // See comments on CompilerCalls below for details about the callbacks argument.
-pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
-    macro_rules! do_or_return {($expr: expr) => {
+pub fn run_compiler<'a>(args: &[String],
+                        callbacks: &mut CompilerCalls<'a>)
+                        -> (CompileResult, Option<Session>) {
+    macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         match $expr {
-            Compilation::Stop => return,
+            Compilation::Stop => return (Ok(()), $sess),
             Compilation::Continue => {}
         }
     }}
 
     let matches = match handle_options(args.to_vec()) {
         Some(matches) => matches,
-        None => return,
+        None => return (Ok(()), None),
     };
 
     let sopts = config::build_session_options(&matches);
 
     let descriptions = diagnostics_registry();
 
-    do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.error_format));
+    do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.error_format), None);
 
     let (odir, ofile) = make_output(&matches);
     let (input, input_file_path) = match make_input(&matches.free) {
         Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
         None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
             Some((input, input_file_path)) => (input, input_file_path),
-            None => return,
+            None => return (Ok(()), None),
         },
     };
 
     let cstore = Rc::new(CStore::new(token::get_ident_interner()));
-    let sess = build_session(sopts, input_file_path, descriptions,
-                                 cstore.clone());
+    let sess = build_session(sopts, input_file_path, descriptions, cstore.clone());
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     let mut cfg = config::build_configuration(&sess);
     target_features::add_configuration(&mut cfg, &sess);
 
-    do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile));
+    do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile), Some(sess));
 
     // It is somewhat unfortunate that this is hardwired in - this is forced by
     // the fact that pretty_print_input requires the session by value.
@@ -154,7 +201,7 @@ macro_rules! do_or_return {($expr: expr) => {
     match pretty {
         Some((ppm, opt_uii)) => {
             pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
-            return;
+            return (Ok(()), None);
         }
         None => {
             // continue
@@ -163,8 +210,9 @@ macro_rules! do_or_return {($expr: expr) => {
 
     let plugins = sess.opts.debugging_opts.extra_plugins.clone();
     let control = callbacks.build_controller(&sess);
-    driver::compile_input(sess, &cstore, cfg, &input, &odir, &ofile,
-                          Some(plugins), control);
+    (driver::compile_input(&sess, &cstore, cfg, &input, &odir, &ofile,
+                           Some(plugins), control),
+     Some(sess))
 }
 
 // Extract output directory and file from matches.
index ba5ecc22e747487123ecc94ccbed98953653cee5..1e99067bf32ed9e0a5bc8c9ec0425418b2ebcb94 100644 (file)
@@ -17,7 +17,7 @@
 
 use rustc_trans::back::link;
 
-use driver;
+use {driver, abort_on_err};
 
 use rustc::middle::ty;
 use rustc::middle::cfg;
@@ -194,21 +194,21 @@ fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
                 f(&annotation, payload, &ast_map.forest.krate)
             }
             PpmTyped => {
-                driver::phase_3_run_analysis_passes(sess,
-                                                    cstore,
-                                                    ast_map.clone(),
-                                                    arenas,
-                                                    id,
-                                                    resolve::MakeGlobMap::No,
-                                                    |tcx, _, _| {
-                                                        let annotation = TypedAnnotation {
-                                                            tcx: tcx,
-                                                        };
-                                                        let _ignore = tcx.dep_graph.in_ignore();
-                                                        f(&annotation,
-                                                          payload,
-                                                          &ast_map.forest.krate)
-                                                    })
+                abort_on_err(driver::phase_3_run_analysis_passes(sess,
+                                                                 cstore,
+                                                                 ast_map.clone(),
+                                                                 arenas,
+                                                                 id,
+                                                                 resolve::MakeGlobMap::No,
+                                                                 |tcx, _, _| {
+                    let annotation = TypedAnnotation {
+                        tcx: tcx,
+                    };
+                    let _ignore = tcx.dep_graph.in_ignore();
+                    f(&annotation,
+                      payload,
+                      &ast_map.forest.krate)
+                }), sess)
             }
             _ => panic!("Should use call_with_pp_support"),
         }
@@ -694,8 +694,8 @@ pub fn pretty_print_input(sess: Session,
     let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
     let krate = if compute_ast_map {
         match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id[..], None) {
-            None => return,
-            Some(k) => driver::assign_node_ids(&sess, k),
+            Err(_) => return,
+            Ok(k) => driver::assign_node_ids(&sess, k),
         }
     } else {
         krate
@@ -818,19 +818,19 @@ pub fn pretty_print_input(sess: Session,
             match code {
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
-                    driver::phase_3_run_analysis_passes(&sess,
-                                                        &cstore,
-                                                        ast_map,
-                                                        &arenas,
-                                                        &id,
-                                                        resolve::MakeGlobMap::No,
-                                                        |tcx, _, _| {
-                                                            print_flowgraph(variants,
-                                                                            tcx,
-                                                                            code,
-                                                                            mode,
-                                                                            out)
-                                                        })
+                    abort_on_err(driver::phase_3_run_analysis_passes(&sess,
+                                                                     &cstore,
+                                                                     ast_map,
+                                                                     &arenas,
+                                                                     &id,
+                                                                     resolve::MakeGlobMap::No,
+                                                                     |tcx, _, _| {
+                        print_flowgraph(variants,
+                                        tcx,
+                                        code,
+                                        mode,
+                                        out)
+                    }), &sess)
                 }
                 None => {
                     let message = format!("--pretty=flowgraph needs block, fn, or method; got \
index b12c41d060a077cd488d9fbcfa739585539aa6e5..02ad69e8a7c3a21ba149bb2261e3fabd5cf093bf 100644 (file)
@@ -19,8 +19,9 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "http://doc.rust-lang.org/nightly/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "http://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
index c5ce76c1b6e69c20d055f82fed7a67dbbc7204b0..dd39d3b63c4f9b8b00e8770aac99a462e80328b2 100644 (file)
@@ -319,7 +319,7 @@ pub fn variant_to_string(var: &hir::Variant) -> String {
 }
 
 pub fn arg_to_string(arg: &hir::Arg) -> String {
-    to_string(|s| s.print_arg(arg))
+    to_string(|s| s.print_arg(arg, false))
 }
 
 pub fn visibility_qualified(vis: hir::Visibility, s: &str) -> String {
@@ -1935,7 +1935,8 @@ pub fn print_fn(&mut self,
 
     pub fn print_fn_args(&mut self,
                          decl: &hir::FnDecl,
-                         opt_explicit_self: Option<&hir::ExplicitSelf_>)
+                         opt_explicit_self: Option<&hir::ExplicitSelf_>,
+                         is_closure: bool)
                          -> io::Result<()> {
         // It is unfortunate to duplicate the commasep logic, but we want the
         // self type and the args all in the same box.
@@ -1965,7 +1966,7 @@ pub fn print_fn_args(&mut self,
             } else {
                 try!(self.word_space(","));
             }
-            try!(self.print_arg(arg));
+            try!(self.print_arg(arg, is_closure));
         }
 
         self.end()
@@ -1976,7 +1977,7 @@ pub fn print_fn_args_and_ret(&mut self,
                                  opt_explicit_self: Option<&hir::ExplicitSelf_>)
                                  -> io::Result<()> {
         try!(self.popen());
-        try!(self.print_fn_args(decl, opt_explicit_self));
+        try!(self.print_fn_args(decl, opt_explicit_self, false));
         if decl.variadic {
             try!(word(&mut self.s, ", ..."));
         }
@@ -1987,7 +1988,7 @@ pub fn print_fn_args_and_ret(&mut self,
 
     pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
         try!(word(&mut self.s, "|"));
-        try!(self.print_fn_args(decl, None));
+        try!(self.print_fn_args(decl, None, true));
         try!(word(&mut self.s, "|"));
 
         if let hir::DefaultReturn(..) = decl.output {
@@ -2204,10 +2205,10 @@ pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
         self.print_type(&*mt.ty)
     }
 
-    pub fn print_arg(&mut self, input: &hir::Arg) -> io::Result<()> {
+    pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> {
         try!(self.ibox(indent_unit));
         match input.ty.node {
-            hir::TyInfer => try!(self.print_pat(&*input.pat)),
+            hir::TyInfer if is_closure => try!(self.print_pat(&*input.pat)),
             _ => {
                 match input.pat.node {
                     hir::PatIdent(_, ref path1, _) if
index 78252c491ecfe72818d60ce33be5c97a04c38a38..6868b4f2ab768a054bc70c487e12dcedcec98d24 100644 (file)
@@ -26,6 +26,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![cfg_attr(test, feature(test))]
 #![feature(box_patterns)]
index 0f85c4528d2e913cfec784f61754ff673a93addb..0bb3ddc9ad170b4eb51f3f25af85c912101d311a 100644 (file)
@@ -21,6 +21,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
 #![feature(box_syntax)]
index 42332c46969790a4d8974e7aaeabce004b0e27d3..f416ec75010f33241e52c94b31a4bbe69f7e76cb 100644 (file)
@@ -13,8 +13,9 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_patterns)]
 #![feature(enumset)]
index 9cc40bbc3838a2e35c549c8d2fe54ba280d19a03..6f4128fc24de47498ed4f8c79a51abc1c5e7f61b 100644 (file)
 #![crate_name = "rustc_mir"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
+#![cfg_attr(not(stage0), deny(warnings))]
+#![unstable(feature = "rustc_private", issue = "27812")]
 
 #![feature(rustc_private)]
+#![feature(staged_api)]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
index fcdbd6384d543465653a66515c4b880a2184d477..91bfb19aa9d60371c563703b021bf3c9d0014e86 100644 (file)
@@ -19,8 +19,9 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(rustc_diagnostic_macros)]
 #![feature(staged_api)]
index e857434682d158a8a16a844bdcb465493733227e..6a43ef65d6a068a55b417a033e48cd1734fe9d69 100644 (file)
@@ -13,6 +13,7 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![feature(staged_api, rustc_private)]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 extern crate rustc_llvm as llvm;
 extern crate rustc;
index 333c226c2a373f0de6af00782b6f1018cd1ee44c..c55e97412bb1bde510fa9a2c659d3e42da6b0170 100644 (file)
@@ -55,8 +55,9 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(dynamic_lib)]
 #![feature(staged_api)]
index cfd0540cc60e782227f5430e270e76c9c07f5f69..929ec523f639f22caba83ad491e23f1007167723 100644 (file)
@@ -15,6 +15,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
index c698f72955320b6b033a58967fc82ba2d80dda89..2536a12dfcb7d03ff7d35ff1d5e5280a1874a117 100644 (file)
@@ -15,6 +15,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
 #![feature(borrow_state)]
@@ -723,7 +724,7 @@ enum FallbackSuggestion {
 }
 
 #[derive(Copy, Clone)]
-enum TypeParameters<'a> {
+enum TypeParameters<'tcx, 'a> {
     NoTypeParameters,
     HasTypeParameters(// Type parameters.
                       &'a Generics,
@@ -733,13 +734,13 @@ enum TypeParameters<'a> {
                       ParamSpace,
 
                       // The kind of the rib used for type parameters.
-                      RibKind),
+                      RibKind<'tcx>),
 }
 
 // The rib kind controls the translation of local
 // definitions (`Def::Local`) to upvars (`Def::Upvar`).
 #[derive(Copy, Clone, Debug)]
-enum RibKind {
+enum RibKind<'a> {
     // No translation needs to be applied.
     NormalRibKind,
 
@@ -758,6 +759,9 @@ enum RibKind {
 
     // We're in a constant item. Can't refer to dynamic stuff.
     ConstantItemRibKind,
+
+    // We passed through an anonymous module.
+    AnonymousModuleRibKind(Module<'a>),
 }
 
 #[derive(Copy, Clone)]
@@ -799,13 +803,13 @@ enum BareIdentifierPatternResolution {
 
 /// One local scope.
 #[derive(Debug)]
-struct Rib {
+struct Rib<'a> {
     bindings: HashMap<Name, DefLike>,
-    kind: RibKind,
+    kind: RibKind<'a>,
 }
 
-impl Rib {
-    fn new(kind: RibKind) -> Rib {
+impl<'a> Rib<'a> {
+    fn new(kind: RibKind<'a>) -> Rib<'a> {
         Rib {
             bindings: HashMap::new(),
             kind: kind,
@@ -1180,13 +1184,13 @@ pub struct Resolver<'a, 'tcx: 'a> {
 
     // The current set of local scopes, for values.
     // FIXME #4948: Reuse ribs to avoid allocation.
-    value_ribs: Vec<Rib>,
+    value_ribs: Vec<Rib<'a>>,
 
     // The current set of local scopes, for types.
-    type_ribs: Vec<Rib>,
+    type_ribs: Vec<Rib<'a>>,
 
     // The current set of local scopes, for labels.
-    label_ribs: Vec<Rib>,
+    label_ribs: Vec<Rib<'a>>,
 
     // The trait that the current context can refer to.
     current_trait_ref: Option<(DefId, TraitRef)>,
@@ -1304,6 +1308,10 @@ fn new_module(&self,
         self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public))
     }
 
+    fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec<Rib<'a>> {
+        match ns { ValueNS => &mut self.value_ribs, TypeNS => &mut self.type_ribs }
+    }
+
     #[inline]
     fn record_import_use(&mut self, import_id: NodeId, name: Name) {
         if !self.make_glob_map {
@@ -2122,7 +2130,7 @@ fn resolve_item(&mut self, item: &Item) {
         }
     }
 
-    fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F)
+    fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<'a, 'b>, f: F)
         where F: FnOnce(&mut Resolver)
     {
         match type_parameters {
@@ -2191,7 +2199,7 @@ fn with_constant_rib<F>(&mut self, f: F)
         }
     }
 
-    fn resolve_function(&mut self, rib_kind: RibKind, declaration: &FnDecl, block: &Block) {
+    fn resolve_function(&mut self, rib_kind: RibKind<'a>, declaration: &FnDecl, block: &Block) {
         // Create a value rib for the function.
         self.value_ribs.push(Rib::new(rib_kind));
 
@@ -2494,18 +2502,18 @@ fn resolve_arm(&mut self, arm: &Arm) {
 
     fn resolve_block(&mut self, block: &Block) {
         debug!("(resolving block) entering block");
-        self.value_ribs.push(Rib::new(NormalRibKind));
-
         // Move down in the graph, if there's an anonymous module rooted here.
         let orig_module = self.current_module;
-        match orig_module.anonymous_children.borrow().get(&block.id) {
-            None => {
-                // Nothing to do.
-            }
-            Some(anonymous_module) => {
-                debug!("(resolving block) found anonymous module, moving down");
-                self.current_module = anonymous_module;
-            }
+        let anonymous_module =
+            orig_module.anonymous_children.borrow().get(&block.id).map(|module| *module);
+
+        if let Some(anonymous_module) = anonymous_module {
+            debug!("(resolving block) found anonymous module, moving down");
+            self.value_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
+            self.type_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
+            self.current_module = anonymous_module;
+        } else {
+            self.value_ribs.push(Rib::new(NormalRibKind));
         }
 
         // Check for imports appearing after non-item statements.
@@ -2538,6 +2546,9 @@ fn resolve_block(&mut self, block: &Block) {
         if !self.resolved {
             self.current_module = orig_module;
             self.value_ribs.pop();
+            if let Some(_) = anonymous_module {
+                self.type_ribs.pop();
+            }
         }
         debug!("(resolving block) leaving block");
     }
@@ -3076,7 +3087,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
             Def::Local(_, node_id) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind => {
+                        NormalRibKind | AnonymousModuleRibKind(..) => {
                             // Nothing to do. Continue.
                         }
                         ClosureRibKind(function_id) => {
@@ -3124,7 +3135,8 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
             Def::TyParam(..) | Def::SelfTy(..) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
+                        NormalRibKind | MethodRibKind | ClosureRibKind(..) |
+                        AnonymousModuleRibKind(..) => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind => {
@@ -3275,13 +3287,10 @@ fn resolve_identifier_in_local_ribs(&mut self,
                                         namespace: Namespace)
                                         -> Option<LocalDef> {
         // Check the local set of ribs.
-        let (name, ribs) = match namespace {
-            ValueNS => (ident.name, &self.value_ribs),
-            TypeNS => (ident.unhygienic_name, &self.type_ribs),
-        };
+        let name = match namespace { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
 
-        for (i, rib) in ribs.iter().enumerate().rev() {
-            if let Some(def_like) = rib.bindings.get(&name).cloned() {
+        for i in (0 .. self.get_ribs(namespace).len()).rev() {
+            if let Some(def_like) = self.get_ribs(namespace)[i].bindings.get(&name).cloned() {
                 match def_like {
                     DlDef(def) => {
                         debug!("(resolving path in local ribs) resolved `{}` to {:?} at {}",
@@ -3301,6 +3310,18 @@ fn resolve_identifier_in_local_ribs(&mut self,
                     }
                 }
             }
+
+            if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
+                if let Success((target, _)) = self.resolve_name_in_module(module,
+                                                                          ident.unhygienic_name,
+                                                                          namespace,
+                                                                          PathSearch,
+                                                                          true) {
+                    if let Some(def) = target.binding.def() {
+                        return Some(LocalDef::from_def(def));
+                    }
+                }
+            }
         }
 
         None
index c1ab0284ade5235e226f30237eb8fc30652499eb..9ab056a187b65d22b329b27daa78b569a1e52ac7 100644 (file)
@@ -21,6 +21,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
index 47cd31d9898d19bb9f4e48fc14f45ae8bbc3718f..56b02412c31b2f1c65fb703206e7647868333713 100644 (file)
@@ -86,7 +86,6 @@
 use check::dropck;
 use check::FnCtxt;
 use middle::free_region::FreeRegionMap;
-use middle::implicator::{self, Implication};
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Categorization;
 use middle::region::{self, CodeExtent};
@@ -365,12 +364,7 @@ fn visit_region_obligations(&mut self, node_id: ast::NodeId)
                    r_o, r_o.cause);
             let sup_type = self.resolve_type(r_o.sup_type);
             let origin = self.code_to_origin(r_o.cause.span, sup_type, &r_o.cause.code);
-
-            if r_o.sub_region != ty::ReEmpty {
-                type_must_outlive(self, origin, sup_type, r_o.sub_region);
-            } else {
-                self.visit_old_school_wf(node_id, sup_type, origin);
-            }
+            type_must_outlive(self, origin, sup_type, r_o.sub_region);
         }
 
         // Processing the region obligations should not cause the list to grow further:
@@ -378,47 +372,6 @@ fn visit_region_obligations(&mut self, node_id: ast::NodeId)
                    self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len());
     }
 
-    fn visit_old_school_wf(&mut self,
-                           body_id: ast::NodeId,
-                           ty: Ty<'tcx>,
-                           origin: infer::SubregionOrigin<'tcx>) {
-        // As a weird kind of hack, we use a region of empty as a signal
-        // to mean "old-school WF rules". The only reason the old-school
-        // WF rules are not encoded using WF is that this leads to errors,
-        // and we want to phase those in gradually.
-
-        // FIXME(#27579) remove this weird special case once we phase in new WF rules completely
-        let implications = implicator::implications(self.infcx(),
-                                                    body_id,
-                                                    ty,
-                                                    ty::ReEmpty,
-                                                    origin.span());
-        let origin_for_ty = |ty: Option<Ty<'tcx>>| match ty {
-            None => origin.clone(),
-            Some(ty) => infer::ReferenceOutlivesReferent(ty, origin.span()),
-        };
-        for implication in implications {
-            match implication {
-                Implication::RegionSubRegion(ty, r1, r2) => {
-                    self.fcx.mk_subr(origin_for_ty(ty), r1, r2);
-                }
-                Implication::RegionSubGeneric(ty, r1, GenericKind::Param(param_ty)) => {
-                    param_ty_must_outlive(self, origin_for_ty(ty), r1, param_ty);
-                }
-                Implication::RegionSubGeneric(ty, r1, GenericKind::Projection(proj_ty)) => {
-                    projection_must_outlive(self, origin_for_ty(ty), r1, proj_ty);
-                }
-                Implication::Predicate(def_id, predicate) => {
-                    let cause = traits::ObligationCause::new(origin.span(),
-                                                             body_id,
-                                                             traits::ItemObligation(def_id));
-                    let obligation = traits::Obligation::new(cause, predicate);
-                    self.fcx.register_predicate(obligation);
-                }
-            }
-        }
-    }
-
     fn code_to_origin(&self,
                       span: Span,
                       sup_type: Ty<'tcx>,
index 17d71fa7be9a6b38d585e7d36c978176928e639f..49de0efa61d4d9e94063b55a8115c674fc9ee330 100644 (file)
@@ -70,6 +70,7 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![allow(non_camel_case_types)]
 
index 161da079110615b877a264c3bce951361fa16dbc..4cbcfd5a0b2a5a1457416ee1c85e24638392a965 100644 (file)
@@ -29,6 +29,7 @@
        html_playground_url = "https://play.rust-lang.org/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 #![no_std]
 
 #![feature(core_char_ext)]
index a7fd170b91c37778196b1a080c66acd5c605aeee..5eac358f1bf39bf4e767cf9b11935850f4593543 100644 (file)
@@ -10,7 +10,7 @@
 pub use self::MaybeTyped::*;
 
 use rustc_lint;
-use rustc_driver::{driver, target_features};
+use rustc_driver::{driver, target_features, abort_on_err};
 use rustc::session::{self, config};
 use rustc::middle::def_id::DefId;
 use rustc::middle::privacy::AccessLevels;
@@ -147,13 +147,13 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
     let arenas = ty::CtxtArenas::new();
     let hir_map = driver::make_map(&sess, &mut hir_forest);
 
-    driver::phase_3_run_analysis_passes(&sess,
-                                        &cstore,
-                                        hir_map,
-                                        &arenas,
-                                        &name,
-                                        resolve::MakeGlobMap::No,
-                                        |tcx, _, analysis| {
+    abort_on_err(driver::phase_3_run_analysis_passes(&sess,
+                                                     &cstore,
+                                                     hir_map,
+                                                     &arenas,
+                                                     &name,
+                                                     resolve::MakeGlobMap::No,
+                                                     |tcx, _, analysis| {
         let _ignore = tcx.dep_graph.in_ignore();
         let ty::CrateAnalysis { access_levels, .. } = analysis;
 
@@ -200,5 +200,5 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
         *analysis.inlined.borrow_mut() = map;
         analysis.deref_trait_did = ctxt.deref_trait_did.get();
         (krate, analysis)
-    })
+    }), &sess)
 }
index ac5b64f37aafedf9e940823ef1d6d8b5391a157d..c52459f6c105920e0a6195b3ba9f016254f76065 100644 (file)
@@ -16,6 +16,7 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
index de117b44b6f6ac60a34862d60b57b5c198b616ce..81f984a5927809f0d14559626c7771904fe4d0b8 100644 (file)
@@ -250,7 +250,12 @@ fn drop(&mut self) {
     if no_run {
         control.after_analysis.stop = Compilation::Stop;
     }
-    driver::compile_input(sess, &cstore, cfg, &input, &out, &None, None, control);
+    let result = driver::compile_input(&sess, &cstore, cfg, &input,
+                                       &out, &None, None, control);
+    match result {
+        Err(count) if count > 0 => sess.fatal("aborting due to previous error(s)"),
+        _ => {}
+    }
 
     if no_run { return }
 
index e21307cc75292cd9be71a494ebb057a71c7bbf8a..804e1af19aba2816f8b42baf9f13a1822484f861 100644 (file)
@@ -10,8 +10,7 @@
 
 //! Implementations of serialization for structures found in libcollections
 
-use std::hash::Hash;
-use std::collections::hash_state::HashState;
+use std::hash::{Hash, BuildHasher};
 use std::mem;
 
 use {Decodable, Encodable, Decoder, Encoder};
@@ -159,7 +158,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<EnumSet<T>, D::Error> {
 impl<K, V, S> Encodable for HashMap<K, V, S>
     where K: Encodable + Hash + Eq,
           V: Encodable,
-          S: HashState,
+          S: BuildHasher,
 {
     fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_map(self.len(), |e| {
@@ -177,12 +176,12 @@ fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
 impl<K, V, S> Decodable for HashMap<K, V, S>
     where K: Decodable + Hash + Eq,
           V: Decodable,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
         d.read_map(|d, len| {
             let state = Default::default();
-            let mut map = HashMap::with_capacity_and_hash_state(len, state);
+            let mut map = HashMap::with_capacity_and_hasher(len, state);
             for i in 0..len {
                 let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                 let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
@@ -195,7 +194,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
 
 impl<T, S> Encodable for HashSet<T, S>
     where T: Encodable + Hash + Eq,
-          S: HashState,
+          S: BuildHasher,
 {
     fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
@@ -211,12 +210,12 @@ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
 
 impl<T, S> Decodable for HashSet<T, S>
     where T: Decodable + Hash + Eq,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
         d.read_seq(|d, len| {
             let state = Default::default();
-            let mut set = HashSet::with_capacity_and_hash_state(len, state);
+            let mut set = HashSet::with_capacity_and_hasher(len, state);
             for i in 0..len {
                 set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
index 9e1e3c6a558055436dc2fa38cc25b8bc3c8cf84c..2310a8237f4262649f4869de008ba855212f0fa0 100644 (file)
@@ -2606,7 +2606,6 @@ fn from_str(s: &str) -> Result<Json, BuilderError> {
 mod tests {
     extern crate test;
     use self::Animal::*;
-    use self::DecodeEnum::*;
     use self::test::Bencher;
     use {Encodable, Decodable};
     use super::Json::*;
index 910600d91e45605ff519d8c07518dbb85ab9c0b9..d683769af7b0af0f1ebb715e4e4dcb7d2e1ea770 100644 (file)
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(allow(unused_variables), deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(enumset)]
-#![feature(hashmap_hasher)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(str_char)]
index 43bf86a00399c8da07108937e10afdf3da3a2fd9..173214eda44c79ecf5e6fb6199e5025d860b0bfa 100644 (file)
 use self::VacantEntryState::*;
 
 use borrow::Borrow;
-use clone::Clone;
-use cmp::{max, Eq, PartialEq};
-use default::Default;
+use cmp::max;
 use fmt::{self, Debug};
-use hash::{Hash, SipHasher};
-use iter::{self, Iterator, ExactSizeIterator, IntoIterator, FromIterator, Extend, Map};
-use marker::Sized;
+use hash::{Hash, SipHasher, BuildHasher};
+use iter::{self, Map, FromIterator};
 use mem::{self, replace};
-use ops::{Deref, FnMut, FnOnce, Index};
-use option::Option::{self, Some, None};
+use ops::{Deref, Index};
 use rand::{self, Rng};
 
 use super::table::{
@@ -39,7 +35,6 @@
     Empty,
     Full,
 };
-use super::state::HashState;
 
 const INITIAL_LOG2_CAP: usize = 5;
 const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5
@@ -336,7 +331,7 @@ fn test_resize_policy() {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashMap<K, V, S = RandomState> {
     // All hashes are keyed on these values, to prevent hash collision attacks.
-    hash_state: S,
+    hash_builder: S,
 
     table: RawTable<K, V>,
 
@@ -484,10 +479,10 @@ fn into_option(self) -> Option<FullBucket<K, V, M>> {
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash {
-        table::make_hash(&self.hash_state, x)
+        table::make_hash(&self.hash_builder, x)
     }
 
     /// Search for a key, yielding the index if it's found in the hashtable.
@@ -557,40 +552,52 @@ pub fn new() -> HashMap<K, V, RandomState> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize) -> HashMap<K, V, RandomState> {
-        HashMap::with_capacity_and_hash_state(capacity, Default::default())
+        HashMap::with_capacity_and_hasher(capacity, Default::default())
     }
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
-    /// Creates an empty hashmap which will use the given hasher to hash keys.
+    /// Creates an empty hashmap which will use the given hash builder to hash
+    /// keys.
     ///
     /// The created map has the default initial capacity.
     ///
+    /// Warning: `hash_builder` is normally randomly generated, and
+    /// is designed to allow HashMaps to be resistant to attacks that
+    /// cause many collisions and very poor performance. Setting it
+    /// manually using this function can expose a DoS attack vector.
+    ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut map = HashMap::with_hash_state(s);
+    /// let mut map = HashMap::with_hasher(s);
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
-               issue = "27713")]
-    pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap {
-            hash_state:    hash_state,
+            hash_builder: hash_builder,
             resize_policy: DefaultResizePolicy::new(),
-            table:         RawTable::new(0),
+            table: RawTable::new(0),
         }
     }
 
+    /// Deprecated, renamed to `with_hasher`
+    #[inline]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+               issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0", reason = "renamed to with_hasher")]
+    pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
+        HashMap::with_hasher(hash_state)
+    }
+
     /// Creates an empty HashMap with space for at least `capacity`
     /// elements, using `hasher` to hash the keys.
     ///
@@ -602,31 +609,39 @@ pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut map = HashMap::with_capacity_and_hash_state(10, s);
+    /// let mut map = HashMap::with_capacity_and_hasher(10, s);
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
-               issue = "27713")]
-    pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
-                                        -> HashMap<K, V, S> {
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S)
+                                    -> HashMap<K, V, S> {
         let resize_policy = DefaultResizePolicy::new();
         let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
         let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow");
         assert!(internal_cap >= capacity, "capacity overflow");
         HashMap {
-            hash_state:    hash_state,
+            hash_builder: hash_builder,
             resize_policy: resize_policy,
-            table:         RawTable::new(internal_cap),
+            table: RawTable::new(internal_cap),
         }
     }
 
+    /// Deprecated, renamed to `with_capacity_and_hasher`
+    #[inline]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+               issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0",
+                       reason = "renamed to with_capacity_and_hasher")]
+    pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
+                                        -> HashMap<K, V, S> {
+        HashMap::with_capacity_and_hasher(capacity, hash_state)
+    }
+
     /// Returns the number of elements the map can hold without reallocating.
     ///
     /// This number is a lower bound; the `HashMap<K, V>` might be able to hold
@@ -1241,7 +1256,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> PartialEq for HashMap<K, V, S>
-    where K: Eq + Hash, V: PartialEq, S: HashState
+    where K: Eq + Hash, V: PartialEq, S: BuildHasher
 {
     fn eq(&self, other: &HashMap<K, V, S>) -> bool {
         if self.len() != other.len() { return false; }
@@ -1254,12 +1269,12 @@ fn eq(&self, other: &HashMap<K, V, S>) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Eq for HashMap<K, V, S>
-    where K: Eq + Hash, V: Eq, S: HashState
+    where K: Eq + Hash, V: Eq, S: BuildHasher
 {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Debug for HashMap<K, V, S>
-    where K: Eq + Hash + Debug, V: Debug, S: HashState
+    where K: Eq + Hash + Debug, V: Debug, S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_map().entries(self.iter()).finish()
@@ -1269,10 +1284,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Default for HashMap<K, V, S>
     where K: Eq + Hash,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn default() -> HashMap<K, V, S> {
-        HashMap::with_hash_state(Default::default())
+        HashMap::with_hasher(Default::default())
     }
 }
 
@@ -1280,7 +1295,7 @@ fn default() -> HashMap<K, V, S> {
 impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap<K, V, S>
     where K: Eq + Hash + Borrow<Q>,
           Q: Eq + Hash,
-          S: HashState,
+          S: BuildHasher,
 {
     type Output = V;
 
@@ -1397,7 +1412,7 @@ enum VacantEntryState<K, V, M> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     type Item = (&'a K, &'a V);
     type IntoIter = Iter<'a, K, V>;
@@ -1409,7 +1424,7 @@ fn into_iter(self) -> Iter<'a, K, V> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     type Item = (&'a K, &'a mut V);
     type IntoIter = IterMut<'a, K, V>;
@@ -1421,7 +1436,7 @@ fn into_iter(mut self) -> IterMut<'a, K, V> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> IntoIterator for HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     type Item = (K, V);
     type IntoIter = IntoIter<K, V>;
@@ -1600,13 +1615,12 @@ pub fn insert(self, value: V) -> &'a mut V {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState + Default
+    where K: Eq + Hash, S: BuildHasher + Default
 {
     fn from_iter<T: IntoIterator<Item=(K, V)>>(iterable: T) -> HashMap<K, V, S> {
         let iter = iterable.into_iter();
         let lower = iter.size_hint().0;
-        let mut map = HashMap::with_capacity_and_hash_state(lower,
-                                                            Default::default());
+        let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
         map.extend(iter);
         map
     }
@@ -1614,7 +1628,7 @@ fn from_iter<T: IntoIterator<Item=(K, V)>>(iterable: T) -> HashMap<K, V, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
         for (k, v) in iter {
@@ -1625,7 +1639,7 @@ fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
 
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
-    where K: Eq + Hash + Copy, V: Copy, S: HashState
+    where K: Eq + Hash + Copy, V: Copy, S: BuildHasher
 {
     fn extend<T: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iter: T) {
         self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
@@ -1638,34 +1652,28 @@ fn extend<T: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iter: T) {
 /// `Hasher`, but the hashers created by two different `RandomState`
 /// instances are unlikely to produce the same result for the same values.
 #[derive(Clone)]
-#[unstable(feature = "hashmap_hasher",
-           reason = "hashing an hash maps may be altered",
-           issue = "27713")]
+#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
 pub struct RandomState {
     k0: u64,
     k1: u64,
 }
 
-#[unstable(feature = "hashmap_hasher",
-           reason = "hashing an hash maps may be altered",
-           issue = "27713")]
 impl RandomState {
     /// Constructs a new `RandomState` that is initialized with random keys.
     #[inline]
     #[allow(deprecated)] // rand
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn new() -> RandomState {
         let mut r = rand::thread_rng();
         RandomState { k0: r.gen(), k1: r.gen() }
     }
 }
 
-#[unstable(feature = "hashmap_hasher",
-           reason = "hashing an hash maps may be altered",
-           issue = "27713")]
-impl HashState for RandomState {
+#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+impl BuildHasher for RandomState {
     type Hasher = SipHasher;
     #[inline]
-    fn hasher(&self) -> SipHasher {
+    fn build_hasher(&self) -> SipHasher {
         SipHasher::new_with_keys(self.k0, self.k1)
     }
 }
@@ -1679,7 +1687,7 @@ fn default() -> RandomState {
 }
 
 impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
-    where K: Eq + Hash + Borrow<Q>, S: HashState, Q: Eq + Hash
+    where K: Eq + Hash + Borrow<Q>, S: BuildHasher, Q: Eq + Hash
 {
     type Key = K;
 
index 761709d41e77c296641e88d11a3b740690143924..b5f47853afd4ef0bebbcd254f2ee5949a47d8734 100644 (file)
@@ -9,19 +9,13 @@
 // except according to those terms.
 
 use borrow::Borrow;
-use clone::Clone;
-use cmp::{Eq, PartialEq};
-use core::marker::Sized;
-use default::Default;
 use fmt;
-use hash::Hash;
-use iter::{Iterator, IntoIterator, ExactSizeIterator, FromIterator, Map, Chain, Extend};
+use hash::{Hash, BuildHasher};
+use iter::{Map, Chain, FromIterator};
 use ops::{BitOr, BitAnd, BitXor, Sub};
-use option::Option::{Some, None, self};
 
 use super::Recover;
 use super::map::{self, HashMap, Keys, RandomState};
-use super::state::HashState;
 
 const INITIAL_CAPACITY: usize = 32;
 
@@ -144,30 +138,32 @@ pub fn with_capacity(capacity: usize) -> HashSet<T, RandomState> {
 }
 
 impl<T, S> HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     /// Creates a new empty hash set which will use the given hasher to hash
     /// keys.
     ///
     /// The hash set is also created with the default initial capacity.
     ///
+    /// Warning: `hasher` is normally randomly generated, and
+    /// is designed to allow `HashSet`s to be resistant to attacks that
+    /// cause many collisions and very poor performance. Setting it
+    /// manually using this function can expose a DoS attack vector.
+    ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashSet;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut set = HashSet::with_hash_state(s);
+    /// let mut set = HashSet::with_hasher(s);
     /// set.insert(2);
     /// ```
     #[inline]
-    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
-               issue = "27713")]
-    pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
-        HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_hasher(hasher: S) -> HashSet<T, S> {
+        HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
 
     /// Creates an empty HashSet with space for at least `capacity`
@@ -181,23 +177,40 @@ pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashSet;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut set = HashSet::with_capacity_and_hash_state(10, s);
+    /// let mut set = HashSet::with_capacity_and_hasher(10, s);
     /// set.insert(1);
     /// ```
     #[inline]
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_capacity_and_hasher(capacity: usize, hasher: S)
+                                    -> HashSet<T, S> {
+        HashSet {
+            map: HashMap::with_capacity_and_hasher(capacity, hasher),
+        }
+    }
+
+    /// Deprecated, renamed to `with_hasher`
+    #[inline]
     #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
                issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0", reason = "renamed to with_hasher")]
+    pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
+        HashSet::with_hasher(hash_state)
+    }
+
+    /// Deprecated, renamed to `with_capacity_and_hasher`
+    #[inline]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+               issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0",
+                       reason = "renamed to with_capacity_and_hasher")]
     pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
                                         -> HashSet<T, S> {
-        HashSet {
-            map: HashMap::with_capacity_and_hash_state(capacity, hash_state),
-        }
+        HashSet::with_capacity_and_hasher(capacity, hash_state)
     }
 
     /// Returns the number of elements the set can hold without reallocating.
@@ -604,7 +617,7 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> PartialEq for HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     fn eq(&self, other: &HashSet<T, S>) -> bool {
         if self.len() != other.len() { return false; }
@@ -615,13 +628,13 @@ fn eq(&self, other: &HashSet<T, S>) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Eq for HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> fmt::Debug for HashSet<T, S>
     where T: Eq + Hash + fmt::Debug,
-          S: HashState
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_set().entries(self.iter()).finish()
@@ -631,12 +644,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> FromIterator<T> for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> HashSet<T, S> {
         let iter = iterable.into_iter();
         let lower = iter.size_hint().0;
-        let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default());
+        let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
         set.extend(iter);
         set
     }
@@ -645,7 +658,7 @@ fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> HashSet<T, S> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Extend<T> for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState,
+          S: BuildHasher,
 {
     fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
         for k in iter {
@@ -657,7 +670,7 @@ fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
     where T: 'a + Eq + Hash + Copy,
-          S: HashState,
+          S: BuildHasher,
 {
     fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
@@ -667,17 +680,17 @@ fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Default for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn default() -> HashSet<T, S> {
-        HashSet::with_hash_state(Default::default())
+        HashSet::with_hasher(Default::default())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -709,7 +722,7 @@ fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -741,7 +754,7 @@ fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -773,7 +786,7 @@ fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -852,7 +865,7 @@ pub struct Union<'a, T: 'a, S: 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
@@ -865,7 +878,7 @@ fn into_iter(self) -> Iter<'a, T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> IntoIterator for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState
+          S: BuildHasher
 {
     type Item = T;
     type IntoIter = IntoIter<T>;
@@ -947,7 +960,7 @@ fn clone(&self) -> Intersection<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Intersection<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
@@ -977,7 +990,7 @@ fn clone(&self) -> Difference<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Difference<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
@@ -1007,7 +1020,7 @@ fn clone(&self) -> SymmetricDifference<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
@@ -1022,7 +1035,7 @@ fn clone(&self) -> Union<'a, T, S> { Union { iter: self.iter.clone() } }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Union<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
index 1790eeb00b701d397d4258490d51d566d119137d..167aca083038ef948caeb368239c3620ddb81715 100644 (file)
 
 #![unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
             issue = "27713")]
+#![rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash")]
+#![allow(deprecated)]
 
 use clone::Clone;
 use default::Default;
 use hash;
 use marker;
 
-/// A trait representing stateful hashes which can be used to hash keys in a
-/// `HashMap`.
-///
-/// A HashState is used as a factory for instances of `Hasher` which a `HashMap`
-/// can then use to hash keys independently. A `HashMap` by default uses a state
-/// which will create instances of a `SipHasher`, but a custom state factory can
-/// be provided to the `with_hash_state` function.
-///
-/// If a hashing algorithm has no initial state, then the `Hasher` type for that
-/// algorithm can implement the `Default` trait and create hash maps with the
-/// `DefaultState` structure. This state is 0-sized and will simply delegate
-/// to `Default` when asked to create a hasher.
-pub trait HashState {
-    /// Type of the hasher that will be created.
-    type Hasher: hash::Hasher;
-
-    /// Creates a new hasher based on the given state of this object.
-    fn hasher(&self) -> Self::Hasher;
-}
+pub use hash::HashState;
 
 /// A structure which is a factory for instances of `Hasher` which implement the
 /// default trait.
index f8550fd8842e1de54920eafd9b4e1b1561f4792a..316c75952667c9e621e91da24e2bc40657c78bab 100644 (file)
 use alloc::heap::{allocate, deallocate, EMPTY};
 
 use cmp;
-use hash::{Hash, Hasher};
+use hash::{Hash, Hasher, BuildHasher};
 use marker;
 use mem::{align_of, size_of};
 use mem;
 use ops::{Deref, DerefMut};
 use ptr::{self, Unique};
-use collections::hash_state::HashState;
 
 use self::BucketState::*;
 
@@ -144,9 +143,9 @@ pub fn inspect(&self) -> u64 { self.hash }
 /// This function wraps up `hash_keyed` to be the only way outside this
 /// module to generate a SafeHash.
 pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
-    where T: Hash, S: HashState
+    where T: Hash, S: BuildHasher
 {
-    let mut state = hash_state.hasher();
+    let mut state = hash_state.build_hasher();
     t.hash(&mut state);
     // We need to avoid 0 in order to prevent collisions with
     // EMPTY_HASH. We can maintain our precious uniform distribution
index 07ddfe237be93f91dcba8f71c5b7a60ffa737b72..417261cf4c304a3073aa624c773692b302e6ac1b 100644 (file)
@@ -444,6 +444,8 @@ pub mod hash_set {
 /// HashSet.
 #[unstable(feature = "hashmap_hasher", reason = "module was recently added",
            issue = "27713")]
+#[rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash")]
+#[allow(deprecated)]
 pub mod hash_state {
     pub use super::hash::state::*;
 }
index 41001153c3cc47e7de8c0036b9cc873a87e83435..585051a98e5f7db7047af818a5ecfc5c8a37ef63 100644 (file)
@@ -16,7 +16,6 @@
             reason = "API has not been scrutinized and is highly likely to \
                       either disappear or change",
             issue = "27810")]
-#![rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")]
 #![allow(missing_docs)]
 #![allow(deprecated)]
 
 use ffi::{CString, OsString};
 use path::{Path, PathBuf};
 
+#[unstable(feature = "dynamic_lib",
+           reason = "API has not been scrutinized and is highly likely to \
+                     either disappear or change",
+           issue = "27810")]
+#[rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")]
 pub struct DynamicLibrary {
     handle: *mut u8
 }
@@ -43,6 +47,11 @@ fn drop(&mut self) {
     }
 }
 
+#[unstable(feature = "dynamic_lib",
+           reason = "API has not been scrutinized and is highly likely to \
+                     either disappear or change",
+           issue = "27810")]
+#[rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")]
 impl DynamicLibrary {
     /// Lazily open a dynamic library. When passed None it gives a
     /// handle to the calling process
@@ -126,7 +135,6 @@ mod tests {
     use prelude::v1::*;
     use libc;
     use mem;
-    use path::Path;
 
     #[test]
     #[cfg_attr(any(windows,
@@ -167,6 +175,8 @@ fn test_loading_cosine() {
               target_os = "openbsd"))]
     #[allow(deprecated)]
     fn test_errors_do_not_crash() {
+        use path::Path;
+
         // Open /dev/null as a library to get an error, and make sure
         // that only causes an error, and not a crash.
         let path = Path::new("/dev/null");
index 5ec51eaa567331cb3551e859fc332c8e4e653098..ccebf3682c217c2683dc2a6450566d59915cc531 100644 (file)
@@ -1095,8 +1095,8 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
 
         thread::spawn(|| {
             let mut writer = BufWriter::new(PanicWriter);
-            writer.write(b"hello world");
-            writer.flush();
+            let _ = writer.write(b"hello world");
+            let _ = writer.flush();
         }).join().err().unwrap();
 
         assert_eq!(WRITES.load(Ordering::SeqCst), 1);
index 79091fd3d6b9d07bd227f935d4d541d2dec67e25..cd2d5e52462bb91b8e63d4bd02e74411ad0ec874 100644 (file)
@@ -112,7 +112,7 @@ fn flush(&mut self) -> io::Result<()> {
 impl<R: io::Read> io::Read for Maybe<R> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         match *self {
-            Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), buf.len()),
+            Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
             Maybe::Fake => Ok(0)
         }
     }
index 9adea351e3d0e4d148dde9c78f2df1d5931fa310..416c01b539fcb5c7df5528a8cece4a0f84696543 100644 (file)
 #![feature(float_from_str_radix)]
 #![feature(fnbox)]
 #![feature(heap_api)]
+#![feature(hashmap_hasher)]
 #![feature(int_error_internals)]
 #![feature(into_cow)]
 #![feature(lang_items)]
 
 #![deny(missing_docs)]
 #![allow(unused_features)] // std may use features in a platform-specific way
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #[cfg(test)] extern crate test;
 #[cfg(test)] #[macro_use] extern crate log;
index 62080fee48ec1178e62e0acecd44199ca47918b3..31d889fd422b75e54753870efbe09d9ab9677070 100644 (file)
@@ -68,6 +68,7 @@ pub enum c_void {
 }
 
 #[cfg(test)]
+#[allow(unused_imports)]
 mod tests {
     use any::TypeId;
     use libc;
index 8561ecd9c4cb92d9e21952fe65167c03b9ad9ab5..490c5f4b3522e41479b155a944c5b20de4b6df80 100644 (file)
@@ -16,6 +16,7 @@
 use cell::RefCell;
 use intrinsics;
 use sync::StaticRwLock;
+use sync::atomic::{AtomicBool, Ordering};
 use sys::stdio::Stderr;
 use sys_common::backtrace;
 use sys_common::thread_info;
@@ -38,6 +39,7 @@ enum Handler {
 
 static HANDLER_LOCK: StaticRwLock = StaticRwLock::new();
 static mut HANDLER: Handler = Handler::Default;
+static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
 
 /// Registers a custom panic handler, replacing any that was previously
 /// registered.
@@ -173,8 +175,11 @@ fn default_handler(info: &PanicInfo) {
     let write = |err: &mut ::io::Write| {
         let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
                          name, msg, file, line);
+
         if log_backtrace {
             let _ = backtrace::write(err);
+        } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
+            let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` for a backtrace.");
         }
     };
 
index e398a5a28c9043de5c46fc4a859912d03b56c91e..207c4d02e481703b52de58f74db2e29a87141b1a 100644 (file)
@@ -3326,11 +3326,13 @@ macro_rules! tc(
                          "{:?}.ends_with({:?}), expected {:?}, got {:?}", $path1, $path2,
                          $ends_with, ends_with);
 
-                 let relative_from = path1.relative_from(path2).map(|p| p.to_str().unwrap());
+                 let relative_from = path1.strip_prefix(path2)
+                                          .map(|p| p.to_str().unwrap())
+                                          .ok();
                  let exp: Option<&str> = $relative_from;
                  assert!(relative_from == exp,
-                         "{:?}.relative_from({:?}), expected {:?}, got {:?}", $path1, $path2,
-                         exp, relative_from);
+                         "{:?}.strip_prefix({:?}), expected {:?}, got {:?}",
+                         $path1, $path2, exp, relative_from);
             });
         );
 
index be1fe9b2a9bd7d27344379acf6638be59cbf88b3..7197dfa8b2d47986da6d26ba21f3b7e8a1e10eb2 100644 (file)
@@ -618,8 +618,8 @@ mod tests {
 
     // FIXME(#10380) these tests should not all be ignored on android.
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn smoke() {
         let p = Command::new("true").spawn();
         assert!(p.is_ok());
@@ -627,8 +627,8 @@ fn smoke() {
         assert!(p.wait().unwrap().success());
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn smoke_failure() {
         match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
             Ok(..) => panic!(),
@@ -636,8 +636,8 @@ fn smoke_failure() {
         }
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn exit_reported_right() {
         let p = Command::new("false").spawn();
         assert!(p.is_ok());
@@ -646,8 +646,9 @@ fn exit_reported_right() {
         drop(p.wait());
     }
 
-    #[cfg(all(unix, not(target_os="android")))]
     #[test]
+    #[cfg(unix)]
+    #[cfg_attr(target_os = "android", ignore)]
     fn signal_reported_right() {
         use os::unix::process::ExitStatusExt;
 
@@ -674,16 +675,16 @@ pub fn run_output(mut cmd: Command) -> String {
         return ret;
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn stdout_works() {
         let mut cmd = Command::new("echo");
         cmd.arg("foobar").stdout(Stdio::piped());
         assert_eq!(run_output(cmd), "foobar\n");
     }
 
-    #[cfg(all(unix, not(target_os="android")))]
     #[test]
+    #[cfg_attr(any(windows, target_os = "android"), ignore)]
     fn set_current_dir_works() {
         let mut cmd = Command::new("/bin/sh");
         cmd.arg("-c").arg("pwd")
@@ -692,8 +693,8 @@ fn set_current_dir_works() {
         assert_eq!(run_output(cmd), "/\n");
     }
 
-    #[cfg(all(unix, not(target_os="android")))]
     #[test]
+    #[cfg_attr(any(windows, target_os = "android"), ignore)]
     fn stdin_works() {
         let mut p = Command::new("/bin/sh")
                             .arg("-c").arg("read line; echo $line")
@@ -709,8 +710,9 @@ fn stdin_works() {
     }
 
 
-    #[cfg(all(unix, not(target_os="android")))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
+    #[cfg(unix)]
     fn uid_works() {
         use os::unix::prelude::*;
         use libc;
@@ -722,8 +724,9 @@ fn uid_works() {
         assert!(p.wait().unwrap().success());
     }
 
-    #[cfg(all(unix, not(target_os="android")))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
+    #[cfg(unix)]
     fn uid_to_root_fails() {
         use os::unix::prelude::*;
         use libc;
@@ -734,8 +737,8 @@ fn uid_to_root_fails() {
         assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn test_process_status() {
         let mut status = Command::new("false").status().unwrap();
         assert!(status.code() == Some(1));
@@ -752,8 +755,8 @@ fn test_process_output_fail_to_start() {
         }
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn test_process_output_output() {
         let Output {status, stdout, stderr}
              = Command::new("echo").arg("hello").output().unwrap();
@@ -764,8 +767,8 @@ fn test_process_output_output() {
         assert_eq!(stderr, Vec::new());
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn test_process_output_error() {
         let Output {status, stdout, stderr}
              = Command::new("mkdir").arg(".").output().unwrap();
@@ -775,23 +778,23 @@ fn test_process_output_error() {
         assert!(!stderr.is_empty());
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn test_finish_once() {
         let mut prog = Command::new("false").spawn().unwrap();
         assert!(prog.wait().unwrap().code() == Some(1));
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn test_finish_twice() {
         let mut prog = Command::new("false").spawn().unwrap();
         assert!(prog.wait().unwrap().code() == Some(1));
         assert!(prog.wait().unwrap().code() == Some(1));
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
+    #[cfg_attr(target_os = "android", ignore)]
     fn test_wait_with_output_once() {
         let prog = Command::new("echo").arg("hello").stdout(Stdio::piped())
             .spawn().unwrap();
@@ -821,7 +824,6 @@ pub fn env_cmd() -> Command {
         cmd
     }
 
-    #[cfg(not(target_os="android"))]
     #[test]
     fn test_inherit_env() {
         use env;
@@ -830,36 +832,22 @@ fn test_inherit_env() {
         let output = String::from_utf8(result.stdout).unwrap();
 
         for (ref k, ref v) in env::vars() {
+            // don't check android RANDOM variables
+            if cfg!(target_os = "android") && *k == "RANDOM" {
+                continue
+            }
+
             // Windows has hidden environment variables whose names start with
             // equals signs (`=`). Those do not show up in the output of the
             // `set` command.
             assert!((cfg!(windows) && k.starts_with("=")) ||
                     k.starts_with("DYLD") ||
-                    output.contains(&format!("{}={}", *k, *v)),
+                    output.contains(&format!("{}={}", *k, *v)) ||
+                    output.contains(&format!("{}='{}'", *k, *v)),
                     "output doesn't contain `{}={}`\n{}",
                     k, v, output);
         }
     }
-    #[cfg(target_os="android")]
-    #[test]
-    fn test_inherit_env() {
-        use env;
-
-        let mut result = env_cmd().output().unwrap();
-        let output = String::from_utf8(result.stdout).unwrap();
-
-        for (ref k, ref v) in env::vars() {
-            // don't check android RANDOM variables
-            if *k != "RANDOM".to_string() {
-                assert!(output.contains(&format!("{}={}",
-                                                 *k,
-                                                 *v)) ||
-                        output.contains(&format!("{}=\'{}\'",
-                                                 *k,
-                                                 *v)));
-            }
-        }
-    }
 
     #[test]
     fn test_override_env() {
index d743cbb18909f005d557f38d9906a7557182b24f..5aa4ce81b8ae43c53c4b9ecf8a19fcae72230106 100644 (file)
@@ -789,7 +789,7 @@ fn fmt_debug_select() {
     fn fmt_debug_handle() {
         let (_, rx) = channel::<i32>();
         let sel = Select::new();
-        let mut handle = sel.handle(&rx);
+        let handle = sel.handle(&rx);
         assert_eq!(format!("{:?}", handle), "Handle { .. }");
     }
 }
index ac5ce298c5c6f0b49899038042906817f586b6d7..dd76444d3ae02edbbc0064f794b2b43e7f7b6de3 100644 (file)
@@ -12,9 +12,6 @@
             reason = "the interaction between semaphores and the acquisition/release \
                       of resources is currently unclear",
             issue = "27798")]
-#![rustc_deprecated(since = "1.7.0",
-                    reason = "easily confused with system semaphores and not \
-                              used enough to pull its weight")]
 #![allow(deprecated)]
 
 use ops::Drop;
 /// // Release our initially acquired resource
 /// sem.release();
 /// ```
+#[rustc_deprecated(since = "1.7.0",
+                   reason = "easily confused with system semaphores and not \
+                             used enough to pull its weight")]
+#[unstable(feature = "semaphore",
+           reason = "the interaction between semaphores and the acquisition/release \
+                     of resources is currently unclear",
+           issue = "27798")]
 pub struct Semaphore {
     lock: Mutex<isize>,
     cvar: Condvar,
@@ -56,10 +60,24 @@ pub struct Semaphore {
 
 /// An RAII guard which will release a resource acquired from a semaphore when
 /// dropped.
+#[rustc_deprecated(since = "1.7.0",
+                   reason = "easily confused with system semaphores and not \
+                             used enough to pull its weight")]
+#[unstable(feature = "semaphore",
+           reason = "the interaction between semaphores and the acquisition/release \
+                     of resources is currently unclear",
+           issue = "27798")]
 pub struct SemaphoreGuard<'a> {
     sem: &'a Semaphore,
 }
 
+#[rustc_deprecated(since = "1.7.0",
+                   reason = "easily confused with system semaphores and not \
+                             used enough to pull its weight")]
+#[unstable(feature = "semaphore",
+           reason = "the interaction between semaphores and the acquisition/release \
+                     of resources is currently unclear",
+           issue = "27798")]
 impl Semaphore {
     /// Creates a new semaphore with the initial count specified.
     ///
index 9771b057d8d21f5bfac77a38cbb71b5130e5c899..2e89becfa67e625439d3342d3dd8984b83133275 100644 (file)
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(missing_docs)]
-#![allow(non_camel_case_types)]
+#![allow(missing_docs, bad_style)]
 
 use io::{self, ErrorKind};
 use libc;
 use num::One;
 use ops::Neg;
-use alloc::oom;
 
 #[cfg(target_os = "android")]   pub use os::android as platform;
 #[cfg(target_os = "bitrig")]    pub use os::bitrig as platform;
 pub mod time;
 pub mod stdio;
 
-// A nicer handler for out-of-memory situations than the default one. This one
-// prints a message to stderr before aborting. It is critical that this code
-// does not allocate any memory since we are in an OOM situation. Any errors are
-// ignored while printing since there's nothing we can do about them and we are
-// about to exit anyways.
-fn oom_handler() -> ! {
-    use intrinsics;
-    let msg = "fatal runtime error: out of memory\n";
-    unsafe {
-        libc::write(libc::STDERR_FILENO,
-                    msg.as_ptr() as *const libc::c_void,
-                    msg.len() as libc::size_t);
-        intrinsics::abort();
-    }
-}
-
-#[cfg(not(any(target_os = "nacl", test)))]
+#[cfg(not(test))]
 pub fn init() {
-    use libc::signal;
+    use alloc::oom;
+
     // By default, some platforms will send a *signal* when an EPIPE error
     // would otherwise be delivered. This runtime doesn't install a SIGPIPE
     // handler, causing it to kill the program, which isn't exactly what we
@@ -73,15 +56,33 @@ pub fn init() {
     // Hence, we set SIGPIPE to ignore when the program starts up in order
     // to prevent this problem.
     unsafe {
-        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
+        reset_sigpipe();
     }
 
     oom::set_oom_handler(oom_handler);
-}
 
-#[cfg(all(target_os = "nacl", not(test)))]
-pub fn init() {
-    oom::set_oom_handler(oom_handler);
+    // A nicer handler for out-of-memory situations than the default one. This
+    // one prints a message to stderr before aborting. It is critical that this
+    // code does not allocate any memory since we are in an OOM situation. Any
+    // errors are ignored while printing since there's nothing we can do about
+    // them and we are about to exit anyways.
+    fn oom_handler() -> ! {
+        use intrinsics;
+        let msg = "fatal runtime error: out of memory\n";
+        unsafe {
+            libc::write(libc::STDERR_FILENO,
+                        msg.as_ptr() as *const libc::c_void,
+                        msg.len() as libc::size_t);
+            intrinsics::abort();
+        }
+    }
+
+    #[cfg(not(target_os = "nacl"))]
+    unsafe fn reset_sigpipe() {
+        assert!(libc::signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
+    }
+    #[cfg(target_os = "nacl")]
+    unsafe fn reset_sigpipe() {}
 }
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
index fc49f4257be2ace4908917a38edd0278ce04b774..c7614db3299592239d6e933c319e57d918b3f6fb 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
 #![cfg_attr(test, allow(dead_code))]
 
 use libc;
index 4d715b579c6c5d9d5b14bbb8006ed0cd2a406e90..9e28cf06d619a13e9a8b724885a8a317013bc101 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)]
-
 use prelude::v1::*;
 
 use alloc::boxed::FnBox;
@@ -174,6 +172,7 @@ fn drop(&mut self) {
           not(target_os = "bitrig"),
           not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
           not(target_os = "openbsd")))]
+#[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     pub unsafe fn current() -> Option<usize> { None }
     pub unsafe fn init() -> Option<usize> { None }
@@ -185,15 +184,13 @@ pub unsafe fn init() -> Option<usize> { None }
           target_os = "bitrig",
           all(target_os = "netbsd", not(target_vendor = "rumprun")),
           target_os = "openbsd"))]
-#[allow(unused_imports)]
+#[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     use prelude::v1::*;
 
-    use libc::{self, pthread_t};
+    use libc;
     use libc::mmap;
     use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
-    use mem;
-    use ptr;
     use sys::os;
 
     #[cfg(any(target_os = "macos",
@@ -206,10 +203,10 @@ unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
     #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         let mut ret = None;
-        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        let mut attr: libc::pthread_attr_t = ::mem::zeroed();
         assert_eq!(libc::pthread_attr_init(&mut attr), 0);
         if libc::pthread_getattr_np(libc::pthread_self(), &mut attr) == 0 {
-            let mut stackaddr = ptr::null_mut();
+            let mut stackaddr = ::ptr::null_mut();
             let mut stacksize = 0;
             assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
                                                    &mut stacksize), 0);
@@ -265,7 +262,7 @@ pub unsafe fn current() -> Option<usize> {
 
     #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
     pub unsafe fn current() -> Option<usize> {
-        let mut current_stack: libc::stack_t = mem::zeroed();
+        let mut current_stack: libc::stack_t = ::mem::zeroed();
         assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
                                              &mut current_stack), 0);
 
@@ -282,7 +279,7 @@ pub unsafe fn current() -> Option<usize> {
     #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
     pub unsafe fn current() -> Option<usize> {
         let mut ret = None;
-        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        let mut attr: libc::pthread_attr_t = ::mem::zeroed();
         assert_eq!(libc::pthread_attr_init(&mut attr), 0);
         if libc::pthread_getattr_np(libc::pthread_self(), &mut attr) == 0 {
             let mut guardsize = 0;
@@ -290,7 +287,7 @@ pub unsafe fn current() -> Option<usize> {
             if guardsize == 0 {
                 panic!("there is no guard page");
             }
-            let mut stackaddr = ptr::null_mut();
+            let mut stackaddr = ::ptr::null_mut();
             let mut size = 0;
             assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
                                                    &mut size), 0);
index 60e3f7c22bd58c0484be6c0ba684e1e6fb714f0b..a8b82ef5f297c09e2a99f93b07044eec3e6f511d 100644 (file)
@@ -639,7 +639,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
 fn directory_junctions_are_directories() {
     use ffi::OsStr;
     use env;
-    use rand::{self, StdRng, Rng};
+    use rand::{self, Rng};
     use vec::Vec;
 
     macro_rules! t {
@@ -683,7 +683,7 @@ fn create_junction(src: &Path, dst: &Path) -> io::Result<()> {
             let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
             let mut db = data.as_mut_ptr()
                             as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
-            let mut buf = &mut (*db).ReparseTarget as *mut _;
+            let buf = &mut (*db).ReparseTarget as *mut _;
             let mut i = 0;
             let v = br"\??\";
             let v = v.iter().map(|x| *x as u16);
index 16c4ae8257c132d7018e018fcab09c682f8f8db6..9ecef5ee92c714c6e1cbb3b9ca7be9a1046fbf40 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(missing_docs)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
+#![allow(missing_docs, bad_style)]
 
 use prelude::v1::*;
 
@@ -20,7 +18,6 @@
 use os::windows::ffi::{OsStrExt, OsStringExt};
 use path::PathBuf;
 use time::Duration;
-use alloc::oom;
 
 #[macro_use] pub mod compat;
 
 pub mod time;
 pub mod stdio;
 
-// See comment in sys/unix/mod.rs
-fn oom_handler() -> ! {
-    use intrinsics;
-    use ptr;
-    let msg = "fatal runtime error: out of memory\n";
-    unsafe {
-        // WriteFile silently fails if it is passed an invalid handle, so there
-        // is no need to check the result of GetStdHandle.
-        c::WriteFile(c::GetStdHandle(c::STD_ERROR_HANDLE),
-                     msg.as_ptr() as c::LPVOID,
-                     msg.len() as c::DWORD,
-                     ptr::null_mut(),
-                     ptr::null_mut());
-        intrinsics::abort();
-    }
-}
-
+#[cfg(not(test))]
 pub fn init() {
-    oom::set_oom_handler(oom_handler);
+    ::alloc::oom::set_oom_handler(oom_handler);
+
+    // See comment in sys/unix/mod.rs
+    fn oom_handler() -> ! {
+        use intrinsics;
+        use ptr;
+        let msg = "fatal runtime error: out of memory\n";
+        unsafe {
+            // WriteFile silently fails if it is passed an invalid handle, so
+            // there is no need to check the result of GetStdHandle.
+            c::WriteFile(c::GetStdHandle(c::STD_ERROR_HANDLE),
+                         msg.as_ptr() as c::LPVOID,
+                         msg.len() as c::DWORD,
+                         ptr::null_mut(),
+                         ptr::null_mut());
+            intrinsics::abort();
+        }
+    }
 }
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
index e0f8d6f9df96306ed3ec3ea38d7413a93e05beaa..8b17a0531621d156c6aa456db8842743242c3650 100644 (file)
@@ -351,10 +351,15 @@ fn make_dirp(d: Option<&OsString>) -> (*const u16, Vec<u16>) {
 impl Stdio {
     fn to_handle(&self, stdio_id: c::DWORD) -> io::Result<Handle> {
         match *self {
+            // If no stdio handle is available, then inherit means that it
+            // should still be unavailable so propagate the
+            // INVALID_HANDLE_VALUE.
             Stdio::Inherit => {
-                stdio::get(stdio_id).and_then(|io| {
-                    io.handle().duplicate(0, true, c::DUPLICATE_SAME_ACCESS)
-                })
+                match stdio::get(stdio_id) {
+                    Ok(io) => io.handle().duplicate(0, true,
+                                                    c::DUPLICATE_SAME_ACCESS),
+                    Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)),
+                }
             }
             Stdio::Raw(handle) => {
                 RawHandle::new(handle).duplicate(0, true, c::DUPLICATE_SAME_ACCESS)
@@ -386,7 +391,6 @@ fn to_handle(&self, stdio_id: c::DWORD) -> io::Result<Handle> {
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
-    use str;
     use ffi::{OsStr, OsString};
     use super::make_command_line;
 
index 01317bec0de8879056424984b847656b0c3d1b73..4a406d70e63abc2ceaeaf8aea8656bf06495c577 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![cfg_attr(test, allow(dead_code))]
+
 use sys_common::util::report_overflow;
 use sys::c;
 
index 1ba8586756311b46664d09ca36e97da8dd2446e7..b18772c0c24381c75589fcd140786f87d96067d4 100644 (file)
@@ -83,6 +83,7 @@ pub fn handle(&self) -> &Handle { &self.handle }
     pub fn into_handle(self) -> Handle { self.handle }
 }
 
+#[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     pub unsafe fn current() -> Option<usize> { None }
     pub unsafe fn init() -> Option<usize> { None }
index c21bf1e6a1fa04abaf1033296f2209de5de9138f..51013d68930ea9a36f3770544aff4f8f2712b60c 100644 (file)
@@ -10,7 +10,7 @@
 
 use self::Destination::*;
 
-use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, Pos, Span};
+use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, DUMMY_SP, Pos, Span};
 use diagnostics;
 
 use errors::{Level, RenderSpan, DiagnosticBuilder};
@@ -109,8 +109,8 @@ fn emit(&mut self,
             lvl: Level) {
         let error = match sp {
             Some(COMMAND_LINE_SP) => self.emit_(FileLine(COMMAND_LINE_SP), msg, code, lvl),
+            Some(DUMMY_SP) | None => print_diagnostic(&mut self.dst, "", lvl, msg, code),
             Some(sp) => self.emit_(FullSpan(sp), msg, code, lvl),
-            None => print_diagnostic(&mut self.dst, "", lvl, msg, code),
         };
 
         if let Err(e) = error {
index 9f069cb17ed9033b6174d720e148d563331de281..bfd76db0359bdf2a5f836419e5eeeb6f1881906b 100644 (file)
@@ -1005,7 +1005,7 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
             },
             "path" | "ty" => {
                 match *tok {
-                    OpenDelim(token::DelimToken::Brace) |
+                    OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) |
                     Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true),
                     Ident(i, _) if (i.name.as_str() == "as" ||
                                     i.name.as_str() == "where") => Ok(true),
index 795f4044f6eb1be35c1bb8b74a49093b813be9c9..d7d3e576a613d5fe9de131cf36624cc4b597b8dd 100644 (file)
@@ -22,6 +22,7 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
 #![feature(filling_drop)]
index 883a54079d8d3e7bed485745f0049f3173ce49bf..b8e5642474c78be775e6268b1869f6d730abe570 100644 (file)
@@ -2233,6 +2233,12 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                         ex = ExprBreak(None);
                     }
                     hi = self.last_span.hi;
+                } else if self.token.is_keyword(keywords::Let) {
+                    // Catch this syntax error here, instead of in `check_strict_keywords`, so
+                    // that we can explicitly mention that let is not to be used as an expression
+                    let mut db = self.fatal("expected expression, found statement (`let`)");
+                    db.note("variable declaration using `let` is a statement");
+                    return Err(db);
                 } else if self.check(&token::ModSep) ||
                         self.token.is_ident() &&
                         !self.check_keyword(keywords::True) &&
index 67817ee0740e6d38a0f5bbdba768d778e31b79bb..e80297eb797e543e87bbac2726e8d1f8dbdb4318 100644 (file)
@@ -425,7 +425,7 @@ pub fn variant_to_string(var: &ast::Variant) -> String {
 }
 
 pub fn arg_to_string(arg: &ast::Arg) -> String {
-    to_string(|s| s.print_arg(arg))
+    to_string(|s| s.print_arg(arg, false))
 }
 
 pub fn mac_to_string(arg: &ast::Mac) -> String {
@@ -2672,8 +2672,8 @@ pub fn print_fn(&mut self,
     }
 
     pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
-                         opt_explicit_self: Option<&ast::ExplicitSelf_>)
-        -> io::Result<()> {
+                         opt_explicit_self: Option<&ast::ExplicitSelf_>,
+                         is_closure: bool) -> io::Result<()> {
         // It is unfortunate to duplicate the commasep logic, but we want the
         // self type and the args all in the same box.
         try!(self.rbox(0, Inconsistent));
@@ -2698,7 +2698,7 @@ pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
 
         for arg in args {
             if first { first = false; } else { try!(self.word_space(",")); }
-            try!(self.print_arg(arg));
+            try!(self.print_arg(arg, is_closure));
         }
 
         self.end()
@@ -2708,7 +2708,7 @@ pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl,
                                  opt_explicit_self: Option<&ast::ExplicitSelf_>)
         -> io::Result<()> {
         try!(self.popen());
-        try!(self.print_fn_args(decl, opt_explicit_self));
+        try!(self.print_fn_args(decl, opt_explicit_self, false));
         if decl.variadic {
             try!(word(&mut self.s, ", ..."));
         }
@@ -2722,7 +2722,7 @@ pub fn print_fn_block_args(
             decl: &ast::FnDecl)
             -> io::Result<()> {
         try!(word(&mut self.s, "|"));
-        try!(self.print_fn_args(decl, None));
+        try!(self.print_fn_args(decl, None, true));
         try!(word(&mut self.s, "|"));
 
         if let ast::DefaultReturn(..) = decl.output {
@@ -2967,10 +2967,10 @@ pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> {
         self.print_type(&*mt.ty)
     }
 
-    pub fn print_arg(&mut self, input: &ast::Arg) -> io::Result<()> {
+    pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()> {
         try!(self.ibox(INDENT_UNIT));
         match input.ty.node {
-            ast::TyInfer => try!(self.print_pat(&*input.pat)),
+            ast::TyInfer if is_closure => try!(self.print_pat(&*input.pat)),
             _ => {
                 match input.pat.node {
                     ast::PatIdent(_, ref path1, _) if
@@ -3149,7 +3149,6 @@ mod tests {
     use super::*;
 
     use ast;
-    use ast_util;
     use codemap;
     use parse::token;
 
index 0f049fa9792553a8992a0e05d2b42f2b5a909f97..97531d4279d4b47c73b763785baf46b5d124e3f7 100644 (file)
 //! Syntax extensions in the Rust compiler.
 
 #![crate_name = "syntax_ext"]
+#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(rustc_private)]
 #![feature(staged_api)]
index df1fedf3d4e6610c23ee2a5fe341f28e9c44aca1..771e24704558d806ff458770db12030eb14320a5 100644 (file)
@@ -52,6 +52,7 @@
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
 #![deny(missing_docs)]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_syntax)]
 #![feature(staged_api)]
index ac5b235854a04cc54fb174cd94ea2fdc1f99026c..130ce3a9637f304badab07f923c58cfce99a44d4 100644 (file)
@@ -31,6 +31,7 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
+#![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(asm)]
 #![feature(box_syntax)]
diff --git a/src/test/compile-fail/macro-follow.rs b/src/test/compile-fail/macro-follow.rs
new file mode 100644 (file)
index 0000000..35944ba
--- /dev/null
@@ -0,0 +1,122 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// Check the macro follow sets (see corresponding rpass test).
+
+// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
+macro_rules! follow_pat {
+    ($p:pat ()) => {};       //~WARN  `$p:pat` is followed by `(`
+    ($p:pat []) => {};       //~WARN  `$p:pat` is followed by `[`
+    ($p:pat {}) => {};       //~WARN  `$p:pat` is followed by `{`
+    ($p:pat :) => {};        //~ERROR `$p:pat` is followed by `:`
+    ($p:pat >) => {};        //~ERROR `$p:pat` is followed by `>`
+    ($p:pat +) => {};        //~ERROR `$p:pat` is followed by `+`
+    ($p:pat ident) => {};    //~ERROR `$p:pat` is followed by `ident`
+    ($p:pat $p:pat) => {};   //~ERROR `$p:pat` is followed by `$p:pat`
+    ($p:pat $e:expr) => {};  //~ERROR `$p:pat` is followed by `$e:expr`
+    ($p:pat $t:ty) => {};    //~ERROR `$p:pat` is followed by `$t:ty`
+    ($p:pat $s:stmt) => {};  //~ERROR `$p:pat` is followed by `$s:stmt`
+    ($p:pat $p:path) => {};  //~ERROR `$p:pat` is followed by `$p:path`
+    ($p:pat $b:block) => {}; //~ERROR `$p:pat` is followed by `$b:block`
+    ($p:pat $i:ident) => {}; //~ERROR `$p:pat` is followed by `$i:ident`
+    ($p:pat $t:tt) => {};    //~ERROR `$p:pat` is followed by `$t:tt`
+    ($p:pat $i:item) => {};  //~ERROR `$p:pat` is followed by `$i:item`
+    ($p:pat $m:meta) => {};  //~ERROR `$p:pat` is followed by `$m:meta`
+}
+// FOLLOW(expr) = {FatArrow, Comma, Semicolon}
+macro_rules! follow_expr {
+    ($e:expr ()) => {};       //~WARN  `$e:expr` is followed by `(`
+    ($e:expr []) => {};       //~WARN  `$e:expr` is followed by `[`
+    ($e:expr {}) => {};       //~WARN  `$e:expr` is followed by `{`
+    ($e:expr =) => {};        //~ERROR `$e:expr` is followed by `=`
+    ($e:expr |) => {};        //~ERROR `$e:expr` is followed by `|`
+    ($e:expr :) => {};        //~ERROR `$e:expr` is followed by `:`
+    ($e:expr >) => {};        //~ERROR `$e:expr` is followed by `>`
+    ($e:expr +) => {};        //~ERROR `$e:expr` is followed by `+`
+    ($e:expr ident) => {};    //~ERROR `$e:expr` is followed by `ident`
+    ($e:expr if) => {};       //~ERROR `$e:expr` is followed by `if`
+    ($e:expr in) => {};       //~ERROR `$e:expr` is followed by `in`
+    ($e:expr $p:pat) => {};   //~ERROR `$e:expr` is followed by `$p:pat`
+    ($e:expr $e:expr) => {};  //~ERROR `$e:expr` is followed by `$e:expr`
+    ($e:expr $t:ty) => {};    //~ERROR `$e:expr` is followed by `$t:ty`
+    ($e:expr $s:stmt) => {};  //~ERROR `$e:expr` is followed by `$s:stmt`
+    ($e:expr $p:path) => {};  //~ERROR `$e:expr` is followed by `$p:path`
+    ($e:expr $b:block) => {}; //~ERROR `$e:expr` is followed by `$b:block`
+    ($e:expr $i:ident) => {}; //~ERROR `$e:expr` is followed by `$i:ident`
+    ($e:expr $t:tt) => {};    //~ERROR `$e:expr` is followed by `$t:tt`
+    ($e:expr $i:item) => {};  //~ERROR `$e:expr` is followed by `$i:item`
+    ($e:expr $m:meta) => {};  //~ERROR `$e:expr` is followed by `$m:meta`
+}
+// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
+//               Ident(as), Ident(where), OpenDelim(Bracket)}
+macro_rules! follow_ty {
+    ($t:ty ()) => {};       //~WARN  `$t:ty` is followed by `(`
+    ($t:ty []) => {};       // ok (RFC 1462)
+    ($t:ty +) => {};        //~ERROR `$t:ty` is followed by `+`
+    ($t:ty ident) => {};    //~ERROR `$t:ty` is followed by `ident`
+    ($t:ty if) => {};       //~ERROR `$t:ty` is followed by `if`
+    ($t:ty $p:pat) => {};   //~ERROR `$t:ty` is followed by `$p:pat`
+    ($t:ty $e:expr) => {};  //~ERROR `$t:ty` is followed by `$e:expr`
+    ($t:ty $t:ty) => {};    //~ERROR `$t:ty` is followed by `$t:ty`
+    ($t:ty $s:stmt) => {};  //~ERROR `$t:ty` is followed by `$s:stmt`
+    ($t:ty $p:path) => {};  //~ERROR `$t:ty` is followed by `$p:path`
+    ($t:ty $b:block) => {}; //~ERROR `$t:ty` is followed by `$b:block`
+    ($t:ty $i:ident) => {}; //~ERROR `$t:ty` is followed by `$i:ident`
+    ($t:ty $t:tt) => {};    //~ERROR `$t:ty` is followed by `$t:tt`
+    ($t:ty $i:item) => {};  //~ERROR `$t:ty` is followed by `$i:item`
+    ($t:ty $m:meta) => {};  //~ERROR `$t:ty` is followed by `$m:meta`
+}
+// FOLLOW(stmt) = FOLLOW(expr)
+macro_rules! follow_stmt {
+    ($s:stmt ()) => {};       //~WARN  `$s:stmt` is followed by `(`
+    ($s:stmt []) => {};       //~WARN  `$s:stmt` is followed by `[`
+    ($s:stmt {}) => {};       //~WARN  `$s:stmt` is followed by `{`
+    ($s:stmt =) => {};        //~ERROR `$s:stmt` is followed by `=`
+    ($s:stmt |) => {};        //~ERROR `$s:stmt` is followed by `|`
+    ($s:stmt :) => {};        //~ERROR `$s:stmt` is followed by `:`
+    ($s:stmt >) => {};        //~ERROR `$s:stmt` is followed by `>`
+    ($s:stmt +) => {};        //~ERROR `$s:stmt` is followed by `+`
+    ($s:stmt ident) => {};    //~ERROR `$s:stmt` is followed by `ident`
+    ($s:stmt if) => {};       //~ERROR `$s:stmt` is followed by `if`
+    ($s:stmt in) => {};       //~ERROR `$s:stmt` is followed by `in`
+    ($s:stmt $p:pat) => {};   //~ERROR `$s:stmt` is followed by `$p:pat`
+    ($s:stmt $e:expr) => {};  //~ERROR `$s:stmt` is followed by `$e:expr`
+    ($s:stmt $t:ty) => {};    //~ERROR `$s:stmt` is followed by `$t:ty`
+    ($s:stmt $s:stmt) => {};  //~ERROR `$s:stmt` is followed by `$s:stmt`
+    ($s:stmt $p:path) => {};  //~ERROR `$s:stmt` is followed by `$p:path`
+    ($s:stmt $b:block) => {}; //~ERROR `$s:stmt` is followed by `$b:block`
+    ($s:stmt $i:ident) => {}; //~ERROR `$s:stmt` is followed by `$i:ident`
+    ($s:stmt $t:tt) => {};    //~ERROR `$s:stmt` is followed by `$t:tt`
+    ($s:stmt $i:item) => {};  //~ERROR `$s:stmt` is followed by `$i:item`
+    ($s:stmt $m:meta) => {};  //~ERROR `$s:stmt` is followed by `$m:meta`
+}
+// FOLLOW(path) = FOLLOW(ty)
+macro_rules! follow_path {
+    ($p:path ()) => {};       //~WARN  `$p:path` is followed by `(`
+    ($p:path []) => {};       // ok (RFC 1462)
+    ($p:path +) => {};        //~ERROR `$p:path` is followed by `+`
+    ($p:path ident) => {};    //~ERROR `$p:path` is followed by `ident`
+    ($p:path if) => {};       //~ERROR `$p:path` is followed by `if`
+    ($p:path $p:pat) => {};   //~ERROR `$p:path` is followed by `$p:pat`
+    ($p:path $e:expr) => {};  //~ERROR `$p:path` is followed by `$e:expr`
+    ($p:path $t:ty) => {};    //~ERROR `$p:path` is followed by `$t:ty`
+    ($p:path $s:stmt) => {};  //~ERROR `$p:path` is followed by `$s:stmt`
+    ($p:path $p:path) => {};  //~ERROR `$p:path` is followed by `$p:path`
+    ($p:path $b:block) => {}; //~ERROR `$p:path` is followed by `$b:block`
+    ($p:path $i:ident) => {}; //~ERROR `$p:path` is followed by `$i:ident`
+    ($p:path $t:tt) => {};    //~ERROR `$p:path` is followed by `$t:tt`
+    ($p:path $i:item) => {};  //~ERROR `$p:path` is followed by `$i:item`
+    ($p:path $m:meta) => {};  //~ERROR `$p:path` is followed by `$m:meta`
+}
+// FOLLOW(block) = any token
+// FOLLOW(ident) = any token
+
+fn main() {}
+
index 146265bf0e1508bfaa7755642f04d3c43a5a12d6..b986878f78396ae823bf9e3fac40e93486dd65f2 100644 (file)
@@ -16,12 +16,6 @@ struct Foo {
     second: Option<[usize; 4]>
 }
 
-enum Color {
-    Red,
-    Green,
-    CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
-}
-
 fn struct_with_a_nested_enum_and_vector() {
     match (Foo { first: true, second: None }) {
 //~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
@@ -32,10 +26,40 @@ fn struct_with_a_nested_enum_and_vector() {
     }
 }
 
-fn enum_with_multiple_missing_variants() {
+enum Color {
+    Red,
+    Green,
+    CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+}
+
+fn enum_with_single_missing_variant() {
     match Color::Red {
     //~^ ERROR non-exhaustive patterns: `Red` not covered
-        Color::CustomRGBA { .. } => ()
+        Color::CustomRGBA { .. } => (),
+        Color::Green => ()
+    }
+}
+
+enum Direction {
+    North, East, South, West
+}
+
+fn enum_with_multiple_missing_variants() {
+    match Direction::North {
+    //~^ ERROR non-exhaustive patterns: `East`, `South` and `West` not covered
+        Direction::North => ()
+    }
+}
+
+enum ExcessiveEnum {
+    First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+}
+
+fn enum_with_excessive_missing_variants() {
+    match ExcessiveEnum::First {
+    //~^ ERROR `Second`, `Third`, `Fourth` and 8 more not covered
+
+        ExcessiveEnum::First => ()
     }
 }
 
diff --git a/src/test/pretty/issue-31073.pp b/src/test/pretty/issue-31073.pp
new file mode 100644 (file)
index 0000000..872923f
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact:issue-31073.pp
+
+fn main() {
+    fn f1(x: i32, y: i32) -> i32 { y }
+    let f: fn(_, i32) -> i32 = f1;
+    f(1, 2);
+}
diff --git a/src/test/pretty/issue-31073.rs b/src/test/pretty/issue-31073.rs
new file mode 100644 (file)
index 0000000..872923f
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact:issue-31073.pp
+
+fn main() {
+    fn f1(x: i32, y: i32) -> i32 { y }
+    let f: fn(_, i32) -> i32 = f1;
+    f(1, 2);
+}
index d42a777a019a30bd03d797aa7ae0f6eb981fa89f..41a6fd05c3741fb6090cc956442c5ee0bfb8ae2c 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-cross-compile
 
-// error-pattern:expected identifier, found keyword `let`
+// error-pattern:expected expression, found statement (`let`)
 
 #![feature(quote, rustc_private)]
 
index dc409f393a86a971fa82fb3005fc0ef78eb286dc..fe6a5faf9324a3a46e4b0bdd8634c9e14c9d0f40 100644 (file)
@@ -32,7 +32,7 @@
 use rustc::middle::ty;
 use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
 use rustc::session::build_session;
-use rustc_driver::driver;
+use rustc_driver::{driver, abort_on_err};
 use rustc_front::lowering::{lower_crate, LoweringContext};
 use rustc_resolve::MakeGlobMap;
 use rustc_metadata::cstore::CStore;
@@ -234,7 +234,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
         let arenas = ty::CtxtArenas::new();
         let ast_map = driver::make_map(&sess, &mut hir_forest);
 
-        driver::phase_3_run_analysis_passes(
+        abort_on_err(driver::phase_3_run_analysis_passes(
             &sess, &cstore, ast_map, &arenas, &id,
             MakeGlobMap::No, |tcx, mir_map, analysis| {
 
@@ -254,7 +254,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
             let modp = llmod as usize;
 
             (modp, deps)
-        })
+        }), &sess)
     }).unwrap();
 
     match handle.join() {
index 4b1c84ce64fee3e84c85292a8ae5e88af593011a..b2aed91545842e61042eee48fdca2f633058be29 100644 (file)
@@ -65,7 +65,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     let cfg = build_configuration(&sess);
     let control = CompileController::basic();
 
-    compile_input(sess, &cstore,
+    compile_input(&sess, &cstore,
             cfg,
             &Input::Str(code),
             &None,
diff --git a/src/test/run-pass/lexical-scoping.rs b/src/test/run-pass/lexical-scoping.rs
new file mode 100644 (file)
index 0000000..3660404
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that items in subscopes can shadow type parameters and local variables (see issue #23880).
+
+#![allow(unused)]
+struct Foo<X> { x: Box<X> }
+impl<Bar> Foo<Bar> {
+    fn foo(&self) {
+        type Bar = i32;
+        let _: Bar = 42;
+    }
+}
+
+fn main() {
+    let f = 1;
+    {
+        fn f() {}
+        f();
+    }
+}
diff --git a/src/test/run-pass/lint-expr-stmt-attrs-for-early-lints.rs b/src/test/run-pass/lint-expr-stmt-attrs-for-early-lints.rs
new file mode 100644 (file)
index 0000000..16c7176
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(stmt_expr_attributes)]
+#![deny(unused_parens)]
+
+// Tests that lint attributes on statements/expressions are
+// correctly applied to non-builtin early (AST) lints
+
+fn main() {
+    #[allow(unused_parens)]
+    {
+        let _ = (9);
+    }
+}
diff --git a/src/test/run-pass/macro-follow.rs b/src/test/run-pass/macro-follow.rs
new file mode 100644 (file)
index 0000000..ce6498f
--- /dev/null
@@ -0,0 +1,190 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check the macro follow sets (see corresponding cfail test).
+
+// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
+macro_rules! follow_pat {
+    ($p:pat =>) => {};
+    ($p:pat ,) => {};
+    ($p:pat =) => {};
+    ($p:pat |) => {};
+    ($p:pat if) => {};
+    ($p:pat in) => {};
+}
+// FOLLOW(expr) = {FatArrow, Comma, Semicolon}
+macro_rules! follow_expr {
+    ($e:expr =>) => {};
+    ($e:expr ,) => {};
+    ($e:expr ;) => {};
+}
+// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
+//               Ident(as), Ident(where), OpenDelim(Bracket)}
+macro_rules! follow_ty {
+    ($t:ty {}) => {};
+    ($t:ty ,) => {};
+    ($t:ty =>) => {};
+    ($t:ty :) => {};
+    ($t:ty =) => {};
+    ($t:ty >) => {};
+    ($t:ty ;) => {};
+    ($t:ty |) => {};
+    ($t:ty as) => {};
+    ($t:ty where) => {};
+    ($t:ty []) => {};
+}
+// FOLLOW(stmt) = FOLLOW(expr)
+macro_rules! follow_stmt {
+    ($s:stmt =>) => {};
+    ($s:stmt ,) => {};
+    ($s:stmt ;) => {};
+}
+// FOLLOW(path) = FOLLOW(ty)
+macro_rules! follow_path {
+    ($p:path {}) => {};
+    ($p:path ,) => {};
+    ($p:path =>) => {};
+    ($p:path :) => {};
+    ($p:path =) => {};
+    ($p:path >) => {};
+    ($p:path ;) => {};
+    ($p:path |) => {};
+    ($p:path as) => {};
+    ($p:path where) => {};
+    ($p:path []) => {};
+}
+// FOLLOW(block) = any token
+macro_rules! follow_block {
+    ($b:block ()) => {};
+    ($b:block []) => {};
+    ($b:block {}) => {};
+    ($b:block ,) => {};
+    ($b:block =>) => {};
+    ($b:block :) => {};
+    ($b:block =) => {};
+    ($b:block >) => {};
+    ($b:block ;) => {};
+    ($b:block |) => {};
+    ($b:block +) => {};
+    ($b:block ident) => {};
+    ($b:block $p:pat) => {};
+    ($b:block $e:expr) => {};
+    ($b:block $t:ty) => {};
+    ($b:block $s:stmt) => {};
+    ($b:block $p:path) => {};
+    ($b:block $b:block) => {};
+    ($b:block $i:ident) => {};
+    ($b:block $t:tt) => {};
+    ($b:block $i:item) => {};
+    ($b:block $m:meta) => {};
+}
+// FOLLOW(ident) = any token
+macro_rules! follow_ident {
+    ($i:ident ()) => {};
+    ($i:ident []) => {};
+    ($i:ident {}) => {};
+    ($i:ident ,) => {};
+    ($i:ident =>) => {};
+    ($i:ident :) => {};
+    ($i:ident =) => {};
+    ($i:ident >) => {};
+    ($i:ident ;) => {};
+    ($i:ident |) => {};
+    ($i:ident +) => {};
+    ($i:ident ident) => {};
+    ($i:ident $p:pat) => {};
+    ($i:ident $e:expr) => {};
+    ($i:ident $t:ty) => {};
+    ($i:ident $s:stmt) => {};
+    ($i:ident $p:path) => {};
+    ($i:ident $b:block) => {};
+    ($i:ident $i:ident) => {};
+    ($i:ident $t:tt) => {};
+    ($i:ident $i:item) => {};
+    ($i:ident $m:meta) => {};
+}
+// FOLLOW(tt) = any token
+macro_rules! follow_tt {
+    ($t:tt ()) => {};
+    ($t:tt []) => {};
+    ($t:tt {}) => {};
+    ($t:tt ,) => {};
+    ($t:tt =>) => {};
+    ($t:tt :) => {};
+    ($t:tt =) => {};
+    ($t:tt >) => {};
+    ($t:tt ;) => {};
+    ($t:tt |) => {};
+    ($t:tt +) => {};
+    ($t:tt ident) => {};
+    ($t:tt $p:pat) => {};
+    ($t:tt $e:expr) => {};
+    ($t:tt $t:ty) => {};
+    ($t:tt $s:stmt) => {};
+    ($t:tt $p:path) => {};
+    ($t:tt $b:block) => {};
+    ($t:tt $i:ident) => {};
+    ($t:tt $t:tt) => {};
+    ($t:tt $i:item) => {};
+    ($t:tt $m:meta) => {};
+}
+// FOLLOW(item) = any token
+macro_rules! follow_item {
+    ($i:item ()) => {};
+    ($i:item []) => {};
+    ($i:item {}) => {};
+    ($i:item ,) => {};
+    ($i:item =>) => {};
+    ($i:item :) => {};
+    ($i:item =) => {};
+    ($i:item >) => {};
+    ($i:item ;) => {};
+    ($i:item |) => {};
+    ($i:item +) => {};
+    ($i:item ident) => {};
+    ($i:item $p:pat) => {};
+    ($i:item $e:expr) => {};
+    ($i:item $t:ty) => {};
+    ($i:item $s:stmt) => {};
+    ($i:item $p:path) => {};
+    ($i:item $b:block) => {};
+    ($i:item $i:ident) => {};
+    ($i:item $t:tt) => {};
+    ($i:item $i:item) => {};
+    ($i:item $m:meta) => {};
+}
+// FOLLOW(meta) = any token
+macro_rules! follow_meta {
+    ($m:meta ()) => {};
+    ($m:meta []) => {};
+    ($m:meta {}) => {};
+    ($m:meta ,) => {};
+    ($m:meta =>) => {};
+    ($m:meta :) => {};
+    ($m:meta =) => {};
+    ($m:meta >) => {};
+    ($m:meta ;) => {};
+    ($m:meta |) => {};
+    ($m:meta +) => {};
+    ($m:meta ident) => {};
+    ($m:meta $p:pat) => {};
+    ($m:meta $e:expr) => {};
+    ($m:meta $t:ty) => {};
+    ($m:meta $s:stmt) => {};
+    ($m:meta $p:path) => {};
+    ($m:meta $b:block) => {};
+    ($m:meta $i:ident) => {};
+    ($m:meta $t:tt) => {};
+    ($m:meta $i:item) => {};
+    ($m:meta $m:meta) => {};
+}
+
+fn main() {}
+
diff --git a/src/test/run-pass/multi-panic.rs b/src/test/run-pass/multi-panic.rs
new file mode 100644 (file)
index 0000000..7bf0731
--- /dev/null
@@ -0,0 +1,30 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let args: Vec<String> = std::env::args().collect();
+    if args.len() > 1 && args[1] == "run_test" {
+        let _ = std::thread::spawn(|| {
+            panic!();
+        }).join();
+
+        panic!();
+    } else {
+        let test = std::process::Command::new(&args[0]).arg("run_test").output().unwrap();
+        assert!(!test.status.success());
+        let err = String::from_utf8_lossy(&test.stderr);
+        let mut it = err.lines();
+
+        assert_eq!(it.next().map(|l| l.starts_with("thread '<unnamed>' panicked at")), Some(true));
+        assert_eq!(it.next(), Some("note: Run with `RUST_BACKTRACE=1` for a backtrace."));
+        assert_eq!(it.next().map(|l| l.starts_with("thread '<main>' panicked at")), Some(true));
+        assert_eq!(it.next(), None);
+    }
+}
diff --git a/src/test/run-pass/no-stdio.rs b/src/test/run-pass/no-stdio.rs
new file mode 100644 (file)
index 0000000..3658b6a
--- /dev/null
@@ -0,0 +1,124 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(libc)]
+
+extern crate libc;
+
+use std::process::{Command, Stdio};
+use std::env;
+use std::io::{self, Read, Write};
+
+#[cfg(unix)]
+unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
+    let doit = |a| {
+        let r = libc::dup(a);
+        assert!(r >= 0);
+        return r
+    };
+    let a = doit(0);
+    let b = doit(1);
+    let c = doit(2);
+
+    assert!(libc::close(0) >= 0);
+    assert!(libc::close(1) >= 0);
+    assert!(libc::close(2) >= 0);
+
+    let r = f();
+
+    assert!(libc::dup2(a, 0) >= 0);
+    assert!(libc::dup2(b, 1) >= 0);
+    assert!(libc::dup2(c, 2) >= 0);
+
+    return r
+}
+
+#[cfg(windows)]
+unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
+    type DWORD = u32;
+    type HANDLE = *mut u8;
+    type BOOL = i32;
+
+    const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
+    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
+    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
+    const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
+
+    extern "system" {
+        fn GetStdHandle(which: DWORD) -> HANDLE;
+        fn SetStdHandle(which: DWORD, handle: HANDLE) -> BOOL;
+    }
+
+    let doit = |id| {
+        let handle = GetStdHandle(id);
+        assert!(handle != INVALID_HANDLE_VALUE);
+        assert!(SetStdHandle(id, INVALID_HANDLE_VALUE) != 0);
+        return handle
+    };
+
+    let a = doit(STD_INPUT_HANDLE);
+    let b = doit(STD_OUTPUT_HANDLE);
+    let c = doit(STD_ERROR_HANDLE);
+
+    let r = f();
+
+    let doit = |id, handle| {
+        assert!(SetStdHandle(id, handle) != 0);
+    };
+    doit(STD_INPUT_HANDLE, a);
+    doit(STD_OUTPUT_HANDLE, b);
+    doit(STD_ERROR_HANDLE, c);
+
+    return r
+}
+
+fn main() {
+    if env::args().len() > 1 {
+        println!("test");
+        assert!(io::stdout().write(b"test\n").is_ok());
+        assert!(io::stderr().write(b"test\n").is_ok());
+        assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0);
+        return
+    }
+
+    // First, make sure reads/writes without stdio work if stdio itself is
+    // missing.
+    let (a, b, c) = unsafe {
+        without_stdio(|| {
+            let a = io::stdout().write(b"test\n");
+            let b = io::stderr().write(b"test\n");
+            let c = io::stdin().read(&mut [0; 10]);
+
+            (a, b, c)
+        })
+    };
+
+    assert_eq!(a.unwrap(), 5);
+    assert_eq!(b.unwrap(), 5);
+    assert_eq!(c.unwrap(), 0);
+
+    // Second, spawn a child and do some work with "null" descriptors to make
+    // sure it's ok
+    let me = env::current_exe().unwrap();
+    let status = Command::new(&me)
+                        .arg("next")
+                        .stdin(Stdio::null())
+                        .stdout(Stdio::null())
+                        .stderr(Stdio::null())
+                        .status().unwrap();
+    assert!(status.success(), "{:?} isn't a success", status);
+
+    // Finally, close everything then spawn a child to make sure everything is
+    // *still* ok.
+    let status = unsafe {
+        without_stdio(|| Command::new(&me).arg("next").status())
+    }.unwrap();
+    assert!(status.success(), "{:?} isn't a success", status);
+}