]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #37123 - srinivasreddy:libcore_num, r=erickt
authorJonathan Turner <jonathandturner@users.noreply.github.com>
Fri, 14 Oct 2016 19:07:08 +0000 (12:07 -0700)
committerGitHub <noreply@github.com>
Fri, 14 Oct 2016 19:07:08 +0000 (12:07 -0700)
run rustfmt on libcore/num folder

124 files changed:
configure
src/bootstrap/lib.rs
src/doc/book/lifetimes.md
src/doc/book/type-aliases.md
src/doc/reference.md
src/libcollections/vec.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/slice.rs
src/libcollectionstest/vec.rs
src/libcore/any.rs
src/libcore/hash/mod.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libgraphviz/lib.rs
src/liblibc
src/liblog/directive.rs
src/librustc/diagnostics.rs
src/librustc/hir/lowering.rs
src/librustc/lib.rs
src/librustc/session/mod.rs
src/librustc_back/lib.rs
src/librustc_borrowck/bitslice.rs [deleted file]
src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/indexed_set.rs [deleted file]
src/librustc_borrowck/lib.rs
src/librustc_const_eval/eval.rs
src/librustc_const_eval/lib.rs
src/librustc_const_math/lib.rs
src/librustc_data_structures/bitslice.rs [new file with mode: 0644]
src/librustc_data_structures/indexed_set.rs [new file with mode: 0644]
src/librustc_data_structures/lib.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_errors/lib.rs
src/librustc_incremental/calculate_svh/hasher.rs [new file with mode: 0644]
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_incremental/lib.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/lib.rs
src/librustc_mir/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/common.rs
src/librustc_trans/lib.rs
src/librustc_typeck/lib.rs
src/librustdoc/externalfiles.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/libserialize/json.rs
src/libserialize/lib.rs
src/libserialize/opaque.rs
src/libserialize/serialize.rs
src/libstd/collections/hash/table.rs
src/libstd/error.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/net/addr.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sys/common/poison.rs
src/libsyntax/ast.rs
src/libsyntax/config.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/lib.rs
src/libsyntax_pos/lib.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/test/compile-fail/E0408.rs
src/test/compile-fail/feature-gate-try-operator.rs [deleted file]
src/test/compile-fail/issue-2848.rs
src/test/compile-fail/issue-32709.rs
src/test/compile-fail/issue-33876.rs
src/test/compile-fail/macro-shadowing.rs
src/test/compile-fail/macro-use-scope.rs
src/test/compile-fail/mir-dataflow/def-inits-1.rs
src/test/compile-fail/mir-dataflow/inits-1.rs
src/test/compile-fail/mir-dataflow/uninits-1.rs
src/test/compile-fail/mir-dataflow/uninits-2.rs
src/test/compile-fail/resolve-inconsistent-names.rs
src/test/compile-fail/stmt_expr_attrs_no_feature.rs
src/test/incremental/hashes/struct_defs.rs
src/test/run-pass-fulldeps/macro-crate.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs
src/test/run-pass-fulldeps/proc-macro/load-two.rs
src/test/run-pass/const-err.rs
src/test/run-pass/const-negation.rs
src/test/run-pass/enum-discrim-autosizing.rs
src/test/run-pass/ifmt.rs
src/test/run-pass/impl-trait/example-st.rs
src/test/run-pass/issue-17121.rs
src/test/run-pass/issue-19404.rs
src/test/run-pass/issue-20797.rs
src/test/run-pass/issue-21400.rs
src/test/run-pass/issue-37020.rs [new file with mode: 0644]
src/test/run-pass/issue-37109.rs [new file with mode: 0644]
src/test/run-pass/issue-8460.rs
src/test/run-pass/try-operator-hygiene.rs
src/test/run-pass/try-operator.rs
src/tools/compiletest/src/main.rs
src/tools/error_index_generator/main.rs
src/tools/linkchecker/main.rs
src/tools/rustbook/main.rs

index 9e65bc789b4c507a072b2409c8fe91411aaaccc3..d0c85c0a008be71362a82d16701c180d397220da 100755 (executable)
--- a/configure
+++ b/configure
@@ -1635,8 +1635,8 @@ do
         ("ccache gcc")
             LLVM_CXX_32="ccache"
             LLVM_CC_32="ccache"
-            LLVM_CXX_32_ARG1="clang++"
-            LLVM_CC_32_ARG1="clang"
+            LLVM_CXX_32_ARG1="g++"
+            LLVM_CC_32_ARG1="gcc"
 
             LLVM_CXX_64="ccache"
             LLVM_CC_64="ccache"
index 12938b8326e79805de9c2e34d5471497c3b3b80d..30983869c2e3b1e41641a2ace4239b1403c2a0c5 100644 (file)
@@ -991,7 +991,8 @@ fn rustc_flags(&self, target: &str) -> Vec<String> {
 
     /// Returns the "musl root" for this `target`, if defined
     fn musl_root(&self, target: &str) -> Option<&Path> {
-        self.config.target_config[target].musl_root.as_ref()
+        self.config.target_config.get(target)
+            .and_then(|t| t.musl_root.as_ref())
             .or(self.config.musl_root.as_ref())
             .map(|p| &**p)
     }
index e865609f217f0cb094fe4c5884feb66970992f60..df1ee5a293c9d6b8e2638ff8c8394c2a6a286ed6 100644 (file)
@@ -50,11 +50,78 @@ complicated. For example, imagine this set of operations:
 4. You decide to use the resource.
 
 Uh oh! Your reference is pointing to an invalid resource. This is called a
-dangling pointer or â€˜use after free’, when the resource is memory.
+dangling pointer or â€˜use after free’, when the resource is memory. A small
+example of such a situation would be:
+
+```rust,compile_fail
+let r;              // Introduce reference: r
+{
+    let i = 1;      // Introduce scoped value: i
+    r = &i;         // Store reference of i in r
+}                   // i goes out of scope and is dropped.
+
+println!("{}", r);  // r still refers to i
+```
 
 To fix this, we have to make sure that step four never happens after step
-three. The ownership system in Rust does this through a concept called
-lifetimes, which describe the scope that a reference is valid for.
+three. In the small example above the Rust compiler is able to report the issue
+as it can see the lifetimes of the various values in the function.
+
+When we have a function that takes arguments by reference the situation becomes
+more complex. Consider the following example:
+
+```rust,compile_fail,E0106
+fn skip_prefix(line: &str, prefix: &str) -> &str {
+    // ...
+#   line
+}
+
+let line = "lang:en=Hello World!";
+let lang = "en";
+
+let v;
+{
+    let p = format!("lang:{}=", lang);  // -+ p goes into scope
+    v = skip_prefix(line, p.as_str());  //  |
+}                                       // -+ p goes out of scope
+println!("{}", v);
+```
+
+Here we have a function `skip_prefix` which takes two `&str` references
+as parameters and returns a single `&str` reference. We call it
+by passing in references to `line` and `p`: Two variables with different
+lifetimes. Now the safety of the `println!`-line depends on whether the
+reference returned by `skip_prefix` function references the still living
+`line` or the already dropped `p` string.
+
+Because of the above ambiguity, Rust will refuse to compile the example
+code. To get it to compile we need to tell the compiler more about the
+lifetimes of the references. This can be done by making the lifetimes
+explicit in the function declaration:
+
+```rust
+fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
+    // ...
+#   line
+}
+```
+
+Let's examine the changes without going too deep into the syntax for now -
+we'll get to that later. The first change was adding the `<'a, 'b>` after the
+method name. This introduces two lifetime parameters: `'a` and `'b`. Next each
+reference in the function signature was associated with one of the lifetime
+parameters by adding the lifetime name after the `&`. This tells the compiler
+how the lifetimes between different references are related.
+
+As a result the compiler is now able to deduce that the return value of
+`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v`
+reference safe to use even after the `p` goes out of scope in the original
+example.
+
+In addition to the compiler being able to validate the usage of `skip_prefix`
+return value, it can also ensure that the implementation follows the contract
+established by the function declaration. This is useful especially when you are
+implementing traits that are introduced [later in the book][traits].
 
 **Note** It's important to understand that lifetime annotations are
 _descriptive_, not _prescriptive_. This means that how long a reference is valid
@@ -63,20 +130,14 @@ give information about lifetimes to the compiler that uses them to check the
 validity of references. The compiler can do so without annotations in simple
 cases, but needs the programmers support in complex scenarios.
 
-```rust
-// implicit
-fn foo(x: &i32) {
-}
+[traits]: traits.html
 
-// explicit
-fn bar<'a>(x: &'a i32) {
-}
-```
+# Syntax
 
 The `'a` reads â€˜the lifetime a’. Technically, every reference has some lifetime
 associated with it, but the compiler lets you elide (i.e. omit, see
-["Lifetime Elision"][lifetime-elision] below) them in common cases.
-Before we get to that, though, let’s break the explicit example down:
+["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
+get to that, though, let’s look at a short example with explicit lifetimes:
 
 [lifetime-elision]: #lifetime-elision
 
@@ -94,7 +155,8 @@ focus on the lifetimes aspect.
 [generics]: generics.html
 
 We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
-`'a`. If we had two reference parameters, it would look like this:
+`'a`. If we had two reference parameters with different lifetimes, it would
+look like this:
 
 
 ```rust,ignore
index def2e31f3514b595fe24912c4e704e7b5f12b82d..3798336f0a52419c579cf8f9c1c2b8e191c27a0b 100644 (file)
@@ -1,4 +1,4 @@
-% `type` Aliases
+% Type Aliases
 
 The `type` keyword lets you declare an alias of another type:
 
index 08ff982d4d73b6e5c7341771fbd3b9d91344174e..84f459bf8724fd40d10034d0ece03d002f8b07f4 100644 (file)
@@ -2472,8 +2472,7 @@ The currently implemented features of the reference compiler are:
 * - `default_type_parameter_fallback` - Allows type parameter defaults to
                                         influence type inference.
 
-* - `stmt_expr_attributes` - Allows attributes on expressions and
-                             non-item statements.
+* - `stmt_expr_attributes` - Allows attributes on expressions.
 
 * - `type_ascription` - Allows type ascription expressions `expr: Type`.
 
index 54fd19dbe3058cd7a310ba34077b749fb82634bb..2bb311cc5ae900f25aad671508c49cd49a4d8706 100644 (file)
@@ -781,6 +781,130 @@ pub fn retain<F>(&mut self, mut f: F)
         }
     }
 
+    /// Removes consecutive elements in the vector that resolve to the same key.
+    ///
+    /// If the vector is sorted, this removes all duplicates.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(dedup_by)]
+    ///
+    /// let mut vec = vec![10, 20, 21, 30, 20];
+    ///
+    /// vec.dedup_by_key(|i| *i / 10);
+    ///
+    /// assert_eq!(vec, [10, 20, 30, 20]);
+    /// ```
+    #[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
+    #[inline]
+    pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
+        self.dedup_by(|a, b| key(a) == key(b))
+    }
+
+    /// Removes consecutive elements in the vector that resolve to the same key.
+    ///
+    /// If the vector is sorted, this removes all duplicates.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(dedup_by)]
+    /// use std::ascii::AsciiExt;
+    ///
+    /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
+    ///
+    /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+    ///
+    /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
+    /// ```
+    #[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
+    pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
+        unsafe {
+            // Although we have a mutable reference to `self`, we cannot make
+            // *arbitrary* changes. The `PartialEq` comparisons could panic, so we
+            // must ensure that the vector is in a valid state at all time.
+            //
+            // The way that we handle this is by using swaps; we iterate
+            // over all the elements, swapping as we go so that at the end
+            // the elements we wish to keep are in the front, and those we
+            // wish to reject are at the back. We can then truncate the
+            // vector. This operation is still O(n).
+            //
+            // Example: We start in this state, where `r` represents "next
+            // read" and `w` represents "next_write`.
+            //
+            //           r
+            //     +---+---+---+---+---+---+
+            //     | 0 | 1 | 1 | 2 | 3 | 3 |
+            //     +---+---+---+---+---+---+
+            //           w
+            //
+            // Comparing self[r] against self[w-1], this is not a duplicate, so
+            // we swap self[r] and self[w] (no effect as r==w) and then increment both
+            // r and w, leaving us with:
+            //
+            //               r
+            //     +---+---+---+---+---+---+
+            //     | 0 | 1 | 1 | 2 | 3 | 3 |
+            //     +---+---+---+---+---+---+
+            //               w
+            //
+            // Comparing self[r] against self[w-1], this value is a duplicate,
+            // so we increment `r` but leave everything else unchanged:
+            //
+            //                   r
+            //     +---+---+---+---+---+---+
+            //     | 0 | 1 | 1 | 2 | 3 | 3 |
+            //     +---+---+---+---+---+---+
+            //               w
+            //
+            // Comparing self[r] against self[w-1], this is not a duplicate,
+            // so swap self[r] and self[w] and advance r and w:
+            //
+            //                       r
+            //     +---+---+---+---+---+---+
+            //     | 0 | 1 | 2 | 1 | 3 | 3 |
+            //     +---+---+---+---+---+---+
+            //                   w
+            //
+            // Not a duplicate, repeat:
+            //
+            //                           r
+            //     +---+---+---+---+---+---+
+            //     | 0 | 1 | 2 | 3 | 1 | 3 |
+            //     +---+---+---+---+---+---+
+            //                       w
+            //
+            // Duplicate, advance r. End of vec. Truncate to w.
+
+            let ln = self.len();
+            if ln <= 1 {
+                return;
+            }
+
+            // Avoid bounds checks by using raw pointers.
+            let p = self.as_mut_ptr();
+            let mut r: usize = 1;
+            let mut w: usize = 1;
+
+            while r < ln {
+                let p_r = p.offset(r as isize);
+                let p_wm1 = p.offset((w - 1) as isize);
+                if !same_bucket(&mut *p_r, &mut *p_wm1) {
+                    if r != w {
+                        let p_w = p_wm1.offset(1);
+                        mem::swap(&mut *p_r, &mut *p_w);
+                    }
+                    w += 1;
+                }
+                r += 1;
+            }
+
+            self.truncate(w);
+        }
+    }
+
     /// Appends an element to the back of a collection.
     ///
     /// # Panics
@@ -1155,90 +1279,9 @@ impl<T: PartialEq> Vec<T> {
     /// assert_eq!(vec, [1, 2, 3, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn dedup(&mut self) {
-        unsafe {
-            // Although we have a mutable reference to `self`, we cannot make
-            // *arbitrary* changes. The `PartialEq` comparisons could panic, so we
-            // must ensure that the vector is in a valid state at all time.
-            //
-            // The way that we handle this is by using swaps; we iterate
-            // over all the elements, swapping as we go so that at the end
-            // the elements we wish to keep are in the front, and those we
-            // wish to reject are at the back. We can then truncate the
-            // vector. This operation is still O(n).
-            //
-            // Example: We start in this state, where `r` represents "next
-            // read" and `w` represents "next_write`.
-            //
-            //           r
-            //     +---+---+---+---+---+---+
-            //     | 0 | 1 | 1 | 2 | 3 | 3 |
-            //     +---+---+---+---+---+---+
-            //           w
-            //
-            // Comparing self[r] against self[w-1], this is not a duplicate, so
-            // we swap self[r] and self[w] (no effect as r==w) and then increment both
-            // r and w, leaving us with:
-            //
-            //               r
-            //     +---+---+---+---+---+---+
-            //     | 0 | 1 | 1 | 2 | 3 | 3 |
-            //     +---+---+---+---+---+---+
-            //               w
-            //
-            // Comparing self[r] against self[w-1], this value is a duplicate,
-            // so we increment `r` but leave everything else unchanged:
-            //
-            //                   r
-            //     +---+---+---+---+---+---+
-            //     | 0 | 1 | 1 | 2 | 3 | 3 |
-            //     +---+---+---+---+---+---+
-            //               w
-            //
-            // Comparing self[r] against self[w-1], this is not a duplicate,
-            // so swap self[r] and self[w] and advance r and w:
-            //
-            //                       r
-            //     +---+---+---+---+---+---+
-            //     | 0 | 1 | 2 | 1 | 3 | 3 |
-            //     +---+---+---+---+---+---+
-            //                   w
-            //
-            // Not a duplicate, repeat:
-            //
-            //                           r
-            //     +---+---+---+---+---+---+
-            //     | 0 | 1 | 2 | 3 | 1 | 3 |
-            //     +---+---+---+---+---+---+
-            //                       w
-            //
-            // Duplicate, advance r. End of vec. Truncate to w.
-
-            let ln = self.len();
-            if ln <= 1 {
-                return;
-            }
-
-            // Avoid bounds checks by using raw pointers.
-            let p = self.as_mut_ptr();
-            let mut r: usize = 1;
-            let mut w: usize = 1;
-
-            while r < ln {
-                let p_r = p.offset(r as isize);
-                let p_wm1 = p.offset((w - 1) as isize);
-                if *p_r != *p_wm1 {
-                    if r != w {
-                        let p_w = p_wm1.offset(1);
-                        mem::swap(&mut *p_r, &mut *p_w);
-                    }
-                    w += 1;
-                }
-                r += 1;
-            }
-
-            self.truncate(w);
-        }
+        self.dedup_by(|a, b| a == b)
     }
 }
 
index c2b34647c32791afe93ce5328866481a9839ce59..88fb6540a9af4a723aa7351fd6333347e1033ee2 100644 (file)
@@ -16,6 +16,7 @@
 #![feature(collections)]
 #![feature(collections_bound)]
 #![feature(const_fn)]
+#![feature(dedup_by)]
 #![feature(enumset)]
 #![feature(pattern)]
 #![feature(rand)]
index 9580714075ad78260e8c68e50354d8af085319ea..130c16d7c150e7ff6e8a8f755a743fc86a6c2be5 100644 (file)
@@ -315,47 +315,6 @@ fn test_clear() {
     // If the unsafe block didn't drop things properly, we blow up here.
 }
 
-#[test]
-fn test_dedup() {
-    fn case(a: Vec<i32>, b: Vec<i32>) {
-        let mut v = a;
-        v.dedup();
-        assert_eq!(v, b);
-    }
-    case(vec![], vec![]);
-    case(vec![1], vec![1]);
-    case(vec![1, 1], vec![1]);
-    case(vec![1, 2, 3], vec![1, 2, 3]);
-    case(vec![1, 1, 2, 3], vec![1, 2, 3]);
-    case(vec![1, 2, 2, 3], vec![1, 2, 3]);
-    case(vec![1, 2, 3, 3], vec![1, 2, 3]);
-    case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
-}
-
-#[test]
-fn test_dedup_unique() {
-    let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
-    v0.dedup();
-    let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
-    v1.dedup();
-    let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
-    v2.dedup();
-    // If the boxed pointers were leaked or otherwise misused, valgrind
-    // and/or rt should raise errors.
-}
-
-#[test]
-fn test_dedup_shared() {
-    let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
-    v0.dedup();
-    let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
-    v1.dedup();
-    let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
-    v2.dedup();
-    // If the pointers were leaked or otherwise misused, valgrind and/or
-    // rt should raise errors.
-}
-
 #[test]
 fn test_retain() {
     let mut v = vec![1, 2, 3, 4, 5];
index ee2b898d5c2c2a7698a5dfbba39fd468d532a05a..8417be289eb9eaf5e44826ba4635a66ca9179e2e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::iter::{FromIterator, repeat};
 use std::mem::size_of;
@@ -213,6 +214,60 @@ fn test_retain() {
     assert_eq!(vec, [2, 4]);
 }
 
+#[test]
+fn test_dedup() {
+    fn case(a: Vec<i32>, b: Vec<i32>) {
+        let mut v = a;
+        v.dedup();
+        assert_eq!(v, b);
+    }
+    case(vec![], vec![]);
+    case(vec![1], vec![1]);
+    case(vec![1, 1], vec![1]);
+    case(vec![1, 2, 3], vec![1, 2, 3]);
+    case(vec![1, 1, 2, 3], vec![1, 2, 3]);
+    case(vec![1, 2, 2, 3], vec![1, 2, 3]);
+    case(vec![1, 2, 3, 3], vec![1, 2, 3]);
+    case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
+}
+
+#[test]
+fn test_dedup_by_key() {
+    fn case(a: Vec<i32>, b: Vec<i32>) {
+        let mut v = a;
+        v.dedup_by_key(|i| *i / 10);
+        assert_eq!(v, b);
+    }
+    case(vec![], vec![]);
+    case(vec![10], vec![10]);
+    case(vec![10, 11], vec![10]);
+    case(vec![10, 20, 30], vec![10, 20, 30]);
+    case(vec![10, 11, 20, 30], vec![10, 20, 30]);
+    case(vec![10, 20, 21, 30], vec![10, 20, 30]);
+    case(vec![10, 20, 30, 31], vec![10, 20, 30]);
+    case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
+}
+
+#[test]
+fn test_dedup_by() {
+    let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
+    vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
+
+    assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
+}
+
+#[test]
+fn test_dedup_unique() {
+    let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
+    v0.dedup();
+    let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
+    v1.dedup();
+    let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
+    v2.dedup();
+    // If the boxed pointers were leaked or otherwise misused, valgrind
+    // and/or rt should raise errors.
+}
+
 #[test]
 fn zero_sized_values() {
     let mut v = Vec::new();
index a3018a46eea22063545331e6937609597a98654d..f7edcb998a927328a8c33dadeea5841fc43ac5c8 100644 (file)
@@ -73,7 +73,6 @@
 
 use fmt;
 use intrinsics;
-use marker::Reflect;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Any trait
@@ -86,7 +85,7 @@
 ///
 /// [mod]: index.html
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait Any: Reflect + 'static {
+pub trait Any: 'static {
     /// Gets the `TypeId` of `self`.
     ///
     /// # Examples
@@ -112,7 +111,7 @@ pub trait Any: Reflect + 'static {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Reflect + 'static + ?Sized > Any for T {
+impl<T: 'static + ?Sized > Any for T {
     fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
 }
 
@@ -366,7 +365,7 @@ impl TypeId {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
+    pub fn of<T: ?Sized + 'static>() -> TypeId {
         TypeId {
             t: unsafe { intrinsics::type_id::<T>() },
         }
index 6a60cfcc120840de075596f6224a64ba75e45db0..ac36cbaace7a89fe85cc97e5e57ee86b85dca396 100644 (file)
@@ -38,7 +38,9 @@
 //! ```
 //!
 //! If you need more control over how a value is hashed, you need to implement
-//! the `Hash` trait:
+//! the [`Hash`] trait:
+//!
+//! [`Hash`]: trait.Hash.html
 //!
 //! ```rust
 //! use std::hash::{Hash, Hasher, SipHasher};
@@ -90,7 +92,7 @@
 /// The `H` type parameter is an abstract hash state that is used by the `Hash`
 /// to compute the hash.
 ///
-/// If you are also implementing `Eq`, there is an additional property that
+/// If you are also implementing [`Eq`], there is an additional property that
 /// is important:
 ///
 /// ```text
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes should also be equal.
-/// `HashMap` and `HashSet` both rely on this behavior.
+/// [`HashMap`] and [`HashSet`] both rely on this behavior.
 ///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]` if all fields implement `Hash`.
 /// When `derive`d, the resulting hash will be the combination of the values
-/// from calling `.hash()` on each field.
+/// from calling [`.hash()`] on each field.
 ///
 /// ## How can I implement `Hash`?
 ///
 ///     }
 /// }
 /// ```
+///
+/// [`Eq`]: ../../std/cmp/trait.Eq.html
+/// [`HashMap`]: ../../std/collections/struct.HashMap.html
+/// [`HashSet`]: ../../std/collections/struct.HashSet.html
+/// [`.hash()`]: #tymethod.hash
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hash {
     /// Feeds this value into the state given, updating the hasher as necessary.
@@ -151,35 +158,35 @@ pub trait Hasher {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn finish(&self) -> u64;
 
-    /// Writes some data into this `Hasher`
+    /// Writes some data into this `Hasher`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write(&mut self, bytes: &[u8]);
 
-    /// Write a single `u8` into this hasher
+    /// Write a single `u8` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_u8(&mut self, i: u8) {
         self.write(&[i])
     }
-    /// Write a single `u16` into this hasher.
+    /// Writes a single `u16` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_u16(&mut self, i: u16) {
         self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
     }
-    /// Write a single `u32` into this hasher.
+    /// Writes a single `u32` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_u32(&mut self, i: u32) {
         self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
     }
-    /// Write a single `u64` into this hasher.
+    /// Writes a single `u64` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_u64(&mut self, i: u64) {
         self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
     }
-    /// Write a single `usize` into this hasher.
+    /// Writes a single `usize` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_usize(&mut self, i: usize) {
@@ -189,31 +196,31 @@ fn write_usize(&mut self, i: usize) {
         self.write(bytes);
     }
 
-    /// Write a single `i8` into this hasher.
+    /// Writes a single `i8` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_i8(&mut self, i: i8) {
         self.write_u8(i as u8)
     }
-    /// Write a single `i16` into this hasher.
+    /// Writes a single `i16` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_i16(&mut self, i: i16) {
         self.write_u16(i as u16)
     }
-    /// Write a single `i32` into this hasher.
+    /// Writes a single `i32` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_i32(&mut self, i: i32) {
         self.write_u32(i as u32)
     }
-    /// Write a single `i64` into this hasher.
+    /// Writes a single `i64` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_i64(&mut self, i: i64) {
         self.write_u64(i as u64)
     }
-    /// Write a single `isize` into this hasher.
+    /// Writes a single `isize` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_isize(&mut self, i: isize) {
index 1ae4cf8e5ef5f05b37c920206786768eba05d41c..28101d21fc25ecd691ae7eae8e91f43b270f652d 100644 (file)
@@ -89,7 +89,7 @@
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(never_type)]
 #![feature(prelude_import)]
 
index 99c24e4c48d44a51a7a0ce0aa7f76add4845ff5d..6e08abd34614386c41479764b91248ea788f23d0 100644 (file)
@@ -255,6 +255,9 @@ macro_rules! debug_assert_ne {
 /// Helper macro for reducing boilerplate code for matching `Result` together
 /// with converting downstream errors.
 ///
+/// Prefer using `?` syntax to `try!`. `?` is built in to the language and is
+/// more succinct than `try!`. It is the standard method for error propagation.
+///
 /// `try!` matches the given `Result`. In case of the `Ok` variant, the
 /// expression has the value of the wrapped value.
 ///
index 5a1a034a36358d9d1098f537517fe2d26c7d8839..03d8af1563d6de1e639bd7fc4ea73068acb077d9 100644 (file)
@@ -587,6 +587,7 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 #[unstable(feature = "reflect_marker",
            reason = "requires RFC and more experience",
            issue = "27749")]
+#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")]
 #[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
                             ensure all type parameters are bounded by `Any`"]
 pub trait Reflect {}
@@ -594,4 +595,6 @@ pub trait Reflect {}
 #[unstable(feature = "reflect_marker",
            reason = "requires RFC and more experience",
            issue = "27749")]
+#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")]
+#[allow(deprecated)]
 impl Reflect for .. { }
index 74cc498a7df23478effa5f7644a736caad606470..95c46ec5715e742740963b414c75195050a4ba6c 100644 (file)
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(str_escape)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 use self::LabelText::*;
 
index 5a17b4a733a22d445fdd63326f826fcd8a584328..ebeab042e6bb14a447627b57ed9a493e2cc0e095 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5a17b4a733a22d445fdd63326f826fcd8a584328
+Subproject commit ebeab042e6bb14a447627b57ed9a493e2cc0e095
index f1ebf16737831a96ec0970ff279058f3d262743b..eb50d6e6135ef2124e10987519d18225fdf566f4 100644 (file)
@@ -22,12 +22,12 @@ pub struct LogDirective {
 /// Parse an individual log level that is either a number or a symbolic log level
 fn parse_log_level(level: &str) -> Option<u32> {
     level.parse::<u32>()
-         .ok()
-         .or_else(|| {
-             let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
-             pos.map(|p| p as u32 + 1)
-         })
-         .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
+        .ok()
+        .or_else(|| {
+            let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
+            pos.map(|p| p as u32 + 1)
+        })
+        .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
 }
 
 /// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
@@ -52,32 +52,31 @@ pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
                 continue;
             }
             let mut parts = s.split('=');
-            let (log_level, name) = match (parts.next(),
-                                           parts.next().map(|s| s.trim()),
-                                           parts.next()) {
-                (Some(part0), None, None) => {
-                    // if the single argument is a log-level string or number,
-                    // treat that as a global fallback
-                    match parse_log_level(part0) {
-                        Some(num) => (num, None),
-                        None => (::MAX_LOG_LEVEL, Some(part0)),
+            let (log_level, name) =
+                match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
+                    (Some(part0), None, None) => {
+                        // if the single argument is a log-level string or number,
+                        // treat that as a global fallback
+                        match parse_log_level(part0) {
+                            Some(num) => (num, None),
+                            None => (::MAX_LOG_LEVEL, Some(part0)),
+                        }
                     }
-                }
-                (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
-                (Some(part0), Some(part1), None) => {
-                    match parse_log_level(part1) {
-                        Some(num) => (num, Some(part0)),
-                        _ => {
-                            println!("warning: invalid logging spec '{}', ignoring it", part1);
-                            continue;
+                    (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
+                    (Some(part0), Some(part1), None) => {
+                        match parse_log_level(part1) {
+                            Some(num) => (num, Some(part0)),
+                            _ => {
+                                println!("warning: invalid logging spec '{}', ignoring it", part1);
+                                continue;
+                            }
                         }
                     }
-                }
-                _ => {
-                    println!("warning: invalid logging spec '{}', ignoring it", s);
-                    continue;
-                }
-            };
+                    _ => {
+                        println!("warning: invalid logging spec '{}', ignoring it", s);
+                        continue;
+                    }
+                };
             dirs.push(LogDirective {
                 name: name.map(str::to_owned),
                 level: log_level,
index de68cc707ad7a2020e3d7e6061f46968697ce394..12a1a4255246a43ad64fdd77b39d5180cac56aab 100644 (file)
@@ -1327,30 +1327,6 @@ fn main() {}
 //      |
 //    type `i32` assigned to variable `x`
 ```
-
-Another situation in which this occurs is when you attempt to use the `try!`
-macro inside a function that does not return a `Result<T, E>`:
-
-```compile_fail,E0308
-use std::fs::File;
-
-fn main() {
-    let mut f = try!(File::create("foo.txt"));
-}
-```
-
-This code gives an error like this:
-
-```text
-<std macros>:5:8: 6:42 error: mismatched types:
- expected `()`,
-     found `core::result::Result<_, _>`
- (expected (),
-     found enum `core::result::Result`) [E0308]
-```
-
-`try!` returns a `Result<T, E>`, and so the function must. But `main()` has
-`()` as its return type, hence the error.
 "##,
 
 E0309: r##"
index bca3ed93812026b062645a37c57658c85e95ed73..137c6b58dc99817cde20d652f6f747b579391398 100644 (file)
@@ -94,13 +94,7 @@ pub fn lower_crate(sess: &Session,
     let _ignore = sess.dep_graph.in_ignore();
 
     LoweringContext {
-        crate_root: if std_inject::no_core(krate) {
-            None
-        } else if std_inject::no_std(krate) {
-            Some("core")
-        } else {
-            Some("std")
-        },
+        crate_root: std_inject::injected_crate_name(krate),
         sess: sess,
         parent_def: None,
         resolver: resolver,
index c34286f0195bfb61005beb5bdc676537932ae928..25731df47785392ce6b91a28f278bf683ce2810a 100644 (file)
@@ -40,7 +40,7 @@
 #![feature(rustc_private)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![cfg_attr(test, feature(test))]
 
 extern crate arena;
index f706bab32c80a0a74d6583a463de7c8b3415537c..d002aba595bcac22f70fc8215c4eb1febd36c2e6 100644 (file)
@@ -118,6 +118,8 @@ pub struct PerfStats {
     pub incr_comp_hashes_time: Cell<Duration>,
     // The number of incr. comp. hash computations performed
     pub incr_comp_hashes_count: Cell<u64>,
+    // The number of bytes hashed when computing ICH values
+    pub incr_comp_bytes_hashed: Cell<u64>,
     // The accumulated time spent on computing symbol hashes
     pub symbol_hash_time: Cell<Duration>,
 }
@@ -439,6 +441,11 @@ pub fn print_perf_stats(&self) {
                  duration_to_secs_str(self.perf_stats.incr_comp_hashes_time.get()));
         println!("Total number of incr. comp. hashes computed:   {}",
                  self.perf_stats.incr_comp_hashes_count.get());
+        println!("Total number of bytes hashed for incr. comp.:  {}",
+                 self.perf_stats.incr_comp_bytes_hashed.get());
+        println!("Average bytes hashed per incr. comp. HIR node: {}",
+                 self.perf_stats.incr_comp_bytes_hashed.get() /
+                 self.perf_stats.incr_comp_hashes_count.get());
         println!("Total time spent computing symbol hashes:      {}",
                  duration_to_secs_str(self.perf_stats.symbol_hash_time.get()));
     }
@@ -571,6 +578,7 @@ pub fn build_session_(sopts: config::Options,
             svh_time: Cell::new(Duration::from_secs(0)),
             incr_comp_hashes_time: Cell::new(Duration::from_secs(0)),
             incr_comp_hashes_count: Cell::new(0),
+            incr_comp_bytes_hashed: Cell::new(0),
             symbol_hash_time: Cell::new(Duration::from_secs(0)),
         }
     };
index c0f358ca8017bd884c3bfa53a892ee58a2e67a95..e6d1982d31c2d3370adaac3ceafe3e2ccfc6111c 100644 (file)
@@ -37,7 +37,7 @@
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(step_by)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![cfg_attr(test, feature(test, rand))]
 
 extern crate syntax;
diff --git a/src/librustc_borrowck/bitslice.rs b/src/librustc_borrowck/bitslice.rs
deleted file mode 100644 (file)
index 80fa86a..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2012-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.
-
-// FIXME: move this to `rustc_data_structures` and potentially merge
-// with `bitvec` there.
-
-use std::mem;
-
-pub type Word = usize;
-
-/// `BitSlice` provides helper methods for treating a `[Word]`
-/// as a bitvector.
-pub trait BitSlice {
-    fn clear_bit(&mut self, idx: usize) -> bool;
-    fn set_bit(&mut self, idx: usize) -> bool;
-    fn get_bit(&self, idx: usize) -> bool;
-}
-
-impl BitSlice for [Word] {
-    /// Clears bit at `idx` to 0; returns true iff this changed `self.`
-    fn clear_bit(&mut self, idx: usize) -> bool {
-        let words = self;
-        debug!("clear_bit: words={} idx={}",
-               bits_to_string(words, words.len() * mem::size_of::<Word>()), bit_str(idx));
-        let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
-        debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
-        let oldv = words[word];
-        let newv = oldv & !bit_mask;
-        words[word] = newv;
-        oldv != newv
-    }
-
-    /// Sets bit at `idx` to 1; returns true iff this changed `self.`
-    fn set_bit(&mut self, idx: usize) -> bool {
-        let words = self;
-        debug!("set_bit: words={} idx={}",
-               bits_to_string(words, words.len() * mem::size_of::<Word>()), bit_str(idx));
-        let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
-        debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
-        let oldv = words[word];
-        let newv = oldv | bit_mask;
-        words[word] = newv;
-        oldv != newv
-    }
-
-    /// Extracts value of bit at `idx` in `self`.
-    fn get_bit(&self, idx: usize) -> bool {
-        let words = self;
-        let BitLookup { word, bit_mask, .. } = bit_lookup(idx);
-        (words[word] & bit_mask) != 0
-    }
-}
-
-struct BitLookup {
-    /// An index of the word holding the bit in original `[Word]` of query.
-    word: usize,
-    /// Index of the particular bit within the word holding the bit.
-    bit_in_word: usize,
-    /// Word with single 1-bit set corresponding to where the bit is located.
-    bit_mask: Word,
-}
-
-#[inline]
-fn bit_lookup(bit: usize) -> BitLookup {
-    let word_bits = mem::size_of::<Word>() * 8;
-    let word = bit / word_bits;
-    let bit_in_word = bit % word_bits;
-    let bit_mask = 1 << bit_in_word;
-    BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask }
-}
-
-
-fn bit_str(bit: Word) -> String {
-    let byte = bit >> 3;
-    let lobits = 1 << (bit & 0b111);
-    format!("[{}:{}-{:02x}]", bit, byte, lobits)
-}
-
-pub fn bits_to_string(words: &[Word], bits: usize) -> String {
-    let mut result = String::new();
-    let mut sep = '[';
-
-    // Note: this is a little endian printout of bytes.
-
-    // i tracks how many bits we have printed so far.
-    let mut i = 0;
-    for &word in words.iter() {
-        let mut v = word;
-        loop { // for each byte in `v`:
-            let remain = bits - i;
-            // If less than a byte remains, then mask just that many bits.
-            let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF };
-            assert!(mask <= 0xFF);
-            let byte = v & mask;
-
-            result.push(sep);
-            result.push_str(&format!("{:02x}", byte));
-
-            if remain <= 8 { break; }
-            v >>= 8;
-            i += 8;
-            sep = '-';
-        }
-    }
-    result.push(']');
-    return result
-}
-
-#[inline]
-pub fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
-                                   in_vec: &[usize],
-                                   op: &Op) -> bool {
-    assert_eq!(out_vec.len(), in_vec.len());
-    let mut changed = false;
-    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) {
-        let old_val = *out_elt;
-        let new_val = op.join(old_val, *in_elt);
-        *out_elt = new_val;
-        changed |= old_val != new_val;
-    }
-    changed
-}
-
-pub trait BitwiseOperator {
-    /// Applies some bit-operation pointwise to each of the bits in the two inputs.
-    fn join(&self, pred1: usize, pred2: usize) -> usize;
-}
-
-pub struct Union;
-impl BitwiseOperator for Union {
-    fn join(&self, a: usize, b: usize) -> usize { a | b }
-}
-pub struct Subtract;
-impl BitwiseOperator for Subtract {
-    fn join(&self, a: usize, b: usize) -> usize { a & !b }
-}
index 91be50d11f952c68fe9e1bc8a28758ad93ef2300..f6260527039d0129823fa91d1678d1cc721dfc07 100644 (file)
@@ -12,6 +12,8 @@
 
 use syntax::ast::NodeId;
 use rustc::mir::repr::{BasicBlock, Mir};
+use rustc_data_structures::bitslice::bits_to_string;
+use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
 use dot;
@@ -27,8 +29,6 @@
 
 use super::super::MoveDataParamEnv;
 use super::super::MirBorrowckCtxtPreDataflow;
-use bitslice::bits_to_string;
-use indexed_set::{IdxSet};
 use super::{BitDenotation, DataflowState};
 
 impl<O: BitDenotation> DataflowState<O> {
index 55dda8eda3a4a552e52c9dd33da78d36cdbaadf8..dce167975cf34d0fb7d8f749b77839da40d24ebb 100644 (file)
@@ -10,6 +10,9 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::repr::{self, Mir, Location};
+use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
+use rustc_data_structures::bitslice::{BitwiseOperator};
+use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
 
 use super::{BitDenotation, BlockSets, DataflowOperator};
 
-use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
-use bitslice::{BitwiseOperator};
-use indexed_set::{IdxSet};
-
 // Dataflow analyses are built upon some interpretation of the
 // bitvectors attached to each basic block, represented via a
 // zero-sized structure.
index a9b4de450967cfa0bcfebe5b82034f5105ca39df..0c510e95b67fe26b6402037d5cbdc444cd9484d5 100644 (file)
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
 
 use rustc::ty::TyCtxt;
 use rustc::mir::repr::{self, Mir};
@@ -22,9 +24,6 @@
 use super::MirBorrowckCtxtPreDataflow;
 use super::MoveDataParamEnv;
 
-use bitslice::{bitwise, BitwiseOperator};
-use indexed_set::{IdxSet, IdxSetBuf};
-
 pub use self::sanity_check::sanity_check_via_rustc_peek;
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
 pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements};
index 188fce467be52c8024be3e5f2606fb51493b7afa..25986b85f7b3a3d0cf603a9105ebb0800cd128fc 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use indexed_set::IdxSetBuf;
 use super::gather_moves::{MoveData, MovePathIndex, LookupResult};
 use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use super::dataflow::{DataflowResults};
@@ -23,6 +22,7 @@
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::lang_items;
 use rustc::util::nodemap::FnvHashMap;
+use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 
diff --git a/src/librustc_borrowck/indexed_set.rs b/src/librustc_borrowck/indexed_set.rs
deleted file mode 100644 (file)
index 671aff9..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2012-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.
-
-// FIXME: move this to `rustc_data_structures`
-
-use std::fmt;
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::{Deref, DerefMut, Range};
-use bitslice::{BitSlice, Word};
-use bitslice::{bitwise, Union, Subtract};
-
-use rustc_data_structures::indexed_vec::Idx;
-
-/// Represents a set (or packed family of sets), of some element type
-/// E, where each E is identified by some unique index type `T`.
-///
-/// In other words, `T` is the type used to index into the bitvector
-/// this type uses to represent the set of object it holds.
-pub struct IdxSetBuf<T: Idx> {
-    _pd: PhantomData<fn(&T)>,
-    bits: Vec<Word>,
-}
-
-impl<T: Idx> Clone for IdxSetBuf<T> {
-    fn clone(&self) -> Self {
-        IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() }
-    }
-}
-
-// pnkfelix wants to have this be `IdxSet<T>([Word]) and then pass
-// around `&mut IdxSet<T>` or `&IdxSet<T>`.
-//
-// WARNING: Mapping a `&IdxSetBuf<T>` to `&IdxSet<T>` (at least today)
-// requires a transmute relying on representation guarantees that may
-// not hold in the future.
-
-/// Represents a set (or packed family of sets), of some element type
-/// E, where each E is identified by some unique index type `T`.
-///
-/// In other words, `T` is the type used to index into the bitslice
-/// this type uses to represent the set of object it holds.
-pub struct IdxSet<T: Idx> {
-    _pd: PhantomData<fn(&T)>,
-    bits: [Word],
-}
-
-impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
-}
-
-impl<T: Idx> fmt::Debug for IdxSet<T> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
-}
-
-impl<T: Idx> IdxSetBuf<T> {
-    fn new(init: Word, universe_size: usize) -> Self {
-        let bits_per_word = mem::size_of::<Word>() * 8;
-        let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word;
-        IdxSetBuf {
-            _pd: Default::default(),
-            bits: vec![init; num_words],
-        }
-    }
-
-    /// Creates set holding every element whose index falls in range 0..universe_size.
-    pub fn new_filled(universe_size: usize) -> Self {
-        Self::new(!0, universe_size)
-    }
-
-    /// Creates set holding no elements.
-    pub fn new_empty(universe_size: usize) -> Self {
-        Self::new(0, universe_size)
-    }
-}
-
-impl<T: Idx> IdxSet<T> {
-    unsafe fn from_slice(s: &[Word]) -> &Self {
-        mem::transmute(s) // (see above WARNING)
-    }
-
-    unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self {
-        mem::transmute(s) // (see above WARNING)
-    }
-}
-
-impl<T: Idx> Deref for IdxSetBuf<T> {
-    type Target = IdxSet<T>;
-    fn deref(&self) -> &IdxSet<T> {
-        unsafe { IdxSet::from_slice(&self.bits[..]) }
-    }
-}
-
-impl<T: Idx> DerefMut for IdxSetBuf<T> {
-    fn deref_mut(&mut self) -> &mut IdxSet<T> {
-        unsafe { IdxSet::from_slice_mut(&mut self.bits[..]) }
-    }
-}
-
-impl<T: Idx> IdxSet<T> {
-    pub fn to_owned(&self) -> IdxSetBuf<T> {
-        IdxSetBuf {
-            _pd: Default::default(),
-            bits: self.bits.to_owned(),
-        }
-    }
-
-    /// Removes `elem` from the set `self`; returns true iff this changed `self`.
-    pub fn remove(&mut self, elem: &T) -> bool {
-        self.bits.clear_bit(elem.index())
-    }
-
-    /// Adds `elem` to the set `self`; returns true iff this changed `self`.
-    pub fn add(&mut self, elem: &T) -> bool {
-        self.bits.set_bit(elem.index())
-    }
-
-    pub fn range(&self, elems: &Range<T>) -> &Self {
-        let elems = elems.start.index()..elems.end.index();
-        unsafe { Self::from_slice(&self.bits[elems]) }
-    }
-
-    pub fn range_mut(&mut self, elems: &Range<T>) -> &mut Self {
-        let elems = elems.start.index()..elems.end.index();
-        unsafe { Self::from_slice_mut(&mut self.bits[elems]) }
-    }
-
-    /// Returns true iff set `self` contains `elem`.
-    pub fn contains(&self, elem: &T) -> bool {
-        self.bits.get_bit(elem.index())
-    }
-
-    pub fn words(&self) -> &[Word] {
-        &self.bits[..]
-    }
-
-    pub fn words_mut(&mut self) -> &mut [Word] {
-        &mut self.bits[..]
-    }
-
-    pub fn clone_from(&mut self, other: &IdxSet<T>) {
-        self.words_mut().clone_from_slice(other.words());
-    }
-
-    pub fn union(&mut self, other: &IdxSet<T>) -> bool {
-        bitwise(self.words_mut(), other.words(), &Union)
-    }
-
-    pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
-        bitwise(self.words_mut(), other.words(), &Subtract)
-    }
-}
index 22b590592fe168d3277d3f7a4e31b28b4706debc..da899714e935138704b63ca6321a3f42e7e98daa 100644 (file)
@@ -26,7 +26,7 @@
 #![feature(staged_api)]
 #![feature(associated_consts)]
 #![feature(nonzero)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
@@ -50,8 +50,6 @@
 pub mod diagnostics;
 
 mod borrowck;
-mod bitslice;
-mod indexed_set;
 
 pub mod graphviz;
 
index d876b4b6fec2eb1054ddd493ecafbaae614afc07..81dd642de5d275c33df5f3a578cc7512e47dc12a 100644 (file)
@@ -732,6 +732,10 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
               hir::BiBitOr => a | b,
               hir::BiEq => a == b,
               hir::BiNe => a != b,
+              hir::BiLt => a < b,
+              hir::BiLe => a <= b,
+              hir::BiGe => a >= b,
+              hir::BiGt => a > b,
               _ => signal!(e, InvalidOpForBools(op.node)),
              })
           }
index f926fef065ea6c228fed4cc17a473a5ac0e7930f..7b40269ba56ad271ac459e55c88c1d111fbdd762 100644 (file)
@@ -27,7 +27,7 @@
 #![feature(staged_api)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 
index 741dd4107e001e0886d8484fb744e01445357ad9..31fccb41ce573840ec8bcbbed5c5534e0ca07504 100644 (file)
@@ -25,7 +25,7 @@
 
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs
new file mode 100644 (file)
index 0000000..ba53578
--- /dev/null
@@ -0,0 +1,142 @@
+// Copyright 2012-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.
+
+// FIXME: merge with `bitvec`
+
+use std::mem;
+
+pub type Word = usize;
+
+/// `BitSlice` provides helper methods for treating a `[Word]`
+/// as a bitvector.
+pub trait BitSlice {
+    fn clear_bit(&mut self, idx: usize) -> bool;
+    fn set_bit(&mut self, idx: usize) -> bool;
+    fn get_bit(&self, idx: usize) -> bool;
+}
+
+impl BitSlice for [Word] {
+    /// Clears bit at `idx` to 0; returns true iff this changed `self.`
+    fn clear_bit(&mut self, idx: usize) -> bool {
+        let words = self;
+        debug!("clear_bit: words={} idx={}",
+               bits_to_string(words, words.len() * mem::size_of::<Word>()), bit_str(idx));
+        let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
+        debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
+        let oldv = words[word];
+        let newv = oldv & !bit_mask;
+        words[word] = newv;
+        oldv != newv
+    }
+
+    /// Sets bit at `idx` to 1; returns true iff this changed `self.`
+    fn set_bit(&mut self, idx: usize) -> bool {
+        let words = self;
+        debug!("set_bit: words={} idx={}",
+               bits_to_string(words, words.len() * mem::size_of::<Word>()), bit_str(idx));
+        let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
+        debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
+        let oldv = words[word];
+        let newv = oldv | bit_mask;
+        words[word] = newv;
+        oldv != newv
+    }
+
+    /// Extracts value of bit at `idx` in `self`.
+    fn get_bit(&self, idx: usize) -> bool {
+        let words = self;
+        let BitLookup { word, bit_mask, .. } = bit_lookup(idx);
+        (words[word] & bit_mask) != 0
+    }
+}
+
+struct BitLookup {
+    /// An index of the word holding the bit in original `[Word]` of query.
+    word: usize,
+    /// Index of the particular bit within the word holding the bit.
+    bit_in_word: usize,
+    /// Word with single 1-bit set corresponding to where the bit is located.
+    bit_mask: Word,
+}
+
+#[inline]
+fn bit_lookup(bit: usize) -> BitLookup {
+    let word_bits = mem::size_of::<Word>() * 8;
+    let word = bit / word_bits;
+    let bit_in_word = bit % word_bits;
+    let bit_mask = 1 << bit_in_word;
+    BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask }
+}
+
+
+fn bit_str(bit: Word) -> String {
+    let byte = bit >> 3;
+    let lobits = 1 << (bit & 0b111);
+    format!("[{}:{}-{:02x}]", bit, byte, lobits)
+}
+
+pub fn bits_to_string(words: &[Word], bits: usize) -> String {
+    let mut result = String::new();
+    let mut sep = '[';
+
+    // Note: this is a little endian printout of bytes.
+
+    // i tracks how many bits we have printed so far.
+    let mut i = 0;
+    for &word in words.iter() {
+        let mut v = word;
+        loop { // for each byte in `v`:
+            let remain = bits - i;
+            // If less than a byte remains, then mask just that many bits.
+            let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF };
+            assert!(mask <= 0xFF);
+            let byte = v & mask;
+
+            result.push(sep);
+            result.push_str(&format!("{:02x}", byte));
+
+            if remain <= 8 { break; }
+            v >>= 8;
+            i += 8;
+            sep = '-';
+        }
+    }
+    result.push(']');
+    return result
+}
+
+#[inline]
+pub fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
+                                   in_vec: &[usize],
+                                   op: &Op) -> bool {
+    assert_eq!(out_vec.len(), in_vec.len());
+    let mut changed = false;
+    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) {
+        let old_val = *out_elt;
+        let new_val = op.join(old_val, *in_elt);
+        *out_elt = new_val;
+        changed |= old_val != new_val;
+    }
+    changed
+}
+
+pub trait BitwiseOperator {
+    /// Applies some bit-operation pointwise to each of the bits in the two inputs.
+    fn join(&self, pred1: usize, pred2: usize) -> usize;
+}
+
+pub struct Union;
+impl BitwiseOperator for Union {
+    fn join(&self, a: usize, b: usize) -> usize { a | b }
+}
+pub struct Subtract;
+impl BitwiseOperator for Subtract {
+    fn join(&self, a: usize, b: usize) -> usize { a & !b }
+}
diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs
new file mode 100644 (file)
index 0000000..2e9e054
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright 2012-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.
+
+use std::fmt;
+use std::marker::PhantomData;
+use std::mem;
+use std::ops::{Deref, DerefMut, Range};
+use bitslice::{BitSlice, Word};
+use bitslice::{bitwise, Union, Subtract};
+use indexed_vec::Idx;
+
+/// Represents a set (or packed family of sets), of some element type
+/// E, where each E is identified by some unique index type `T`.
+///
+/// In other words, `T` is the type used to index into the bitvector
+/// this type uses to represent the set of object it holds.
+pub struct IdxSetBuf<T: Idx> {
+    _pd: PhantomData<fn(&T)>,
+    bits: Vec<Word>,
+}
+
+impl<T: Idx> Clone for IdxSetBuf<T> {
+    fn clone(&self) -> Self {
+        IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() }
+    }
+}
+
+// pnkfelix wants to have this be `IdxSet<T>([Word]) and then pass
+// around `&mut IdxSet<T>` or `&IdxSet<T>`.
+//
+// WARNING: Mapping a `&IdxSetBuf<T>` to `&IdxSet<T>` (at least today)
+// requires a transmute relying on representation guarantees that may
+// not hold in the future.
+
+/// Represents a set (or packed family of sets), of some element type
+/// E, where each E is identified by some unique index type `T`.
+///
+/// In other words, `T` is the type used to index into the bitslice
+/// this type uses to represent the set of object it holds.
+pub struct IdxSet<T: Idx> {
+    _pd: PhantomData<fn(&T)>,
+    bits: [Word],
+}
+
+impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
+}
+
+impl<T: Idx> fmt::Debug for IdxSet<T> {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
+}
+
+impl<T: Idx> IdxSetBuf<T> {
+    fn new(init: Word, universe_size: usize) -> Self {
+        let bits_per_word = mem::size_of::<Word>() * 8;
+        let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word;
+        IdxSetBuf {
+            _pd: Default::default(),
+            bits: vec![init; num_words],
+        }
+    }
+
+    /// Creates set holding every element whose index falls in range 0..universe_size.
+    pub fn new_filled(universe_size: usize) -> Self {
+        Self::new(!0, universe_size)
+    }
+
+    /// Creates set holding no elements.
+    pub fn new_empty(universe_size: usize) -> Self {
+        Self::new(0, universe_size)
+    }
+}
+
+impl<T: Idx> IdxSet<T> {
+    unsafe fn from_slice(s: &[Word]) -> &Self {
+        mem::transmute(s) // (see above WARNING)
+    }
+
+    unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self {
+        mem::transmute(s) // (see above WARNING)
+    }
+}
+
+impl<T: Idx> Deref for IdxSetBuf<T> {
+    type Target = IdxSet<T>;
+    fn deref(&self) -> &IdxSet<T> {
+        unsafe { IdxSet::from_slice(&self.bits[..]) }
+    }
+}
+
+impl<T: Idx> DerefMut for IdxSetBuf<T> {
+    fn deref_mut(&mut self) -> &mut IdxSet<T> {
+        unsafe { IdxSet::from_slice_mut(&mut self.bits[..]) }
+    }
+}
+
+impl<T: Idx> IdxSet<T> {
+    pub fn to_owned(&self) -> IdxSetBuf<T> {
+        IdxSetBuf {
+            _pd: Default::default(),
+            bits: self.bits.to_owned(),
+        }
+    }
+
+    /// Removes `elem` from the set `self`; returns true iff this changed `self`.
+    pub fn remove(&mut self, elem: &T) -> bool {
+        self.bits.clear_bit(elem.index())
+    }
+
+    /// Adds `elem` to the set `self`; returns true iff this changed `self`.
+    pub fn add(&mut self, elem: &T) -> bool {
+        self.bits.set_bit(elem.index())
+    }
+
+    pub fn range(&self, elems: &Range<T>) -> &Self {
+        let elems = elems.start.index()..elems.end.index();
+        unsafe { Self::from_slice(&self.bits[elems]) }
+    }
+
+    pub fn range_mut(&mut self, elems: &Range<T>) -> &mut Self {
+        let elems = elems.start.index()..elems.end.index();
+        unsafe { Self::from_slice_mut(&mut self.bits[elems]) }
+    }
+
+    /// Returns true iff set `self` contains `elem`.
+    pub fn contains(&self, elem: &T) -> bool {
+        self.bits.get_bit(elem.index())
+    }
+
+    pub fn words(&self) -> &[Word] {
+        &self.bits[..]
+    }
+
+    pub fn words_mut(&mut self) -> &mut [Word] {
+        &mut self.bits[..]
+    }
+
+    pub fn clone_from(&mut self, other: &IdxSet<T>) {
+        self.words_mut().clone_from_slice(other.words());
+    }
+
+    pub fn union(&mut self, other: &IdxSet<T>) -> bool {
+        bitwise(self.words_mut(), other.words(), &Union)
+    }
+
+    pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
+        bitwise(self.words_mut(), other.words(), &Subtract)
+    }
+}
index e7da18cef10f967eb83b78a74d187241c23b7d64..c8f4d766153cf9788b26ff8d00963b5a7abc5340 100644 (file)
 #[cfg(unix)]
 extern crate libc;
 
+pub mod bitslice;
 pub mod bitvec;
 pub mod graph;
 pub mod ivar;
+pub mod indexed_set;
 pub mod indexed_vec;
 pub mod obligation_forest;
 pub mod snapshot_map;
index ea42f7ba93e447486cd99f41071ec8b155430f46..e8ab2f3a2405b541553dfa908585ca297c4b998f 100644 (file)
@@ -649,7 +649,7 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
     let resolver_arenas = Resolver::arenas();
     let mut resolver =
         Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas);
-    syntax_ext::register_builtins(&mut resolver, sess.features.borrow().quote);
+    syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote);
 
     krate = time(time_passes, "expansion", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
@@ -686,11 +686,17 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
             ..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string())
         };
         let mut ecx = ExtCtxt::new(&sess.parse_sess, krate.config.clone(), cfg, &mut resolver);
-        let ret = syntax::ext::expand::expand_crate(&mut ecx, syntax_exts, krate);
+        let err_count = ecx.parse_sess.span_diagnostic.err_count();
+
+        let krate = ecx.monotonic_expander().expand_crate(krate);
+
+        if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
+            ecx.parse_sess.span_diagnostic.abort_if_errors();
+        }
         if cfg!(windows) {
             env::set_var("PATH", &old_path);
         }
-        ret
+        krate
     });
 
     krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new());
index 492165e2f2a8e081290d8af025ea390352c5b330..f051c8692491f0d4b51923033e4aa300432a2785 100644 (file)
@@ -31,7 +31,7 @@
 #![feature(rustc_private)]
 #![feature(set_stdio)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 extern crate arena;
 extern crate flate;
@@ -1110,7 +1110,7 @@ fn flush(&mut self) -> io::Result<()> {
                              errors::Level::Note);
             }
 
-            println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap());
+            writeln!(io::stderr(), "{}", str::from_utf8(&data.lock().unwrap()).unwrap()).unwrap();
         }
 
         exit_on_err();
index bc599a8207656aadff7a97317ce884f9c7bbd3bb..af8ac81b4fbb1d916f979e7fdee76bf4bdb68c2f 100644 (file)
@@ -21,7 +21,7 @@
 #![allow(unused_attributes)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(range_contains)]
 #![feature(libc)]
 #![feature(unicode)]
diff --git a/src/librustc_incremental/calculate_svh/hasher.rs b/src/librustc_incremental/calculate_svh/hasher.rs
new file mode 100644 (file)
index 0000000..28db39d
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+use std::hash::Hasher;
+use std::collections::hash_map::DefaultHasher;
+
+#[derive(Debug)]
+pub struct IchHasher {
+    // FIXME: this should use SHA1, not DefaultHasher. DefaultHasher is not
+    // built to avoid collisions.
+    state: DefaultHasher,
+    bytes_hashed: u64,
+}
+
+impl IchHasher {
+    pub fn new() -> IchHasher {
+        IchHasher {
+            state: DefaultHasher::new(),
+            bytes_hashed: 0
+        }
+    }
+
+    pub fn bytes_hashed(&self) -> u64 {
+        self.bytes_hashed
+    }
+}
+
+impl Hasher for IchHasher {
+    #[inline]
+    fn finish(&self) -> u64 {
+        self.state.finish()
+    }
+
+    #[inline]
+    fn write(&mut self, bytes: &[u8]) {
+        self.state.write(bytes);
+        self.bytes_hashed += bytes.len() as u64;
+    }
+}
index a22b51ac0446167b980a832a429073e2b877ac06..12627e02debd0d723427d028e1cad35a042a8603 100644 (file)
@@ -30,7 +30,6 @@
 use syntax::ast;
 use std::cell::RefCell;
 use std::hash::{Hash, Hasher};
-use std::collections::hash_map::DefaultHasher;
 use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use self::def_path_hash::DefPathHashes;
 use self::svh_visitor::StrictVersionHashVisitor;
 use self::caching_codemap_view::CachingCodemapView;
+use self::hasher::IchHasher;
 
 mod def_path_hash;
 mod svh_visitor;
 mod caching_codemap_view;
+mod hasher;
 
 pub struct IncrementalHashesMap {
     hashes: FnvHashMap<DepNode<DefId>, u64>,
@@ -74,6 +75,10 @@ pub fn insert(&mut self, k: DepNode<DefId>, v: u64) -> Option<u64> {
     pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, DepNode<DefId>, u64> {
         self.hashes.iter()
     }
+
+    pub fn len(&self) -> usize {
+        self.hashes.len()
+    }
 }
 
 impl<'a> ::std::ops::Index<&'a DepNode<DefId>> for IncrementalHashesMap {
@@ -102,6 +107,9 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                  |v| visit::walk_crate(v, krate));
         krate.visit_all_items(&mut visitor);
     });
+
+    tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
+
     record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash());
     visitor.hashes
 }
@@ -127,9 +135,7 @@ fn calculate_def_id<W>(&mut self, def_id: DefId, mut walk_op: W)
     {
         assert!(def_id.is_local());
         debug!("HashItemsVisitor::calculate(def_id={:?})", def_id);
-        // FIXME: this should use SHA1, not DefaultHasher. DefaultHasher is not
-        // built to avoid collisions.
-        let mut state = DefaultHasher::new();
+        let mut state = IchHasher::new();
         walk_op(&mut StrictVersionHashVisitor::new(&mut state,
                                                    self.tcx,
                                                    &mut self.def_path_hashes,
@@ -138,12 +144,16 @@ fn calculate_def_id<W>(&mut self, def_id: DefId, mut walk_op: W)
         let item_hash = state.finish();
         self.hashes.insert(DepNode::Hir(def_id), item_hash);
         debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash);
+
+        let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
+                           state.bytes_hashed();
+        self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
     }
 
     fn compute_crate_hash(&mut self) {
         let krate = self.tcx.map.krate();
 
-        let mut crate_state = DefaultHasher::new();
+        let mut crate_state = IchHasher::new();
 
         let crate_disambiguator = self.tcx.sess.local_crate_disambiguator();
         "crate_disambiguator".hash(&mut crate_state);
index 3df68ac583d46c8792c42d1a32a0ecdf6dae85a4..584e5598b9f9ffec78ecb6e9f9f4233dcc14c119 100644 (file)
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv;
 use std::hash::Hash;
-use std::collections::hash_map::DefaultHasher;
 
 use super::def_path_hash::DefPathHashes;
 use super::caching_codemap_view::CachingCodemapView;
+use super::hasher::IchHasher;
 
 const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
     "cfg",
@@ -48,7 +48,7 @@
 
 pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
     pub tcx: TyCtxt<'hash, 'tcx, 'tcx>,
-    pub st: &'a mut DefaultHasher,
+    pub st: &'a mut IchHasher,
     // collect a deterministic hash of def-ids that we have seen
     def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
     hash_spans: bool,
@@ -56,7 +56,7 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
 }
 
 impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
-    pub fn new(st: &'a mut DefaultHasher,
+    pub fn new(st: &'a mut IchHasher,
                tcx: TyCtxt<'hash, 'tcx, 'tcx>,
                def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
                codemap: &'a mut CachingCodemapView<'tcx>,
index 2c1340e566dda587f3022e019e581b6081ac3e40..67104e912f90ecc9a0a7ecfa9739b5eb1c584976 100644 (file)
@@ -20,7 +20,7 @@
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(dotdot_in_tuple_patterns)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(rand)]
index 84d65308f952ffbbdd613ec43cff0bbeb5158b5a..acb92bec7c7971bd7ab305148ad6329c428156fe 100644 (file)
 pub enum MethodLateContext {
     TraitDefaultImpl,
     TraitImpl,
-    PlainImpl
+    PlainImpl,
 }
 
 pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext {
     let def_id = cx.tcx.map.local_def_id(id);
     match cx.tcx.impl_or_trait_items.borrow().get(&def_id) {
         None => span_bug!(span, "missing method descriptor?!"),
-        Some(item) => match item.container() {
-            ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
-            ty::ImplContainer(cid) => {
-                match cx.tcx.impl_trait_ref(cid) {
-                    Some(_) => MethodLateContext::TraitImpl,
-                    None => MethodLateContext::PlainImpl
+        Some(item) => {
+            match item.container() {
+                ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
+                ty::ImplContainer(cid) => {
+                    match cx.tcx.impl_trait_ref(cid) {
+                        Some(_) => MethodLateContext::TraitImpl,
+                        None => MethodLateContext::PlainImpl,
+                    }
                 }
             }
         }
@@ -63,19 +65,20 @@ fn is_camel_case(name: ast::Name) -> bool {
 
             // start with a non-lowercase letter rather than non-uppercase
             // ones (some scripts don't have a concept of upper/lowercase)
-            !name.is_empty() &&
-                !name.chars().next().unwrap().is_lowercase() &&
-                !name.contains('_')
+            !name.is_empty() && !name.chars().next().unwrap().is_lowercase() && !name.contains('_')
         }
 
         fn to_camel_case(s: &str) -> String {
-            s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
-                if i == 0 {
-                    c.to_uppercase().collect::<String>()
-                } else {
-                    c.to_lowercase().collect()
-                }
-            )).collect::<Vec<_>>().concat()
+            s.split('_')
+                .flat_map(|word| {
+                    word.chars().enumerate().map(|(i, c)| if i == 0 {
+                        c.to_uppercase().collect::<String>()
+                    } else {
+                        c.to_lowercase().collect()
+                    })
+                })
+                .collect::<Vec<_>>()
+                .concat()
         }
 
         let s = name.as_str();
@@ -83,9 +86,14 @@ fn to_camel_case(s: &str) -> String {
         if !is_camel_case(name) {
             let c = to_camel_case(&s);
             let m = if c.is_empty() {
-                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
+                format!("{} `{}` should have a camel case name such as `CamelCase`",
+                        sort,
+                        s)
             } else {
-                format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
+                format!("{} `{}` should have a camel case name such as `{}`",
+                        sort,
+                        s,
+                        c)
             };
             cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
         }
@@ -100,10 +108,14 @@ fn get_lints(&self) -> LintArray {
 
 impl LateLintPass for NonCamelCaseTypes {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        let extern_repr_count = it.attrs.iter().filter(|attr| {
-            attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
-                .any(|r| r == &attr::ReprExtern)
-        }).count();
+        let extern_repr_count = it.attrs
+            .iter()
+            .filter(|attr| {
+                attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr)
+                    .iter()
+                    .any(|r| r == &attr::ReprExtern)
+            })
+            .count();
         let has_extern_repr = extern_repr_count > 0;
 
         if has_extern_repr {
@@ -111,12 +123,10 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         }
 
         match it.node {
-            hir::ItemTy(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => {
-                self.check_case(cx, "type", it.name, it.span)
-            }
-            hir::ItemTrait(..) => {
-                self.check_case(cx, "trait", it.name, it.span)
-            }
+            hir::ItemTy(..) |
+            hir::ItemStruct(..) |
+            hir::ItemUnion(..) => self.check_case(cx, "type", it.name, it.span),
+            hir::ItemTrait(..) => self.check_case(cx, "trait", it.name, it.span),
             hir::ItemEnum(ref enum_definition, _) => {
                 if has_extern_repr {
                     return;
@@ -126,7 +136,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     self.check_case(cx, "variant", variant.node.name, variant.span);
                 }
             }
-            _ => ()
+            _ => (),
         }
     }
 
@@ -165,9 +175,7 @@ fn to_snake_case(mut str: &str) -> String {
                 continue;
             }
             for ch in s.chars() {
-                if !buf.is_empty() && buf != "'"
-                                   && ch.is_uppercase()
-                                   && !last_upper {
+                if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
                     words.push(buf);
                     buf = String::new();
                 }
@@ -205,10 +213,11 @@ fn is_snake_case(ident: &str) -> bool {
             let sc = NonSnakeCase::to_snake_case(name);
             let msg = if sc != name {
                 format!("{} `{}` should have a snake case name such as `{}`",
-                        sort, name, sc)
+                        sort,
+                        name,
+                        sc)
             } else {
-                format!("{} `{}` should have a snake case name",
-                        sort, name)
+                format!("{} `{}` should have a snake case name", sort, name)
             };
             match span {
                 Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
@@ -226,8 +235,10 @@ fn get_lints(&self) -> LintArray {
 
 impl LateLintPass for NonSnakeCase {
     fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
-        let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name"))
-                                      .and_then(|at| at.value_str().map(|s| (at, s)));
+        let attr_crate_name = cr.attrs
+            .iter()
+            .find(|at| at.check_name("crate_name"))
+            .and_then(|at| at.value_str().map(|s| (at, s)));
         if let Some(ref name) = cx.tcx.sess.opts.crate_name {
             self.check_snake_case(cx, "crate", name, None);
         } else if let Some((attr, ref name)) = attr_crate_name {
@@ -235,22 +246,28 @@ fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
         }
     }
 
-    fn check_fn(&mut self, cx: &LateContext,
-                fk: FnKind, _: &hir::FnDecl,
-                _: &hir::Block, span: Span, id: ast::NodeId) {
+    fn check_fn(&mut self,
+                cx: &LateContext,
+                fk: FnKind,
+                _: &hir::FnDecl,
+                _: &hir::Block,
+                span: Span,
+                id: ast::NodeId) {
         match fk {
-            FnKind::Method(name, ..) => match method_context(cx, id, span) {
-                MethodLateContext::PlainImpl => {
-                    self.check_snake_case(cx, "method", &name.as_str(), Some(span))
-                },
-                MethodLateContext::TraitDefaultImpl => {
-                    self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
-                },
-                _ => (),
-            },
+            FnKind::Method(name, ..) => {
+                match method_context(cx, id, span) {
+                    MethodLateContext::PlainImpl => {
+                        self.check_snake_case(cx, "method", &name.as_str(), Some(span))
+                    }
+                    MethodLateContext::TraitDefaultImpl => {
+                        self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
+                    }
+                    _ => (),
+                }
+            }
             FnKind::ItemFn(name, ..) => {
                 self.check_snake_case(cx, "function", &name.as_str(), Some(span))
-            },
+            }
             FnKind::Closure(_) => (),
         }
     }
@@ -263,13 +280,17 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 
     fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
         if let hir::MethodTraitItem(_, None) = trait_item.node {
-            self.check_snake_case(cx, "trait method", &trait_item.name.as_str(),
+            self.check_snake_case(cx,
+                                  "trait method",
+                                  &trait_item.name.as_str(),
                                   Some(trait_item.span));
         }
     }
 
     fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
-        self.check_snake_case(cx, "lifetime", &t.lifetime.name.as_str(),
+        self.check_snake_case(cx,
+                              "lifetime",
+                              &t.lifetime.name.as_str(),
                               Some(t.lifetime.span));
     }
 
@@ -282,8 +303,12 @@ fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         }
     }
 
-    fn check_struct_def(&mut self, cx: &LateContext, s: &hir::VariantData,
-                        _: ast::Name, _: &hir::Generics, _: ast::NodeId) {
+    fn check_struct_def(&mut self,
+                        cx: &LateContext,
+                        s: &hir::VariantData,
+                        _: ast::Name,
+                        _: &hir::Generics,
+                        _: ast::NodeId) {
         for sf in s.fields() {
             self.check_snake_case(cx, "structure field", &sf.name.as_str(), Some(sf.span));
         }
@@ -306,13 +331,16 @@ fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
         if s.chars().any(|c| c.is_lowercase()) {
             let uc = NonSnakeCase::to_snake_case(&s).to_uppercase();
             if uc != &s[..] {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
-                    &format!("{} `{}` should have an upper case name such as `{}`",
-                             sort, s, uc));
+                cx.span_lint(NON_UPPER_CASE_GLOBALS,
+                             span,
+                             &format!("{} `{}` should have an upper case name such as `{}`",
+                                      sort,
+                                      s,
+                                      uc));
             } else {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
-                    &format!("{} `{}` should have an upper case name",
-                             sort, s));
+                cx.span_lint(NON_UPPER_CASE_GLOBALS,
+                             span,
+                             &format!("{} `{}` should have an upper case name", sort, s));
             }
         }
     }
@@ -341,8 +369,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
     fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
         match ti.node {
             hir::ConstTraitItem(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ti.name, ti.span);
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ti.name, ti.span);
             }
             _ => {}
         }
@@ -351,8 +378,7 @@ fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
     fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Const(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ii.name, ii.span);
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ii.name, ii.span);
             }
             _ => {}
         }
@@ -363,8 +389,10 @@ fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         if let PatKind::Path(None, ref path) = p.node {
             if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
                 if let Def::Const(..) = cx.tcx.expect_def(p.id) {
-                    NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
-                                                          path.segments[0].name, path.span);
+                    NonUpperCaseGlobals::check_upper_case(cx,
+                                                          "constant in pattern",
+                                                          path.segments[0].name,
+                                                          path.span);
                 }
             }
         }
index b610a924a339666e264c515538af7a7a32ffc0f8..3428ec8d4c9602ffc2ac2a41a16778499da31832 100644 (file)
 use rustc::ty::adjustment;
 use rustc::traits::{self, Reveal};
 use rustc::hir::map as hir_map;
-use util::nodemap::{NodeSet};
+use util::nodemap::NodeSet;
 use lint::{Level, LateContext, LintContext, LintArray, Lint};
 use lint::{LintPass, LateLintPass};
 
 use std::collections::HashSet;
 
-use syntax::{ast};
+use syntax::ast;
 use syntax::attr;
-use syntax_pos::{Span};
+use syntax_pos::Span;
 
 use rustc::hir::{self, PatKind};
 use rustc::hir::intravisit::FnKind;
@@ -75,7 +75,8 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
         if let hir::ExprWhile(ref cond, ..) = e.node {
             if let hir::ExprLit(ref lit) = cond.node {
                 if let ast::LitKind::Bool(true) = lit.node {
-                    cx.span_lint(WHILE_TRUE, e.span,
+                    cx.span_lint(WHILE_TRUE,
+                                 e.span,
                                  "denote infinite loops with loop { ... }");
                 }
             }
@@ -93,8 +94,7 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
 pub struct BoxPointers;
 
 impl BoxPointers {
-    fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>,
-                                 span: Span, ty: Ty<'tcx>) {
+    fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) {
         for leaf_ty in ty.walk() {
             if let ty::TyBox(_) = leaf_ty.sty {
                 let m = format!("type uses owned (Box type) pointers: {}", ty);
@@ -117,10 +117,8 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             hir::ItemTy(..) |
             hir::ItemEnum(..) |
             hir::ItemStruct(..) |
-            hir::ItemUnion(..) =>
-                self.check_heap_type(cx, it.span,
-                                     cx.tcx.node_id_to_type(it.id)),
-            _ => ()
+            hir::ItemUnion(..) => self.check_heap_type(cx, it.span, cx.tcx.node_id_to_type(it.id)),
+            _ => (),
         }
 
         // If it's a struct, we also have to check the fields' types
@@ -128,11 +126,12 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             hir::ItemStruct(ref struct_def, _) |
             hir::ItemUnion(ref struct_def, _) => {
                 for struct_field in struct_def.fields() {
-                    self.check_heap_type(cx, struct_field.span,
+                    self.check_heap_type(cx,
+                                         struct_field.span,
                                          cx.tcx.node_id_to_type(struct_field.id));
                 }
             }
-            _ => ()
+            _ => (),
         }
     }
 
@@ -166,9 +165,11 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                 }
                 if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node {
                     if ident.node == fieldpat.node.name {
-                        cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
+                        cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS,
+                                     fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant and can \
-                                              be removed", ident.node))
+                                              be removed",
+                                              ident.node))
                     }
                 }
             }
@@ -203,27 +204,35 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
 
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
-            hir::ItemTrait(hir::Unsafety::Unsafe, ..) =>
-                cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"),
+            hir::ItemTrait(hir::Unsafety::Unsafe, ..) => {
+                cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait")
+            }
 
-            hir::ItemImpl(hir::Unsafety::Unsafe, ..) =>
-                cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"),
+            hir::ItemImpl(hir::Unsafety::Unsafe, ..) => {
+                cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait")
+            }
 
             _ => return,
         }
     }
 
-    fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl,
-                _: &hir::Block, span: Span, _: ast::NodeId) {
+    fn check_fn(&mut self,
+                cx: &LateContext,
+                fk: FnKind,
+                _: &hir::FnDecl,
+                _: &hir::Block,
+                span: Span,
+                _: ast::NodeId) {
         match fk {
-            FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, ..) =>
-                cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
+            FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, ..) => {
+                cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function")
+            }
 
             FnKind::Method(_, sig, ..) => {
                 if sig.unsafety == hir::Unsafety::Unsafe {
                     cx.span_lint(UNSAFE_CODE, span, "implementation of an `unsafe` method")
                 }
-            },
+            }
 
             _ => (),
         }
@@ -232,7 +241,8 @@ fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl,
     fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
         if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
             if sig.unsafety == hir::Unsafety::Unsafe {
-                cx.span_lint(UNSAFE_CODE, trait_item.span,
+                cx.span_lint(UNSAFE_CODE,
+                             trait_item.span,
                              "declaration of an `unsafe` method")
             }
         }
@@ -263,9 +273,9 @@ pub struct MissingDoc {
 impl MissingDoc {
     pub fn new() -> MissingDoc {
         MissingDoc {
-            struct_def_stack: vec!(),
+            struct_def_stack: vec![],
             in_variant: false,
-            doc_hidden_stack: vec!(false),
+            doc_hidden_stack: vec![false],
             private_traits: HashSet::new(),
         }
     }
@@ -275,11 +285,11 @@ fn doc_hidden(&self) -> bool {
     }
 
     fn check_missing_docs_attrs(&self,
-                               cx: &LateContext,
-                               id: Option<ast::NodeId>,
-                               attrs: &[ast::Attribute],
-                               sp: Span,
-                               desc: &'static str) {
+                                cx: &LateContext,
+                                id: Option<ast::NodeId>,
+                                attrs: &[ast::Attribute],
+                                sp: Span,
+                                desc: &'static str) {
         // If we're building a test harness, then warning about
         // documentation is probably not really relevant right now.
         if cx.sess().opts.test {
@@ -302,7 +312,8 @@ fn check_missing_docs_attrs(&self,
 
         let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
         if !has_doc {
-            cx.span_lint(MISSING_DOCS, sp,
+            cx.span_lint(MISSING_DOCS,
+                         sp,
                          &format!("missing documentation for {}", desc));
         }
     }
@@ -316,8 +327,10 @@ fn get_lints(&self) -> LintArray {
 
 impl LateLintPass for MissingDoc {
     fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
-        let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
-            attr.check_name("doc") && match attr.meta_item_list() {
+        let doc_hidden = self.doc_hidden() ||
+                         attrs.iter().any(|attr| {
+            attr.check_name("doc") &&
+            match attr.meta_item_list() {
                 None => false,
                 Some(l) => attr::list_contains_name(&l[..], "hidden"),
             }
@@ -329,13 +342,21 @@ fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) {
         self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
     }
 
-    fn check_struct_def(&mut self, _: &LateContext, _: &hir::VariantData,
-                        _: ast::Name, _: &hir::Generics, item_id: ast::NodeId) {
+    fn check_struct_def(&mut self,
+                        _: &LateContext,
+                        _: &hir::VariantData,
+                        _: ast::Name,
+                        _: &hir::Generics,
+                        item_id: ast::NodeId) {
         self.struct_def_stack.push(item_id);
     }
 
-    fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::VariantData,
-                             _: ast::Name, _: &hir::Generics, item_id: ast::NodeId) {
+    fn check_struct_def_post(&mut self,
+                             _: &LateContext,
+                             _: &hir::VariantData,
+                             _: ast::Name,
+                             _: &hir::Generics,
+                             item_id: ast::NodeId) {
         let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
         assert!(popped == item_id);
     }
@@ -358,10 +379,10 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     for itm in items {
                         self.private_traits.insert(itm.id);
                     }
-                    return
+                    return;
                 }
                 "a trait"
-            },
+            }
             hir::ItemTy(..) => "a type alias",
             hir::ItemImpl(.., Some(ref trait_ref), _, ref impl_items) => {
                 // If the trait is private, add the impl items to private_traits so they don't get
@@ -369,26 +390,30 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                 let real_trait = cx.tcx.expect_def(trait_ref.ref_id).def_id();
                 if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) {
                     match cx.tcx.map.find(node_id) {
-                        Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited {
-                            for itm in impl_items {
-                                self.private_traits.insert(itm.id);
+                        Some(hir_map::NodeItem(item)) => {
+                            if item.vis == hir::Visibility::Inherited {
+                                for itm in impl_items {
+                                    self.private_traits.insert(itm.id);
+                                }
                             }
-                        },
-                        _ => { }
+                        }
+                        _ => {}
                     }
                 }
-                return
-            },
+                return;
+            }
             hir::ItemConst(..) => "a constant",
             hir::ItemStatic(..) => "a static",
-            _ => return
+            _ => return,
         };
 
         self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc);
     }
 
     fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
-        if self.private_traits.contains(&trait_item.id) { return }
+        if self.private_traits.contains(&trait_item.id) {
+            return;
+        }
 
         let desc = match trait_item.node {
             hir::ConstTraitItem(..) => "an associated constant",
@@ -396,9 +421,11 @@ fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
             hir::TypeTraitItem(..) => "an associated type",
         };
 
-        self.check_missing_docs_attrs(cx, Some(trait_item.id),
+        self.check_missing_docs_attrs(cx,
+                                      Some(trait_item.id),
                                       &trait_item.attrs,
-                                      trait_item.span, desc);
+                                      trait_item.span,
+                                      desc);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
@@ -412,26 +439,34 @@ fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
             hir::ImplItemKind::Method(..) => "a method",
             hir::ImplItemKind::Type(_) => "an associated type",
         };
-        self.check_missing_docs_attrs(cx, Some(impl_item.id),
+        self.check_missing_docs_attrs(cx,
+                                      Some(impl_item.id),
                                       &impl_item.attrs,
-                                      impl_item.span, desc);
+                                      impl_item.span,
+                                      desc);
     }
 
     fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) {
         if !sf.is_positional() {
             if sf.vis == hir::Public || self.in_variant {
-                let cur_struct_def = *self.struct_def_stack.last()
+                let cur_struct_def = *self.struct_def_stack
+                    .last()
                     .expect("empty struct_def_stack");
-                self.check_missing_docs_attrs(cx, Some(cur_struct_def),
-                                              &sf.attrs, sf.span,
+                self.check_missing_docs_attrs(cx,
+                                              Some(cur_struct_def),
+                                              &sf.attrs,
+                                              sf.span,
                                               "a struct field")
             }
         }
     }
 
     fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
-        self.check_missing_docs_attrs(cx, Some(v.node.data.id()),
-                                      &v.node.attrs, v.span, "a variant");
+        self.check_missing_docs_attrs(cx,
+                                      Some(v.node.data.id()),
+                                      &v.node.attrs,
+                                      v.span,
+                                      "a variant");
         assert!(!self.in_variant);
         self.in_variant = true;
     }
@@ -486,7 +521,9 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
             }
             _ => return,
         };
-        if def.has_dtor() { return; }
+        if def.has_dtor() {
+            return;
+        }
         let parameter_environment = cx.tcx.empty_parameter_environment();
         // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
         // method
@@ -514,9 +551,7 @@ pub struct MissingDebugImplementations {
 
 impl MissingDebugImplementations {
     pub fn new() -> MissingDebugImplementations {
-        MissingDebugImplementations {
-            impling_types: None,
-        }
+        MissingDebugImplementations { impling_types: None }
     }
 }
 
@@ -533,7 +568,9 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         }
 
         match item.node {
-            hir::ItemStruct(..) | hir::ItemUnion(..) | hir::ItemEnum(..) => {},
+            hir::ItemStruct(..) |
+            hir::ItemUnion(..) |
+            hir::ItemEnum(..) => {}
             _ => return,
         }
 
@@ -585,12 +622,13 @@ pub struct Deprecated {
 
 impl Deprecated {
     pub fn new() -> Deprecated {
-        Deprecated {
-            current_item: ast::CRATE_NODE_ID,
-        }
+        Deprecated { current_item: ast::CRATE_NODE_ID }
     }
 
-    fn lint(&self, cx: &LateContext, _id: DefId, span: Span,
+    fn lint(&self,
+            cx: &LateContext,
+            _id: DefId,
+            span: Span,
             stability: &Option<&attr::Stability>,
             deprecation: &Option<stability::DeprecationEntry>) {
         // Deprecated attributes apply in-crate and cross-crate.
@@ -641,9 +679,10 @@ fn get_lints(&self) -> LintArray {
 impl LateLintPass for Deprecated {
     fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         self.push_item(item.id);
-        stability::check_item(cx.tcx, item, false,
-                              &mut |id, sp, stab, depr|
-                                self.lint(cx, id, sp, &stab, &depr));
+        stability::check_item(cx.tcx,
+                              item,
+                              false,
+                              &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
     }
 
     fn check_item_post(&mut self, cx: &LateContext, item: &hir::Item) {
@@ -651,27 +690,30 @@ fn check_item_post(&mut self, cx: &LateContext, item: &hir::Item) {
     }
 
     fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
-        stability::check_expr(cx.tcx, e,
-                              &mut |id, sp, stab, depr|
-                                self.lint(cx, id, sp, &stab, &depr));
+        stability::check_expr(cx.tcx,
+                              e,
+                              &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
     }
 
     fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
-        stability::check_path(cx.tcx, path, id,
-                              &mut |id, sp, stab, depr|
-                                self.lint(cx, id, sp, &stab, &depr));
+        stability::check_path(cx.tcx,
+                              path,
+                              id,
+                              &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
     }
 
     fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
-        stability::check_path_list_item(cx.tcx, item,
-                                         &mut |id, sp, stab, depr|
-                                           self.lint(cx, id, sp, &stab, &depr));
+        stability::check_path_list_item(cx.tcx,
+                                        item,
+                                        &mut |id, sp, stab, depr| {
+                                            self.lint(cx, id, sp, &stab, &depr)
+                                        });
     }
 
     fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
-        stability::check_pat(cx.tcx, pat,
-                             &mut |id, sp, stab, depr|
-                                self.lint(cx, id, sp, &stab, &depr));
+        stability::check_pat(cx.tcx,
+                             pat,
+                             &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
     }
 
     fn check_impl_item(&mut self, _: &LateContext, item: &hir::ImplItem) {
@@ -716,15 +758,20 @@ fn get_lints(&self) -> LintArray {
 }
 
 impl LateLintPass for UnconditionalRecursion {
-    fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
-                blk: &hir::Block, sp: Span, id: ast::NodeId) {
+    fn check_fn(&mut self,
+                cx: &LateContext,
+                fn_kind: FnKind,
+                _: &hir::FnDecl,
+                blk: &hir::Block,
+                sp: Span,
+                id: ast::NodeId) {
         let method = match fn_kind {
             FnKind::ItemFn(..) => None,
             FnKind::Method(..) => {
                 cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method()
             }
             // closures can't recur, so they don't matter.
-            FnKind::Closure(_) => return
+            FnKind::Closure(_) => return,
         };
 
         // Walk through this function (say `f`) looking to see if
@@ -779,10 +826,8 @@ fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
             // is this a recursive call?
             let self_recursive = if node_id != ast::DUMMY_NODE_ID {
                 match method {
-                    Some(ref method) => {
-                        expr_refers_to_this_method(cx.tcx, method, node_id)
-                    }
-                    None => expr_refers_to_this_fn(cx.tcx, id, node_id)
+                    Some(ref method) => expr_refers_to_this_method(cx.tcx, method, node_id),
+                    None => expr_refers_to_this_fn(cx.tcx, id, node_id),
                 }
             } else {
                 false
@@ -808,7 +853,8 @@ fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
         // no break */ }`) shouldn't be linted unless it actually
         // recurs.
         if !reached_exit_without_self_call && !self_call_spans.is_empty() {
-            let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp,
+            let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION,
+                                             sp,
                                              "function cannot return without recurring");
 
             // FIXME #19668: these could be span_lint_note's instead of this manual guard.
@@ -829,23 +875,21 @@ fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
         // Functions for identifying if the given Expr NodeId `id`
         // represents a call to the function `fn_id`/method `method`.
 
-        fn expr_refers_to_this_fn(tcx: TyCtxt,
-                                  fn_id: ast::NodeId,
-                                  id: ast::NodeId) -> bool {
+        fn expr_refers_to_this_fn(tcx: TyCtxt, fn_id: ast::NodeId, id: ast::NodeId) -> bool {
             match tcx.map.get(id) {
                 hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
-                    tcx.expect_def_or_none(callee.id).map_or(false, |def| {
-                        def.def_id() == tcx.map.local_def_id(fn_id)
-                    })
+                    tcx.expect_def_or_none(callee.id)
+                        .map_or(false, |def| def.def_id() == tcx.map.local_def_id(fn_id))
                 }
-                _ => false
+                _ => false,
             }
         }
 
         // Check if the expression `id` performs a call to `method`.
         fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 method: &ty::Method,
-                                                id: ast::NodeId) -> bool {
+                                                id: ast::NodeId)
+                                                -> bool {
             // Check for method calls and overloaded operators.
             let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned();
             if let Some(m) = opt_m {
@@ -859,9 +903,11 @@ fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj {
                 for i in 0..adj.autoderefs {
                     let method_call = ty::MethodCall::autoderef(id, i as u32);
-                    if let Some(m) = tcx.tables.borrow().method_map
-                                                        .get(&method_call)
-                                                        .cloned() {
+                    if let Some(m) = tcx.tables
+                        .borrow()
+                        .method_map
+                        .get(&method_call)
+                        .cloned() {
                         if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) {
                             return true;
                         }
@@ -877,13 +923,16 @@ fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     match tcx.expect_def_or_none(callee.id) {
                         Some(Def::Method(def_id)) => {
                             let item_substs = tcx.node_id_item_substs(callee.id);
-                            method_call_refers_to_method(
-                                tcx, method, def_id, &item_substs.substs, id)
+                            method_call_refers_to_method(tcx,
+                                                         method,
+                                                         def_id,
+                                                         &item_substs.substs,
+                                                         id)
                         }
-                        _ => false
+                        _ => false,
                     }
                 }
-                _ => false
+                _ => false,
             }
         }
 
@@ -893,15 +942,14 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                   method: &ty::Method,
                                                   callee_id: DefId,
                                                   callee_substs: &Substs<'tcx>,
-                                                  expr_id: ast::NodeId) -> bool {
+                                                  expr_id: ast::NodeId)
+                                                  -> bool {
             let callee_item = tcx.impl_or_trait_item(callee_id);
 
             match callee_item.container() {
                 // This is an inherent method, so the `def_id` refers
                 // directly to the method definition.
-                ty::ImplContainer(_) => {
-                    callee_id == method.def_id
-                }
+                ty::ImplContainer(_) => callee_id == method.def_id,
 
                 // A trait method, from any number of possible sources.
                 // Attempt to select a concrete impl before checking.
@@ -939,13 +987,12 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 let container = ty::ImplContainer(vtable_impl.impl_def_id);
                                 // It matches if it comes from the same impl,
                                 // and has the same method name.
-                                container == method.container
-                                    && callee_item.name() == method.name
+                                container == method.container && callee_item.name() == method.name
                             }
 
                             // There's no way to know if this call is
                             // recursive, so we assume it's not.
-                            _ => false
+                            _ => false,
                         }
                     })
                 }
@@ -992,7 +1039,8 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         };
 
         if prfn.is_some() {
-            cx.span_lint(PLUGIN_AS_LIBRARY, it.span,
+            cx.span_lint(PLUGIN_AS_LIBRARY,
+                         it.span,
                          "compiler plugin used as an ordinary library");
         }
     }
@@ -1050,15 +1098,15 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                                      "generic functions must be mangled");
                     }
                 }
-            },
+            }
             hir::ItemStatic(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") &&
-                       !cx.access_levels.is_reachable(it.id) {
+                   !cx.access_levels.is_reachable(it.id) {
                     let msg = format!("static {} is marked #[no_mangle], but not exported",
                                       it.name);
                     cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
                 }
-            },
+            }
             hir::ItemConst(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") {
                     // Const items do not refer to a particular location in memory, and therefore
@@ -1068,7 +1116,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
                 }
             }
-            _ => {},
+            _ => {}
         }
     }
 }
@@ -1096,19 +1144,21 @@ fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
                    consider instead using an UnsafeCell";
         match get_transmute_from_to(cx, expr) {
             Some((&ty::TyRef(_, from_mt), &ty::TyRef(_, to_mt))) => {
-                if to_mt.mutbl == hir::Mutability::MutMutable
-                    && from_mt.mutbl == hir::Mutability::MutImmutable {
+                if to_mt.mutbl == hir::Mutability::MutMutable &&
+                   from_mt.mutbl == hir::Mutability::MutImmutable {
                     cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
                 }
             }
-            _ => ()
+            _ => (),
         }
 
-        fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr)
-            -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
+        fn get_transmute_from_to<'a, 'tcx>
+            (cx: &LateContext<'a, 'tcx>,
+             expr: &hir::Expr)
+             -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
             match expr.node {
                 hir::ExprPath(..) => (),
-                _ => return None
+                _ => return None,
             }
             if let Def::Fn(did) = cx.tcx.expect_def(expr.id) {
                 if !def_id_is_transmute(cx, did) {
@@ -1120,8 +1170,8 @@ fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr)
                         let from = bare_fn.sig.0.inputs[0];
                         let to = bare_fn.sig.0.output;
                         return Some((&from.sty, &to.sty));
-                    },
-                    _ => ()
+                    }
+                    _ => (),
                 }
             }
             None
@@ -1130,7 +1180,7 @@ fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr)
         fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
             match cx.tcx.lookup_item_type(def_id).ty.sty {
                 ty::TyFnDef(.., ref bfty) if bfty.abi == RustIntrinsic => (),
-                _ => return false
+                _ => return false,
             }
             cx.tcx.item_name(def_id).as_str() == "transmute"
         }
index 47d248fe2f2416ab7e74b415cbf98b17e4aa9bae..74483b89cea22f1671b75cc8840dbe6cd79cba55 100644 (file)
 extern crate rustc_const_eval;
 extern crate syntax_pos;
 
-pub use rustc::lint as lint;
-pub use rustc::middle as middle;
-pub use rustc::session as session;
-pub use rustc::util as util;
+pub use rustc::lint;
+pub use rustc::middle;
+pub use rustc::session;
+pub use rustc::util;
 
 use session::Session;
 use lint::LintId;
@@ -139,13 +139,24 @@ macro_rules! add_lint_group {
                           MissingDebugImplementations,
                           );
 
-    add_lint_group!(sess, "bad_style",
-                    NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS);
-
-    add_lint_group!(sess, "unused",
-                    UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
-                    UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
-                    UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
+    add_lint_group!(sess,
+                    "bad_style",
+                    NON_CAMEL_CASE_TYPES,
+                    NON_SNAKE_CASE,
+                    NON_UPPER_CASE_GLOBALS);
+
+    add_lint_group!(sess,
+                    "unused",
+                    UNUSED_IMPORTS,
+                    UNUSED_VARIABLES,
+                    UNUSED_ASSIGNMENTS,
+                    DEAD_CODE,
+                    UNUSED_MUT,
+                    UNREACHABLE_CODE,
+                    UNUSED_MUST_USE,
+                    UNUSED_UNSAFE,
+                    PATH_STATEMENTS,
+                    UNUSED_ATTRIBUTES);
 
     // Guidelines for creating a future incompatibility lint:
     //
@@ -155,7 +166,8 @@ macro_rules! add_lint_group {
     //   and include the full URL.
     // - Later, change lint to error
     // - Eventually, remove lint
-    store.register_future_incompatible(sess, vec![
+    store.register_future_incompatible(sess,
+                                       vec![
         FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
@@ -204,11 +216,13 @@ macro_rules! add_lint_group {
 
     // Register renamed and removed lints
     store.register_renamed("unknown_features", "unused_features");
-    store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
+    store.register_removed("unsigned_negation",
+                           "replaced by negate_unsigned feature gate");
     store.register_removed("negate_unsigned", "cast a signed value instead");
     store.register_removed("raw_pointer_derive", "using derive with raw pointers is ok");
     // This was renamed to raw_pointer_derive, which was then removed,
     // so it is also considered removed
-    store.register_removed("raw_pointer_deriving", "using derive with raw pointers is ok");
+    store.register_removed("raw_pointer_deriving",
+                           "using derive with raw pointers is ok");
     store.register_removed("drop_with_repr_extern", "drop flags have been removed");
 }
index 4caf7a04fe05806d40834755117b5f87e95e4a5a..9464bf30b693fd86dcedad02e5157c94a123fbb4 100644 (file)
@@ -18,7 +18,7 @@
 use middle::const_val::ConstVal;
 use rustc_const_eval::eval_const_expr_partial;
 use rustc_const_eval::EvalHint::ExprTypeChecked;
-use util::nodemap::{FnvHashSet};
+use util::nodemap::FnvHashSet;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
 
@@ -91,15 +91,15 @@ pub struct TypeLimits {
 
 impl TypeLimits {
     pub fn new() -> TypeLimits {
-        TypeLimits {
-            negated_expr_id: ast::DUMMY_NODE_ID,
-        }
+        TypeLimits { negated_expr_id: ast::DUMMY_NODE_ID }
     }
 }
 
 impl LintPass for TypeLimits {
     fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS)
+        lint_array!(UNUSED_COMPARISONS,
+                    OVERFLOWING_LITERALS,
+                    EXCEEDING_BITSHIFTS)
     }
 }
 
@@ -111,13 +111,13 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                     match lit.node {
                         ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)) => {
                             forbid_unsigned_negation(cx, e.span);
-                        },
+                        }
                         ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
                             if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
                                 forbid_unsigned_negation(cx, e.span);
                             }
-                        },
-                        _ => ()
+                        }
+                        _ => (),
                     }
                 } else {
                     let t = cx.tcx.node_id_to_type(expr.id);
@@ -129,10 +129,11 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                 if self.negated_expr_id != e.id {
                     self.negated_expr_id = expr.id;
                 }
-            },
+            }
             hir::ExprBinary(binop, ref l, ref r) => {
                 if is_comparison(binop) && !check_limits(cx.tcx, binop, &l, &r) {
-                    cx.span_lint(UNUSED_COMPARISONS, e.span,
+                    cx.span_lint(UNUSED_COMPARISONS,
+                                 e.span,
                                  "comparison is useless due to type limits");
                 }
 
@@ -140,30 +141,35 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                     let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty {
                         ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
                         ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
-                        _ => None
+                        _ => None,
                     };
 
                     if let Some(bits) = opt_ty_bits {
                         let exceeding = if let hir::ExprLit(ref lit) = r.node {
-                            if let ast::LitKind::Int(shift, _) = lit.node { shift >= bits }
-                            else { false }
+                            if let ast::LitKind::Int(shift, _) = lit.node {
+                                shift >= bits
+                            } else {
+                                false
+                            }
                         } else {
                             match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked, None) {
                                 Ok(ConstVal::Integral(i)) => {
-                                    i.is_negative() || i.to_u64()
-                                                        .map(|i| i >= bits)
-                                                        .unwrap_or(true)
-                                },
-                                _ => { false }
+                                    i.is_negative() ||
+                                    i.to_u64()
+                                        .map(|i| i >= bits)
+                                        .unwrap_or(true)
+                                }
+                                _ => false,
                             }
                         };
                         if exceeding {
-                            cx.span_lint(EXCEEDING_BITSHIFTS, e.span,
+                            cx.span_lint(EXCEEDING_BITSHIFTS,
+                                         e.span,
                                          "bitshift exceeds the type's number of bits");
                         }
                     };
                 }
-            },
+            }
             hir::ExprLit(ref lit) => {
                 match cx.tcx.node_id_to_type(e.id).sty {
                     ty::TyInt(t) => {
@@ -182,14 +188,15 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                                 // avoiding use of -min to prevent overflow/panic
                                 if (negative && v > max as u64 + 1) ||
                                    (!negative && v > max as u64) {
-                                    cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                    cx.span_lint(OVERFLOWING_LITERALS,
+                                                 e.span,
                                                  &format!("literal out of range for {:?}", t));
                                     return;
                                 }
                             }
-                            _ => bug!()
+                            _ => bug!(),
                         };
-                    },
+                    }
                     ty::TyUint(t) => {
                         let uint_type = if let ast::UintTy::Us = t {
                             cx.sess().target.uint_type
@@ -201,13 +208,14 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                             // _v is u8, within range by definition
                             ast::LitKind::Byte(_v) => return,
                             ast::LitKind::Int(v, _) => v,
-                            _ => bug!()
+                            _ => bug!(),
                         };
                         if lit_val < min || lit_val > max {
-                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                            cx.span_lint(OVERFLOWING_LITERALS,
+                                         e.span,
                                          &format!("literal out of range for {:?}", t));
                         }
-                    },
+                    }
                     ty::TyFloat(t) => {
                         let (min, max) = float_ty_range(t);
                         let lit_val: f64 = match lit.node {
@@ -215,70 +223,71 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                             ast::LitKind::FloatUnsuffixed(ref v) => {
                                 match v.parse() {
                                     Ok(f) => f,
-                                    Err(_) => return
+                                    Err(_) => return,
                                 }
                             }
-                            _ => bug!()
+                            _ => bug!(),
                         };
                         if lit_val < min || lit_val > max {
-                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                            cx.span_lint(OVERFLOWING_LITERALS,
+                                         e.span,
                                          &format!("literal out of range for {:?}", t));
                         }
-                    },
-                    _ => ()
+                    }
+                    _ => (),
                 };
-            },
-            _ => ()
+            }
+            _ => (),
         };
 
-        fn is_valid<T:cmp::PartialOrd>(binop: hir::BinOp, v: T,
-                                min: T, max: T) -> bool {
+        fn is_valid<T: cmp::PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
             match binop.node {
-                hir::BiLt => v >  min && v <= max,
-                hir::BiLe => v >= min && v <  max,
-                hir::BiGt => v >= min && v <  max,
-                hir::BiGe => v >  min && v <= max,
+                hir::BiLt => v > min && v <= max,
+                hir::BiLe => v >= min && v < max,
+                hir::BiGt => v >= min && v < max,
+                hir::BiGe => v > min && v <= max,
                 hir::BiEq | hir::BiNe => v >= min && v <= max,
-                _ => bug!()
+                _ => bug!(),
             }
         }
 
         fn rev_binop(binop: hir::BinOp) -> hir::BinOp {
-            codemap::respan(binop.span, match binop.node {
-                hir::BiLt => hir::BiGt,
-                hir::BiLe => hir::BiGe,
-                hir::BiGt => hir::BiLt,
-                hir::BiGe => hir::BiLe,
-                _ => return binop
-            })
+            codemap::respan(binop.span,
+                            match binop.node {
+                                hir::BiLt => hir::BiGt,
+                                hir::BiLe => hir::BiGe,
+                                hir::BiGt => hir::BiLt,
+                                hir::BiGe => hir::BiLe,
+                                _ => return binop,
+                            })
         }
 
         // for isize & usize, be conservative with the warnings, so that the
         // warnings are consistent between 32- and 64-bit platforms
         fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
             match int_ty {
-                ast::IntTy::Is => (i64::MIN,        i64::MAX),
-                ast::IntTy::I8 =>    (i8::MIN  as i64, i8::MAX  as i64),
-                ast::IntTy::I16 =>   (i16::MIN as i64, i16::MAX as i64),
-                ast::IntTy::I32 =>   (i32::MIN as i64, i32::MAX as i64),
-                ast::IntTy::I64 =>   (i64::MIN,        i64::MAX)
+                ast::IntTy::Is => (i64::MIN, i64::MAX),
+                ast::IntTy::I8 => (i8::MIN as i64, i8::MAX as i64),
+                ast::IntTy::I16 => (i16::MIN as i64, i16::MAX as i64),
+                ast::IntTy::I32 => (i32::MIN as i64, i32::MAX as i64),
+                ast::IntTy::I64 => (i64::MIN, i64::MAX),
             }
         }
 
         fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
             match uint_ty {
-                ast::UintTy::Us => (u64::MIN,         u64::MAX),
-                ast::UintTy::U8 =>    (u8::MIN   as u64, u8::MAX   as u64),
-                ast::UintTy::U16 =>   (u16::MIN  as u64, u16::MAX  as u64),
-                ast::UintTy::U32 =>   (u32::MIN  as u64, u32::MAX  as u64),
-                ast::UintTy::U64 =>   (u64::MIN,         u64::MAX)
+                ast::UintTy::Us => (u64::MIN, u64::MAX),
+                ast::UintTy::U8 => (u8::MIN as u64, u8::MAX as u64),
+                ast::UintTy::U16 => (u16::MIN as u64, u16::MAX as u64),
+                ast::UintTy::U32 => (u32::MIN as u64, u32::MAX as u64),
+                ast::UintTy::U64 => (u64::MIN, u64::MAX),
             }
         }
 
         fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
             match float_ty {
                 ast::FloatTy::F32 => (f32::MIN as f64, f32::MAX as f64),
-                ast::FloatTy::F64 => (f64::MIN,        f64::MAX)
+                ast::FloatTy::F64 => (f64::MIN, f64::MAX),
             }
         }
 
@@ -305,60 +314,60 @@ fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 {
         fn check_limits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   binop: hir::BinOp,
                                   l: &hir::Expr,
-                                  r: &hir::Expr) -> bool {
+                                  r: &hir::Expr)
+                                  -> bool {
             let (lit, expr, swap) = match (&l.node, &r.node) {
                 (&hir::ExprLit(_), _) => (l, r, true),
                 (_, &hir::ExprLit(_)) => (r, l, false),
-                _ => return true
+                _ => return true,
             };
             // Normalize the binop so that the literal is always on the RHS in
             // the comparison
-            let norm_binop = if swap {
-                rev_binop(binop)
-            } else {
-                binop
-            };
+            let norm_binop = if swap { rev_binop(binop) } else { binop };
             match tcx.node_id_to_type(expr.id).sty {
                 ty::TyInt(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i64 = match lit.node {
-                        hir::ExprLit(ref li) => match li.node {
-                            ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
-                            ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64,
-                            _ => return true
-                        },
-                        _ => bug!()
+                        hir::ExprLit(ref li) => {
+                            match li.node {
+                                ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
+                                ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64,
+                                _ => return true,
+                            }
+                        }
+                        _ => bug!(),
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
                 ty::TyUint(uint_ty) => {
                     let (min, max): (u64, u64) = uint_ty_range(uint_ty);
                     let lit_val: u64 = match lit.node {
-                        hir::ExprLit(ref li) => match li.node {
-                            ast::LitKind::Int(v, _) => v,
-                            _ => return true
-                        },
-                        _ => bug!()
+                        hir::ExprLit(ref li) => {
+                            match li.node {
+                                ast::LitKind::Int(v, _) => v,
+                                _ => return true,
+                            }
+                        }
+                        _ => bug!(),
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
-                _ => true
+                _ => true,
             }
         }
 
         fn is_comparison(binop: hir::BinOp) -> bool {
             match binop.node {
-                hir::BiEq | hir::BiLt | hir::BiLe |
-                hir::BiNe | hir::BiGe | hir::BiGt => true,
-                _ => false
+                hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => true,
+                _ => false,
             }
         }
 
         fn forbid_unsigned_negation(cx: &LateContext, span: Span) {
             cx.sess()
-              .struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519")
-              .span_help(span, "use a cast or the `!` operator")
-              .emit();
+                .struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519")
+                .span_help(span, "use a cast or the `!` operator")
+                .emit();
         }
     }
 }
@@ -370,7 +379,7 @@ fn forbid_unsigned_negation(cx: &LateContext, span: Span) {
 }
 
 struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
-    cx: &'a LateContext<'a, 'tcx>
+    cx: &'a LateContext<'a, 'tcx>,
 }
 
 enum FfiResult {
@@ -403,9 +412,13 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         if def.variants[data_idx].fields.len() == 1 {
             match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
-                ty::TyFnPtr(_) => { return true; }
-                ty::TyRef(..) => { return true; }
-                _ => { }
+                ty::TyFnPtr(_) => {
+                    return true;
+                }
+                ty::TyRef(..) => {
+                    return true;
+                }
+                _ => {}
             }
         }
     }
@@ -415,10 +428,7 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     /// Check if the given type is "ffi-safe" (has a stable, well-defined
     /// representation which can be exported to C code).
-    fn check_type_for_ffi(&self,
-                          cache: &mut FnvHashSet<Ty<'tcx>>,
-                          ty: Ty<'tcx>)
-                          -> FfiResult {
+    fn check_type_for_ffi(&self, cache: &mut FnvHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> FfiResult {
         use self::FfiResult::*;
         let cx = self.cx.tcx;
 
@@ -431,112 +441,118 @@ fn check_type_for_ffi(&self,
         }
 
         match ty.sty {
-            ty::TyAdt(def, substs) => match def.adt_kind() {
-                AdtKind::Struct => {
-                    if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
-                        return FfiUnsafe(
-                            "found struct without foreign-function-safe \
-                            representation annotation in foreign module, \
-                            consider adding a #[repr(C)] attribute to \
-                            the type");
-                    }
+            ty::TyAdt(def, substs) => {
+                match def.adt_kind() {
+                    AdtKind::Struct => {
+                        if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
+                            return FfiUnsafe("found struct without foreign-function-safe \
+                                              representation annotation in foreign module, \
+                                              consider adding a #[repr(C)] attribute to the type");
+                        }
 
-                    // We can't completely trust repr(C) markings; make sure the
-                    // fields are actually safe.
-                    if def.struct_variant().fields.is_empty() {
-                        return FfiUnsafe(
-                            "found zero-size struct in foreign module, consider \
-                            adding a member to this struct");
-                    }
+                        // We can't completely trust repr(C) markings; make sure the
+                        // fields are actually safe.
+                        if def.struct_variant().fields.is_empty() {
+                            return FfiUnsafe("found zero-size struct in foreign module, consider \
+                                              adding a member to this struct");
+                        }
 
-                    for field in &def.struct_variant().fields {
-                        let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
-                        let r = self.check_type_for_ffi(cache, field_ty);
-                        match r {
-                            FfiSafe => {}
-                            FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
-                            FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
+                        for field in &def.struct_variant().fields {
+                            let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
+                            let r = self.check_type_for_ffi(cache, field_ty);
+                            match r {
+                                FfiSafe => {}
+                                FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
+                                    return r;
+                                }
+                                FfiUnsafe(s) => {
+                                    return FfiBadStruct(def.did, s);
+                                }
+                            }
                         }
+                        FfiSafe
                     }
-                    FfiSafe
-                }
-                AdtKind::Union => {
-                    if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
-                        return FfiUnsafe(
-                            "found union without foreign-function-safe \
-                            representation annotation in foreign module, \
-                            consider adding a #[repr(C)] attribute to \
-                            the type");
-                    }
+                    AdtKind::Union => {
+                        if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
+                            return FfiUnsafe("found union without foreign-function-safe \
+                                              representation annotation in foreign module, \
+                                              consider adding a #[repr(C)] attribute to the type");
+                        }
 
-                    for field in &def.struct_variant().fields {
-                        let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
-                        let r = self.check_type_for_ffi(cache, field_ty);
-                        match r {
-                            FfiSafe => {}
-                            FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
-                            FfiUnsafe(s) => { return FfiBadUnion(def.did, s); }
+                        for field in &def.struct_variant().fields {
+                            let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
+                            let r = self.check_type_for_ffi(cache, field_ty);
+                            match r {
+                                FfiSafe => {}
+                                FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
+                                    return r;
+                                }
+                                FfiUnsafe(s) => {
+                                    return FfiBadUnion(def.did, s);
+                                }
+                            }
                         }
+                        FfiSafe
                     }
-                    FfiSafe
-                }
-                AdtKind::Enum => {
-                    if def.variants.is_empty() {
-                        // Empty enums are okay... although sort of useless.
-                        return FfiSafe
-                    }
+                    AdtKind::Enum => {
+                        if def.variants.is_empty() {
+                            // Empty enums are okay... although sort of useless.
+                            return FfiSafe;
+                        }
 
-                    // Check for a repr() attribute to specify the size of the
-                    // discriminant.
-                    let repr_hints = cx.lookup_repr_hints(def.did);
-                    match &repr_hints[..] {
-                        &[] => {
-                            // Special-case types like `Option<extern fn()>`.
-                            if !is_repr_nullable_ptr(cx, def, substs) {
-                                return FfiUnsafe(
-                                    "found enum without foreign-function-safe \
-                                    representation annotation in foreign module, \
-                                    consider adding a #[repr(...)] attribute to \
-                                    the type")
+                        // Check for a repr() attribute to specify the size of the
+                        // discriminant.
+                        let repr_hints = cx.lookup_repr_hints(def.did);
+                        match &repr_hints[..] {
+                            &[] => {
+                                // Special-case types like `Option<extern fn()>`.
+                                if !is_repr_nullable_ptr(cx, def, substs) {
+                                    return FfiUnsafe("found enum without foreign-function-safe \
+                                                      representation annotation in foreign \
+                                                      module, consider adding a #[repr(...)] \
+                                                      attribute to the type");
+                                }
                             }
-                        }
-                        &[ref hint] => {
-                            if !hint.is_ffi_safe() {
+                            &[ref hint] => {
+                                if !hint.is_ffi_safe() {
+                                    // FIXME: This shouldn't be reachable: we should check
+                                    // this earlier.
+                                    return FfiUnsafe("enum has unexpected #[repr(...)] attribute");
+                                }
+
+                                // Enum with an explicitly sized discriminant; either
+                                // a C-style enum or a discriminated union.
+
+                                // The layout of enum variants is implicitly repr(C).
+                                // FIXME: Is that correct?
+                            }
+                            _ => {
                                 // FIXME: This shouldn't be reachable: we should check
                                 // this earlier.
-                                return FfiUnsafe(
-                                    "enum has unexpected #[repr(...)] attribute")
+                                return FfiUnsafe("enum has too many #[repr(...)] attributes");
                             }
-
-                            // Enum with an explicitly sized discriminant; either
-                            // a C-style enum or a discriminated union.
-
-                            // The layout of enum variants is implicitly repr(C).
-                            // FIXME: Is that correct?
                         }
-                        _ => {
-                            // FIXME: This shouldn't be reachable: we should check
-                            // this earlier.
-                            return FfiUnsafe(
-                                "enum has too many #[repr(...)] attributes");
-                        }
-                    }
 
-                    // Check the contained variants.
-                    for variant in &def.variants {
-                        for field in &variant.fields {
-                            let arg = cx.normalize_associated_type(&field.ty(cx, substs));
-                            let r = self.check_type_for_ffi(cache, arg);
-                            match r {
-                                FfiSafe => {}
-                                FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
-                                FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
+                        // Check the contained variants.
+                        for variant in &def.variants {
+                            for field in &variant.fields {
+                                let arg = cx.normalize_associated_type(&field.ty(cx, substs));
+                                let r = self.check_type_for_ffi(cache, arg);
+                                match r {
+                                    FfiSafe => {}
+                                    FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
+                                        return r;
+                                    }
+                                    FfiUnsafe(s) => {
+                                        return FfiBadEnum(def.did, s);
+                                    }
+                                }
                             }
                         }
+                        FfiSafe
                     }
-                    FfiSafe
                 }
-            },
+            }
 
             ty::TyChar => {
                 FfiUnsafe("found Rust type `char` in foreign module, while \
@@ -544,8 +560,7 @@ fn check_type_for_ffi(&self,
             }
 
             // Primitive types with a stable representation.
-            ty::TyBool | ty::TyInt(..) | ty::TyUint(..) |
-            ty::TyFloat(..) | ty::TyNever => FfiSafe,
+            ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe,
 
             ty::TyBox(..) => {
                 FfiUnsafe("found Rust type Box<_> in foreign module, \
@@ -572,24 +587,17 @@ fn check_type_for_ffi(&self,
                            consider using a struct instead")
             }
 
-            ty::TyRawPtr(ref m) | ty::TyRef(_, ref m) => {
-                self.check_type_for_ffi(cache, m.ty)
-            }
+            ty::TyRawPtr(ref m) |
+            ty::TyRef(_, ref m) => self.check_type_for_ffi(cache, m.ty),
 
-            ty::TyArray(ty, _) => {
-                self.check_type_for_ffi(cache, ty)
-            }
+            ty::TyArray(ty, _) => self.check_type_for_ffi(cache, ty),
 
             ty::TyFnPtr(bare_fn) => {
                 match bare_fn.abi {
-                    Abi::Rust |
-                    Abi::RustIntrinsic |
-                    Abi::PlatformIntrinsic |
-                    Abi::RustCall => {
-                        return FfiUnsafe(
-                            "found function pointer with Rust calling \
-                             convention in foreign module; consider using an \
-                             `extern` function pointer")
+                    Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
+                        return FfiUnsafe("found function pointer with Rust calling convention in \
+                                          foreign module; consider using an `extern` function \
+                                          pointer")
                     }
                     _ => {}
                 }
@@ -599,24 +607,30 @@ fn check_type_for_ffi(&self,
                     let r = self.check_type_for_ffi(cache, sig.output);
                     match r {
                         FfiSafe => {}
-                        _ => { return r; }
+                        _ => {
+                            return r;
+                        }
                     }
                 }
                 for arg in sig.inputs {
                     let r = self.check_type_for_ffi(cache, arg);
                     match r {
                         FfiSafe => {}
-                        _ => { return r; }
+                        _ => {
+                            return r;
+                        }
                     }
                 }
                 FfiSafe
             }
 
-            ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
-            ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) |
-            ty::TyFnDef(..) => {
-                bug!("Unexpected type in foreign function")
-            }
+            ty::TyParam(..) |
+            ty::TyInfer(..) |
+            ty::TyError |
+            ty::TyClosure(..) |
+            ty::TyProjection(..) |
+            ty::TyAnon(..) |
+            ty::TyFnDef(..) => bug!("Unexpected type in foreign function"),
         }
     }
 
@@ -633,23 +647,28 @@ fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
             FfiResult::FfiBadStruct(_, s) => {
                 // FIXME: This diagnostic is difficult to read, and doesn't
                 // point at the relevant field.
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                    &format!("found non-foreign-function-safe member in \
-                              struct marked #[repr(C)]: {}", s));
+                self.cx.span_lint(IMPROPER_CTYPES,
+                                  sp,
+                                  &format!("found non-foreign-function-safe member in struct \
+                                            marked #[repr(C)]: {}",
+                                           s));
             }
             FfiResult::FfiBadUnion(_, s) => {
                 // FIXME: This diagnostic is difficult to read, and doesn't
                 // point at the relevant field.
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                    &format!("found non-foreign-function-safe member in \
-                              union marked #[repr(C)]: {}", s));
+                self.cx.span_lint(IMPROPER_CTYPES,
+                                  sp,
+                                  &format!("found non-foreign-function-safe member in union \
+                                            marked #[repr(C)]: {}",
+                                           s));
             }
             FfiResult::FfiBadEnum(_, s) => {
                 // FIXME: This diagnostic is difficult to read, and doesn't
                 // point at the relevant variant.
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                    &format!("found non-foreign-function-safe member in \
-                              enum: {}", s));
+                self.cx.span_lint(IMPROPER_CTYPES,
+                                  sp,
+                                  &format!("found non-foreign-function-safe member in enum: {}",
+                                           s));
             }
         }
     }
@@ -719,13 +738,13 @@ fn get_lints(&self) -> LintArray {
 impl LateLintPass for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
-            if gens.ty_params.is_empty() {  // sizes only make sense for non-generic types
+            if gens.ty_params.is_empty() {
+                // sizes only make sense for non-generic types
                 let t = cx.tcx.node_id_to_type(it.id);
                 let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
                     let ty = cx.tcx.erase_regions(&t);
-                    ty.layout(&infcx).unwrap_or_else(|e| {
-                        bug!("failed to get layout for `{}`: {}", t, e)
-                    })
+                    ty.layout(&infcx)
+                        .unwrap_or_else(|e| bug!("failed to get layout for `{}`: {}", t, e))
                 });
 
                 if let Layout::General { ref variants, ref size, discr, .. } = *layout {
@@ -738,23 +757,21 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                         .zip(variants)
                         .map(|(variant, variant_layout)| {
                             // Subtract the size of the enum discriminant
-                            let bytes = variant_layout.min_size.bytes()
-                                                                 .saturating_sub(discr_size);
+                            let bytes = variant_layout.min_size
+                                .bytes()
+                                .saturating_sub(discr_size);
 
                             debug!("- variant `{}` is {} bytes large", variant.node.name, bytes);
                             bytes
                         })
                         .enumerate()
-                        .fold((0, 0, 0),
-                            |(l, s, li), (idx, size)|
-                                if size > l {
-                                    (size, l, idx)
-                                } else if size > s {
-                                    (l, size, li)
-                                } else {
-                                    (l, s, li)
-                                }
-                        );
+                        .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
+                            (size, l, idx)
+                        } else if size > s {
+                            (l, size, li)
+                        } else {
+                            (l, s, li)
+                        });
 
                     // we only warn if the largest variant is at least thrice as large as
                     // the second-largest.
@@ -762,7 +779,8 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                         cx.span_lint(VARIANT_SIZE_DIFFERENCES,
                                      enum_definition.variants[largest_index].span,
                                      &format!("enum variant is more than three times larger \
-                                               ({} bytes) than the next largest", largest));
+                                               ({} bytes) than the next largest",
+                                              largest));
                     }
                 }
             }
index d31f16df693569ed1a5270d3508901e86d859337..a29ff18ab53188311c9ff13343fa7268c10222e0 100644 (file)
@@ -49,8 +49,12 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
                 if let hir::BindByValue(hir::MutMutable) = mode {
                     if !name.as_str().starts_with("_") {
                         match mutables.entry(name.0 as usize) {
-                            Vacant(entry) => { entry.insert(vec![id]); },
-                            Occupied(mut entry) => { entry.get_mut().push(id); },
+                            Vacant(entry) => {
+                                entry.insert(vec![id]);
+                            }
+                            Occupied(mut entry) => {
+                                entry.get_mut().push(id);
+                            }
                         }
                     }
                 }
@@ -60,7 +64,8 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
         let used_mutables = cx.tcx.used_mut_nodes.borrow();
         for (_, v) in &mutables {
             if !v.iter().any(|e| used_mutables.contains(e)) {
-                cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]),
+                cx.span_lint(UNUSED_MUT,
+                             cx.tcx.map.span(v[0]),
                              "variable does not need to be mutable");
             }
         }
@@ -90,9 +95,13 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         }
     }
 
-    fn check_fn(&mut self, cx: &LateContext,
-                _: FnKind, decl: &hir::FnDecl,
-                _: &hir::Block, _: Span, _: ast::NodeId) {
+    fn check_fn(&mut self,
+                cx: &LateContext,
+                _: FnKind,
+                decl: &hir::FnDecl,
+                _: &hir::Block,
+                _: Span,
+                _: ast::NodeId) {
         for a in &decl.inputs {
             self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
         }
@@ -124,7 +133,7 @@ impl LateLintPass for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         let expr = match s.node {
             hir::StmtSemi(ref expr, _) => &**expr,
-            _ => return
+            _ => return,
         };
 
         if let hir::ExprRet(..) = expr.node {
@@ -184,8 +193,8 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
         if let hir::ExprBlock(ref blk) = e.node {
             // Don't warn about generated blocks, that'll just pollute the output.
             if blk.rules == hir::UnsafeBlock(hir::UserProvided) &&
-                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
-                    cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
+               !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
+                cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
             }
         }
     }
@@ -210,8 +219,7 @@ impl LateLintPass for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         if let hir::StmtSemi(ref expr, _) = s.node {
             if let hir::ExprPath(..) = expr.node {
-                cx.span_lint(PATH_STATEMENTS, s.span,
-                             "path statement with no effect");
+                cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect");
             }
         }
     }
@@ -242,8 +250,8 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
                 AttributeType::Whitelisted if attr.check_name(name) => {
                     debug!("{:?} is Whitelisted", name);
                     break;
-                },
-                _ => ()
+                }
+                _ => (),
             }
         }
 
@@ -259,24 +267,22 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
             debug!("Emitting warning for: {:?}", attr);
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
             // Is it a builtin attribute that must be used at the crate level?
-            let known_crate = KNOWN_ATTRIBUTES.iter().find(|&&(name, ty, _)| {
-                attr.name() == name &&
-                ty == AttributeType::CrateLevel
-            }).is_some();
+            let known_crate = KNOWN_ATTRIBUTES.iter()
+                .find(|&&(name, ty, _)| attr.name() == name && ty == AttributeType::CrateLevel)
+                .is_some();
 
             // Has a plugin registered this attribute as one which must be used at
             // the crate level?
             let plugin_crate = plugin_attributes.iter()
-                                                .find(|&&(ref x, t)| {
-                                                        &*attr.name() == x &&
-                                                        AttributeType::CrateLevel == t
-                                                    }).is_some();
-            if  known_crate || plugin_crate {
+                .find(|&&(ref x, t)| &*attr.name() == x && AttributeType::CrateLevel == t)
+                .is_some();
+            if known_crate || plugin_crate {
                 let msg = match attr.node.style {
-                    ast::AttrStyle::Outer => "crate-level attribute should be an inner \
-                                              attribute: add an exclamation mark: #![foo]",
-                    ast::AttrStyle::Inner => "crate-level attribute should be in the \
-                                              root module",
+                    ast::AttrStyle::Outer => {
+                        "crate-level attribute should be an inner attribute: add an exclamation \
+                         mark: #![foo]"
+                    }
+                    ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
                 };
                 cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg);
             }
@@ -296,12 +302,16 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
 pub struct UnusedParens;
 
 impl UnusedParens {
-    fn check_unused_parens_core(&self, cx: &EarlyContext, value: &ast::Expr, msg: &str,
+    fn check_unused_parens_core(&self,
+                                cx: &EarlyContext,
+                                value: &ast::Expr,
+                                msg: &str,
                                 struct_lit_needs_parens: bool) {
         if let ast::ExprKind::Paren(ref inner) = value.node {
             let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&inner);
             if !necessary {
-                cx.span_lint(UNUSED_PARENS, value.span,
+                cx.span_lint(UNUSED_PARENS,
+                             value.span,
                              &format!("unnecessary parentheses around {}", msg))
             }
         }
@@ -319,8 +329,7 @@ fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
                 ast::ExprKind::AssignOp(_, ref lhs, ref rhs) |
                 ast::ExprKind::Binary(_, ref lhs, ref rhs) => {
                     // X { y: 1 } + X { y: 2 }
-                    contains_exterior_struct_lit(&lhs) ||
-                        contains_exterior_struct_lit(&rhs)
+                    contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
                 }
                 ast::ExprKind::Unary(_, ref x) |
                 ast::ExprKind::Cast(ref x, _) |
@@ -337,7 +346,7 @@ fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
                     contains_exterior_struct_lit(&exprs[0])
                 }
 
-                _ => false
+                _ => false,
             }
         }
     }
@@ -363,18 +372,20 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
             Assign(_, ref value) => (value, "assigned value", false),
             AssignOp(.., ref value) => (value, "assigned value", false),
             InPlace(_, ref value) => (value, "emplacement value", false),
-            _ => return
+            _ => return,
         };
         self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens);
     }
 
     fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) {
         let (value, msg) = match s.node {
-            ast::StmtKind::Local(ref local) => match local.init {
-                Some(ref value) => (value, "assigned value"),
-                None => return
-            },
-            _ => return
+            ast::StmtKind::Local(ref local) => {
+                match local.init {
+                    Some(ref value) => (value, "assigned value"),
+                    None => return,
+                }
+            }
+            _ => return,
         };
         self.check_unused_parens_core(cx, &value, msg, false);
     }
@@ -427,23 +438,24 @@ impl LateLintPass for UnusedAllocation {
     fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
         match e.node {
             hir::ExprBox(_) => {}
-            _ => return
+            _ => return,
         }
 
         if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
-            if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
-                ref autoref, ..
-            }) = *adjustment {
+            if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { ref autoref, .. }) =
+                *adjustment {
                 match autoref {
                     &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => {
-                        cx.span_lint(UNUSED_ALLOCATION, e.span,
+                        cx.span_lint(UNUSED_ALLOCATION,
+                                     e.span,
                                      "unnecessary allocation, use & instead");
                     }
                     &Some(adjustment::AutoPtr(_, hir::MutMutable)) => {
-                        cx.span_lint(UNUSED_ALLOCATION, e.span,
+                        cx.span_lint(UNUSED_ALLOCATION,
+                                     e.span,
                                      "unnecessary allocation, use &mut instead");
                     }
-                    _ => ()
+                    _ => (),
                 }
             }
         }
index 579a97138f250dc3c492b961f0c69038aaa66486..bdb4d383cee7d70776088839357f7a2aff9375f1 100644 (file)
@@ -32,6 +32,7 @@
 
 use rustc::mir::repr::Mir;
 
+use std::borrow::Cow;
 use std::cell::Ref;
 use std::io;
 use std::mem;
@@ -202,7 +203,7 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
         read_f64 -> f64;
         read_f32 -> f32;
         read_char -> char;
-        read_str -> String;
+        read_str -> Cow<str>;
     }
 
     fn error(&mut self, err: &str) -> Self::Error {
index acaafb35425d040c5913c37a39dad658abb494ec..3d8a10f6c31fcc2a24febf28c3e6878844da6f7c 100644 (file)
@@ -23,7 +23,7 @@
 #![feature(dotdot_in_tuple_patterns)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_lib)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
index 12f1eb8535a3eb7bd27a48a060988b326d3ed06d..02f15602d708b3472a39f42aa391282213a7f8c8 100644 (file)
@@ -26,7 +26,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
index 9149202c1c1bb516526e7d517b9a41200ccf10b5..5600669d45fb97988583fb08e6e6b300a77dacc9 100644 (file)
@@ -13,7 +13,7 @@
 //! Here we build the "reduced graph": the graph of the module tree without
 //! any imports resolved.
 
-use macros;
+use macros::{InvocationData, LegacyScope};
 use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
 use {Module, ModuleS, ModuleKind};
 use Namespace::{self, TypeNS, ValueNS};
@@ -200,16 +200,16 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                         LoadedMacroKind::Def(mut def) => {
                             let name = def.ident.name;
                             if def.use_locally {
-                                let ext = macro_rules::compile(&self.session.parse_sess, &def);
-                                let shadowing =
-                                    self.resolve_macro_name(Mark::root(), name, false).is_some();
-                                self.expansion_data[&Mark::root()].module.macros.borrow_mut()
-                                    .insert(name, macros::NameBinding {
-                                        ext: Rc::new(ext),
-                                        expansion: expansion,
-                                        shadowing: shadowing,
-                                        span: loaded_macro.import_site,
-                                    });
+                                let ext =
+                                    Rc::new(macro_rules::compile(&self.session.parse_sess, &def));
+                                if self.builtin_macros.insert(name, ext).is_some() &&
+                                   expansion != Mark::root() {
+                                    let msg = format!("`{}` is already in scope", name);
+                                    self.session.struct_span_err(loaded_macro.import_site, &msg)
+                                        .note("macro-expanded `#[macro_use]`s may not shadow \
+                                               existing macros (see RFC 1560)")
+                                        .emit();
+                                }
                                 self.macro_names.insert(name);
                             }
                             if def.export {
@@ -250,7 +250,6 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                         attr::contains_name(&item.attrs, "no_implicit_prelude")
                     },
                     normal_ancestor_id: Some(item.id),
-                    macros_escape: self.contains_macro_use(&item.attrs),
                     ..ModuleS::new(Some(parent), ModuleKind::Def(def, name))
                 });
                 self.define(parent, name, TypeNS, (module, sp, vis));
@@ -520,22 +519,26 @@ fn insert_custom_derive(&mut self, name: &str, ext: Rc<MultiItemModifier>, sp: S
 
 pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {
     pub resolver: &'a mut Resolver<'b>,
+    pub legacy_scope: LegacyScope<'b>,
     pub expansion: Mark,
 }
 
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
-    fn visit_invoc(&mut self, id: ast::NodeId) {
-        self.resolver.expansion_data.get_mut(&Mark::from_placeholder_id(id)).unwrap().module =
-            self.resolver.current_module;
+    fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
+        let invocation = self.resolver.invocations[&Mark::from_placeholder_id(id)];
+        invocation.module.set(self.resolver.current_module);
+        invocation.legacy_scope.set(self.legacy_scope);
+        invocation
     }
 }
 
 macro_rules! method {
     ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => {
         fn $visit(&mut self, node: &$ty) {
-            match node.node {
-                $invoc(..) => self.visit_invoc(node.id),
-                _ => visit::$walk(self, node),
+            if let $invoc(..) = node.node {
+                self.visit_invoc(node.id);
+            } else {
+                visit::$walk(self, node);
             }
         }
     }
@@ -543,22 +546,35 @@ fn $visit(&mut self, node: &$ty) {
 
 impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
     method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
-    method!(visit_stmt:      ast::Stmt,     ast::StmtKind::Mac,       walk_stmt);
     method!(visit_expr:      ast::Expr,     ast::ExprKind::Mac,       walk_expr);
     method!(visit_pat:       ast::Pat,      ast::PatKind::Mac,        walk_pat);
     method!(visit_ty:        ast::Ty,       ast::TyKind::Mac,         walk_ty);
 
     fn visit_item(&mut self, item: &Item) {
-        match item.node {
+        let macro_use = match item.node {
             ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder
-            ItemKind::Mac(..) => return self.visit_invoc(item.id),
-            _ => {}
-        }
+            ItemKind::Mac(..) => {
+                return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
+            }
+            ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
+            _ => false,
+        };
 
-        let parent = self.resolver.current_module;
+        let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope);
         self.resolver.build_reduced_graph_for_item(item, self.expansion);
         visit::walk_item(self, item);
         self.resolver.current_module = parent;
+        if !macro_use {
+            self.legacy_scope = legacy_scope;
+        }
+    }
+
+    fn visit_stmt(&mut self, stmt: &ast::Stmt) {
+        if let ast::StmtKind::Mac(..) = stmt.node {
+            self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id));
+        } else {
+            visit::walk_stmt(self, stmt);
+        }
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
@@ -567,10 +583,11 @@ fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
     }
 
     fn visit_block(&mut self, block: &Block) {
-        let parent = self.resolver.current_module;
+        let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope);
         self.resolver.build_reduced_graph_for_block(block);
         visit::walk_block(self, block);
         self.resolver.current_module = parent;
+        self.legacy_scope = legacy_scope;
     }
 
     fn visit_trait_item(&mut self, item: &TraitItem) {
@@ -578,7 +595,8 @@ fn visit_trait_item(&mut self, item: &TraitItem) {
         let def_id = parent.def_id().unwrap();
 
         if let TraitItemKind::Macro(_) = item.node {
-            return self.visit_invoc(item.id);
+            self.visit_invoc(item.id);
+            return
         }
 
         // Add the item to the trait info.
index b573a78d3b327c5e862b175e3c0bc9c030a8246f..83e66fdd3bc40e4c72c7bcaf2350b2be4084061d 100644 (file)
@@ -57,6 +57,7 @@
 use syntax::ext::hygiene::Mark;
 use syntax::ast::{self, FloatTy};
 use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy};
+use syntax::ext::base::SyntaxExtension;
 use syntax::parse::token::{self, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 
@@ -77,6 +78,7 @@
 use std::rc::Rc;
 
 use resolve_imports::{ImportDirective, NameResolution};
+use macros::{InvocationData, LegacyBinding, LegacyScope};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
@@ -274,13 +276,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err
         }
         ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
-            struct_span_err!(resolver.session,
+            let mut err = struct_span_err!(resolver.session,
                              span,
                              E0408,
                              "variable `{}` from pattern #{} is not bound in pattern #{}",
                              variable_name,
                              from,
-                             to)
+                             to);
+            err.span_label(span, &format!("pattern doesn't bind `{}`", variable_name));
+            err
         }
         ResolutionError::VariableBoundWithDifferentMode(variable_name,
                                                         pattern_number,
@@ -791,9 +795,6 @@ pub struct ModuleS<'a> {
     // access the children must be preceded with a
     // `populate_module_if_necessary` call.
     populated: Cell<bool>,
-
-    macros: RefCell<FnvHashMap<Name, macros::NameBinding>>,
-    macros_escape: bool,
 }
 
 pub type Module<'a> = &'a ModuleS<'a>;
@@ -811,8 +812,6 @@ fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
             globs: RefCell::new((Vec::new())),
             traits: RefCell::new(None),
             populated: Cell::new(true),
-            macros: RefCell::new(FnvHashMap()),
-            macros_escape: false,
         }
     }
 
@@ -1076,7 +1075,7 @@ pub struct Resolver<'a> {
 
     privacy_errors: Vec<PrivacyError<'a>>,
     ambiguity_errors: Vec<AmbiguityError<'a>>,
-    macro_shadowing_errors: FnvHashSet<Span>,
+    disallowed_shadowing: Vec<(Name, Span, LegacyScope<'a>)>,
 
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
@@ -1086,9 +1085,10 @@ pub struct Resolver<'a> {
     pub derive_modes: FnvHashMap<Name, Rc<MultiItemModifier>>,
     crate_loader: &'a mut CrateLoader,
     macro_names: FnvHashSet<Name>,
+    builtin_macros: FnvHashMap<Name, Rc<SyntaxExtension>>,
 
     // Maps the `Mark` of an expansion to its containing module or block.
-    expansion_data: FnvHashMap<Mark, macros::ExpansionData<'a>>,
+    invocations: FnvHashMap<Mark, &'a InvocationData<'a>>,
 }
 
 pub struct ResolverArenas<'a> {
@@ -1097,6 +1097,8 @@ pub struct ResolverArenas<'a> {
     name_bindings: arena::TypedArena<NameBinding<'a>>,
     import_directives: arena::TypedArena<ImportDirective<'a>>,
     name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
+    invocation_data: arena::TypedArena<InvocationData<'a>>,
+    legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
 }
 
 impl<'a> ResolverArenas<'a> {
@@ -1120,6 +1122,13 @@ fn alloc_import_directive(&'a self, import_directive: ImportDirective<'a>)
     fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
         self.name_resolutions.alloc(Default::default())
     }
+    fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>)
+                             -> &'a InvocationData<'a> {
+        self.invocation_data.alloc(expansion_data)
+    }
+    fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
+        self.legacy_bindings.alloc(binding)
+    }
 }
 
 impl<'a> ty::NodeIdTree for Resolver<'a> {
@@ -1205,8 +1214,9 @@ pub fn new(session: &'a Session,
         let mut definitions = Definitions::new();
         DefCollector::new(&mut definitions).collect_root();
 
-        let mut expansion_data = FnvHashMap();
-        expansion_data.insert(Mark::root(), macros::ExpansionData::root(graph_root));
+        let mut invocations = FnvHashMap();
+        invocations.insert(Mark::root(),
+                           arenas.alloc_invocation_data(InvocationData::root(graph_root)));
 
         Resolver {
             session: session,
@@ -1252,7 +1262,7 @@ pub fn new(session: &'a Session,
 
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
-            macro_shadowing_errors: FnvHashSet(),
+            disallowed_shadowing: Vec::new(),
 
             arenas: arenas,
             dummy_binding: arenas.alloc_name_binding(NameBinding {
@@ -1266,7 +1276,8 @@ pub fn new(session: &'a Session,
             derive_modes: FnvHashMap(),
             crate_loader: crate_loader,
             macro_names: FnvHashSet(),
-            expansion_data: expansion_data,
+            builtin_macros: FnvHashMap(),
+            invocations: invocations,
         }
     }
 
@@ -1277,6 +1288,8 @@ pub fn arenas() -> ResolverArenas<'a> {
             name_bindings: arena::TypedArena::new(),
             import_directives: arena::TypedArena::new(),
             name_resolutions: arena::TypedArena::new(),
+            invocation_data: arena::TypedArena::new(),
+            legacy_bindings: arena::TypedArena::new(),
         }
     }
 
@@ -3338,7 +3351,8 @@ fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
         vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self)
     }
 
-    fn report_errors(&self) {
+    fn report_errors(&mut self) {
+        self.report_shadowing_errors();
         let mut reported_spans = FnvHashSet();
 
         for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors {
@@ -3366,6 +3380,20 @@ fn report_errors(&self) {
         }
     }
 
+    fn report_shadowing_errors(&mut self) {
+        let mut reported_errors = FnvHashSet();
+        for (name, span, scope) in replace(&mut self.disallowed_shadowing, Vec::new()) {
+            if self.resolve_macro_name(scope, name, false).is_some() &&
+               reported_errors.insert((name, span)) {
+                let msg = format!("`{}` is already in scope", name);
+                self.session.struct_span_err(span, &msg)
+                    .note("macro-expanded `macro_rules!`s may not shadow \
+                           existing macros (see RFC 1560)")
+                    .emit();
+            }
+        }
+    }
+
     fn report_conflict(&self,
                        parent: Module,
                        name: Name,
index 3f6c69278bee8a2ec91472228925a01d262f4909..86ab077191eefd9429fcb24eb6a4e6d16e85eb58 100644 (file)
 use build_reduced_graph::BuildReducedGraphVisitor;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::map::{self, DefCollector};
+use rustc::util::nodemap::FnvHashMap;
+use std::cell::Cell;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::errors::DiagnosticBuilder;
-use syntax::ext::base::{self, MultiModifier, MultiDecorator, MultiItemModifier};
+use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator, MultiItemModifier};
 use syntax::ext::base::{NormalTT, SyntaxExtension};
 use syntax::ext::expand::{Expansion, Invocation, InvocationKind};
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::parse::token::intern;
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax_pos::{Span, DUMMY_SP};
-
-// FIXME(jseyfried) Merge with `::NameBinding`.
-pub struct NameBinding {
-    pub ext: Rc<SyntaxExtension>,
-    pub expansion: Mark,
-    pub shadowing: bool,
-    pub span: Span,
-}
+use syntax_pos::Span;
 
 #[derive(Clone)]
-pub struct ExpansionData<'a> {
-    backtrace: SyntaxContext,
-    pub module: Module<'a>,
+pub struct InvocationData<'a> {
+    pub module: Cell<Module<'a>>,
     def_index: DefIndex,
     // True if this expansion is in a `const_integer` position, for example `[u32; m!()]`.
     // c.f. `DefCollector::visit_ast_const_integer`.
     const_integer: bool,
+    // The scope in which the invocation path is resolved.
+    pub legacy_scope: Cell<LegacyScope<'a>>,
+    // The smallest scope that includes this invocation's expansion,
+    // or `Empty` if this invocation has not been expanded yet.
+    pub expansion: Cell<LegacyScope<'a>>,
 }
 
-impl<'a> ExpansionData<'a> {
+impl<'a> InvocationData<'a> {
     pub fn root(graph_root: Module<'a>) -> Self {
-        ExpansionData {
-            backtrace: SyntaxContext::empty(),
-            module: graph_root,
+        InvocationData {
+            module: Cell::new(graph_root),
             def_index: CRATE_DEF_INDEX,
             const_integer: false,
+            legacy_scope: Cell::new(LegacyScope::Empty),
+            expansion: Cell::new(LegacyScope::Empty),
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum LegacyScope<'a> {
+    Empty,
+    Invocation(&'a InvocationData<'a>), // The scope of the invocation, not including its expansion
+    Expansion(&'a InvocationData<'a>), // The scope of the invocation, including its expansion
+    Binding(&'a LegacyBinding<'a>),
+}
+
+impl<'a> LegacyScope<'a> {
+    fn simplify_expansion(mut invoc: &'a InvocationData<'a>) -> Self {
+        while let LegacyScope::Invocation(_) = invoc.expansion.get() {
+            match invoc.legacy_scope.get() {
+                LegacyScope::Expansion(new_invoc) => invoc = new_invoc,
+                LegacyScope::Binding(_) => break,
+                scope @ _ => return scope,
+            }
         }
+        LegacyScope::Expansion(invoc)
     }
 }
 
+pub struct LegacyBinding<'a> {
+    parent: LegacyScope<'a>,
+    name: ast::Name,
+    ext: Rc<SyntaxExtension>,
+    span: Span,
+}
+
+pub type LegacyImports = FnvHashMap<ast::Name, (Rc<SyntaxExtension>, Span)>;
+
 impl<'a> base::Resolver for Resolver<'a> {
     fn next_node_id(&mut self) -> ast::NodeId {
         self.session.next_node_id()
@@ -61,19 +90,28 @@ fn next_node_id(&mut self) -> ast::NodeId {
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
         let mark = Mark::fresh();
         let module = self.module_map[&id];
-        self.expansion_data.insert(mark, ExpansionData {
-            backtrace: SyntaxContext::empty(),
-            module: module,
+        self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
+            module: Cell::new(module),
             def_index: module.def_id().unwrap().index,
             const_integer: false,
-        });
+            legacy_scope: Cell::new(LegacyScope::Empty),
+            expansion: Cell::new(LegacyScope::Empty),
+        }));
         mark
     }
 
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
-        self.collect_def_ids(mark, expansion);
-        self.current_module = self.expansion_data[&mark].module;
-        expansion.visit_with(&mut BuildReducedGraphVisitor { resolver: self, expansion: mark });
+        let invocation = self.invocations[&mark];
+        self.collect_def_ids(invocation, expansion);
+
+        self.current_module = invocation.module.get();
+        let mut visitor = BuildReducedGraphVisitor {
+            resolver: self,
+            legacy_scope: LegacyScope::Invocation(invocation),
+            expansion: mark,
+        };
+        expansion.visit_with(&mut visitor);
+        invocation.expansion.set(visitor.legacy_scope);
     }
 
     fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) {
@@ -81,17 +119,14 @@ fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) {
             self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
         }
         if def.use_locally {
-            let ExpansionData { mut module, backtrace, .. } = self.expansion_data[&scope];
-            while module.macros_escape {
-                module = module.parent.unwrap();
-            }
-            let binding = NameBinding {
+            let invocation = self.invocations[&scope];
+            let binding = self.arenas.alloc_legacy_binding(LegacyBinding {
+                parent: invocation.legacy_scope.get(),
+                name: def.ident.name,
                 ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
-                expansion: backtrace.data().prev_ctxt.data().outer_mark,
-                shadowing: self.resolve_macro_name(scope, def.ident.name, false).is_some(),
                 span: def.span,
-            };
-            module.macros.borrow_mut().insert(def.ident.name, binding);
+            });
+            invocation.legacy_scope.set(LegacyScope::Binding(binding));
             self.macro_names.insert(def.ident.name);
         }
         if def.export {
@@ -104,12 +139,7 @@ fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         if let NormalTT(..) = *ext {
             self.macro_names.insert(ident.name);
         }
-        self.graph_root.macros.borrow_mut().insert(ident.name, NameBinding {
-            ext: ext,
-            expansion: Mark::root(),
-            shadowing: false,
-            span: DUMMY_SP,
-        });
+        self.builtin_macros.insert(ident.name, ext);
     }
 
     fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>) {
@@ -119,8 +149,8 @@ fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>) {
     fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
         for i in 0..attrs.len() {
             let name = intern(&attrs[i].name());
-            match self.expansion_data[&Mark::root()].module.macros.borrow().get(&name) {
-                Some(binding) => match *binding.ext {
+            match self.builtin_macros.get(&name) {
+                Some(ext) => match **ext {
                     MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
                         return Some(attrs.remove(i))
                     }
@@ -132,7 +162,8 @@ fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::At
         None
     }
 
-    fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<SyntaxExtension>> {
+    fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool)
+                     -> Result<Rc<SyntaxExtension>, Determinacy> {
         let (name, span) = match invoc.kind {
             InvocationKind::Bang { ref mac, .. } => {
                 let path = &mac.node.path;
@@ -140,19 +171,27 @@ fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<Syntax
                    !path.segments[0].parameters.is_empty() {
                     self.session.span_err(path.span,
                                           "expected macro name without module separators");
-                    return None;
+                    return Err(Determinacy::Determined);
                 }
                 (path.segments[0].identifier.name, path.span)
             }
             InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span),
         };
 
-        self.resolve_macro_name(scope, name, true).or_else(|| {
-            let mut err =
-                self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name));
-            self.suggest_macro_name(&name.as_str(), &mut err);
-            err.emit();
-            None
+        let invocation = self.invocations[&scope];
+        if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() {
+            invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent));
+        }
+        self.resolve_macro_name(invocation.legacy_scope.get(), name, true).ok_or_else(|| {
+            if force {
+                let mut err =
+                    self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name));
+                self.suggest_macro_name(&name.as_str(), &mut err);
+                err.emit();
+                Determinacy::Determined
+            } else {
+                Determinacy::Undetermined
+            }
         })
     }
 
@@ -162,36 +201,40 @@ fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModif
 }
 
 impl<'a> Resolver<'a> {
-    pub fn resolve_macro_name(&mut self, scope: Mark, name: ast::Name, record_used: bool)
+    pub fn resolve_macro_name(&mut self,
+                              mut scope: LegacyScope<'a>,
+                              name: ast::Name,
+                              record_used: bool)
                               -> Option<Rc<SyntaxExtension>> {
-        let ExpansionData { mut module, backtrace, .. } = self.expansion_data[&scope];
+        let mut relative_depth: u32 = 0;
         loop {
-            if let Some(binding) = module.macros.borrow().get(&name) {
-                let mut backtrace = backtrace.data();
-                while binding.expansion != backtrace.outer_mark {
-                    if backtrace.outer_mark != Mark::root() {
-                        backtrace = backtrace.prev_ctxt.data();
-                        continue
+            scope = match scope {
+                LegacyScope::Empty => break,
+                LegacyScope::Expansion(invocation) => {
+                    if let LegacyScope::Empty = invocation.expansion.get() {
+                        invocation.legacy_scope.get()
+                    } else {
+                        relative_depth += 1;
+                        invocation.expansion.get()
                     }
-
-                    if record_used && binding.shadowing &&
-                       self.macro_shadowing_errors.insert(binding.span) {
-                        let msg = format!("`{}` is already in scope", name);
-                        self.session.struct_span_err(binding.span, &msg)
-                            .note("macro-expanded `macro_rules!`s and `#[macro_use]`s \
-                                   may not shadow existing macros (see RFC 1560)")
-                            .emit();
+                }
+                LegacyScope::Invocation(invocation) => {
+                    relative_depth = relative_depth.saturating_sub(1);
+                    invocation.legacy_scope.get()
+                }
+                LegacyScope::Binding(binding) => {
+                    if binding.name == name {
+                        if record_used && relative_depth > 0 {
+                            self.disallowed_shadowing.push((name, binding.span, binding.parent));
+                        }
+                        return Some(binding.ext.clone());
                     }
-                    break
+                    binding.parent
                 }
-                return Some(binding.ext.clone());
-            }
-            match module.parent {
-                Some(parent) => module = parent,
-                None => break,
-            }
+            };
         }
-        None
+
+        self.builtin_macros.get(&name).cloned()
     }
 
     fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) {
@@ -204,15 +247,19 @@ fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) {
         }
     }
 
-    fn collect_def_ids(&mut self, mark: Mark, expansion: &Expansion) {
-        let expansion_data = &mut self.expansion_data;
-        let ExpansionData { backtrace, def_index, const_integer, module } = expansion_data[&mark];
+    fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Expansion) {
+        let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
+        let InvocationData { def_index, const_integer, .. } = *invocation;
+
         let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
-            expansion_data.entry(invoc.mark).or_insert(ExpansionData {
-                backtrace: backtrace.apply_mark(invoc.mark),
-                def_index: invoc.def_index,
-                const_integer: invoc.const_integer,
-                module: module,
+            invocations.entry(invoc.mark).or_insert_with(|| {
+                arenas.alloc_invocation_data(InvocationData {
+                    def_index: invoc.def_index,
+                    const_integer: invoc.const_integer,
+                    module: Cell::new(graph_root),
+                    expansion: Cell::new(LegacyScope::Empty),
+                    legacy_scope: Cell::new(LegacyScope::Empty),
+                })
             });
         };
 
index 4689c4ded5c0a4aaec56e47266575f531eb4d4ee..0939e6f1644de8fb496b8d565da955c0c5105459 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use self::Determinacy::*;
 use self::ImportDirectiveSubclass::*;
 
 use Module;
@@ -26,6 +25,7 @@
 use rustc::hir::def::*;
 
 use syntax::ast::{NodeId, Name};
+use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
 
@@ -37,12 +37,6 @@ pub fn resolve_imports(&mut self) {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum Determinacy {
-    Determined,
-    Undetermined,
-}
-
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
 pub enum ImportDirectiveSubclass<'a> {
@@ -197,7 +191,8 @@ pub fn resolve_name_in_module(&mut self,
         // If the resolution doesn't depend on glob definability, check privacy and return.
         if let Some(result) = self.try_result(&resolution, ns) {
             return result.and_then(|binding| {
-                if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) {
+                if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) ||
+                   binding.is_extern_crate() { // c.f. issue #37020
                     Success(binding)
                 } else {
                     Failed(None)
index 6ae5fc1657aa728359f7b8f27df4743b537ec15a..9b893e19894e858d5ed2d46ee029ce6cd1f5b65f 100644 (file)
@@ -114,7 +114,8 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
             if tys.len() != 2 {
                 return None;
             }
-            Some([tys[0], tys[1]])
+            Some([ccx.tcx().normalize_associated_type(&tys[0]),
+                  ccx.tcx().normalize_associated_type(&tys[1])])
         }
         _ => None
     }
index 41c8d565d418c93a75e1639378bf76a08b84dc52..81c0c184f66b2e76441d1c79ae9443060cbbe449 100644 (file)
@@ -36,7 +36,7 @@
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(unicode)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 use rustc::dep_graph::WorkProduct;
 
index 1f34cee5143c61e9e147bd4584efbaa3bfb121f1..cb9b162cabe11911e3180c4acee2ad39c4ad0034 100644 (file)
@@ -82,7 +82,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
index 2ecb071fcc2a4228694c8eeb47c693b19b246fd9..d78f00497ca557694b44a8f19b82218f382c6342 100644 (file)
 use std::fs::File;
 use std::io::prelude::*;
 use std::io;
-use std::path::{PathBuf, Path};
+use std::path::Path;
 use std::str;
 
 #[derive(Clone)]
 pub struct ExternalHtml{
+    /// Content that will be included inline in the <head> section of a
+    /// rendered Markdown file or generated documentation
     pub in_header: String,
+    /// Content that will be included inline between <body> and the content of
+    /// a rendered Markdown file or generated documentation
     pub before_content: String,
+    /// Content that will be included inline between the content and </body> of
+    /// a rendered Markdown file or generated documentation
     pub after_content: String
 }
 
 impl ExternalHtml {
     pub fn load(in_header: &[String], before_content: &[String], after_content: &[String])
             -> Option<ExternalHtml> {
-        match (load_external_files(in_header),
-               load_external_files(before_content),
-               load_external_files(after_content)) {
-            (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml {
-                in_header: ih,
-                before_content: bc,
-                after_content: ac
-            }),
-            _ => None
-        }
+        load_external_files(in_header)
+            .and_then(|ih|
+                load_external_files(before_content)
+                    .map(|bc| (ih, bc))
+            )
+            .and_then(|(ih, bc)|
+                load_external_files(after_content)
+                    .map(|ac| (ih, bc, ac))
+            )
+            .map(|(ih, bc, ac)|
+                ExternalHtml {
+                    in_header: ih,
+                    before_content: bc,
+                    after_content: ac,
+                }
+            )
     }
 }
 
-pub fn load_string(input: &Path) -> io::Result<Option<String>> {
-    let mut f = File::open(input)?;
-    let mut d = Vec::new();
-    f.read_to_end(&mut d)?;
-    Ok(str::from_utf8(&d).map(|s| s.to_string()).ok())
+pub enum LoadStringError {
+    ReadFail,
+    BadUtf8,
 }
 
-macro_rules! load_or_return {
-    ($input: expr, $cant_read: expr, $not_utf8: expr) => {
-        {
-            let input = PathBuf::from(&$input[..]);
-            match ::externalfiles::load_string(&input) {
-                Err(e) => {
-                    let _ = writeln!(&mut io::stderr(),
-                                     "error reading `{}`: {}", input.display(), e);
-                    return $cant_read;
-                }
-                Ok(None) => {
-                    let _ = writeln!(&mut io::stderr(),
-                                     "error reading `{}`: not UTF-8", input.display());
-                    return $not_utf8;
-                }
-                Ok(Some(s)) => s
-            }
+pub fn load_string<P: AsRef<Path>>(file_path: P) -> Result<String, LoadStringError> {
+    let file_path = file_path.as_ref();
+    let mut contents = vec![];
+    let result = File::open(file_path)
+                      .and_then(|mut f| f.read_to_end(&mut contents));
+    if let Err(e) = result {
+        let _ = writeln!(&mut io::stderr(),
+                         "error reading `{}`: {}",
+                         file_path.display(), e);
+        return Err(LoadStringError::ReadFail);
+    }
+    match str::from_utf8(&contents) {
+        Ok(s) => Ok(s.to_string()),
+        Err(_) => {
+            let _ = writeln!(&mut io::stderr(),
+                             "error reading `{}`: not UTF-8",
+                             file_path.display());
+            Err(LoadStringError::BadUtf8)
         }
     }
 }
 
-pub fn load_external_files(names: &[String]) -> Option<String> {
+fn load_external_files(names: &[String]) -> Option<String> {
     let mut out = String::new();
     for name in names {
-        out.push_str(&*load_or_return!(&name, None, None));
+        let s = match load_string(name) {
+            Ok(s) => s,
+            Err(_) => return None,
+        };
+        out.push_str(&s);
         out.push('\n');
     }
     Some(out)
index 881352cb73e181902748b7c5abdff3c86254d0ea..d1fe7853445f204cb3c6be10f2e7964933b58c07 100644 (file)
@@ -104,6 +104,7 @@ pub enum Class {
     Lifetime,
     PreludeTy,
     PreludeVal,
+    QuestionMark,
 }
 
 /// Trait that controls writing the output of syntax highlighting. Users should
@@ -237,8 +238,10 @@ fn write_token<W: Writer>(&mut self,
             token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
                 token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
                 token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
-                token::CloseDelim(token::NoDelim) |
-                token::Question => Class::None,
+                token::CloseDelim(token::NoDelim) => Class::None,
+
+            token::Question => Class::QuestionMark,
+
             token::Dollar => {
                 if self.lexer.peek().tok.is_ident() {
                     self.in_macro_nonterminal = true;
@@ -348,6 +351,7 @@ pub fn rustdoc_class(self) -> &'static str {
             Class::Lifetime => "lifetime",
             Class::PreludeTy => "prelude-ty",
             Class::PreludeVal => "prelude-val",
+            Class::QuestionMark => "question-mark"
         }
     }
 }
index f8133ea49cebae5b63edefd319466a3fbb98568f..85ec4fe3f3f4d32c2d7b60a2c0576e3ca9512489 100644 (file)
@@ -570,6 +570,10 @@ pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
 pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
 pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
 pre.rust .lifetime { color: #B76514; }
+pre.rust .question-mark {
+    color: #ff9011;
+    font-weight: bold;
+}
 
 .rusttest { display: none; }
 pre.rust { position: relative; }
index 006dda7d661995d9e67041b156d54765d4a48d98..0be36eb3a85088d7dd7125e95e88fa21468cfd0e 100644 (file)
@@ -28,7 +28,7 @@
 #![feature(staged_api)]
 #![feature(test)]
 #![feature(unicode)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 
 extern crate arena;
 extern crate getopts;
index 1421a3c78fc5a40a7c4803b2cc21ff73677cc4c4..f708aa5461999be4de11f6e424e78f849dee9e6e 100644 (file)
@@ -19,7 +19,7 @@
 use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::Externs;
 
-use externalfiles::ExternalHtml;
+use externalfiles::{ExternalHtml, LoadStringError, load_string};
 
 use html::render::reset_ids;
 use html::escape::Escape;
@@ -58,7 +58,11 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
         css.push_str(&s)
     }
 
-    let input_str = load_or_return!(input, 1, 2);
+    let input_str = match load_string(input) {
+        Ok(s) => s,
+        Err(LoadStringError::ReadFail) => return 1,
+        Err(LoadStringError::BadUtf8) => return 2,
+    };
     let playground = matches.opt_str("markdown-playground-url");
     if playground.is_some() {
         markdown::PLAYGROUND_KRATE.with(|s| { *s.borrow_mut() = Some(None); });
@@ -144,7 +148,11 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
 /// Run any tests/code examples in the markdown file `input`.
 pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
             mut test_args: Vec<String>) -> isize {
-    let input_str = load_or_return!(input, 1, 2);
+    let input_str = match load_string(input) {
+        Ok(s) => s,
+        Err(LoadStringError::ReadFail) => return 1,
+        Err(LoadStringError::BadUtf8) => return 2,
+    };
 
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
index 5e25c61bae995b254b239644df01c38a3b25fd12..3e976c90628308c25669c2a80b337ab6ab7e6bd8 100644 (file)
 use self::ParserState::*;
 use self::InternalStackElement::*;
 
+use std::borrow::Cow;
 use std::collections::{HashMap, BTreeMap};
 use std::io::prelude::*;
 use std::io;
@@ -2081,9 +2082,7 @@ impl Decoder {
     pub fn new(json: Json) -> Decoder {
         Decoder { stack: vec![json] }
     }
-}
 
-impl Decoder {
     fn pop(&mut self) -> Json {
         self.stack.pop().unwrap()
     }
@@ -2182,8 +2181,8 @@ fn read_char(&mut self) -> DecodeResult<char> {
         Err(ExpectedError("single character string".to_owned(), format!("{}", s)))
     }
 
-    fn read_str(&mut self) -> DecodeResult<string::String> {
-        expect!(self.pop(), String)
+    fn read_str(&mut self) -> DecodeResult<Cow<str>> {
+        expect!(self.pop(), String).map(Cow::Owned)
     }
 
     fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T> where
index 7cb02e2412c65808e6363456bce5b9c0901f90ba..884f24ddc4c75a8b739c83096d9322bc30998007 100644 (file)
@@ -35,7 +35,7 @@
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(unicode)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![cfg_attr(test, feature(test))]
 
 // test harness access
index e97834f63cee4eaf7756c0e884a852fef11654a7..a2c0ca954472c3d36676336fbc9b9f20e76e08ef 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
+use std::borrow::Cow;
 use std::io::{self, Write};
 use serialize;
 
@@ -246,11 +247,11 @@ fn read_char(&mut self) -> Result<char, Self::Error> {
         Ok(::std::char::from_u32(bits).unwrap())
     }
 
-    fn read_str(&mut self) -> Result<String, Self::Error> {
+    fn read_str(&mut self) -> Result<Cow<str>, Self::Error> {
         let len = self.read_usize()?;
         let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap();
         self.position += len;
-        Ok(s.to_string())
+        Ok(Cow::Borrowed(s))
     }
 
     fn error(&mut self, err: &str) -> Self::Error {
index 6650a981884d8eaad31fd551d948c72161a7fead..c4613c661a84bf26b8a3ca8bc840de91a5bc75cb 100644 (file)
@@ -14,6 +14,7 @@
 Core encoding and decoding interfaces.
 */
 
+use std::borrow::Cow;
 use std::intrinsics;
 use std::path;
 use std::rc::Rc;
@@ -156,7 +157,7 @@ pub trait Decoder {
     fn read_f64(&mut self) -> Result<f64, Self::Error>;
     fn read_f32(&mut self) -> Result<f32, Self::Error>;
     fn read_char(&mut self) -> Result<char, Self::Error>;
-    fn read_str(&mut self) -> Result<String, Self::Error>;
+    fn read_str(&mut self) -> Result<Cow<str>, Self::Error>;
 
     // Compound types:
     fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
@@ -401,7 +402,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 
 impl Decodable for String {
     fn decode<D: Decoder>(d: &mut D) -> Result<String, D::Error> {
-        d.read_str()
+        Ok(d.read_str()?.into_owned())
     }
 }
 
index b12f132a3a97f7db7edc003200c2e6ad202bea78..b357bc3552a5e807b7e483e3665f7816019b420a 100644 (file)
 const EMPTY_BUCKET: u64 = 0;
 
 /// The raw hashtable, providing safe-ish access to the unzipped and highly
-/// optimized arrays of hashes, keys, and values.
+/// optimized arrays of hashes, and key-value pairs.
 ///
-/// This design uses less memory and is a lot faster than the naive
-/// `Vec<Option<u64, K, V>>`, because we don't pay for the overhead of an
+/// This design is a lot faster than the naive
+/// `Vec<Option<(u64, K, V)>>`, because we don't pay for the overhead of an
 /// option on every element, and we get a generally more cache-aware design.
 ///
 /// Essential invariants of this structure:
 ///     which will likely map to the same bucket, while not being confused
 ///     with "empty".
 ///
-///   - All three "arrays represented by pointers" are the same length:
+///   - Both "arrays represented by pointers" are the same length:
 ///     `capacity`. This is set at creation and never changes. The arrays
-///     are unzipped to save space (we don't have to pay for the padding
-///     between odd sized elements, such as in a map from u64 to u8), and
-///     be more cache aware (scanning through 8 hashes brings in at most
-///     2 cache lines, since they're all right beside each other).
+///     are unzipped and are more cache aware (scanning through 8 hashes
+///     brings in at most 2 cache lines, since they're all right beside each
+///     other). This layout may waste space in padding such as in a map from
+///     u64 to u8, but is a more cache conscious layout as the key-value pairs
+///     are only very shortly probed and the desired value will be in the same
+///     or next cache line.
 ///
 /// You can kind of think of this module/data structure as a safe wrapper
 /// around just the "table" part of the hashtable. It enforces some
 /// invariants at the type level and employs some performance trickery,
-/// but in general is just a tricked out `Vec<Option<u64, K, V>>`.
+/// but in general is just a tricked out `Vec<Option<(u64, K, V)>>`.
 pub struct RawTable<K, V> {
     capacity: usize,
     size: usize,
@@ -74,10 +76,8 @@ unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {}
 
 struct RawBucket<K, V> {
     hash: *mut u64,
-
     // We use *const to ensure covariance with respect to K and V
-    key: *const K,
-    val: *const V,
+    pair: *const (K, V),
     _marker: marker::PhantomData<(K, V)>,
 }
 
@@ -181,8 +181,7 @@ impl<K, V> RawBucket<K, V> {
     unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
         RawBucket {
             hash: self.hash.offset(count),
-            key: self.key.offset(count),
-            val: self.val.offset(count),
+            pair: self.pair.offset(count),
             _marker: marker::PhantomData,
         }
     }
@@ -370,8 +369,7 @@ impl<K, V, M> EmptyBucket<K, V, M>
     pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
         unsafe {
             *self.raw.hash = hash.inspect();
-            ptr::write(self.raw.key as *mut K, key);
-            ptr::write(self.raw.val as *mut V, value);
+            ptr::write(self.raw.pair as *mut (K, V), (key, value));
 
             self.table.borrow_table_mut().size += 1;
         }
@@ -430,7 +428,7 @@ pub fn hash(&self) -> SafeHash {
 
     /// Gets references to the key and value at a given index.
     pub fn read(&self) -> (&K, &V) {
-        unsafe { (&*self.raw.key, &*self.raw.val) }
+        unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
     }
 }
 
@@ -447,13 +445,14 @@ pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
 
         unsafe {
             *self.raw.hash = EMPTY_BUCKET;
+            let (k, v) = ptr::read(self.raw.pair);
             (EmptyBucket {
                  raw: self.raw,
                  idx: self.idx,
                  table: self.table,
              },
-             ptr::read(self.raw.key),
-             ptr::read(self.raw.val))
+            k,
+            v)
         }
     }
 }
@@ -466,8 +465,7 @@ impl<K, V, M> FullBucket<K, V, M>
     pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) {
         unsafe {
             let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h);
-            let old_key = ptr::replace(self.raw.key as *mut K, k);
-            let old_val = ptr::replace(self.raw.val as *mut V, v);
+            let (old_key, old_val) = ptr::replace(self.raw.pair as *mut (K, V), (k, v));
 
             (old_hash, old_key, old_val)
         }
@@ -479,7 +477,8 @@ impl<K, V, M> FullBucket<K, V, M>
 {
     /// Gets mutable references to the key and value at a given index.
     pub fn read_mut(&mut self) -> (&mut K, &mut V) {
-        unsafe { (&mut *(self.raw.key as *mut K), &mut *(self.raw.val as *mut V)) }
+        let pair_mut = self.raw.pair as *mut (K, V);
+        unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
     }
 }
 
@@ -492,7 +491,7 @@ impl<'t, K, V, M> FullBucket<K, V, M>
     /// in exchange for this, the returned references have a longer lifetime
     /// than the references returned by `read()`.
     pub fn into_refs(self) -> (&'t K, &'t V) {
-        unsafe { (&*self.raw.key, &*self.raw.val) }
+        unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
     }
 }
 
@@ -502,7 +501,8 @@ impl<'t, K, V, M> FullBucket<K, V, M>
     /// This works similarly to `into_refs`, exchanging a bucket state
     /// for mutable references into the table.
     pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
-        unsafe { (&mut *(self.raw.key as *mut K), &mut *(self.raw.val as *mut V)) }
+        let pair_mut = self.raw.pair as *mut (K, V);
+        unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
     }
 }
 
@@ -517,8 +517,7 @@ pub fn full(&self) -> &FullBucket<K, V, M> {
     pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
         unsafe {
             *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
-            ptr::copy_nonoverlapping(self.full.raw.key, self.gap.raw.key as *mut K, 1);
-            ptr::copy_nonoverlapping(self.full.raw.val, self.gap.raw.val as *mut V, 1);
+            ptr::copy_nonoverlapping(self.full.raw.pair, self.gap.raw.pair as *mut (K, V), 1);
         }
 
         let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
@@ -560,49 +559,42 @@ fn test_rounding() {
     assert_eq!(round_up_to_next(5, 4), 8);
 }
 
-// Returns a tuple of (key_offset, val_offset),
+// Returns a tuple of (pairs_offset, end_of_pairs_offset),
 // from the start of a mallocated array.
 #[inline]
 fn calculate_offsets(hashes_size: usize,
-                     keys_size: usize,
-                     keys_align: usize,
-                     vals_align: usize)
+                     pairs_size: usize,
+                     pairs_align: usize)
                      -> (usize, usize, bool) {
-    let keys_offset = round_up_to_next(hashes_size, keys_align);
-    let (end_of_keys, oflo) = keys_offset.overflowing_add(keys_size);
-
-    let vals_offset = round_up_to_next(end_of_keys, vals_align);
+    let pairs_offset = round_up_to_next(hashes_size, pairs_align);
+    let (end_of_pairs, oflo) = pairs_offset.overflowing_add(pairs_size);
 
-    (keys_offset, vals_offset, oflo)
+    (pairs_offset, end_of_pairs, oflo)
 }
 
 // Returns a tuple of (minimum required malloc alignment, hash_offset,
 // array_size), from the start of a mallocated array.
 fn calculate_allocation(hash_size: usize,
                         hash_align: usize,
-                        keys_size: usize,
-                        keys_align: usize,
-                        vals_size: usize,
-                        vals_align: usize)
+                        pairs_size: usize,
+                        pairs_align: usize)
                         -> (usize, usize, usize, bool) {
     let hash_offset = 0;
-    let (_, vals_offset, oflo) = calculate_offsets(hash_size, keys_size, keys_align, vals_align);
-    let (end_of_vals, oflo2) = vals_offset.overflowing_add(vals_size);
+    let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align);
 
-    let align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
+    let align = cmp::max(hash_align, pairs_align);
 
-    (align, hash_offset, end_of_vals, oflo || oflo2)
+    (align, hash_offset, end_of_pairs, oflo)
 }
 
 #[test]
 fn test_offset_calculation() {
-    assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4),
-               (8, 0, 148, false));
-    assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6, false));
-    assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48, false));
-    assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144, false));
-    assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5, false));
-    assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24, false));
+    assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 0, 144, false));
+    assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 0, 5, false));
+    assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 0, 20, false));
+    assert_eq!(calculate_offsets(128, 15, 4), (128, 143, false));
+    assert_eq!(calculate_offsets(3, 2, 4), (4, 6, false));
+    assert_eq!(calculate_offsets(6, 12, 4), (8, 20, false));
 }
 
 impl<K, V> RawTable<K, V> {
@@ -620,11 +612,10 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
 
         // No need for `checked_mul` before a more restrictive check performed
         // later in this method.
-        let hashes_size = capacity * size_of::<u64>();
-        let keys_size = capacity * size_of::<K>();
-        let vals_size = capacity * size_of::<V>();
+        let hashes_size = capacity.wrapping_mul(size_of::<u64>());
+        let pairs_size = capacity.wrapping_mul(size_of::<(K, V)>());
 
-        // Allocating hashmaps is a little tricky. We need to allocate three
+        // Allocating hashmaps is a little tricky. We need to allocate two
         // arrays, but since we know their sizes and alignments up front,
         // we just allocate a single array, and then have the subarrays
         // point into it.
@@ -632,27 +623,20 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         // This is great in theory, but in practice getting the alignment
         // right is a little subtle. Therefore, calculating offsets has been
         // factored out into a different function.
-        let (malloc_alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
-                                                                               align_of::<u64>(),
-                                                                               keys_size,
-                                                                               align_of::<K>(),
-                                                                               vals_size,
-                                                                               align_of::<V>());
-
+        let (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
+                                                                        align_of::<u64>(),
+                                                                        pairs_size,
+                                                                        align_of::<(K, V)>());
         assert!(!oflo, "capacity overflow");
 
         // One check for overflow that covers calculation and rounding of size.
-        let size_of_bucket = size_of::<u64>()
-            .checked_add(size_of::<K>())
-            .unwrap()
-            .checked_add(size_of::<V>())
-            .unwrap();
+        let size_of_bucket = size_of::<u64>().checked_add(size_of::<(K, V)>()).unwrap();
         assert!(size >=
                 capacity.checked_mul(size_of_bucket)
                     .expect("capacity overflow"),
                 "capacity overflow");
 
-        let buffer = allocate(size, malloc_alignment);
+        let buffer = allocate(size, alignment);
         if buffer.is_null() {
             ::alloc::oom()
         }
@@ -669,17 +653,16 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
 
     fn first_bucket_raw(&self) -> RawBucket<K, V> {
         let hashes_size = self.capacity * size_of::<u64>();
-        let keys_size = self.capacity * size_of::<K>();
+        let pairs_size = self.capacity * size_of::<(K, V)>();
 
-        let buffer = *self.hashes as *const u8;
-        let (keys_offset, vals_offset, oflo) =
-            calculate_offsets(hashes_size, keys_size, align_of::<K>(), align_of::<V>());
+        let buffer = *self.hashes as *mut u8;
+        let (pairs_offset, _, oflo) =
+            calculate_offsets(hashes_size, pairs_size, align_of::<(K, V)>());
         debug_assert!(!oflo, "capacity overflow");
         unsafe {
             RawBucket {
                 hash: *self.hashes,
-                key: buffer.offset(keys_offset as isize) as *const K,
-                val: buffer.offset(vals_offset as isize) as *const V,
+                pair: buffer.offset(pairs_offset as isize) as *const _,
                 _marker: marker::PhantomData,
             }
         }
@@ -844,7 +827,7 @@ fn next(&mut self) -> Option<(K, V)> {
 
                 if *self.raw.hash != EMPTY_BUCKET {
                     self.elems_left -= 1;
-                    return Some((ptr::read(self.raw.key), ptr::read(self.raw.val)));
+                    return Some(ptr::read(self.raw.pair));
                 }
             }
         }
@@ -909,7 +892,7 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
         self.iter.next().map(|bucket| {
             self.elems_left -= 1;
-            unsafe { (&*bucket.key, &*bucket.val) }
+            unsafe { (&(*bucket.pair).0, &(*bucket.pair).1) }
         })
     }
 
@@ -929,7 +912,8 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
         self.iter.next().map(|bucket| {
             self.elems_left -= 1;
-            unsafe { (&*bucket.key, &mut *(bucket.val as *mut V)) }
+            let pair_mut = bucket.pair as *mut (K, V);
+            unsafe { (&(*pair_mut).0, &mut (*pair_mut).1) }
         })
     }
 
@@ -950,7 +934,8 @@ fn next(&mut self) -> Option<(SafeHash, K, V)> {
         self.iter.next().map(|bucket| {
             self.table.size -= 1;
             unsafe {
-                (SafeHash { hash: *bucket.hash }, ptr::read(bucket.key), ptr::read(bucket.val))
+                let (k, v) = ptr::read(bucket.pair);
+                (SafeHash { hash: *bucket.hash }, k, v)
             }
         })
     }
@@ -974,9 +959,8 @@ fn next(&mut self) -> Option<(SafeHash, K, V)> {
         self.iter.next().map(|bucket| {
             unsafe {
                 (**self.table).size -= 1;
-                (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) },
-                 ptr::read(bucket.key),
-                 ptr::read(bucket.val))
+                let (k, v) = ptr::read(bucket.pair);
+                (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) }, k, v)
             }
         })
     }
@@ -1015,8 +999,7 @@ fn clone(&self) -> RawTable<K, V> {
                                 (full.hash(), k.clone(), v.clone())
                             };
                             *new_buckets.raw.hash = h.inspect();
-                            ptr::write(new_buckets.raw.key as *mut K, k);
-                            ptr::write(new_buckets.raw.val as *mut V, v);
+                            ptr::write(new_buckets.raw.pair as *mut (K, V), (k, v));
                         }
                         Empty(..) => {
                             *new_buckets.raw.hash = EMPTY_BUCKET;
@@ -1054,14 +1037,11 @@ fn drop(&mut self) {
         }
 
         let hashes_size = self.capacity * size_of::<u64>();
-        let keys_size = self.capacity * size_of::<K>();
-        let vals_size = self.capacity * size_of::<V>();
+        let pairs_size = self.capacity * size_of::<(K, V)>();
         let (align, _, size, oflo) = calculate_allocation(hashes_size,
                                                           align_of::<u64>(),
-                                                          keys_size,
-                                                          align_of::<K>(),
-                                                          vals_size,
-                                                          align_of::<V>());
+                                                          pairs_size,
+                                                          align_of::<(K, V)>());
 
         debug_assert!(!oflo, "should be impossible");
 
index f1f62bc24c509fe4486d59a94f947ce3f5cca1e9..398bb55ea1bf69f65a5f037212d0d3381d069824 100644 (file)
@@ -55,7 +55,6 @@
 use cell;
 use char;
 use fmt::{self, Debug, Display};
-use marker::Reflect;
 use mem::transmute;
 use num;
 use str;
@@ -63,7 +62,7 @@
 
 /// Base functionality for all errors in Rust.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait Error: Debug + Display + Reflect {
+pub trait Error: Debug + Display {
     /// A short description of the error.
     ///
     /// The description should not contain newlines or sentence-ending
index 93b2d34e27f925d4efa8f232cc7aa415358f5489..44dd4e9874ac43fe6d8ac5bc0b80158ba69b5584 100644 (file)
@@ -12,7 +12,6 @@
 
 use io::prelude::*;
 
-use marker::Reflect;
 use cmp;
 use error;
 use fmt;
 
 /// The `BufReader` struct adds buffering to any reader.
 ///
-/// It can be excessively inefficient to work directly with a `Read` instance.
-/// For example, every call to `read` on `TcpStream` results in a system call.
-/// A `BufReader` performs large, infrequent reads on the underlying `Read`
+/// It can be excessively inefficient to work directly with a [`Read`] instance.
+/// For example, every call to [`read`] on [`TcpStream`] results in a system call.
+/// A `BufReader` performs large, infrequent reads on the underlying [`Read`]
 /// and maintains an in-memory buffer of the results.
 ///
+/// [`Read`]: ../../std/io/trait.Read.html
+/// [`read`]: ../../std/net/struct.TcpStream.html#method.read
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+///
 /// # Examples
 ///
 /// ```
@@ -255,7 +258,7 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 /// Wraps a writer and buffers its output.
 ///
 /// It can be excessively inefficient to work directly with something that
-/// implements `Write`. For example, every call to `write` on `TcpStream`
+/// implements [`Write`]. For example, every call to [`write`] on [`TcpStream`]
 /// results in a system call. A `BufWriter` keeps an in-memory buffer of data
 /// and writes it to an underlying writer in large, infrequent batches.
 ///
@@ -263,7 +266,7 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 ///
 /// # Examples
 ///
-/// Let's write the numbers one through ten to a `TcpStream`:
+/// Let's write the numbers one through ten to a [`TcpStream`]:
 ///
 /// ```no_run
 /// use std::io::prelude::*;
@@ -295,6 +298,10 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped
 /// together by the buffer, and will all be written out in one system call when
 /// the `stream` is dropped.
+///
+/// [`Write`]: ../../std/io/trait.Write.html
+/// [`write`]: ../../std/net/struct.TcpStream.html#method.write
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufWriter<W: Write> {
     inner: Option<W>,
@@ -578,7 +585,7 @@ fn from(iie: IntoInnerError<W>) -> Error { iie.1 }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Reflect + Send + fmt::Debug> error::Error for IntoInnerError<W> {
+impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
     fn description(&self) -> &str {
         error::Error::description(self.error())
     }
index 73105640cd26b23bf376129fcdfe89a2fe21d229..14d046ab0520b4cf5b66282fa128fd1434a8f176 100644 (file)
 //!
 //! The `std::io` module contains a number of common things you'll need
 //! when doing input and output. The most core part of this module is
-//! the [`Read`][read] and [`Write`][write] traits, which provide the
+//! the [`Read`] and [`Write`] traits, which provide the
 //! most general interface for reading and writing input and output.
 //!
-//! [read]: trait.Read.html
-//! [write]: trait.Write.html
-//!
 //! # Read and Write
 //!
-//! Because they are traits, `Read` and `Write` are implemented by a number
+//! Because they are traits, [`Read`] and [`Write`] are implemented by a number
 //! of other types, and you can implement them for your types too. As such,
 //! you'll see a few different types of I/O throughout the documentation in
-//! this module: `File`s, `TcpStream`s, and sometimes even `Vec<T>`s. For
+//! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For
 //! example, `Read` adds a `read()` method, which we can use on `File`s:
 //!
 //! ```
 //! # }
 //! ```
 //!
-//! `Read` and `Write` are so important, implementors of the two traits have a
+//! [`Read`] and [`Write`] are so important, implementors of the two traits have a
 //! nickname: readers and writers. So you'll sometimes see 'a reader' instead
-//! of 'a type that implements the `Read` trait'. Much easier!
+//! of 'a type that implements the [`Read`] trait'. Much easier!
 //!
 //! ## Seek and BufRead
 //!
-//! Beyond that, there are two important traits that are provided: [`Seek`][seek]
-//! and [`BufRead`][bufread]. Both of these build on top of a reader to control
-//! how the reading happens. `Seek` lets you control where the next byte is
+//! Beyond that, there are two important traits that are provided: [`Seek`]
+//! and [`BufRead`]. Both of these build on top of a reader to control
+//! how the reading happens. [`Seek`] lets you control where the next byte is
 //! coming from:
 //!
 //! ```
 //! # }
 //! ```
 //!
-//! [seek]: trait.Seek.html
-//! [bufread]: trait.BufRead.html
-//!
-//! `BufRead` uses an internal buffer to provide a number of other ways to read, but
+//! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but
 //! to show it off, we'll need to talk about buffers in general. Keep reading!
 //!
 //! ## BufReader and BufWriter
 //!
 //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be
 //! making near-constant calls to the operating system. To help with this,
-//! `std::io` comes with two structs, `BufReader` and `BufWriter`, which wrap
+//! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap
 //! readers and writers. The wrapper uses a buffer, reducing the number of
 //! calls and providing nicer methods for accessing exactly what you want.
 //!
-//! For example, `BufReader` works with the `BufRead` trait to add extra
+//! For example, [`BufReader`] works with the [`BufRead`] trait to add extra
 //! methods to any reader:
 //!
 //! ```
 //! # }
 //! ```
 //!
-//! `BufWriter` doesn't add any new ways of writing; it just buffers every call
-//! to [`write()`][write()]:
+//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
+//! to [`write()`]:
 //!
 //! ```
 //! use std::io;
 //! # }
 //! ```
 //!
-//! [write()]: trait.Write.html#tymethod.write
-//!
 //! ## Standard input and output
 //!
 //! A very common source of input is standard input:
 //! # }
 //! ```
 //!
-//! Of course, using `io::stdout()` directly is less common than something like
-//! `println!`.
+//! Of course, using [`io::stdout()`] directly is less common than something like
+//! [`println!`].
 //!
 //! ## Iterator types
 //!
 //! A large number of the structures provided by `std::io` are for various
-//! ways of iterating over I/O. For example, `Lines` is used to split over
+//! ways of iterating over I/O. For example, [`Lines`] is used to split over
 //! lines:
 //!
 //! ```
 //!
 //! ## io::Result
 //!
-//! Last, but certainly not least, is [`io::Result`][result]. This type is used
+//! Last, but certainly not least, is [`io::Result`]. This type is used
 //! as the return type of many `std::io` functions that can cause an error, and
 //! can be returned from your own functions as well. Many of the examples in this
-//! module use the [`try!`][try] macro:
+//! module use the [`try!`] macro:
 //!
 //! ```
 //! use std::io;
 //! }
 //! ```
 //!
-//! The return type of `read_input()`, `io::Result<()>`, is a very common type
-//! for functions which don't have a 'real' return value, but do want to return
-//! errors if they happen. In this case, the only purpose of this function is
+//! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very
+//! common type for functions which don't have a 'real' return value, but do want to
+//! return errors if they happen. In this case, the only purpose of this function is
 //! to read the line and print it, so we use `()`.
 //!
-//! [result]: type.Result.html
-//! [try]: ../macro.try.html
-//!
 //! ## Platform-specific behavior
 //!
 //! Many I/O functions throughout the standard library are documented to indicate
 //! any possibly unclear semantics. Note, however, that this is informative, not a binding
 //! contract. The implementation of many of these functions are subject to change over
 //! time and may call fewer or more syscalls/library functions.
+//!
+//! [`Read`]: trait.Read.html
+//! [`Write`]: trait.Write.html
+//! [`Seek`]: trait.Seek.html
+//! [`BufRead`]: trait.BufRead.html
+//! [`File`]: ../fs/struct.File.html
+//! [`TcpStream`]: ../net/struct.TcpStream.html
+//! [`Vec<T>`]: ../vec/struct.Vec.html
+//! [`BufReader`]: struct.BufReader.html
+//! [`BufWriter`]: struct.BufWriter.html
+//! [`write()`]: trait.Write.html#tymethod.write
+//! [`io::stdout()`]: fn.stdout.html
+//! [`println!`]: ../macro.println.html
+//! [`Lines`]: struct.Lines.html
+//! [`io::Result`]: type.Result.html
+//! [`try!`]: ../macro.try.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index eee85798841254c06ea1d415528ff2b66b76f512..c2f6a6f660c48c4971cd04b809d228a2417cda7f 100644 (file)
 #![feature(panic_unwind)]
 #![feature(placement_in_syntax)]
 #![feature(prelude_import)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(rand)]
 #![feature(raw)]
-#![feature(reflect_marker)]
 #![feature(repr_simd)]
 #![feature(rustc_attrs)]
 #![feature(shared)]
index 58daa7dbf8dc4d843b9b5e49f2da0f860d0e85f8..20dc5b3801ba410560d75100480ee17c6f1099d9 100644 (file)
@@ -93,6 +93,26 @@ pub fn set_port(&mut self, new_port: u16) {
             SocketAddr::V6(ref mut a) => a.set_port(new_port),
         }
     }
+
+    /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address,
+    /// false if it's a valid IPv6 address.
+    #[unstable(feature = "sockaddr_checker", issue = "36949")]
+    pub fn is_ipv4(&self) -> bool {
+        match *self {
+            SocketAddr::V4(_) => true,
+            SocketAddr::V6(_) => false,
+        }
+    }
+
+    /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address,
+    /// false if it's a valid IPv4 address.
+    #[unstable(feature = "sockaddr_checker", issue = "36949")]
+    pub fn is_ipv6(&self) -> bool {
+        match *self {
+            SocketAddr::V4(_) => false,
+            SocketAddr::V6(_) => true,
+        }
+    }
 }
 
 impl SocketAddrV4 {
@@ -631,4 +651,19 @@ fn set_scope_id() {
         v6.set_scope_id(20);
         assert_eq!(v6.scope_id(), 20);
     }
+
+    #[test]
+    fn is_v4() {
+        let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80));
+        assert!(v4.is_ipv4());
+        assert!(!v4.is_ipv6());
+    }
+
+    #[test]
+    fn is_v6() {
+        let v6 = SocketAddr::V6(SocketAddrV6::new(
+                Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0));
+        assert!(!v6.is_ipv4());
+        assert!(v6.is_ipv6());
+    }
 }
index 6d37f1605901accd91c7203687e4e239cb399b4f..fce640e7c7a2c4e504c64138c596b70c7372d89f 100644 (file)
 use fmt;
 use mem;
 use cell::UnsafeCell;
-use marker::Reflect;
 use time::{Duration, Instant};
 
 #[unstable(feature = "mpsc_select", issue = "27800")]
@@ -1163,7 +1162,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + Reflect> error::Error for SendError<T> {
+impl<T: Send> error::Error for SendError<T> {
     fn description(&self) -> &str {
         "sending on a closed channel"
     }
@@ -1198,7 +1197,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + Reflect> error::Error for TrySendError<T> {
+impl<T: Send> error::Error for TrySendError<T> {
 
     fn description(&self) -> &str {
         match *self {
index 55212bf35d698656df80e8d0a55cb767411a0b3a..bdc727f1dfcfe0f20536ce50054f7ec5e6cff3e7 100644 (file)
@@ -10,7 +10,6 @@
 
 use error::{Error};
 use fmt;
-use marker::Reflect;
 use sync::atomic::{AtomicBool, Ordering};
 use thread;
 
@@ -117,7 +116,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Reflect> Error for PoisonError<T> {
+impl<T> Error for PoisonError<T> {
     fn description(&self) -> &str {
         "poisoned lock: another task failed inside"
     }
@@ -174,7 +173,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Reflect> Error for TryLockError<T> {
+impl<T> Error for TryLockError<T> {
     fn description(&self) -> &str {
         match *self {
             TryLockError::Poisoned(ref p) => p.description(),
index fcf2d32ded960aab2c61ccf47baf3ce785a8f91d..30fc4c3dd8045137865da8d779cff1fb65335ba3 100644 (file)
@@ -71,7 +71,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 
 impl Decodable for Name {
     fn decode<D: Decoder>(d: &mut D) -> Result<Name, D::Error> {
-        Ok(token::intern(&d.read_str()?[..]))
+        Ok(token::intern(&d.read_str()?))
     }
 }
 
index 94a7f6030b9373d557fec1c6d3ec4c720f1430a9..3b81ea4917f2bf9e496981d0f5f1050016d635f0 100644 (file)
@@ -153,7 +153,7 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
     }
 
     // Visit attributes on expression and statements (but not attributes on items in blocks).
-    fn visit_stmt_or_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
+    fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
         // flag the offending attributes
         for attr in attrs.iter() {
             if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
@@ -227,7 +227,7 @@ pub fn configure_expr_kind(&mut self, expr_kind: ast::ExprKind) -> ast::ExprKind
     }
 
     pub fn configure_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
-        self.visit_stmt_or_expr_attrs(expr.attrs());
+        self.visit_expr_attrs(expr.attrs());
 
         // If an expr is valid to cfg away it will have been removed by the
         // outer stmt or expression folder before descending in here.
@@ -245,7 +245,6 @@ pub fn configure_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
     }
 
     pub fn configure_stmt(&mut self, stmt: ast::Stmt) -> Option<ast::Stmt> {
-        self.visit_stmt_or_expr_attrs(stmt.attrs());
         self.configure(stmt)
     }
 }
index b56018e1e9dcd98b33e30a6c421e47559ef1bdd4..f7c88073c9d405425e431db0f0110d156ffc6ca6 100644 (file)
@@ -22,7 +22,6 @@
 use parse::token;
 use parse::token::{InternedString, str_to_ident};
 use ptr::P;
-use std_inject;
 use util::small_vector::SmallVector;
 
 use std::path::PathBuf;
@@ -523,10 +522,17 @@ pub trait Resolver {
     fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
 
     fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
-    fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<SyntaxExtension>>;
+    fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool)
+                     -> Result<Rc<SyntaxExtension>, Determinacy>;
     fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>>;
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum Determinacy {
+    Determined,
+    Undetermined,
+}
+
 pub struct DummyResolver;
 
 impl Resolver for DummyResolver {
@@ -540,8 +546,9 @@ fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
 
     fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
     fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option<Rc<MultiItemModifier>> { None }
-    fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation) -> Option<Rc<SyntaxExtension>> {
-        None
+    fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation, _force: bool)
+                     -> Result<Rc<SyntaxExtension>, Determinacy> {
+        Err(Determinacy::Determined)
     }
 }
 
@@ -737,28 +744,6 @@ pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
     pub fn name_of(&self, st: &str) -> ast::Name {
         token::intern(st)
     }
-
-    pub fn initialize(&mut self, user_exts: Vec<NamedSyntaxExtension>, krate: &ast::Crate) {
-        if std_inject::no_core(&krate) {
-            self.crate_root = None;
-        } else if std_inject::no_std(&krate) {
-            self.crate_root = Some("core");
-        } else {
-            self.crate_root = Some("std");
-        }
-
-        for (name, extension) in user_exts {
-            let ident = ast::Ident::with_empty_ctxt(name);
-            self.resolver.add_ext(ident, Rc::new(extension));
-        }
-
-        let mut module = ModuleData {
-            mod_path: vec![token::str_to_ident(&self.ecfg.crate_name)],
-            directory: PathBuf::from(self.parse_sess.codemap().span_to_filename(krate.span)),
-        };
-        module.directory.pop();
-        self.current_expansion.module = Rc::new(module);
-    }
 }
 
 /// Extract a string literal from the macro expanded version of `expr`,
index 3abe7626efc6ef922a277dcec9c17df2664e8090..363ceebf0f4750e23b75ac0aa2d58c3d79b285c8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{Block, Crate, Ident, Mac_, PatKind};
+use ast::{Block, Ident, Mac_, PatKind};
 use ast::{Name, MacStmtStyle, StmtKind, ItemKind};
 use ast;
 use ext::hygiene::Mark;
@@ -26,6 +26,7 @@
 use parse::token::{self, intern, keywords};
 use print::pprust;
 use ptr::P;
+use std_inject;
 use tokenstream::{TokenTree, TokenStream};
 use util::small_vector::SmallVector;
 use visit::Visitor;
@@ -186,8 +187,14 @@ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
         MacroExpander { cx: cx, monotonic: monotonic }
     }
 
-    fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
-        let err_count = self.cx.parse_sess.span_diagnostic.err_count();
+    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
+        self.cx.crate_root = std_inject::injected_crate_name(&krate);
+        let mut module = ModuleData {
+            mod_path: vec![token::str_to_ident(&self.cx.ecfg.crate_name)],
+            directory: PathBuf::from(self.cx.codemap().span_to_filename(krate.span)),
+        };
+        module.directory.pop();
+        self.cx.current_expansion.module = Rc::new(module);
 
         let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
             attrs: krate.attrs,
@@ -206,10 +213,6 @@ fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             _ => unreachable!(),
         };
 
-        if self.cx.parse_sess.span_diagnostic.err_count() - self.cx.resolve_err_count > err_count {
-            self.cx.parse_sess.span_diagnostic.abort_if_errors();
-        }
-
         krate
     }
 
@@ -221,25 +224,47 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
         let (expansion, mut invocations) = self.collect_invocations(expansion);
         invocations.reverse();
 
-        let mut expansions = vec![vec![(0, expansion)]];
-        while let Some(invoc) = invocations.pop() {
+        let mut expansions = Vec::new();
+        let mut undetermined_invocations = Vec::new();
+        let (mut progress, mut force) = (false, !self.monotonic);
+        loop {
+            let invoc = if let Some(invoc) = invocations.pop() {
+                invoc
+            } else if undetermined_invocations.is_empty() {
+                break
+            } else {
+                invocations = mem::replace(&mut undetermined_invocations, Vec::new());
+                force = !mem::replace(&mut progress, false);
+                continue
+            };
+
+            let scope =
+                if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
+            let ext = match self.cx.resolver.resolve_invoc(scope, &invoc, force) {
+                Ok(ext) => Some(ext),
+                Err(Determinacy::Determined) => None,
+                Err(Determinacy::Undetermined) => {
+                    undetermined_invocations.push(invoc);
+                    continue
+                }
+            };
+
+            progress = true;
             let ExpansionData { depth, mark, .. } = invoc.expansion_data;
             self.cx.current_expansion = invoc.expansion_data.clone();
 
-            let scope = if self.monotonic { mark } else { orig_expansion_data.mark };
             self.cx.current_expansion.mark = scope;
-            let expansion = match self.cx.resolver.resolve_invoc(scope, &invoc) {
+            let expansion = match ext {
                 Some(ext) => self.expand_invoc(invoc, ext),
                 None => invoc.expansion_kind.dummy(invoc.span()),
             };
 
-            self.cx.current_expansion.depth = depth + 1;
             let (expansion, new_invocations) = self.collect_invocations(expansion);
 
-            if expansions.len() == depth {
+            if expansions.len() < depth {
                 expansions.push(Vec::new());
             }
-            expansions[depth].push((mark.as_u32(), expansion));
+            expansions[depth - 1].push((mark.as_u32(), expansion));
             if !self.cx.ecfg.single_step {
                 invocations.extend(new_invocations.into_iter().rev());
             }
@@ -250,12 +275,11 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
         let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
         while let Some(expansions) = expansions.pop() {
             for (mark, expansion) in expansions.into_iter().rev() {
-                let expansion = expansion.fold_with(&mut placeholder_expander);
                 placeholder_expander.add(ast::NodeId::from_u32(mark), expansion);
             }
         }
 
-        placeholder_expander.remove(ast::NodeId::from_u32(0))
+        expansion.fold_with(&mut placeholder_expander)
     }
 
     fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec<Invocation>) {
@@ -538,7 +562,11 @@ fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Ex
         self.invocations.push(Invocation {
             kind: kind,
             expansion_kind: expansion_kind,
-            expansion_data: ExpansionData { mark: mark, ..self.cx.current_expansion.clone() },
+            expansion_data: ExpansionData {
+                mark: mark,
+                depth: self.cx.current_expansion.depth + 1,
+                ..self.cx.current_expansion.clone()
+            },
         });
         placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32()))
     }
@@ -866,22 +894,6 @@ fn enable_proc_macro = proc_macro,
     }
 }
 
-pub fn expand_crate(cx: &mut ExtCtxt,
-                    user_exts: Vec<NamedSyntaxExtension>,
-                    c: Crate) -> Crate {
-    cx.initialize(user_exts, &c);
-    cx.monotonic_expander().expand_crate(c)
-}
-
-// Expands crate using supplied MacroExpander - allows for
-// non-standard expansion behaviour (e.g. step-wise).
-pub fn expand_crate_with_expander(expander: &mut MacroExpander,
-                                  user_exts: Vec<NamedSyntaxExtension>,
-                                  c: Crate) -> Crate {
-    expander.cx.initialize(user_exts, &c);
-    expander.expand_crate(c)
-}
-
 // A Marker adds the given mark to the syntax context and
 // sets spans' `expn_id` to the given expn_id (unless it is `None`).
 struct Marker { mark: Mark, expn_id: Option<ExpnId> }
index 0ede6dd98e5b866e53c6d0b1eef1300faf0204e7..e323dd2f623276c16de3cfd6682194867f5c1ec1 100644 (file)
@@ -88,10 +88,11 @@ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
     }
 
     pub fn add(&mut self, id: ast::NodeId, expansion: Expansion) {
+        let expansion = expansion.fold_with(self);
         self.expansions.insert(id, expansion);
     }
 
-    pub fn remove(&mut self, id: ast::NodeId) -> Expansion {
+    fn remove(&mut self, id: ast::NodeId) -> Expansion {
         self.expansions.remove(&id).unwrap()
     }
 }
index 9eed1d61244a49b80585992374881bbac9d236f8..62b88888fc878849f041d6051c7f9b9b88a43e80 100644 (file)
@@ -253,9 +253,6 @@ pub fn new() -> Features {
     // a...b and ...b
     (active, inclusive_range_syntax, "1.7.0", Some(28237)),
 
-    // `expr?`
-    (active, question_mark, "1.9.0", Some(31436)),
-
     // impl specialization (RFC 1210)
     (active, specialization, "1.7.0", Some(31844)),
 
@@ -348,6 +345,8 @@ pub fn new() -> Features {
     (accepted, while_let, "1.0.0", None),
     // Allows `#[deprecated]` attribute
     (accepted, deprecated, "1.9.0", Some(29935)),
+    // `expr?`
+    (accepted, question_mark, "1.14.0", Some(31436)),
 );
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -1072,9 +1071,6 @@ fn visit_expr(&mut self, e: &ast::Expr) {
                                   e.span,
                                   "inclusive range syntax is experimental");
             }
-            ast::ExprKind::Try(..) => {
-                gate_feature_post!(&self, question_mark, e.span, "the `?` operator is not stable");
-            }
             ast::ExprKind::InPlace(..) => {
                 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
             }
index 118ceb17ab4a4538c639e2c493348c44a95fd326..6e671c9efdcf87b2a5e3abfa0ebd64b9c0f164f5 100644 (file)
@@ -31,7 +31,7 @@
 #![feature(staged_api)]
 #![feature(str_escape)]
 #![feature(unicode)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(rustc_diagnostic_macros)]
 #![feature(specialization)]
 
index 09bc5607946de23153dfdaf182bf05d525eeef6d..73d9695a9906b2de92aade848832ea81f8d5cbd1 100644 (file)
@@ -566,7 +566,7 @@ fn ne(&self, other: &InternedString) -> bool {
 
 impl Decodable for InternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
-        Ok(intern(d.read_str()?.as_ref()).as_str())
+        Ok(intern(&d.read_str()?).as_str())
     }
 }
 
index 3c106970232cdb4dbf39e516d9db32544fbd5dec..ecb437f31a5ad03d6462ed034d20a3a86a49fa28 100644 (file)
@@ -112,7 +112,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                                       out,
                                       ann,
                                       is_expanded);
-    if is_expanded && !std_inject::no_std(krate) {
+    if is_expanded && !std_inject::injected_crate_name(krate).is_none() {
         // We need to print `#![no_std]` (and its feature gate) so that
         // compiling pretty-printed source won't inject libstd again.
         // However we don't want these attributes in the AST because
index d1454ab06cbc8179bbb87b294777d68e2ef6f46f..1b63a2b70763aff5da297077c8134a958490c0d9 100644 (file)
@@ -34,23 +34,25 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span {
     return sp;
 }
 
-pub fn no_core(krate: &ast::Crate) -> bool {
-    attr::contains_name(&krate.attrs, "no_core")
-}
-
-pub fn no_std(krate: &ast::Crate) -> bool {
-    attr::contains_name(&krate.attrs, "no_std") || no_core(krate)
+pub fn injected_crate_name(krate: &ast::Crate) -> Option<&'static str> {
+    if attr::contains_name(&krate.attrs, "no_core") {
+        None
+    } else if attr::contains_name(&krate.attrs, "no_std") {
+        Some("core")
+    } else {
+        Some("std")
+    }
 }
 
 pub fn maybe_inject_crates_ref(sess: &ParseSess,
                                mut krate: ast::Crate,
                                alt_std_name: Option<String>)
                                -> ast::Crate {
-    if no_core(&krate) {
-        return krate;
-    }
+    let name = match injected_crate_name(&krate) {
+        Some(name) => name,
+        None => return krate,
+    };
 
-    let name = if no_std(&krate) { "core" } else { "std" };
     let crate_name = token::intern(&alt_std_name.unwrap_or(name.to_string()));
 
     krate.module.items.insert(0, P(ast::Item {
index fdb10a2beb23056a14dbe31af02dc9861b549a05..9f99919c895058ee3ccc955d7f5e4c025cbdbbdb 100644 (file)
@@ -11,6 +11,7 @@
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
 use syntax::ast::{self, MetaItem};
+use syntax::attr::HasAttrs;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::feature_gate;
@@ -104,13 +105,37 @@ pub fn expand_derive(cx: &mut ExtCtxt,
         }
     };
 
-    if mitem.value_str().is_some() {
-        cx.span_err(mitem.span, "unexpected value in `derive`");
+    let mut derive_attrs = Vec::new();
+    item = item.map_attrs(|attrs| {
+        let partition = attrs.into_iter().partition(|attr| &attr.name() == "derive");
+        derive_attrs = partition.0;
+        partition.1
+    });
+
+    // Expand `#[derive]`s after other attribute macro invocations.
+    if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() {
+        return vec![Annotatable::Item(item.map_attrs(|mut attrs| {
+            attrs.push(cx.attribute(span, P(mitem.clone())));
+            attrs.extend(derive_attrs);
+            attrs
+        }))];
     }
 
-    let mut traits = mitem.meta_item_list().unwrap_or(&[]).to_owned();
-    if traits.is_empty() {
-        cx.span_warn(mitem.span, "empty trait list in `derive`");
+    let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| {
+        if mitem.value_str().is_some() {
+            cx.span_err(mitem.span, "unexpected value in `derive`");
+        }
+
+        let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned();
+        if traits.is_empty() {
+            cx.span_warn(mitem.span, "empty trait list in `derive`");
+        }
+        traits
+    };
+
+    let mut traits = get_traits(mitem, cx);
+    for derive_attr in derive_attrs {
+        traits.extend(get_traits(&derive_attr.node.value, cx));
     }
 
     // First, weed out malformed #[derive]
index e9d2c0a503be9718faf110745c9e55398ec55ce8..f336b26ae41f2f3b63dc4cbcc99cc13ab2af94e0 100644 (file)
 
 use std::rc::Rc;
 use syntax::ast;
-use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier};
+use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension};
 use syntax::ext::tt::macro_rules::MacroRulesExpander;
 use syntax::parse::token::intern;
 
-pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, enable_quotes: bool) {
+pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
+                         user_exts: Vec<NamedSyntaxExtension>,
+                         enable_quotes: bool) {
     let mut register = |name, ext| {
-        resolver.add_ext(ast::Ident::with_empty_ctxt(intern(name)), Rc::new(ext));
+        resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
     };
 
-    register("macro_rules", IdentTT(Box::new(MacroRulesExpander), None, false));
+    register(intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false));
 
     macro_rules! register {
         ($( $name:ident: $f:expr, )*) => { $(
-            register(stringify!($name), NormalTT(Box::new($f as MacroExpanderFn), None, false));
+            register(intern(stringify!($name)),
+                     NormalTT(Box::new($f as MacroExpanderFn), None, false));
         )* }
     }
 
@@ -108,7 +111,11 @@ macro_rules! register {
     }
 
     // format_args uses `unstable` things internally.
-    register("format_args", NormalTT(Box::new(format::expand_format_args), None, true));
+    register(intern("format_args"), NormalTT(Box::new(format::expand_format_args), None, true));
 
-    register("derive", MultiModifier(Box::new(deriving::expand_derive)));
+    register(intern("derive"), MultiModifier(Box::new(deriving::expand_derive)));
+
+    for (name, ext) in user_exts {
+        register(name, ext);
+    }
 }
index 13dcf7b188b70b4c551a8229cb774ed5992f362e..e3feaee5369d1c92474bcaebce3387bbcbcca8a0 100644 (file)
@@ -27,7 +27,7 @@
 #![allow(unused_attributes)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(specialization)]
 
 use std::cell::{Cell, RefCell};
index 0244e2657969337bd2e47a4a49e55b11fca67e68..caef808f474ec9553fb436adaa39d402aa57a9ee 100644 (file)
@@ -59,7 +59,7 @@
 #![cfg_attr(windows, feature(libc))]
 // Handle rustfmt skips
 #![feature(custom_attribute)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![allow(unused_attributes)]
 
 use std::io::prelude::*;
index bb42351d3b7c8064def20b552b7a3edd8cbfc219..625666e641c6bed6ece2bda4dd1d3f3983a06f6d 100644 (file)
@@ -38,7 +38,7 @@
 #![feature(rustc_private)]
 #![feature(set_stdio)]
 #![feature(staged_api)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(panic_unwind)]
 
 extern crate getopts;
index 43f6d9d757d7ec3dd30508e6509d1f9003fdf13b..d75f6124827726d79cba494eec55509332645490 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     let x = Some(0);
 
     match x {
-        Some(y) | None => {} //~ ERROR E0408
-        _ => ()
+        Some(y) | None => {} //~  ERROR variable `y` from pattern #1 is not bound in pattern #2
+        _ => ()              //~| NOTE pattern doesn't bind `y`
     }
 }
diff --git a/src/test/compile-fail/feature-gate-try-operator.rs b/src/test/compile-fail/feature-gate-try-operator.rs
deleted file mode 100644 (file)
index b05c732..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-macro_rules! id {
-    ($e:expr) => { $e }
-}
-
-fn main() {
-    id!(x?);  //~ error: the `?` operator is not stable (see issue #31436)
-    y?;  //~ error: the `?` operator is not stable (see issue #31436)
-}
index e5503edfab5e1a9f688f22824e2c5e0f4f0a11dd..f5e0c545bb52436fa4714d87aa3e59511d7f424c 100644 (file)
@@ -19,7 +19,7 @@ pub enum foo {
 fn main() {
     use bar::foo::{alpha, charlie};
     match alpha {
-      alpha | beta => {} //~ ERROR variable `beta` from pattern #2 is not bound in pattern #1
-      charlie => {}
+      alpha | beta => {} //~  ERROR variable `beta` from pattern #2 is not bound in pattern #1
+      charlie => {}      //~| NOTE pattern doesn't bind `beta`
     }
 }
index f9d11f3a171c2118c294044f03c75740ebc41fc1..09538818dcdf9ccf85fc692de32f51bc9e3f43aa 100644 (file)
@@ -8,12 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(question_mark)]
-
 // Make sure that the span of try shorthand does not include the trailing
 // semicolon;
 fn a() -> Result<i32, ()> {
-    Err(5)?; //~ ERROR 16:5: 16:12
+    Err(5)?; //~ ERROR 14:5: 14:12
     Ok(1)
 }
 
index d95890730a0f2205d42f45f9993cd9ec36c45f31..87747d2851f5e3aa32fe464d516d91ba5b591b35 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(reflect_marker)]
-
-use std::marker::Reflect;
 use std::any::Any;
 
 struct Foo;
index 22463825ef98f1618a84af4996a589994163f75e..8381dc34a6a15f695630b44de9be358fdbdfc825 100644 (file)
 
 macro_rules! foo { () => {} }
 macro_rules! macro_one { () => {} }
+#[macro_use(macro_two)] extern crate two_macros;
 
 macro_rules! m1 { () => {
     macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope
-    //~^ NOTE macro-expanded `macro_rules!`s and `#[macro_use]`s may not shadow existing macros
+    //~^ NOTE macro-expanded `macro_rules!`s may not shadow existing macros
 
-    #[macro_use] //~ ERROR `macro_one` is already in scope
-    //~^ NOTE macro-expanded `macro_rules!`s and `#[macro_use]`s may not shadow existing macros
-    extern crate two_macros;
+    #[macro_use] //~ ERROR `macro_two` is already in scope
+    //~^ NOTE macro-expanded `#[macro_use]`s may not shadow existing macros
+    extern crate two_macros as __;
 }}
 m1!(); //~ NOTE in this expansion
        //~| NOTE in this expansion
        //~| NOTE in this expansion
        //~| NOTE in this expansion
 
-fn f() { macro_one!(); }
 foo!();
 
 macro_rules! m2 { () => {
     macro_rules! foo { () => {} }
-    #[macro_use] extern crate two_macros as __;
-
-    fn g() { macro_one!(); }
     foo!();
 }}
 m2!();
-//^ Since `foo` and `macro_one` are not used outside this expansion, they are not shadowing errors.
+//^ Since `foo` is not used outside this expansion, it is not a shadowing error.
 
 fn main() {}
index 5256396a242c9eaac08de95ef01a59a04da4f5c8..9d389413ba9adb0319e964d7cd3fae7bfd883aa6 100644 (file)
@@ -19,10 +19,10 @@ fn f() {
 #[macro_use(macro_one)] // Check that this macro is usable in the above function
 extern crate two_macros;
 
+fn g() {
+    macro_two!();
+}
 macro_rules! m { () => {
-    fn g() {
-        macro_two!();
-    }
     #[macro_use(macro_two)] // Check that this macro is usable in the above function
     extern crate two_macros as _two_macros;
 } }
index a133ddc15f1acb1993177df243055c40ff8fd2cd..1ba1bb35bb5f3b679eec4f749415025bc347402d 100644 (file)
@@ -11,7 +11,6 @@
 // General test of maybe_uninits state computed by MIR dataflow.
 
 #![feature(rustc_attrs)]
-#![feature(stmt_expr_attributes)]
 
 use std::intrinsics::rustc_peek;
 use std::mem::{drop, replace};
index 949688098f62234b856636dea2bf8f4a8e09fd66..c8cf44adb97199d9ad0bafa8595c52254617fd54 100644 (file)
@@ -11,7 +11,6 @@
 // General test of maybe_inits state computed by MIR dataflow.
 
 #![feature(rustc_attrs)]
-#![feature(stmt_expr_attributes)]
 
 use std::intrinsics::rustc_peek;
 use std::mem::{drop, replace};
index c13daae24f35dfe33d0d562de6f2b441c55275d5..a82bfc896988075ac0a718b75833473ce78d8872 100644 (file)
@@ -11,7 +11,6 @@
 // General test of maybe_uninits state computed by MIR dataflow.
 
 #![feature(rustc_attrs)]
-#![feature(stmt_expr_attributes)]
 
 use std::intrinsics::rustc_peek;
 use std::mem::{drop, replace};
index 94f812a40a9b532610cbe5fc26f892ff848d0452..8cfdae506625e3d47d26db6065499f4614b2d6d6 100644 (file)
@@ -11,7 +11,6 @@
 // General test of maybe_uninits state computed by MIR dataflow.
 
 #![feature(rustc_attrs)]
-#![feature(stmt_expr_attributes)]
 
 use std::intrinsics::rustc_peek;
 use std::mem::{drop, replace};
index f7f3acd37d62d0daa6d1d56f262931522e1ccfc5..1e2541502ace874c04d28188a6557850d45361c9 100644 (file)
@@ -11,7 +11,9 @@
 fn main() {
     let y = 1;
     match y {
-       a | b => {} //~ ERROR variable `a` from pattern #1 is not bound in pattern #2
-       //~^ ERROR variable `b` from pattern #2 is not bound in pattern #1
+       a | b => {} //~  ERROR variable `a` from pattern #1 is not bound in pattern #2
+                   //~^ ERROR variable `b` from pattern #2 is not bound in pattern #1
+                   //~| NOTE pattern doesn't bind `a`
+                   //~| NOTE pattern doesn't bind `b`
     }
 }
index 68338b115950c0f901d177a6c01a63530bf8340b..2fda2ee0900c7470ea82f045817f7cd223e54532 100644 (file)
@@ -21,15 +21,15 @@ fn main() {
     #[attr]
     fn a() {}
 
-    #[attr] //~ ERROR 15701
+    #[attr]
     {
 
     }
 
-    #[attr] //~ ERROR 15701
+    #[attr]
     5;
 
-    #[attr] //~ ERROR 15701
+    #[attr]
     stmt_mac!();
 }
 
@@ -43,7 +43,7 @@ fn c() {
 
 #[cfg(not(unset))]
 fn j() {
-    #[attr] //~ ERROR 15701
+    #[attr]
     5;
 }
 
@@ -55,7 +55,7 @@ fn d() {
 
 #[cfg_attr(not(unset), cfg(not(unset)))]
 fn i() {
-    #[attr] //~ ERROR 15701
+    #[attr]
     8;
 }
 
@@ -64,7 +64,7 @@ fn i() {
 macro_rules! item_mac {
     ($e:ident) => {
         fn $e() {
-            #[attr] //~ ERROR 15701
+            #[attr]
             42;
 
             #[cfg(unset)]
@@ -75,7 +75,7 @@ fn f() {
 
             #[cfg(not(unset))]
             fn k() {
-                #[attr] //~ ERROR 15701
+                #[attr]
                 5;
             }
 
@@ -87,7 +87,7 @@ fn g() {
 
             #[cfg_attr(not(unset), cfg(not(unset)))]
             fn h() {
-                #[attr] //~ ERROR 15701
+                #[attr]
                 8;
             }
 
index 74c7797be2ab8cf5815c89f9e0866be3265fb2c8..2d79987823f2036c1c944fdd412c6e22b9a39b13 100644 (file)
@@ -236,3 +236,74 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub struct Visibility;
+
+
+
+
+struct ReferencedType1;
+struct ReferencedType2;
+
+// Tuple Struct Change Field Type Indirectly -----------------------------------
+mod tuple_struct_change_field_type_indirectly {
+    #[cfg(cfail1)]
+    use super::ReferencedType1 as FieldType;
+    #[cfg(not(cfail1))]
+    use super::ReferencedType2 as FieldType;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    struct TupleStruct(FieldType);
+}
+
+
+// Record Struct Change Field Type Indirectly -----------------------------------
+mod record_struct_change_field_type_indirectly {
+    #[cfg(cfail1)]
+    use super::ReferencedType1 as FieldType;
+    #[cfg(not(cfail1))]
+    use super::ReferencedType2 as FieldType;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    struct RecordStruct {
+        _x: FieldType
+    }
+}
+
+
+
+
+trait ReferencedTrait1 {}
+trait ReferencedTrait2 {}
+
+// Change Trait Bound Indirectly -----------------------------------------------
+mod change_trait_bound_indirectly {
+    #[cfg(cfail1)]
+    use super::ReferencedTrait1 as Trait;
+    #[cfg(not(cfail1))]
+    use super::ReferencedTrait2 as Trait;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    struct Struct<T: Trait>(T);
+}
+
+// Change Trait Bound Indirectly In Where Clause -------------------------------
+mod change_trait_bound_indirectly_in_where_clause {
+    #[cfg(cfail1)]
+    use super::ReferencedTrait1 as Trait;
+    #[cfg(not(cfail1))]
+    use super::ReferencedTrait2 as Trait;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    struct Struct<T>(T) where T : Trait;
+}
index fe2317aabea68b43f60c53e0c1e81932b562fdf6..9b2e36c8cea15c7c463fd290b355f2639019ca4e 100644 (file)
@@ -17,8 +17,8 @@
 #[macro_use] #[no_link]
 extern crate macro_crate_test;
 
-#[into_multi_foo]
 #[derive(PartialEq, Clone, Debug)]
+#[into_multi_foo]
 fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
 
 // Check that the `#[into_multi_foo]`-generated `foo2` is configured away
index b9e31fc332959c326d569ae0d1c66805c8c6668d..a942adc4c80203d163136ec6f477e6bf8336b8e1 100644 (file)
@@ -21,6 +21,6 @@
 #[proc_macro_derive(AToB)]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert_eq!(input, "struct A;\n");
+    assert_eq!(input, "#[derive(Copy, Clone)]\nstruct A;\n");
     "struct B;".parse().unwrap()
 }
index 56f9768764c1758df576f0d72a450b5be2852a91..431c8c5902749f69476e340c74b3f7b1b2db0689 100644 (file)
@@ -18,6 +18,7 @@
 #[macro_use]
 extern crate derive_ctod;
 
+#[derive(Copy, Clone)]
 #[derive(AToB)]
 struct A;
 
index 9f4ae1ad927d780a498b58aa52b51775001903bb..a1c9ff8a21edb4b45341181130892a66f50a9e87 100644 (file)
@@ -17,4 +17,8 @@
 fn main() {
     let _ = ((-1 as i8) << 8 - 1) as f32;
     let _ = 0u8 as char;
+    let _ = true > false;
+    let _ = true >= false;
+    let _ = true < false;
+    let _ = true >= false;
 }
index 96f4217e4cb8023f6c9b6ac4bc9435484a7cb062..012fe0d95ec49c7a554201a1c3c46eba539051d5 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(stmt_expr_attributes)]
-
 #[deny(const_err)]
 
 fn main() {
index 53c44f2bb24b5f16ce3eae5d008182fa2ebaba30..c85ab535fc16b4b69e46791149367ad5d60ad714 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(stmt_expr_attributes)]
-
 use std::mem::size_of;
 
 enum Ei8 {
index 8b5536de12e4977eec39d82ec46bdf12ad2794e9..0ebe1ca07c77180259d1b97e61ae3a154a256520 100644 (file)
@@ -14,7 +14,6 @@
 #![allow(unused_must_use)]
 #![allow(unused_features)]
 #![feature(box_syntax)]
-#![feature(question_mark)]
 
 use std::fmt::{self, Write};
 use std::usize;
index 461d4cf4ff053bc0feea5dc3923503704e4aa72f..e9326ed286aff9c49f880c069f1ea6362e1c1932 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(conservative_impl_trait, question_mark)]
+#![feature(conservative_impl_trait)]
 
 struct State;
 type Error = ();
index b3c80041ef88b7f1e0f0d6139bde4d0208406b50..dcbcc2d44b5dd803464e625f0642bd376b10a9d4 100644 (file)
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(question_mark)]
-
 use std::fs::File;
 use std::io::{self, BufReader, Read};
 
index 0eea6ba22cae8d5594f7b56a317b9b4cddc97a5c..c0f13b0b6c7ad35f60f562e26496e0dc2a0da010 100644 (file)
@@ -8,17 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(reflect_marker)]
-
 use std::any::TypeId;
-use std::marker::Reflect;
 use std::rc::Rc;
 
 type Fp<T> = Rc<T>;
 
 struct Engine;
 
-trait Component: 'static + Reflect {}
+trait Component: 'static {}
 impl Component for Engine {}
 
 trait Env {
index de952436650828a4170e33aa894da126445db2dd..e45582dc2d39a09b11e6c95e4ea11ef5b3368d36 100644 (file)
@@ -10,8 +10,6 @@
 
 // Regression test for #20797.
 
-#![feature(question_mark)]
-
 use std::default::Default;
 use std::io;
 use std::fs;
index 0d1be964748bb9b263c191d9f85e4d98d622ceb5..6715b71a5f506eb162792c22a5714e1d4e945ec7 100644 (file)
@@ -11,8 +11,6 @@
 // Regression test for #21400 which itself was extracted from
 // stackoverflow.com/questions/28031155/is-my-borrow-checker-drunk/28031580
 
-#![feature(question_mark)]
-
 fn main() {
     let mut t = Test;
     assert_eq!(t.method1("one"), Ok(1));
diff --git a/src/test/run-pass/issue-37020.rs b/src/test/run-pass/issue-37020.rs
new file mode 100644 (file)
index 0000000..7d0d202
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+#![allow(private_in_public)]
+
+mod foo {
+    pub mod bar {
+        extern crate core;
+    }
+}
+
+mod baz {
+    pub use foo::bar::core;
+}
+
+fn main() {
+    baz::core::cell::Cell::new(0u32);
+}
diff --git a/src/test/run-pass/issue-37109.rs b/src/test/run-pass/issue-37109.rs
new file mode 100644 (file)
index 0000000..1c89307
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait ToRef<'a> {
+    type Ref: 'a;
+}
+
+impl<'a, U: 'a> ToRef<'a> for U {
+    type Ref = &'a U;
+}
+
+fn example<'a, T>(value: &'a T) -> (<T as ToRef<'a>>::Ref, u32) {
+    (value, 0)
+}
+
+fn main() {
+    example(&0);
+}
index 8d15fe30a1b07dd9116bc5adee951cebfa9ceb13..f16057ccab16cbbae5f37db9c44e6c30f457d21b 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-emscripten no threads support
 // ignore-pretty : (#23623) problems when  ending with // comments
 
-#![feature(rustc_attrs, stmt_expr_attributes, zero_one)]
+#![feature(rustc_attrs, zero_one)]
 
 use std::num::Zero;
 use std::thread;
index ae622df498f94b108306a1d5f6dd587a0015acce..53d6185020a0235ffb5f16b691780e4d66548f20 100644 (file)
@@ -18,8 +18,6 @@
 // This test verifies that the expansion is hygienic, i.e. it's not affected by other `val` and
 // `err` bindings that may be in scope.
 
-#![feature(question_mark)]
-
 use std::num::ParseIntError;
 
 fn main() {
index de5ccf09c5923d4ca67331f08f3afc52537c2438..29de6364bf14760b6059cc58b143c8c812116919 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(question_mark)]
-
 use std::fs::File;
 use std::io::{Read, self};
 use std::num::ParseIntError;
index b81258bd6d70289c0cbae86b44ebf3caac203a8c..81478c18d7b24ddac0b102c2b4d28a016299dd5e 100644 (file)
@@ -13,7 +13,6 @@
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 #![feature(test)]
-#![feature(question_mark)]
 #![feature(libc)]
 
 #![deny(warnings)]
index 2c734c8e3e4d4cbeac69ea5b266695df6d8eea95..7bdf1343aa9ccc70a2687c460d1bc081031a0db7 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![feature(rustc_private, rustdoc)]
-#![feature(question_mark)]
 
 extern crate syntax;
 extern crate rustdoc;
index 3e2bc9032a1ccae31c4ca3e8a60847ce2aec90d3..f79cc76e67d0045509a8a1520343f12c9288b6d6 100644 (file)
@@ -24,8 +24,6 @@
 //! A few whitelisted exceptions are allowed as there's known bugs in rustdoc,
 //! but this should catch the majority of "broken link" cases.
 
-#![feature(question_mark)]
-
 extern crate url;
 
 use std::env;
index 436dc1197533638504fb8c6e808f1e8d51137b1c..906251db1c2f216a4643a5cbd6f15c3b746f2a0d 100644 (file)
@@ -12,7 +12,6 @@
 
 #![feature(rustc_private)]
 #![feature(rustdoc)]
-#![feature(question_mark)]
 
 extern crate rustdoc;
 extern crate rustc_back;