]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #37094 - fhartwig:spec-extend-from-slice, r=alexcrichton
authorbors <bors@rust-lang.org>
Sat, 15 Oct 2016 08:48:42 +0000 (01:48 -0700)
committerGitHub <noreply@github.com>
Sat, 15 Oct 2016 08:48:42 +0000 (01:48 -0700)
Specialize Vec::extend to Vec::extend_from_slice

I tried using the existing `SpecExtend` as a helper trait for this, but the instances would always conflict with the instances higher up in the file, so I created a new helper trait.

Benchmarking `extend` vs `extend_from_slice` with an slice of 1000 `u64`s gives the following results:

```
before:

running 2 tests
test tests::bench_extend_from_slice ... bench:         166 ns/iter (+/- 78)
test tests::bench_extend_trait      ... bench:       1,187 ns/iter (+/- 697)

after:
running 2 tests
test tests::bench_extend_from_slice ... bench:         149 ns/iter (+/- 87)
test tests::bench_extend_trait      ... bench:         138 ns/iter (+/- 70)
```

171 files changed:
README.md
configure
src/bootstrap/lib.rs
src/doc/book/lifetimes.md
src/doc/book/type-aliases.md
src/doc/reference.md
src/libcollections/fmt.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/slice.rs
src/libcollectionstest/str.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/libcore/num/bignum.rs
src/libcore/num/diy_float.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/mod.rs
src/libcore/num/wrapping.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/lint/builtin.rs
src/librustc/session/mod.rs
src/librustc/ty/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/check_match.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/check/assoc.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/lib.rs
src/librustdoc/externalfiles.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/render.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/fs.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/sync/rwlock.rs
src/libstd/sys/common/poison.rs
src/libstd/sys/unix/android.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/ext/mod.rs
src/libstd/sys/unix/fd.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/ext/mod.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/handle.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/pp.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/E0007.rs
src/test/compile-fail/E0303.rs
src/test/compile-fail/E0408.rs
src/test/compile-fail/empty-struct-unit-pat-1.rs [deleted file]
src/test/compile-fail/empty-struct-unit-pat-2.rs [deleted file]
src/test/compile-fail/empty-struct-unit-pat.rs [new file with mode: 0644]
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/issue-37026.rs [new file with mode: 0644]
src/test/compile-fail/issue-pr29383.rs [new file with mode: 0644]
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/consts.rs [new file with mode: 0644]
src/test/incremental/hashes/statics.rs [new file with mode: 0644]
src/test/incremental/hashes/struct_defs.rs
src/test/incremental/hashes/trait_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/issue-pr29383.rs [deleted file]
src/test/run-pass/try-operator-hygiene.rs
src/test/run-pass/try-operator.rs
src/test/rustdoc/line-breaks.rs [new file with mode: 0644]
src/tools/compiletest/src/main.rs
src/tools/error_index_generator/main.rs
src/tools/linkchecker/main.rs
src/tools/rustbook/main.rs

index f2385f315186fa37bea59f84901753817bd6d5a1..b79c9703f44ef17d2c37c7e6869e22d55f6ed0a7 100644 (file)
--- a/README.md
+++ b/README.md
@@ -89,6 +89,7 @@ build.
    $ pacman -S git \
                make \
                diffutils \
+               tar \
                mingw-w64-x86_64-python2 \
                mingw-w64-x86_64-cmake \
                mingw-w64-x86_64-gcc
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 f7d9c94bc454f31a052f828a7385623801f7ac5c..df1ee5a293c9d6b8e2638ff8c8394c2a6a286ed6 100644 (file)
@@ -50,29 +50,94 @@ 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 an argument by reference, we can be
-implicit or explicit about the lifetime of the reference:
+When we have a function that takes arguments by reference the situation becomes
+more complex. Consider the following example:
 
-```rust
-// implicit
-fn foo(x: &i32) {
+```rust,compile_fail,E0106
+fn skip_prefix(line: &str, prefix: &str) -> &str {
+    // ...
+#   line
 }
 
-// explicit
-fn bar<'a>(x: &'a i32) {
+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
+is determined by the code, not by the annotations. The annotations, however,
+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.
+
+[traits]: traits.html
+
+# 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
 
@@ -90,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 b095b8131b644d876ac52f4acd8090b0803d0bd3..883417e9f4ec76c90bcc9f3e4dbc7dc32dafe1cb 100644 (file)
 //! format := '{' [ argument ] [ ':' format_spec ] '}'
 //! argument := integer | identifier
 //!
-//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type]
+//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
 //! fill := character
 //! align := '<' | '^' | '>'
 //! sign := '+' | '-'
index 609eb28348e21a2b571c8f063e4749bd9ed32b39..48a74bdecbbefa60db93ba3a74c94dcc1d0e79a3 100644 (file)
@@ -1789,4 +1789,24 @@ pub fn into_string(self: Box<str>) -> String {
             String::from_utf8_unchecked(slice.into_vec())
         }
     }
+
+    /// Create a [`String`] by repeating a string `n` times.
+    ///
+    /// [`String`]: string/struct.String.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(repeat_str)]
+    ///
+    /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
+    /// ```
+    #[unstable(feature = "repeat_str", issue = "37079")]
+    pub fn repeat(&self, n: usize) -> String {
+        let mut s = String::with_capacity(self.len() * n);
+        s.extend((0..n).map(|_| self));
+        s
+    }
 }
index 119828ea43c61c31ce419b1c173ae0fd795f542b..7a61451b900c0322c946430e63fd7bed934b4314 100644 (file)
 //! [`ToString`]s, and several error types that may result from working with
 //! [`String`]s.
 //!
-//! [`String`]: struct.String.html
 //! [`ToString`]: trait.ToString.html
 //!
 //! # Examples
 //!
-//! There are multiple ways to create a new `String` from a string literal:
+//! There are multiple ways to create a new [`String`] from a string literal:
 //!
 //! ```
 //! let s = "Hello".to_string();
 //! let s: String = "also this".into();
 //! ```
 //!
-//! You can create a new `String` from an existing one by concatenating with
+//! You can create a new [`String`] from an existing one by concatenating with
 //! `+`:
 //!
+//! [`String`]: struct.String.html
+//!
 //! ```
 //! let s = "Hello".to_string();
 //!
index 4a727adb797e01b5ea304264e7d866950a040106..52fc8b9dd7049769ee53f6723acf784c0f5fe900 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 950e6ee2e9ef00a5a6c3a4466c37addf2f6a4d27..88fb6540a9af4a723aa7351fd6333347e1033ee2 100644 (file)
 #![feature(collections)]
 #![feature(collections_bound)]
 #![feature(const_fn)]
+#![feature(dedup_by)]
 #![feature(enumset)]
 #![feature(pattern)]
 #![feature(rand)]
+#![feature(repeat_str)]
 #![feature(step_by)]
 #![feature(str_escape)]
 #![feature(str_replacen)]
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 560895f721bbf7aefc8f103bfa2639e532fcf2bd..cc56bbf4890aa46de435ab3048d1952aeaaa7e18 100644 (file)
@@ -1286,6 +1286,13 @@ fn test_cow_from() {
     }
 }
 
+#[test]
+fn test_repeat() {
+    assert_eq!("".repeat(3), "");
+    assert_eq!("abc".repeat(0), "");
+    assert_eq!("α".repeat(3), "ααα");
+}
+
 mod pattern {
     use std::str::pattern::Pattern;
     use std::str::pattern::{Searcher, ReverseSearcher};
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 1ca550c67463c3606c8db65c78577235ca283feb..a1f4630c304bf93dff849a7d479910658e085a43 100644 (file)
 pub trait FullOps: Sized {
     /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
     /// where `W` is the number of bits in `Self`.
-    fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);
+    fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self);
 
     /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`,
     /// where `W` is the number of bits in `Self`.
-    fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self);
+    fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self);
 
     /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`,
     /// where `W` is the number of bits in `Self`.
-    fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self);
+    fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self);
 
     /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
     /// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
-    fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/);
+    fn full_div_rem(self,
+                    other: Self,
+                    borrow: Self)
+                    -> (Self /* quotient */, Self /* remainder */);
 }
 
 macro_rules! impl_full_ops {
@@ -100,11 +103,7 @@ fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
 
 /// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
 /// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
-const SMALL_POW5: [(u64, usize); 3] = [
-    (125, 3),
-    (15625, 6),
-    (1_220_703_125, 13),
-];
+const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)];
 
 macro_rules! define_bignum {
     ($name:ident: type=$ty:ty, n=$n:expr) => (
index 7c369ee3b3bd7b4291fe2a2011651cd5751eb301..11eea753f93f912a579dd607cddae2e39f61eb24 100644 (file)
@@ -49,12 +49,30 @@ pub fn mul(&self, other: &Fp) -> Fp {
     pub fn normalize(&self) -> Fp {
         let mut f = self.f;
         let mut e = self.e;
-        if f >> (64 - 32) == 0 { f <<= 32; e -= 32; }
-        if f >> (64 - 16) == 0 { f <<= 16; e -= 16; }
-        if f >> (64 -  8) == 0 { f <<=  8; e -=  8; }
-        if f >> (64 -  4) == 0 { f <<=  4; e -=  4; }
-        if f >> (64 -  2) == 0 { f <<=  2; e -=  2; }
-        if f >> (64 -  1) == 0 { f <<=  1; e -=  1; }
+        if f >> (64 - 32) == 0 {
+            f <<= 32;
+            e -= 32;
+        }
+        if f >> (64 - 16) == 0 {
+            f <<= 16;
+            e -= 16;
+        }
+        if f >> (64 - 8) == 0 {
+            f <<= 8;
+            e -= 8;
+        }
+        if f >> (64 - 4) == 0 {
+            f <<= 4;
+            e -= 4;
+        }
+        if f >> (64 - 2) == 0 {
+            f <<= 2;
+            e -= 2;
+        }
+        if f >> (64 - 1) == 0 {
+            f <<= 1;
+            e -= 1;
+        }
         debug_assert!(f >= (1 >> 63));
         Fp { f: f, e: e }
     }
@@ -66,6 +84,9 @@ pub fn normalize_to(&self, e: i16) -> Fp {
         assert!(edelta >= 0);
         let edelta = edelta as usize;
         assert_eq!(self.f << edelta >> edelta, self.f);
-        Fp { f: self.f << edelta, e: e }
+        Fp {
+            f: self.f << edelta,
+            e: e,
+        }
     }
 }
index 07b05f91f489f9ecfa3752b2175e5f0bc35a3251..4527d46a27d8a9590f6e64ebdf0376ae561996d6 100644 (file)
 
 /// Not a Number (NaN).
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const NAN: f32 = 0.0_f32/0.0_f32;
+pub const NAN: f32 = 0.0_f32 / 0.0_f32;
 /// Infinity (∞).
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const INFINITY: f32 = 1.0_f32/0.0_f32;
+pub const INFINITY: f32 = 1.0_f32 / 0.0_f32;
 /// Negative infinity (-∞).
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
+pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
 
 /// Basic mathematical constants.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -144,26 +144,40 @@ pub mod consts {
            issue = "32110")]
 impl Float for f32 {
     #[inline]
-    fn nan() -> f32 { NAN }
+    fn nan() -> f32 {
+        NAN
+    }
 
     #[inline]
-    fn infinity() -> f32 { INFINITY }
+    fn infinity() -> f32 {
+        INFINITY
+    }
 
     #[inline]
-    fn neg_infinity() -> f32 { NEG_INFINITY }
+    fn neg_infinity() -> f32 {
+        NEG_INFINITY
+    }
 
     #[inline]
-    fn zero() -> f32 { 0.0 }
+    fn zero() -> f32 {
+        0.0
+    }
 
     #[inline]
-    fn neg_zero() -> f32 { -0.0 }
+    fn neg_zero() -> f32 {
+        -0.0
+    }
 
     #[inline]
-    fn one() -> f32 { 1.0 }
+    fn one() -> f32 {
+        1.0
+    }
 
     /// Returns `true` if the number is NaN.
     #[inline]
-    fn is_nan(self) -> bool { self != self }
+    fn is_nan(self) -> bool {
+        self != self
+    }
 
     /// Returns `true` if the number is infinite.
     #[inline]
@@ -192,11 +206,11 @@ fn classify(self) -> Fp {
 
         let bits: u32 = unsafe { mem::transmute(self) };
         match (bits & MAN_MASK, bits & EXP_MASK) {
-            (0, 0)        => Fp::Zero,
-            (_, 0)        => Fp::Subnormal,
+            (0, 0) => Fp::Zero,
+            (_, 0) => Fp::Subnormal,
             (0, EXP_MASK) => Fp::Infinite,
             (_, EXP_MASK) => Fp::Nan,
-            _             => Fp::Normal,
+            _ => Fp::Normal,
         }
     }
 
@@ -252,7 +266,9 @@ fn is_sign_negative(self) -> bool {
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
     #[inline]
-    fn recip(self) -> f32 { 1.0 / self }
+    fn recip(self) -> f32 {
+        1.0 / self
+    }
 
     #[inline]
     fn powi(self, n: i32) -> f32 {
@@ -261,7 +277,9 @@ fn powi(self, n: i32) -> f32 {
 
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
-    fn to_degrees(self) -> f32 { self * (180.0f32 / consts::PI) }
+    fn to_degrees(self) -> f32 {
+        self * (180.0f32 / consts::PI)
+    }
 
     /// Converts to radians, assuming the number is in degrees.
     #[inline]
index 82a09e599e027a49065a342fcaac64fd31da2a79..991a856834948687cf00c59d5879149733af6bc6 100644 (file)
 
 /// Not a Number (NaN).
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const NAN: f64 = 0.0_f64/0.0_f64;
+pub const NAN: f64 = 0.0_f64 / 0.0_f64;
 /// Infinity (∞).
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const INFINITY: f64 = 1.0_f64/0.0_f64;
+pub const INFINITY: f64 = 1.0_f64 / 0.0_f64;
 /// Negative infinity (-∞).
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64;
+pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
 
 /// Basic mathematical constants.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -144,26 +144,40 @@ pub mod consts {
            issue = "32110")]
 impl Float for f64 {
     #[inline]
-    fn nan() -> f64 { NAN }
+    fn nan() -> f64 {
+        NAN
+    }
 
     #[inline]
-    fn infinity() -> f64 { INFINITY }
+    fn infinity() -> f64 {
+        INFINITY
+    }
 
     #[inline]
-    fn neg_infinity() -> f64 { NEG_INFINITY }
+    fn neg_infinity() -> f64 {
+        NEG_INFINITY
+    }
 
     #[inline]
-    fn zero() -> f64 { 0.0 }
+    fn zero() -> f64 {
+        0.0
+    }
 
     #[inline]
-    fn neg_zero() -> f64 { -0.0 }
+    fn neg_zero() -> f64 {
+        -0.0
+    }
 
     #[inline]
-    fn one() -> f64 { 1.0 }
+    fn one() -> f64 {
+        1.0
+    }
 
     /// Returns `true` if the number is NaN.
     #[inline]
-    fn is_nan(self) -> bool { self != self }
+    fn is_nan(self) -> bool {
+        self != self
+    }
 
     /// Returns `true` if the number is infinite.
     #[inline]
@@ -192,11 +206,11 @@ fn classify(self) -> Fp {
 
         let bits: u64 = unsafe { mem::transmute(self) };
         match (bits & MAN_MASK, bits & EXP_MASK) {
-            (0, 0)        => Fp::Zero,
-            (_, 0)        => Fp::Subnormal,
+            (0, 0) => Fp::Zero,
+            (_, 0) => Fp::Subnormal,
             (0, EXP_MASK) => Fp::Infinite,
             (_, EXP_MASK) => Fp::Nan,
-            _             => Fp::Normal,
+            _ => Fp::Normal,
         }
     }
 
@@ -252,7 +266,9 @@ fn is_sign_negative(self) -> bool {
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
     #[inline]
-    fn recip(self) -> f64 { 1.0 / self }
+    fn recip(self) -> f64 {
+        1.0 / self
+    }
 
     #[inline]
     fn powi(self, n: i32) -> f64 {
@@ -261,7 +277,9 @@ fn powi(self, n: i32) -> f64 {
 
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
-    fn to_degrees(self) -> f64 { self * (180.0f64 / consts::PI) }
+    fn to_degrees(self) -> f64 {
+        self * (180.0f64 / consts::PI)
+    }
 
     /// Converts to radians, assuming the number is in degrees.
     #[inline]
index 516d6f7c4a0bd956d978b8090e9fc2e9bd78f844..a4529909e83ef61ddbd82d2fb5586ca317c98308 100644 (file)
@@ -43,7 +43,8 @@
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
-pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
+pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")]
+                       pub T);
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for Wrapping<T> {
@@ -2402,7 +2403,7 @@ pub enum FpCategory {
 
     /// Positive or negative infinity.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Infinite ,
+    Infinite,
 
     /// Positive or negative zero.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -2662,8 +2663,7 @@ fn checked_add(&self, other: u32) -> Option<Self> {
 }
 doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
 
-fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
-                                         -> Result<T, ParseIntError> {
+fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
     use self::IntErrorKind::*;
     use self::ParseIntError as PIE;
 
@@ -2686,7 +2686,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
     let (is_positive, digits) = match src[0] {
         b'+' => (true, &src[1..]),
         b'-' if is_signed_ty => (false, &src[1..]),
-        _ => (true, src)
+        _ => (true, src),
     };
 
     if digits.is_empty() {
@@ -2738,7 +2738,9 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
 /// [`i8::from_str_radix()`]: ../../std/primitive.i8.html#method.from_str_radix
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseIntError { kind: IntErrorKind }
+pub struct ParseIntError {
+    kind: IntErrorKind,
+}
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 enum IntErrorKind {
index 2c69880dfa35ab4417808f8e8c62bafbfaef0062..d35c451ac2604471de90bf2426d18d528fde1486 100644 (file)
@@ -310,13 +310,13 @@ mod platform {
         pub const isize: u32 = super::i64;
     }
 
-    pub const  i8: u32 = (1 << 3) - 1;
+    pub const i8: u32 = (1 << 3) - 1;
     pub const i16: u32 = (1 << 4) - 1;
     pub const i32: u32 = (1 << 5) - 1;
     pub const i64: u32 = (1 << 6) - 1;
     pub use self::platform::isize;
 
-    pub const  u8: u32 = i8;
+    pub const u8: u32 = i8;
     pub const u16: u32 = i16;
     pub const u32: u32 = i32;
     pub const u64: u32 = i64;
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 f56a27b9ae04a1213463efe6f4f0c06dae80ce02..137c6b58dc99817cde20d652f6f747b579391398 100644 (file)
@@ -44,9 +44,8 @@
 use hir::map::Definitions;
 use hir::map::definitions::DefPathData;
 use hir::def_id::{DefIndex, DefId};
-use hir::def::{Def, CtorKind, PathResolution};
+use hir::def::{Def, PathResolution};
 use session::Session;
-use lint;
 
 use std::collections::BTreeMap;
 use std::iter;
@@ -95,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,
@@ -857,22 +850,8 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 }
                 PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
                 PatKind::TupleStruct(ref path, ref pats, ddpos) => {
-                    match self.resolver.get_resolution(p.id).map(|d| d.base_def) {
-                        Some(def @ Def::StructCtor(_, CtorKind::Const)) |
-                        Some(def @ Def::VariantCtor(_, CtorKind::Const)) => {
-                            // Temporarily lower `UnitVariant(..)` into `UnitVariant`
-                            // for backward compatibility.
-                            let msg = format!("expected tuple struct/variant, found {} `{}`",
-                                            def.kind_name(), path);
-                            self.sess.add_lint(
-                                lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
-                                p.id, p.span, msg
-                            );
-                            hir::PatKind::Path(None, self.lower_path(path))
-                        }
-                        _ => hir::PatKind::TupleStruct(self.lower_path(path),
+                    hir::PatKind::TupleStruct(self.lower_path(path),
                                         pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
-                    }
                 }
                 PatKind::Path(ref opt_qself, ref path) => {
                     let opt_qself = opt_qself.as_ref().map(|qself| {
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 d378772e6557029985b0f825d0f0eae5aae17c1e..7fc3f638979ff4a671608a6ba2a66205f265d908 100644 (file)
      the struct or enum has `#[derive(PartialEq, Eq)]`"
 }
 
-declare_lint! {
-    pub MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
-    Deny,
-    "unit struct or enum variant erroneously allowed to match via path::ident(..)"
-}
-
 declare_lint! {
     pub RAW_POINTER_DERIVE,
     Warn,
@@ -226,7 +220,6 @@ fn get_lints(&self) -> LintArray {
             INVALID_TYPE_PARAM_DEFAULT,
             ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
             ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
-            MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
             CONST_ERR,
             RAW_POINTER_DERIVE,
             TRANSMUTE_FROM_FN_ITEM_TYPES,
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 8e330ee8e824ce2cc6d89c4427b7eff7bddb6baf..6db82b862074de8b9bf9beba0c6513770415c43d 100644 (file)
@@ -2323,7 +2323,11 @@ pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {
                 let enum_did = self.parent_def_id(did).unwrap();
                 self.lookup_adt_def(enum_did).variant_with_id(did)
             }
-            Def::Struct(did) | Def::StructCtor(did, ..) | Def::Union(did) => {
+            Def::Struct(did) | Def::Union(did) => {
+                self.lookup_adt_def(did).struct_variant()
+            }
+            Def::StructCtor(ctor_did, ..) => {
+                let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent");
                 self.lookup_adt_def(did).struct_variant()
             }
             _ => bug!("expect_variant_def used with unexpected def {:?}", def)
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 2bd4a4d302936668a7f9fe070d9b00bbebcfd458..9281d8aa44a56b6d05c758a91e440ab06346a98c 100644 (file)
@@ -1238,8 +1238,10 @@ fn visit_pat(&mut self, pat: &Pat) {
         match pat.node {
             PatKind::Binding(.., ref subpat) => {
                 if !self.bindings_allowed {
-                    span_err!(self.cx.tcx.sess, pat.span, E0303,
-                              "pattern bindings are not allowed after an `@`");
+                    struct_span_err!(self.cx.tcx.sess, pat.span, E0303,
+                                     "pattern bindings are not allowed after an `@`")
+                        .span_label(pat.span,  &format!("not allowed after `@`"))
+                        .emit();
                 }
 
                 if subpat.is_some() {
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 bc2979c806f65abb619ddc63cfcb4100ddf8d3d1..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>",
@@ -172,11 +184,6 @@ macro_rules! add_lint_group {
             id: LintId::of(SUPER_OR_SELF_IN_GLOBAL_PATH),
             reference: "PR #32403 <https://github.com/rust-lang/rust/pull/32403>",
         },
-        FutureIncompatibleInfo {
-            id: LintId::of(MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT),
-            reference: "RFC 218 <https://github.com/rust-lang/rfcs/blob/\
-                        master/text/0218-empty-struct-with-braces.md>",
-        },
         FutureIncompatibleInfo {
             id: LintId::of(TRANSMUTE_FROM_FN_ITEM_TYPES),
             reference: "issue #19925 <https://github.com/rust-lang/rust/issues/19925>",
@@ -209,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 4f41dfc8b645551e23dab1db11024aba5e27fdc0..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(),
         }
     }
 
@@ -2412,15 +2425,11 @@ fn resolve_pattern(&mut self,
                     self.record_def(pat.id, resolution);
                 }
 
-                PatKind::TupleStruct(ref path, ref pats, ddpos) => {
+                PatKind::TupleStruct(ref path, ..) => {
                     self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
                         match def {
                             Def::StructCtor(_, CtorKind::Fn) |
                             Def::VariantCtor(_, CtorKind::Fn) => true,
-                            // `UnitVariant(..)` is accepted for backward compatibility.
-                            Def::StructCtor(_, CtorKind::Const) |
-                            Def::VariantCtor(_, CtorKind::Const)
-                                if pats.is_empty() && ddpos.is_some() => true,
                             _ => false,
                         }
                     }, "tuple struct/variant");
@@ -3342,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 {
@@ -3370,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 41f34b9040e832b3d580cba853fe9d575d2495eb..9610477d8fd919f26e49a37c1130a4e4375eaef5 100644 (file)
@@ -9,13 +9,13 @@
 // except according to those terms.
 
 use rustc::infer::InferCtxt;
-use rustc::traits::{self, FulfillmentContext, Normalized, MiscObligation,
-                     SelectionContext, ObligationCause};
+use rustc::traits::{self, FulfillmentContext, Normalized, MiscObligation, SelectionContext,
+                    ObligationCause};
 use rustc::ty::fold::TypeFoldable;
 use syntax::ast;
 use syntax_pos::Span;
 
-//FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
+// FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
 pub fn normalize_associated_types_in<'a, 'gcx, 'tcx, T>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     fulfillment_cx: &mut FulfillmentContext<'tcx>,
index 19261a2447f9100ed8b7dee42319073e7ad4fdc0..8127bcf8256438e7f1230ec4a6e2357bae9b66ae 100644 (file)
@@ -26,7 +26,7 @@
 #[derive(Copy, Clone, Debug)]
 enum AutoderefKind {
     Builtin,
-    Overloaded
+    Overloaded,
 }
 
 pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> {
@@ -35,7 +35,7 @@ pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> {
     cur_ty: Ty<'tcx>,
     obligations: Vec<traits::PredicateObligation<'tcx>>,
     at_start: bool,
-    span: Span
+    span: Span,
 }
 
 impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
@@ -45,7 +45,8 @@ fn next(&mut self) -> Option<Self::Item> {
         let tcx = self.fcx.tcx;
 
         debug!("autoderef: steps={:?}, cur_ty={:?}",
-               self.steps, self.cur_ty);
+               self.steps,
+               self.cur_ty);
         if self.at_start {
             self.at_start = false;
             debug!("autoderef stage #0 is {:?}", self.cur_ty);
@@ -54,11 +55,13 @@ fn next(&mut self) -> Option<Self::Item> {
 
         if self.steps.len() == tcx.sess.recursion_limit.get() {
             // We've reached the recursion limit, error gracefully.
-            struct_span_err!(tcx.sess, self.span, E0055,
-                      "reached the recursion limit while auto-dereferencing {:?}",
-                      self.cur_ty)
-                      .span_label(self.span, &format!("deref recursion limit reached"))
-                      .emit();
+            struct_span_err!(tcx.sess,
+                             self.span,
+                             E0055,
+                             "reached the recursion limit while auto-dereferencing {:?}",
+                             self.cur_ty)
+                .span_label(self.span, &format!("deref recursion limit reached"))
+                .emit();
             return None;
         }
 
@@ -72,7 +75,7 @@ fn next(&mut self) -> Option<Self::Item> {
         } else {
             match self.overloaded_deref_ty(self.cur_ty) {
                 Some(ty) => (AutoderefKind::Overloaded, ty),
-                _ => return None
+                _ => return None,
             }
         };
 
@@ -81,8 +84,10 @@ fn next(&mut self) -> Option<Self::Item> {
         }
 
         self.steps.push((self.cur_ty, kind));
-        debug!("autoderef stage #{:?} is {:?} from {:?}", self.steps.len(),
-               new_ty, (self.cur_ty, kind));
+        debug!("autoderef stage #{:?} is {:?} from {:?}",
+               self.steps.len(),
+               new_ty,
+               (self.cur_ty, kind));
         self.cur_ty = new_ty;
 
         Some((self.cur_ty, self.steps.len()))
@@ -99,9 +104,9 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let trait_ref = TraitRef {
             def_id: match tcx.lang_items.deref_trait() {
                 Some(f) => f,
-                None => return None
+                None => return None,
             },
-            substs: Substs::new_trait(tcx, self.cur_ty, &[])
+            substs: Substs::new_trait(tcx, self.cur_ty, &[]),
         };
 
         let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
@@ -113,15 +118,13 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
             return None;
         }
 
-        let normalized = traits::normalize_projection_type(
-            &mut selcx,
-            ty::ProjectionTy {
-                trait_ref: trait_ref,
-                item_name: token::intern("Target")
-            },
-            cause,
-            0
-        );
+        let normalized = traits::normalize_projection_type(&mut selcx,
+                                                           ty::ProjectionTy {
+                                                               trait_ref: trait_ref,
+                                                               item_name: token::intern("Target"),
+                                                           },
+                                                           cause,
+                                                           0);
 
         debug!("overloaded_deref_ty({:?}) = {:?}", ty, normalized);
         self.obligations.extend(normalized.obligations);
@@ -134,17 +137,23 @@ pub fn unambiguous_final_ty(&self) -> Ty<'tcx> {
     }
 
     pub fn finalize<'b, I>(self, pref: LvaluePreference, exprs: I)
-        where I: IntoIterator<Item=&'b hir::Expr>
+        where I: IntoIterator<Item = &'b hir::Expr>
     {
-        let methods : Vec<_> = self.steps.iter().map(|&(ty, kind)| {
-            if let AutoderefKind::Overloaded = kind {
-                self.fcx.try_overloaded_deref(self.span, None, ty, pref)
-            } else {
-                None
-            }
-        }).collect();
+        let methods: Vec<_> = self.steps
+            .iter()
+            .map(|&(ty, kind)| {
+                if let AutoderefKind::Overloaded = kind {
+                    self.fcx.try_overloaded_deref(self.span, None, ty, pref)
+                } else {
+                    None
+                }
+            })
+            .collect();
 
-        debug!("finalize({:?}) - {:?},{:?}", pref, methods, self.obligations);
+        debug!("finalize({:?}) - {:?},{:?}",
+               pref,
+               methods,
+               self.obligations);
 
         for expr in exprs {
             debug!("finalize - finalizing #{} - {:?}", expr.id, expr);
@@ -163,18 +172,14 @@ pub fn finalize<'b, I>(self, pref: LvaluePreference, exprs: I)
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn autoderef(&'a self,
-                     span: Span,
-                     base_ty: Ty<'tcx>)
-                     -> Autoderef<'a, 'gcx, 'tcx>
-    {
+    pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'gcx, 'tcx> {
         Autoderef {
             fcx: self,
             steps: vec![],
             cur_ty: self.resolve_type_vars_if_possible(&base_ty),
             obligations: vec![],
             at_start: true,
-            span: span
+            span: span,
         }
     }
 
@@ -183,28 +188,36 @@ pub fn try_overloaded_deref(&self,
                                 base_expr: Option<&hir::Expr>,
                                 base_ty: Ty<'tcx>,
                                 lvalue_pref: LvaluePreference)
-                                -> Option<MethodCallee<'tcx>>
-    {
+                                -> Option<MethodCallee<'tcx>> {
         debug!("try_overloaded_deref({:?},{:?},{:?},{:?})",
-               span, base_expr, base_ty, lvalue_pref);
+               span,
+               base_expr,
+               base_ty,
+               lvalue_pref);
         // Try DerefMut first, if preferred.
         let method = match (lvalue_pref, self.tcx.lang_items.deref_mut_trait()) {
             (PreferMutLvalue, Some(trait_did)) => {
-                self.lookup_method_in_trait(span, base_expr,
-                                            token::intern("deref_mut"), trait_did,
-                                            base_ty, None)
+                self.lookup_method_in_trait(span,
+                                            base_expr,
+                                            token::intern("deref_mut"),
+                                            trait_did,
+                                            base_ty,
+                                            None)
             }
-            _ => None
+            _ => None,
         };
 
         // Otherwise, fall back to Deref.
         let method = match (method, self.tcx.lang_items.deref_trait()) {
             (None, Some(trait_did)) => {
-                self.lookup_method_in_trait(span, base_expr,
-                                            token::intern("deref"), trait_did,
-                                            base_ty, None)
+                self.lookup_method_in_trait(span,
+                                            base_expr,
+                                            token::intern("deref"),
+                                            trait_did,
+                                            base_ty,
+                                            None)
             }
-            (method, _) => method
+            (method, _) => method,
         };
 
         method
index 75c1d28f7d830385c15953f1c86b0f1cd58f8f6e..c5a21d7dd91ce116bb9a4b5585cbd15e041747ef 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{DeferredCallResolution, Expectation, FnCtxt,
-            TupleArgumentsFlag};
+use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag};
 
 use CrateCtxt;
 use hir::def::Def;
 /// method that is called)
 pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
     if ccx.tcx.lang_items.drop_trait() == Some(trait_id) {
-        struct_span_err!(ccx.tcx.sess, span, E0040, "explicit use of destructor method")
+        struct_span_err!(ccx.tcx.sess,
+                         span,
+                         E0040,
+                         "explicit use of destructor method")
             .span_label(span, &format!("explicit destructor calls not allowed"))
             .emit();
     }
@@ -36,7 +38,7 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id:
 enum CallStep<'tcx> {
     Builtin,
     DeferredClosure(ty::FnSig<'tcx>),
-    Overloaded(ty::MethodCallee<'tcx>)
+    Overloaded(ty::MethodCallee<'tcx>),
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@@ -44,15 +46,17 @@ pub fn check_call(&self,
                       call_expr: &'gcx hir::Expr,
                       callee_expr: &'gcx hir::Expr,
                       arg_exprs: &'gcx [P<hir::Expr>],
-                      expected: Expectation<'tcx>) -> Ty<'tcx>
-    {
+                      expected: Expectation<'tcx>)
+                      -> Ty<'tcx> {
         let original_callee_ty = self.check_expr(callee_expr);
         let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
 
         let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
-        let result = autoderef.by_ref().flat_map(|(adj_ty, idx)| {
-            self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx)
-        }).next();
+        let result = autoderef.by_ref()
+            .flat_map(|(adj_ty, idx)| {
+                self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx)
+            })
+            .next();
         let callee_ty = autoderef.unambiguous_final_ty();
         autoderef.finalize(LvaluePreference::NoPreference, Some(callee_expr));
 
@@ -71,8 +75,11 @@ pub fn check_call(&self,
             }
 
             Some(CallStep::Overloaded(method_callee)) => {
-                self.confirm_overloaded_call(call_expr, callee_expr,
-                                             arg_exprs, expected, method_callee)
+                self.confirm_overloaded_call(call_expr,
+                                             callee_expr,
+                                             arg_exprs,
+                                             expected,
+                                             method_callee)
             }
         };
 
@@ -87,8 +94,7 @@ fn try_overloaded_call_step(&self,
                                 callee_expr: &'gcx hir::Expr,
                                 adjusted_ty: Ty<'tcx>,
                                 autoderefs: usize)
-                                -> Option<CallStep<'tcx>>
-    {
+                                -> Option<CallStep<'tcx>> {
         debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
                call_expr,
                adjusted_ty,
@@ -108,20 +114,20 @@ fn try_overloaded_call_step(&self,
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id).is_none() {
-                    let closure_ty =
-                        self.closure_type(def_id, substs);
-                    let fn_sig =
-                        self.replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                                       infer::FnCall,
-                                                                       &closure_ty.sig).0;
-                    self.record_deferred_call_resolution(def_id, Box::new(CallResolution {
-                        call_expr: call_expr,
-                        callee_expr: callee_expr,
-                        adjusted_ty: adjusted_ty,
-                        autoderefs: autoderefs,
-                        fn_sig: fn_sig.clone(),
-                        closure_def_id: def_id
-                    }));
+                    let closure_ty = self.closure_type(def_id, substs);
+                    let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
+                                                                   infer::FnCall,
+                                                                   &closure_ty.sig)
+                        .0;
+                    self.record_deferred_call_resolution(def_id,
+                                                         Box::new(CallResolution {
+                                                             call_expr: call_expr,
+                                                             callee_expr: callee_expr,
+                                                             adjusted_ty: adjusted_ty,
+                                                             autoderefs: autoderefs,
+                                                             fn_sig: fn_sig.clone(),
+                                                             closure_def_id: def_id,
+                                                         }));
                     return Some(CallStep::DeferredClosure(fn_sig));
                 }
             }
@@ -150,14 +156,12 @@ fn try_overloaded_call_traits(&self,
                                   callee_expr: &hir::Expr,
                                   adjusted_ty: Ty<'tcx>,
                                   autoderefs: usize)
-                                  -> Option<ty::MethodCallee<'tcx>>
-    {
+                                  -> Option<ty::MethodCallee<'tcx>> {
         // Try the options that are least restrictive on the caller first.
-        for &(opt_trait_def_id, method_name) in &[
-            (self.tcx.lang_items.fn_trait(), token::intern("call")),
-            (self.tcx.lang_items.fn_mut_trait(), token::intern("call_mut")),
-            (self.tcx.lang_items.fn_once_trait(), token::intern("call_once")),
-        ] {
+        for &(opt_trait_def_id, method_name) in
+            &[(self.tcx.lang_items.fn_trait(), token::intern("call")),
+              (self.tcx.lang_items.fn_mut_trait(), token::intern("call_mut")),
+              (self.tcx.lang_items.fn_once_trait(), token::intern("call_once"))] {
             let trait_def_id = match opt_trait_def_id {
                 Some(def_id) => def_id,
                 None => continue,
@@ -185,19 +189,20 @@ fn confirm_builtin_call(&self,
                             call_expr: &hir::Expr,
                             callee_ty: Ty<'tcx>,
                             arg_exprs: &'gcx [P<hir::Expr>],
-                            expected: Expectation<'tcx>) -> Ty<'tcx>
-    {
+                            expected: Expectation<'tcx>)
+                            -> Ty<'tcx> {
         let error_fn_sig;
 
         let fn_sig = match callee_ty.sty {
-            ty::TyFnDef(.., &ty::BareFnTy {ref sig, ..}) |
-            ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => {
-                sig
-            }
+            ty::TyFnDef(.., &ty::BareFnTy { ref sig, .. }) |
+            ty::TyFnPtr(&ty::BareFnTy { ref sig, .. }) => sig,
             _ => {
-                let mut err = self.type_error_struct(call_expr.span, |actual| {
-                    format!("expected function, found `{}`", actual)
-                }, callee_ty);
+                let mut err = self.type_error_struct(call_expr.span,
+                                                     |actual| {
+                                                         format!("expected function, found `{}`",
+                                                                 actual)
+                                                     },
+                                                     callee_ty);
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
                     let tcx = self.tcx;
@@ -218,7 +223,7 @@ fn confirm_builtin_call(&self,
                 error_fn_sig = ty::Binder(ty::FnSig {
                     inputs: self.err_args(arg_exprs.len()),
                     output: self.tcx.types.err,
-                    variadic: false
+                    variadic: false,
                 });
 
                 &error_fn_sig
@@ -231,17 +236,16 @@ fn confirm_builtin_call(&self,
         // previously appeared within a `Binder<>` and hence would not
         // have been normalized before.
         let fn_sig =
-            self.replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                           infer::FnCall,
-                                                           fn_sig).0;
-        let fn_sig =
-            self.normalize_associated_types_in(call_expr.span, &fn_sig);
+            self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, fn_sig)
+                .0;
+        let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
 
         // Call the generic checker.
-        let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span,
-                                                               expected,
-                                                               fn_sig.output,
-                                                               &fn_sig.inputs);
+        let expected_arg_tys =
+            self.expected_types_for_fn_args(call_expr.span,
+                                            expected,
+                                            fn_sig.output,
+                                            &fn_sig.inputs);
         self.check_argument_types(call_expr.span,
                                   &fn_sig.inputs,
                                   &expected_arg_tys[..],
@@ -256,18 +260,17 @@ fn confirm_deferred_closure_call(&self,
                                      call_expr: &hir::Expr,
                                      arg_exprs: &'gcx [P<hir::Expr>],
                                      expected: Expectation<'tcx>,
-                                     fn_sig: ty::FnSig<'tcx>) -> Ty<'tcx>
-    {
+                                     fn_sig: ty::FnSig<'tcx>)
+                                     -> Ty<'tcx> {
         // `fn_sig` is the *signature* of the cosure being called. We
         // don't know the full details yet (`Fn` vs `FnMut` etc), but we
         // do know the types expected for each argument and the return
         // type.
 
-        let expected_arg_tys =
-            self.expected_types_for_fn_args(call_expr.span,
-                                            expected,
-                                            fn_sig.output.clone(),
-                                            &fn_sig.inputs);
+        let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span,
+                                                               expected,
+                                                               fn_sig.output.clone(),
+                                                               &fn_sig.inputs);
 
         self.check_argument_types(call_expr.span,
                                   &fn_sig.inputs,
@@ -284,15 +287,14 @@ fn confirm_overloaded_call(&self,
                                callee_expr: &'gcx hir::Expr,
                                arg_exprs: &'gcx [P<hir::Expr>],
                                expected: Expectation<'tcx>,
-                               method_callee: ty::MethodCallee<'tcx>) -> Ty<'tcx>
-    {
-        let output_type =
-            self.check_method_argument_types(call_expr.span,
-                                             method_callee.ty,
-                                             callee_expr,
-                                             arg_exprs,
-                                             TupleArgumentsFlag::TupleArguments,
-                                             expected);
+                               method_callee: ty::MethodCallee<'tcx>)
+                               -> Ty<'tcx> {
+        let output_type = self.check_method_argument_types(call_expr.span,
+                                                           method_callee.ty,
+                                                           callee_expr,
+                                                           arg_exprs,
+                                                           TupleArgumentsFlag::TupleArguments,
+                                                           expected);
 
         self.write_overloaded_call_method_map(call_expr, method_callee);
         output_type
@@ -318,16 +320,17 @@ struct CallResolution<'gcx: 'tcx, 'tcx> {
 
 impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tcx> {
     fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
-        debug!("DeferredCallResolution::resolve() {:?}",
-               self);
+        debug!("DeferredCallResolution::resolve() {:?}", self);
 
         // we should not be invoked until the closure kind has been
         // determined by upvar inference
         assert!(fcx.closure_kind(self.closure_def_id).is_some());
 
         // We may now know enough to figure out fn vs fnmut etc.
-        match fcx.try_overloaded_call_traits(self.call_expr, self.callee_expr,
-                                             self.adjusted_ty, self.autoderefs) {
+        match fcx.try_overloaded_call_traits(self.call_expr,
+                                             self.callee_expr,
+                                             self.adjusted_ty,
+                                             self.autoderefs) {
             Some(method_callee) => {
                 // One problem is that when we get here, we are going
                 // to have a newly instantiated function signature
@@ -337,28 +340,24 @@ fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
                 // can't because of the annoying need for a TypeTrace.
                 // (This always bites me, should find a way to
                 // refactor it.)
-                let method_sig = fcx.tcx.no_late_bound_regions(method_callee.ty.fn_sig())
-                                        .unwrap();
+                let method_sig = fcx.tcx
+                    .no_late_bound_regions(method_callee.ty.fn_sig())
+                    .unwrap();
 
-                debug!("attempt_resolution: method_callee={:?}",
-                       method_callee);
+                debug!("attempt_resolution: method_callee={:?}", method_callee);
 
                 for (&method_arg_ty, &self_arg_ty) in
-                    method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs)
-                {
+                    method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs) {
                     fcx.demand_eqtype(self.call_expr.span, self_arg_ty, method_arg_ty);
                 }
 
-                fcx.demand_eqtype(self.call_expr.span,
-                                  method_sig.output,
-                                  self.fn_sig.output);
+                fcx.demand_eqtype(self.call_expr.span, method_sig.output, self.fn_sig.output);
 
                 fcx.write_overloaded_call_method_map(self.call_expr, method_callee);
             }
             None => {
-                span_bug!(
-                    self.call_expr.span,
-                    "failed to find an overloaded call trait for closure call");
+                span_bug!(self.call_expr.span,
+                          "failed to find an overloaded call trait for closure call");
             }
         }
     }
index 51a9b18392dcf332f93eaca5b7fa9e632f6fcd9a..c456b9358b3e2e1f652dd48ab8d846557ac59b9b 100644 (file)
@@ -69,7 +69,7 @@ enum UnsizeKind<'tcx> {
     /// The unsize info of this projection
     OfProjection(&'tcx ty::ProjectionTy<'tcx>),
     /// The unsize info of this parameter
-    OfParam(&'tcx ty::ParamTy)
+    OfParam(&'tcx ty::ParamTy),
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@@ -83,13 +83,13 @@ fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
                 // FIXME(arielb1): do some kind of normalization
                 match def.struct_variant().fields.last() {
                     None => None,
-                    Some(f) => self.unsize_kind(f.ty(self.tcx, substs))
+                    Some(f) => self.unsize_kind(f.ty(self.tcx, substs)),
                 }
             }
             // We should really try to normalize here.
             ty::TyProjection(ref pi) => Some(UnsizeKind::OfProjection(pi)),
             ty::TyParam(ref p) => Some(UnsizeKind::OfParam(p)),
-            _ => None
+            _ => None,
         }
     }
 }
@@ -133,9 +133,7 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                 check.report_cast_to_unsized_type(fcx);
                 Err(ErrorReported)
             }
-            _ => {
-                Ok(check)
-            }
+            _ => Ok(check),
         }
     }
 
@@ -145,18 +143,21 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
             CastError::NeedViaThinPtr |
             CastError::NeedViaInt |
             CastError::NeedViaUsize => {
-                fcx.type_error_struct(self.span, |actual| {
-                    format!("casting `{}` as `{}` is invalid",
-                            actual,
-                            fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty)
-                    .help(&format!("cast through {} first", match e {
-                            CastError::NeedViaPtr => "a raw pointer",
-                            CastError::NeedViaThinPtr => "a thin pointer",
-                            CastError::NeedViaInt => "an integer",
-                            CastError::NeedViaUsize => "a usize",
-                            _ => bug!()
-                        }))
+                fcx.type_error_struct(self.span,
+                                       |actual| {
+                                           format!("casting `{}` as `{}` is invalid",
+                                                   actual,
+                                                   fcx.ty_to_string(self.cast_ty))
+                                       },
+                                       self.expr_ty)
+                    .help(&format!("cast through {} first",
+                                   match e {
+                                       CastError::NeedViaPtr => "a raw pointer",
+                                       CastError::NeedViaThinPtr => "a thin pointer",
+                                       CastError::NeedViaInt => "an integer",
+                                       CastError::NeedViaUsize => "a usize",
+                                       _ => bug!(),
+                                   }))
                     .emit();
             }
             CastError::CastToBool => {
@@ -166,37 +167,49 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                     .emit();
             }
             CastError::CastToChar => {
-                fcx.type_error_message(self.span, |actual| {
-                    format!("only `u8` can be cast as `char`, not `{}`", actual)
-                }, self.expr_ty);
+                fcx.type_error_message(self.span,
+                                       |actual| {
+                                           format!("only `u8` can be cast as `char`, not `{}`",
+                                                   actual)
+                                       },
+                                       self.expr_ty);
             }
             CastError::NonScalar => {
-                fcx.type_error_message(self.span, |actual| {
-                    format!("non-scalar cast: `{}` as `{}`",
-                            actual,
-                            fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty);
+                fcx.type_error_message(self.span,
+                                       |actual| {
+                                           format!("non-scalar cast: `{}` as `{}`",
+                                                   actual,
+                                                   fcx.ty_to_string(self.cast_ty))
+                                       },
+                                       self.expr_ty);
             }
             CastError::IllegalCast => {
-                fcx.type_error_message(self.span, |actual| {
-                    format!("casting `{}` as `{}` is invalid",
-                            actual,
-                            fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty);
+                fcx.type_error_message(self.span,
+                                       |actual| {
+                                           format!("casting `{}` as `{}` is invalid",
+                                                   actual,
+                                                   fcx.ty_to_string(self.cast_ty))
+                                       },
+                                       self.expr_ty);
             }
             CastError::SizedUnsizedCast => {
-                fcx.type_error_message(self.span, |actual| {
-                    format!("cannot cast thin pointer `{}` to fat pointer `{}`",
-                            actual,
-                            fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty)
+                fcx.type_error_message(self.span,
+                                       |actual| {
+                                           format!("cannot cast thin pointer `{}` to fat pointer \
+                                                    `{}`",
+                                                   actual,
+                                                   fcx.ty_to_string(self.cast_ty))
+                                       },
+                                       self.expr_ty)
             }
             CastError::DifferingKinds => {
-                fcx.type_error_struct(self.span, |actual| {
-                    format!("casting `{}` as `{}` is invalid",
-                            actual,
-                            fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty)
+                fcx.type_error_struct(self.span,
+                                       |actual| {
+                                           format!("casting `{}` as `{}` is invalid",
+                                                   actual,
+                                                   fcx.ty_to_string(self.cast_ty))
+                                       },
+                                       self.expr_ty)
                     .note("vtable kinds may not match")
                     .emit();
             }
@@ -204,22 +217,22 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
     }
 
     fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
-        if
-            self.cast_ty.references_error() ||
-            self.expr_ty.references_error()
-        {
+        if self.cast_ty.references_error() || self.expr_ty.references_error() {
             return;
         }
 
         let tstr = fcx.ty_to_string(self.cast_ty);
-        let mut err = fcx.type_error_struct(self.span, |actual| {
-            format!("cast to unsized type: `{}` as `{}`", actual, tstr)
-        }, self.expr_ty);
+        let mut err =
+            fcx.type_error_struct(self.span,
+                                  |actual| {
+                                      format!("cast to unsized type: `{}` as `{}`", actual, tstr)
+                                  },
+                                  self.expr_ty);
         match self.expr_ty.sty {
             ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
                 let mtstr = match mt {
                     hir::MutMutable => "mut ",
-                    hir::MutImmutable => ""
+                    hir::MutImmutable => "",
                 };
                 if self.cast_ty.is_trait() {
                     match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) {
@@ -227,15 +240,17 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
                             err.span_suggestion(self.cast_span,
                                                 "try casting to a reference instead:",
                                                 format!("&{}{}", mtstr, s));
-                        },
-                        Err(_) =>
-                            span_help!(err, self.cast_span,
-                                       "did you mean `&{}{}`?", mtstr, tstr),
+                        }
+                        Err(_) => {
+                            span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr)
+                        }
                     }
                 } else {
-                    span_help!(err, self.span,
+                    span_help!(err,
+                               self.span,
                                "consider using an implicit coercion to `&{}{}` instead",
-                               mtstr, tstr);
+                               mtstr,
+                               tstr);
                 }
             }
             ty::TyBox(..) => {
@@ -244,13 +259,13 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
                         err.span_suggestion(self.cast_span,
                                             "try casting to a `Box` instead:",
                                             format!("Box<{}>", s));
-                    },
-                    Err(_) =>
-                        span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
+                    }
+                    Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
                 }
             }
             _ => {
-                span_help!(err, self.expr.span,
+                span_help!(err,
+                           self.expr.span,
                            "consider using a box or reference as appropriate");
             }
         }
@@ -286,7 +301,9 @@ pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         self.expr_ty = fcx.structurally_resolved_type(self.span, self.expr_ty);
         self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty);
 
-        debug!("check_cast({}, {:?} as {:?})", self.expr.id, self.expr_ty,
+        debug!("check_cast({}, {:?} as {:?})",
+               self.expr.id,
+               self.expr_ty,
                self.cast_ty);
 
         if !fcx.type_is_known_to_be_sized(self.cast_ty, self.span) {
@@ -296,15 +313,16 @@ pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         } else if self.try_coercion_cast(fcx) {
             self.trivial_cast_lint(fcx);
             debug!(" -> CoercionCast");
-            fcx.tcx.cast_kinds.borrow_mut().insert(self.expr.id,
-                                                   CastKind::CoercionCast);
-        } else { match self.do_check(fcx) {
-            Ok(k) => {
-                debug!(" -> {:?}", k);
-                fcx.tcx.cast_kinds.borrow_mut().insert(self.expr.id, k);
-            }
-            Err(e) => self.report_cast_error(fcx, e)
-        };}
+            fcx.tcx.cast_kinds.borrow_mut().insert(self.expr.id, CastKind::CoercionCast);
+        } else {
+            match self.do_check(fcx) {
+                Ok(k) => {
+                    debug!(" -> {:?}", k);
+                    fcx.tcx.cast_kinds.borrow_mut().insert(self.expr.id, k);
+                }
+                Err(e) => self.report_cast_error(fcx, e),
+            };
+        }
     }
 
     /// Check a cast, and report an error if one exists. In some cases, this
@@ -330,9 +348,7 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
                     return Err(CastError::NonScalar);
                 }
             }
-            _ => {
-                return Err(CastError::NonScalar)
-            }
+            _ => return Err(CastError::NonScalar),
         };
 
         match (t_from, t_cast) {
@@ -347,17 +363,20 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
             (_, Int(Char)) => Err(CastError::CastToChar),
 
             // prim -> float,ptr
-            (Int(Bool), Float) | (Int(CEnum), Float) | (Int(Char), Float)
-                => Err(CastError::NeedViaInt),
-            (Int(Bool), Ptr(_)) | (Int(CEnum), Ptr(_)) | (Int(Char), Ptr(_))
-                => Err(CastError::NeedViaUsize),
+            (Int(Bool), Float) |
+            (Int(CEnum), Float) |
+            (Int(Char), Float) => Err(CastError::NeedViaInt),
+            (Int(Bool), Ptr(_)) |
+            (Int(CEnum), Ptr(_)) |
+            (Int(Char), Ptr(_)) => Err(CastError::NeedViaUsize),
 
             // ptr -> *
             (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
             (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
             (Ptr(_), Float) | (FnPtr, Float) => Err(CastError::NeedViaUsize),
             (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
-            (RPtr(_), Int(_)) | (RPtr(_), Float) => Err(CastError::NeedViaPtr),
+            (RPtr(_), Int(_)) |
+            (RPtr(_), Float) => Err(CastError::NeedViaPtr),
             // * -> ptr
             (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
             (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
@@ -366,12 +385,12 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
 
             // prim -> prim
             (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast),
-            (Int(Char), Int(_)) | (Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
+            (Int(Char), Int(_)) |
+            (Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
 
-            (Int(_), Int(_)) |
-            (Int(_), Float) |
-            (Float, Int(_)) |
-            (Float, Float) => Ok(CastKind::NumericCast),
+            (Int(_), Int(_)) | (Int(_), Float) | (Float, Int(_)) | (Float, Float) => {
+                Ok(CastKind::NumericCast)
+            }
 
         }
     }
@@ -380,10 +399,8 @@ fn check_ptr_ptr_cast(&self,
                           fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                           m_expr: &'tcx ty::TypeAndMut<'tcx>,
                           m_cast: &'tcx ty::TypeAndMut<'tcx>)
-                          -> Result<CastKind, CastError>
-    {
-        debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}",
-               m_expr, m_cast);
+                          -> Result<CastKind, CastError> {
+        debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
         // ptr-ptr cast. vtables must match.
 
         // Cast to sized is OK
@@ -399,15 +416,14 @@ fn check_ptr_ptr_cast(&self,
         // vtable kinds must match
         match (fcx.unsize_kind(m_cast.ty), fcx.unsize_kind(m_expr.ty)) {
             (Some(a), Some(b)) if a == b => Ok(CastKind::PtrPtrCast),
-            _ => Err(CastError::DifferingKinds)
+            _ => Err(CastError::DifferingKinds),
         }
     }
 
     fn check_fptr_ptr_cast(&self,
                            fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
-                           -> Result<CastKind, CastError>
-    {
+                           -> Result<CastKind, CastError> {
         // fptr-ptr cast. must be to sized ptr
 
         if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
@@ -420,8 +436,7 @@ fn check_fptr_ptr_cast(&self,
     fn check_ptr_addr_cast(&self,
                            fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                            m_expr: &'tcx ty::TypeAndMut<'tcx>)
-                           -> Result<CastKind, CastError>
-    {
+                           -> Result<CastKind, CastError> {
         // ptr-addr cast. must be from sized ptr
 
         if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
@@ -435,8 +450,7 @@ fn check_ref_cast(&self,
                       fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                       m_expr: &'tcx ty::TypeAndMut<'tcx>,
                       m_cast: &'tcx ty::TypeAndMut<'tcx>)
-                      -> Result<CastKind, CastError>
-    {
+                      -> Result<CastKind, CastError> {
         // array-ptr-cast.
 
         if m_expr.mutbl == hir::MutImmutable && m_cast.mutbl == hir::MutImmutable {
@@ -460,28 +474,22 @@ fn check_ref_cast(&self,
     fn check_addr_ptr_cast(&self,
                            fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
-                           -> Result<CastKind, CastError>
-    {
+                           -> Result<CastKind, CastError> {
         // ptr-addr cast. pointer must be thin.
         if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
-           Ok(CastKind::AddrPtrCast)
+            Ok(CastKind::AddrPtrCast)
         } else {
-           Err(CastError::IllegalCast)
+            Err(CastError::IllegalCast)
         }
     }
 
     fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool {
         fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty).is_ok()
     }
-
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    fn type_is_known_to_be_sized(&self,
-                                 ty: Ty<'tcx>,
-                                 span: Span)
-                                 -> bool
-    {
+    fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool {
         traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span)
     }
 }
index 9e41d1b5676e45d1454d081d9680a69fd81c20c5..1dbd0728bf217ab1b6fcf0f889a94fbe5406ae2e 100644 (file)
@@ -24,7 +24,8 @@ pub fn check_expr_closure(&self,
                               _capture: hir::CaptureClause,
                               decl: &'gcx hir::FnDecl,
                               body: &'gcx hir::Block,
-                              expected: Expectation<'tcx>) -> Ty<'tcx> {
+                              expected: Expectation<'tcx>)
+                              -> Ty<'tcx> {
         debug!("check_expr_closure(expr={:?},expected={:?})",
                expr,
                expected);
@@ -32,9 +33,9 @@ pub fn check_expr_closure(&self,
         // It's always helpful for inference if we know the kind of
         // closure sooner rather than later, so first examine the expected
         // type, and see if can glean a closure kind from there.
-        let (expected_sig,expected_kind) = match expected.to_option(self) {
+        let (expected_sig, expected_kind) = match expected.to_option(self) {
             Some(ty) => self.deduce_expectations_from_expected_type(ty),
-            None => (None, None)
+            None => (None, None),
         };
         self.check_closure(expr, expected_kind, decl, body, expected_sig)
     }
@@ -44,7 +45,8 @@ fn check_closure(&self,
                      opt_kind: Option<ty::ClosureKind>,
                      decl: &'gcx hir::FnDecl,
                      body: &'gcx hir::Block,
-                     expected_sig: Option<ty::FnSig<'tcx>>) -> Ty<'tcx> {
+                     expected_sig: Option<ty::FnSig<'tcx>>)
+                     -> Ty<'tcx> {
         let expr_def_id = self.tcx.map.local_def_id(expr.id);
 
         debug!("check_closure opt_kind={:?} expected_sig={:?}",
@@ -64,18 +66,25 @@ fn check_closure(&self,
         let upvar_tys = self.next_ty_vars(num_upvars);
 
         debug!("check_closure: expr.id={:?} upvar_tys={:?}",
-               expr.id, upvar_tys);
+               expr.id,
+               upvar_tys);
 
         let closure_type = self.tcx.mk_closure(expr_def_id,
-            self.parameter_environment.free_substs,
-            upvar_tys);
-
-        let fn_sig = self.tcx.liberate_late_bound_regions(
-            self.tcx.region_maps.call_site_extent(expr.id, body.id), &fn_ty.sig);
-        let fn_sig =
-            (**self).normalize_associated_types_in(body.span, body.id, &fn_sig);
-
-        check_fn(self, hir::Unsafety::Normal, expr.id, &fn_sig, decl, expr.id, &body);
+                                               self.parameter_environment.free_substs,
+                                               upvar_tys);
+
+        let fn_sig = self.tcx
+            .liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id),
+                                         &fn_ty.sig);
+        let fn_sig = (**self).normalize_associated_types_in(body.span, body.id, &fn_sig);
+
+        check_fn(self,
+                 hir::Unsafety::Normal,
+                 expr.id,
+                 &fn_sig,
+                 decl,
+                 expr.id,
+                 &body);
 
         // Tuple up the arguments and insert the resulting function type into
         // the `closures` table.
@@ -88,46 +97,47 @@ fn check_closure(&self,
 
         self.tables.borrow_mut().closure_tys.insert(expr_def_id, fn_ty);
         match opt_kind {
-            Some(kind) => { self.tables.borrow_mut().closure_kinds.insert(expr_def_id, kind); }
-            None => { }
+            Some(kind) => {
+                self.tables.borrow_mut().closure_kinds.insert(expr_def_id, kind);
+            }
+            None => {}
         }
 
         closure_type
     }
 
-    fn deduce_expectations_from_expected_type(&self, expected_ty: Ty<'tcx>)
-        -> (Option<ty::FnSig<'tcx>>,Option<ty::ClosureKind>)
-    {
+    fn deduce_expectations_from_expected_type
+        (&self,
+         expected_ty: Ty<'tcx>)
+         -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
         debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
                expected_ty);
 
         match expected_ty.sty {
             ty::TyTrait(ref object_type) => {
-                let sig = object_type.projection_bounds.iter().filter_map(|pb| {
-                    let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
-                    self.deduce_sig_from_projection(&pb)
-                }).next();
+                let sig = object_type.projection_bounds
+                    .iter()
+                    .filter_map(|pb| {
+                        let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
+                        self.deduce_sig_from_projection(&pb)
+                    })
+                    .next();
                 let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal.def_id());
                 (sig, kind)
             }
-            ty::TyInfer(ty::TyVar(vid)) => {
-                self.deduce_expectations_from_obligations(vid)
-            }
-            _ => {
-                (None, None)
-            }
+            ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
+            _ => (None, None),
         }
     }
 
-    fn deduce_expectations_from_obligations(&self, expected_vid: ty::TyVid)
-        -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>)
-    {
+    fn deduce_expectations_from_obligations
+        (&self,
+         expected_vid: ty::TyVid)
+         -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
         let fulfillment_cx = self.fulfillment_cx.borrow();
         // Here `expected_ty` is known to be a type inference variable.
 
-        let expected_sig =
-            fulfillment_cx
-            .pending_obligations()
+        let expected_sig = fulfillment_cx.pending_obligations()
             .iter()
             .map(|obligation| &obligation.obligation)
             .filter_map(|obligation| {
@@ -142,9 +152,7 @@ fn deduce_expectations_from_obligations(&self, expected_vid: ty::TyVid)
                         self.self_type_matches_expected_vid(trait_ref, expected_vid)
                             .and_then(|_| self.deduce_sig_from_projection(proj_predicate))
                     }
-                    _ => {
-                        None
-                    }
+                    _ => None,
                 }
             })
             .next();
@@ -153,9 +161,7 @@ fn deduce_expectations_from_obligations(&self, expected_vid: ty::TyVid)
         // infer the kind. This can occur if there is a trait-reference
         // like `F : Fn<A>`. Note that due to subtyping we could encounter
         // many viable options, so pick the most restrictive.
-        let expected_kind =
-            fulfillment_cx
-            .pending_obligations()
+        let expected_kind = fulfillment_cx.pending_obligations()
             .iter()
             .map(|obligation| &obligation.obligation)
             .filter_map(|obligation| {
@@ -178,11 +184,11 @@ fn deduce_expectations_from_obligations(&self, expected_vid: ty::TyVid)
                     // inference variable.
                     ty::Predicate::ClosureKind(..) => None,
                 };
-                opt_trait_ref
-                    .and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
+                opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
                     .and_then(|tr| self.tcx.lang_items.fn_trait_kind(tr.def_id()))
             })
-            .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
+            .fold(None,
+                  |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
 
         (expected_sig, expected_kind)
     }
@@ -190,13 +196,11 @@ fn deduce_expectations_from_obligations(&self, expected_vid: ty::TyVid)
     /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
     /// everything we need to know about a closure.
     fn deduce_sig_from_projection(&self,
-        projection: &ty::PolyProjectionPredicate<'tcx>)
-        -> Option<ty::FnSig<'tcx>>
-    {
+                                  projection: &ty::PolyProjectionPredicate<'tcx>)
+                                  -> Option<ty::FnSig<'tcx>> {
         let tcx = self.tcx;
 
-        debug!("deduce_sig_from_projection({:?})",
-               projection);
+        debug!("deduce_sig_from_projection({:?})", projection);
 
         let trait_ref = projection.to_poly_trait_ref();
 
@@ -206,22 +210,26 @@ fn deduce_sig_from_projection(&self,
 
         let arg_param_ty = trait_ref.substs().type_at(1);
         let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
-        debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty);
+        debug!("deduce_sig_from_projection: arg_param_ty {:?}",
+               arg_param_ty);
 
         let input_tys = match arg_param_ty.sty {
             ty::TyTuple(tys) => tys.to_vec(),
-            _ => { return None; }
+            _ => {
+                return None;
+            }
         };
         debug!("deduce_sig_from_projection: input_tys {:?}", input_tys);
 
         let ret_param_ty = projection.0.ty;
         let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
-        debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
+        debug!("deduce_sig_from_projection: ret_param_ty {:?}",
+               ret_param_ty);
 
         let fn_sig = ty::FnSig {
             inputs: input_tys,
             output: ret_param_ty,
-            variadic: false
+            variadic: false,
         };
         debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
 
@@ -229,10 +237,9 @@ fn deduce_sig_from_projection(&self,
     }
 
     fn self_type_matches_expected_vid(&self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        expected_vid: ty::TyVid)
-        -> Option<ty::PolyTraitRef<'tcx>>
-    {
+                                      trait_ref: ty::PolyTraitRef<'tcx>,
+                                      expected_vid: ty::TyVid)
+                                      -> Option<ty::PolyTraitRef<'tcx>> {
         let self_ty = self.shallow_resolve(trait_ref.self_ty());
         debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
                trait_ref,
index 98a05989b140d97881b25adddeb5bb9bd6e6df90..5be77cb12e9efa25fc21a7285ec20cde45658379 100644 (file)
@@ -60,7 +60,7 @@
 //! sort of a minor point so I've opted to leave it for later---after all
 //! we may want to adjust precisely when coercions occur.
 
-use check::{FnCtxt};
+use check::FnCtxt;
 
 use rustc::hir;
 use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace};
@@ -79,7 +79,7 @@
 use std::collections::VecDeque;
 use std::ops::Deref;
 
-struct Coerce<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     origin: TypeOrigin,
     use_lub: bool,
@@ -102,7 +102,7 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
         (hir::MutMutable, hir::MutMutable) |
         (hir::MutImmutable, hir::MutImmutable) |
         (hir::MutMutable, hir::MutImmutable) => Ok(()),
-        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability)
+        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability),
     }
 }
 
@@ -112,7 +112,7 @@ fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, origin: TypeOrigin) -> Self {
             fcx: fcx,
             origin: origin,
             use_lub: false,
-            unsizing_obligations: RefCell::new(vec![])
+            unsizing_obligations: RefCell::new(vec![]),
         }
     }
 
@@ -144,21 +144,18 @@ fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
 
     /// Synthesize an identity adjustment.
     fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
-        Ok((ty, AdjustDerefRef(AutoDerefRef {
-            autoderefs: 0,
-            autoref: None,
-            unsize: None
-        })))
+        Ok((ty,
+            AdjustDerefRef(AutoDerefRef {
+                autoderefs: 0,
+                autoref: None,
+                unsize: None,
+            })))
     }
 
-    fn coerce<'a, E, I>(&self,
-                        exprs: &E,
-                        a: Ty<'tcx>,
-                        b: Ty<'tcx>)
-                        -> CoerceResult<'tcx>
-        // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
+    fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx>
         where E: Fn() -> I,
-              I: IntoIterator<Item=&'a hir::Expr> {
+              I: IntoIterator<Item = &'a hir::Expr>
+    {
 
         let a = self.shallow_resolve(a);
         debug!("Coerce.tys({:?} => {:?})", a, b);
@@ -223,9 +220,8 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
                                          r_b: &'tcx ty::Region,
                                          mt_b: TypeAndMut<'tcx>)
                                          -> CoerceResult<'tcx>
-        // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
         where E: Fn() -> I,
-              I: IntoIterator<Item=&'a hir::Expr>
+              I: IntoIterator<Item = &'a hir::Expr>
     {
 
         debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
@@ -241,7 +237,7 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
                 (r_a, mt_a)
             }
-            _ => return self.unify_and_identity(a, b)
+            _ => return self.unify_and_identity(a, b),
         };
 
         let span = self.origin.span();
@@ -255,7 +251,7 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
             if autoderefs == 0 {
                 // Don't let this pass, otherwise it would cause
                 // &T to autoref to &&T.
-                continue
+                continue;
             }
 
             // At this point, we have deref'd `a` to `referent_ty`.  So
@@ -333,19 +329,24 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
             } else if autoderefs == 1 {
                 r_a // [3] above
             } else {
-                if r_borrow_var.is_none() { // create var lazilly, at most once
+                if r_borrow_var.is_none() {
+                    // create var lazilly, at most once
                     let coercion = Coercion(span);
                     let r = self.next_region_var(coercion);
                     r_borrow_var = Some(r); // [4] above
                 }
                 r_borrow_var.unwrap()
             };
-            let derefd_ty_a = self.tcx.mk_ref(r, TypeAndMut {
-                ty: referent_ty,
-                mutbl: mt_b.mutbl // [1] above
-            });
+            let derefd_ty_a = self.tcx.mk_ref(r,
+                                              TypeAndMut {
+                                                  ty: referent_ty,
+                                                  mutbl: mt_b.mutbl, // [1] above
+                                              });
             match self.unify(derefd_ty_a, b) {
-                Ok(ty) => { success = Some((ty, autoderefs)); break },
+                Ok(ty) => {
+                    success = Some((ty, autoderefs));
+                    break;
+                }
                 Err(err) => {
                     if first_error.is_none() {
                         first_error = Some(err);
@@ -391,29 +392,27 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
         }
         let r_borrow = match ty.sty {
             ty::TyRef(r_borrow, _) => r_borrow,
-            _ => span_bug!(span, "expected a ref type, got {:?}", ty)
+            _ => span_bug!(span, "expected a ref type, got {:?}", ty),
         };
         let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl));
         debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
-               ty, autoderefs, autoref);
-        Ok((ty, AdjustDerefRef(AutoDerefRef {
-            autoderefs: autoderefs,
-            autoref: autoref,
-            unsize: None
-        })))
+               ty,
+               autoderefs,
+               autoref);
+        Ok((ty,
+            AdjustDerefRef(AutoDerefRef {
+                autoderefs: autoderefs,
+                autoref: autoref,
+                unsize: None,
+            })))
     }
 
 
     // &[T; n] or &mut [T; n] -> &[T]
     // or &mut [T; n] -> &mut [T]
     // or &Concrete -> &Trait, etc.
-    fn coerce_unsized(&self,
-                      source: Ty<'tcx>,
-                      target: Ty<'tcx>)
-                      -> CoerceResult<'tcx> {
-        debug!("coerce_unsized(source={:?}, target={:?})",
-               source,
-               target);
+    fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> {
+        debug!("coerce_unsized(source={:?}, target={:?})", source, target);
 
         let traits = (self.tcx.lang_items.unsize_trait(),
                       self.tcx.lang_items.coerce_unsized_trait());
@@ -442,7 +441,7 @@ fn coerce_unsized(&self,
                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
                 (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl)))
             }
-            _ => (source, None)
+            _ => (source, None),
         };
         let source = source.adjust_for_autoref(self.tcx, reborrow);
 
@@ -454,11 +453,8 @@ fn coerce_unsized(&self,
 
         // Create an obligation for `Source: CoerceUnsized<Target>`.
         let cause = ObligationCause::misc(self.origin.span(), self.body_id);
-        queue.push_back(self.tcx.predicate_for_trait_def(cause,
-                                                         coerce_unsized_did,
-                                                         0,
-                                                         source,
-                                                         &[target]));
+        queue.push_back(self.tcx
+            .predicate_for_trait_def(cause, coerce_unsized_did, 0, source, &[target]));
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -466,10 +462,8 @@ fn coerce_unsized(&self,
         let traits = [coerce_unsized_did, unsize_did];
         while let Some(obligation) = queue.pop_front() {
             debug!("coerce_unsized resolve step: {:?}", obligation);
-            let trait_ref =  match obligation.predicate {
-                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
-                    tr.clone()
-                }
+            let trait_ref = match obligation.predicate {
+                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
                 _ => {
                     leftover_predicates.push(obligation);
                     continue;
@@ -477,7 +471,8 @@ fn coerce_unsized(&self,
             };
             match selcx.select(&obligation.with(trait_ref)) {
                 // Uncertain or unimplemented.
-                Ok(None) | Err(traits::Unimplemented) => {
+                Ok(None) |
+                Err(traits::Unimplemented) => {
                     debug!("coerce_unsized: early return - can't prove obligation");
                     return Err(TypeError::Mismatch);
                 }
@@ -503,22 +498,20 @@ fn coerce_unsized(&self,
         let adjustment = AutoDerefRef {
             autoderefs: if reborrow.is_some() { 1 } else { 0 },
             autoref: reborrow,
-            unsize: Some(target)
+            unsize: Some(target),
         };
         debug!("Success, coerced with {:?}", adjustment);
         Ok((target, AdjustDerefRef(adjustment)))
     }
 
     fn coerce_from_fn_pointer(&self,
-                           a: Ty<'tcx>,
-                           fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
-                           b: Ty<'tcx>)
-                           -> CoerceResult<'tcx>
-    {
-        /*!
-         * Attempts to coerce from the type of a Rust function item
-         * into a closure or a `proc`.
-         */
+                              a: Ty<'tcx>,
+                              fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
+                              b: Ty<'tcx>)
+                              -> CoerceResult<'tcx> {
+        //! Attempts to coerce from the type of a Rust function item
+        //! into a closure or a `proc`.
+        //!
 
         let b = self.shallow_resolve(b);
         debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
@@ -527,9 +520,8 @@ fn coerce_from_fn_pointer(&self,
             match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
                 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                     let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
-                    return self.unify_and_identity(unsafe_a, b).map(|(ty, _)| {
-                        (ty, AdjustUnsafeFnPointer)
-                    });
+                    return self.unify_and_identity(unsafe_a, b)
+                        .map(|(ty, _)| (ty, AdjustUnsafeFnPointer));
                 }
                 _ => {}
             }
@@ -542,10 +534,9 @@ fn coerce_from_fn_item(&self,
                            fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
                            b: Ty<'tcx>)
                            -> CoerceResult<'tcx> {
-        /*!
-         * Attempts to coerce from the type of a Rust function item
-         * into a closure or a `proc`.
-         */
+        //! Attempts to coerce from the type of a Rust function item
+        //! into a closure or a `proc`.
+        //!
 
         let b = self.shallow_resolve(b);
         debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
@@ -553,11 +544,9 @@ fn coerce_from_fn_item(&self,
         match b.sty {
             ty::TyFnPtr(_) => {
                 let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
-                self.unify_and_identity(a_fn_pointer, b).map(|(ty, _)| {
-                    (ty, AdjustReifyFnPointer)
-                })
+                self.unify_and_identity(a_fn_pointer, b).map(|(ty, _)| (ty, AdjustReifyFnPointer))
             }
-            _ => self.unify_and_identity(a, b)
+            _ => self.unify_and_identity(a, b),
         }
     }
 
@@ -566,9 +555,7 @@ fn coerce_unsafe_ptr(&self,
                          b: Ty<'tcx>,
                          mutbl_b: hir::Mutability)
                          -> CoerceResult<'tcx> {
-        debug!("coerce_unsafe_ptr(a={:?}, b={:?})",
-               a,
-               b);
+        debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b);
 
         let (is_ref, mt_a) = match a.sty {
             ty::TyRef(_, mt) => (true, mt),
@@ -579,24 +566,28 @@ fn coerce_unsafe_ptr(&self,
         };
 
         // Check that the types which they point at are compatible.
-        let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut{ mutbl: mutbl_b, ty: mt_a.ty });
+        let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut {
+            mutbl: mutbl_b,
+            ty: mt_a.ty,
+        });
         let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
         coerce_mutbls(mt_a.mutbl, mutbl_b)?;
 
         // Although references and unsafe ptrs have the same
         // representation, we still register an AutoDerefRef so that
         // regionck knows that the region for `a` must be valid here.
-        Ok((ty, if is_ref {
-            AdjustDerefRef(AutoDerefRef {
-                autoderefs: 1,
-                autoref: Some(AutoUnsafe(mutbl_b)),
-                unsize: None
-            })
-        } else if mt_a.mutbl != mutbl_b {
-            AdjustMutToConstPointer
-        } else {
-            noop
-        }))
+        Ok((ty,
+            if is_ref {
+                AdjustDerefRef(AutoDerefRef {
+                    autoderefs: 1,
+                    autoref: Some(AutoUnsafe(mutbl_b)),
+                    unsize: None,
+                })
+            } else if mt_a.mutbl != mutbl_b {
+                AdjustMutToConstPointer
+            } else {
+                noop
+            }))
     }
 }
 
@@ -606,7 +597,8 @@ fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
                                    b: Ty<'tcx>)
                                    -> CoerceResult<'tcx>
     where E: Fn() -> I,
-          I: IntoIterator<Item=&'b hir::Expr> {
+          I: IntoIterator<Item = &'b hir::Expr>
+{
 
     let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?;
 
@@ -638,12 +630,12 @@ pub fn try_coerce(&self,
 
         let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span));
         self.commit_if_ok(|_| {
-            let (ty, adjustment) =
-                apply(&mut coerce, &|| Some(expr), source, target)?;
+            let (ty, adjustment) = apply(&mut coerce, &|| Some(expr), source, target)?;
             if !adjustment.is_identity() {
                 debug!("Success, coerced with {:?}", adjustment);
                 match self.tables.borrow().adjustments.get(&expr.id) {
-                    None | Some(&AdjustNeverToAny(..)) => (),
+                    None |
+                    Some(&AdjustNeverToAny(..)) => (),
                     _ => bug!("expr already has an adjustment on it!"),
                 };
                 self.write_adjustment(expr.id, adjustment);
@@ -662,9 +654,9 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
                                            new: &'b hir::Expr,
                                            new_ty: Ty<'tcx>)
                                            -> RelateResult<'tcx, Ty<'tcx>>
-        // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
         where E: Fn() -> I,
-              I: IntoIterator<Item=&'b hir::Expr> {
+              I: IntoIterator<Item = &'b hir::Expr>
+    {
 
         let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
         let new_ty = self.resolve_type_vars_with_obligations(new_ty);
@@ -675,8 +667,7 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
         // Special-case that coercion alone cannot handle:
         // Two function item types of differing IDs or Substs.
         match (&prev_ty.sty, &new_ty.sty) {
-            (&ty::TyFnDef(a_def_id, a_substs, a_fty),
-             &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
+            (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
                 // The signature must always match.
                 let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
                     .map(|InferOk { value, obligations }| {
@@ -720,9 +711,7 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
         // but only if the new expression has no coercion already applied to it.
         let mut first_error = None;
         if !self.tables.borrow().adjustments.contains_key(&new.id) {
-            let result = self.commit_if_ok(|_| {
-                apply(&mut coerce, &|| Some(new), new_ty, prev_ty)
-            });
+            let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty));
             match result {
                 Ok((ty, adjustment)) => {
                     if !adjustment.is_identity() {
@@ -730,7 +719,7 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
                     }
                     return Ok(ty);
                 }
-                Err(e) => first_error = Some(e)
+                Err(e) => first_error = Some(e),
             }
         }
 
@@ -739,20 +728,20 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
         // previous expressions, other than noop reborrows (ignoring lifetimes).
         for expr in exprs() {
             let noop = match self.tables.borrow().adjustments.get(&expr.id) {
-                Some(&AdjustDerefRef(AutoDerefRef {
-                    autoderefs: 1,
-                    autoref: Some(AutoPtr(_, mutbl_adj)),
-                    unsize: None
-                })) => match self.node_ty(expr.id).sty {
-                    ty::TyRef(_, mt_orig) => {
-                        // Reborrow that we can safely ignore.
-                        mutbl_adj == mt_orig.mutbl
+                Some(&AdjustDerefRef(AutoDerefRef { autoderefs: 1,
+                                                    autoref: Some(AutoPtr(_, mutbl_adj)),
+                                                    unsize: None })) => {
+                    match self.node_ty(expr.id).sty {
+                        ty::TyRef(_, mt_orig) => {
+                            // Reborrow that we can safely ignore.
+                            mutbl_adj == mt_orig.mutbl
+                        }
+                        _ => false,
                     }
-                    _ => false
-                },
+                }
                 Some(&AdjustNeverToAny(_)) => true,
                 Some(_) => false,
-                None => true
+                None => true,
             };
 
             if !noop {
index 826a88127d84e78ec5165c29bd083eb884b5bcee..25e9f1f522c96499bf8906092b3a2a6f81b0833e 100644 (file)
@@ -40,8 +40,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      trait_m: &ty::Method<'tcx>,
                                      impl_trait_ref: &ty::TraitRef<'tcx>,
                                      trait_item_span: Option<Span>) {
-    debug!("compare_impl_method(impl_trait_ref={:?})",
-           impl_trait_ref);
+    debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
 
     debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
            impl_trait_ref);
@@ -58,34 +57,36 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // inscrutable, particularly for cases where one method has no
     // self.
     match (&trait_m.explicit_self, &impl_m.explicit_self) {
-        (&ty::ExplicitSelfCategory::Static,
-         &ty::ExplicitSelfCategory::Static) => {}
+        (&ty::ExplicitSelfCategory::Static, &ty::ExplicitSelfCategory::Static) => {}
         (&ty::ExplicitSelfCategory::Static, _) => {
-            let mut err = struct_span_err!(tcx.sess, impl_m_span, E0185,
-                "method `{}` has a `{}` declaration in the impl, \
-                        but not in the trait",
-                        trait_m.name,
-                        impl_m.explicit_self);
-            err.span_label(impl_m_span, &format!("`{}` used in impl",
-                                                 impl_m.explicit_self));
+            let mut err = struct_span_err!(tcx.sess,
+                                           impl_m_span,
+                                           E0185,
+                                           "method `{}` has a `{}` declaration in the impl, but \
+                                            not in the trait",
+                                           trait_m.name,
+                                           impl_m.explicit_self);
+            err.span_label(impl_m_span,
+                           &format!("`{}` used in impl", impl_m.explicit_self));
             if let Some(span) = tcx.map.span_if_local(trait_m.def_id) {
-                err.span_label(span, &format!("trait declared without `{}`",
-                                              impl_m.explicit_self));
+                err.span_label(span,
+                               &format!("trait declared without `{}`", impl_m.explicit_self));
             }
             err.emit();
             return;
         }
         (_, &ty::ExplicitSelfCategory::Static) => {
-            let mut err = struct_span_err!(tcx.sess, impl_m_span, E0186,
-                "method `{}` has a `{}` declaration in the trait, \
-                        but not in the impl",
-                        trait_m.name,
-                        trait_m.explicit_self);
-            err.span_label(impl_m_span, &format!("expected `{}` in impl",
-                                                  trait_m.explicit_self));
+            let mut err = struct_span_err!(tcx.sess,
+                                           impl_m_span,
+                                           E0186,
+                                           "method `{}` has a `{}` declaration in the trait, but \
+                                            not in the impl",
+                                           trait_m.name,
+                                           trait_m.explicit_self);
+            err.span_label(impl_m_span,
+                           &format!("expected `{}` in impl", trait_m.explicit_self));
             if let Some(span) = tcx.map.span_if_local(trait_m.def_id) {
-                err.span_label(span, & format!("`{}` used in trait",
-                                               trait_m.explicit_self));
+                err.span_label(span, &format!("`{}` used in trait", trait_m.explicit_self));
             }
             err.emit();
             return;
@@ -107,17 +108,23 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     impl_m_span
                 }
             }
-            _ => bug!("{:?} is not a method", impl_m)
+            _ => bug!("{:?} is not a method", impl_m),
         };
 
-        let mut err = struct_span_err!(tcx.sess, span, E0049,
-            "method `{}` has {} type parameter{} \
-             but its trait declaration has {} type parameter{}",
-            trait_m.name,
-            num_impl_m_type_params,
-            if num_impl_m_type_params == 1 {""} else {"s"},
-            num_trait_m_type_params,
-            if num_trait_m_type_params == 1 {""} else {"s"});
+        let mut err = struct_span_err!(tcx.sess,
+                                       span,
+                                       E0049,
+                                       "method `{}` has {} type parameter{} but its trait \
+                                        declaration has {} type parameter{}",
+                                       trait_m.name,
+                                       num_impl_m_type_params,
+                                       if num_impl_m_type_params == 1 { "" } else { "s" },
+                                       num_trait_m_type_params,
+                                       if num_trait_m_type_params == 1 {
+                                           ""
+                                       } else {
+                                           "s"
+                                       });
 
         let mut suffix = None;
 
@@ -154,18 +161,17 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let trait_span = if let Some(trait_id) = trait_m_node_id {
             match tcx.map.expect_trait_item(trait_id).node {
                 TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
-                    if let Some(arg) = trait_m_sig.decl.inputs.get(
-                        if trait_number_args > 0 {
-                            trait_number_args - 1
-                        } else {
-                            0
-                        }) {
+                    if let Some(arg) = trait_m_sig.decl.inputs.get(if trait_number_args > 0 {
+                        trait_number_args - 1
+                    } else {
+                        0
+                    }) {
                         Some(arg.pat.span)
                     } else {
                         trait_item_span
                     }
                 }
-                _ => bug!("{:?} is not a method", impl_m)
+                _ => bug!("{:?} is not a method", impl_m),
             }
         } else {
             trait_item_span
@@ -173,27 +179,28 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap();
         let impl_span = match tcx.map.expect_impl_item(impl_m_node_id).node {
             ImplItemKind::Method(ref impl_m_sig, _) => {
-                if let Some(arg) = impl_m_sig.decl.inputs.get(
-                    if impl_number_args > 0 {
-                        impl_number_args - 1
-                    } else {
-                        0
-                    }) {
+                if let Some(arg) = impl_m_sig.decl.inputs.get(if impl_number_args > 0 {
+                    impl_number_args - 1
+                } else {
+                    0
+                }) {
                     arg.pat.span
                 } else {
                     impl_m_span
                 }
             }
-            _ => bug!("{:?} is not a method", impl_m)
+            _ => bug!("{:?} is not a method", impl_m),
         };
-        let mut err = struct_span_err!(tcx.sess, impl_span, E0050,
-            "method `{}` has {} parameter{} \
-             but the declaration in trait `{}` has {}",
-            trait_m.name,
-            impl_number_args,
-            if impl_number_args == 1 {""} else {"s"},
-            tcx.item_path_str(trait_m.def_id),
-            trait_number_args);
+        let mut err = struct_span_err!(tcx.sess,
+                                       impl_span,
+                                       E0050,
+                                       "method `{}` has {} parameter{} but the declaration in \
+                                        trait `{}` has {}",
+                                       trait_m.name,
+                                       impl_number_args,
+                                       if impl_number_args == 1 { "" } else { "s" },
+                                       tcx.item_path_str(trait_m.def_id),
+                                       trait_number_args);
         if let Some(trait_span) = trait_span {
             err.span_label(trait_span,
                            &format!("trait requires {}",
@@ -210,7 +217,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 } else {
                                     format!("{} parameter", trait_number_args)
                                 },
-                       impl_number_args));
+                                impl_number_args));
         err.emit();
         return;
     }
@@ -287,9 +294,10 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let impl_to_skol_substs = &impl_param_env.free_substs;
 
     // Create mapping from trait to skolemized.
-    let trait_to_skol_substs =
-        impl_to_skol_substs.rebase_onto(tcx, impl_m.container_id(),
-                                        trait_to_impl_substs.subst(tcx, impl_to_skol_substs));
+    let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
+                                                               impl_m.container_id(),
+                                                               trait_to_impl_substs.subst(tcx,
+                                                                          impl_to_skol_substs));
     debug!("compare_impl_method: trait_to_skol_substs={:?}",
            trait_to_skol_substs);
 
@@ -325,31 +333,28 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         //
         // We then register the obligations from the impl_m and check to see
         // if all constraints hold.
-        hybrid_preds.predicates.extend(
-            trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
+        hybrid_preds.predicates
+            .extend(trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
 
         // Construct trait parameter environment and then shift it into the skolemized viewpoint.
         // The key step here is to update the caller_bounds's predicates to be
         // the new hybrid bounds we computed.
         let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
         let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
-        let trait_param_env = traits::normalize_param_env_or_error(tcx,
-                                                                   trait_param_env,
-                                                                   normalize_cause.clone());
+        let trait_param_env =
+            traits::normalize_param_env_or_error(tcx, trait_param_env, normalize_cause.clone());
         // FIXME(@jroesch) this seems ugly, but is a temporary change
         infcx.parameter_environment = trait_param_env;
 
         debug!("compare_impl_method: caller_bounds={:?}",
-            infcx.parameter_environment.caller_bounds);
+               infcx.parameter_environment.caller_bounds);
 
         let mut selcx = traits::SelectionContext::new(&infcx);
 
         let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs);
-        let (impl_m_own_bounds, _) =
-            infcx.replace_late_bound_regions_with_fresh_var(
-                impl_m_span,
-                infer::HigherRankedType,
-                &ty::Binder(impl_m_own_bounds.predicates));
+        let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
+                                                       infer::HigherRankedType,
+                                                       &ty::Binder(impl_m_own_bounds.predicates));
         for predicate in impl_m_own_bounds {
             let traits::Normalized { value: predicate, .. } =
                 traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
@@ -357,7 +362,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             let cause = traits::ObligationCause {
                 span: impl_m_span,
                 body_id: impl_m_body_id,
-                code: traits::ObligationCauseCode::CompareImplMethodObligation
+                code: traits::ObligationCauseCode::CompareImplMethodObligation,
             };
 
             fulfillment_cx.register_predicate_obligation(
@@ -382,40 +387,34 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let tcx = infcx.tcx;
         let origin = TypeOrigin::MethodCompatCheck(impl_m_span);
 
-        let (impl_sig, _) =
-            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
-                                                            infer::HigherRankedType,
-                                                            &impl_m.fty.sig);
-        let impl_sig =
-            impl_sig.subst(tcx, impl_to_skol_substs);
-        let impl_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &mut fulfillment_cx,
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &impl_sig);
+        let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
+                                                       infer::HigherRankedType,
+                                                       &impl_m.fty.sig);
+        let impl_sig = impl_sig.subst(tcx, impl_to_skol_substs);
+        let impl_sig = assoc::normalize_associated_types_in(&infcx,
+                                                            &mut fulfillment_cx,
+                                                            impl_m_span,
+                                                            impl_m_body_id,
+                                                            &impl_sig);
         let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
             unsafety: impl_m.fty.unsafety,
             abi: impl_m.fty.abi,
-            sig: ty::Binder(impl_sig.clone())
+            sig: ty::Binder(impl_sig.clone()),
         }));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
-        let trait_sig = tcx.liberate_late_bound_regions(
-            infcx.parameter_environment.free_id_outlive,
-            &trait_m.fty.sig);
-        let trait_sig =
-            trait_sig.subst(tcx, trait_to_skol_substs);
-        let trait_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &mut fulfillment_cx,
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &trait_sig);
+        let trait_sig = tcx.liberate_late_bound_regions(infcx.parameter_environment.free_id_outlive,
+                                         &trait_m.fty.sig);
+        let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs);
+        let trait_sig = assoc::normalize_associated_types_in(&infcx,
+                                                             &mut fulfillment_cx,
+                                                             impl_m_span,
+                                                             impl_m_body_id,
+                                                             &trait_sig);
         let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
             unsafety: trait_m.fty.unsafety,
             abi: trait_m.fty.abi,
-            sig: ty::Binder(trait_sig.clone())
+            sig: ty::Binder(trait_sig.clone()),
         }));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
@@ -425,36 +424,39 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                    impl_fty,
                    trait_fty);
 
-            let (impl_err_span, trait_err_span) =
-                extract_spans_for_error_reporting(&infcx, &terr, origin, impl_m,
-                    impl_sig, trait_m, trait_sig);
+            let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx,
+                                                                                    &terr,
+                                                                                    origin,
+                                                                                    impl_m,
+                                                                                    impl_sig,
+                                                                                    trait_m,
+                                                                                    trait_sig);
 
             let origin = TypeOrigin::MethodCompatCheck(impl_err_span);
 
-            let mut diag = struct_span_err!(
-                tcx.sess, origin.span(), E0053,
-                "method `{}` has an incompatible type for trait", trait_m.name
-            );
-
-            infcx.note_type_err(
-                &mut diag,
-                origin,
-                trait_err_span.map(|sp| (sp, format!("type in trait"))),
-                Some(infer::ValuePairs::Types(ExpectedFound {
-                     expected: trait_fty,
-                     found: impl_fty
-                })),
-                &terr
-            );
+            let mut diag = struct_span_err!(tcx.sess,
+                                            origin.span(),
+                                            E0053,
+                                            "method `{}` has an incompatible type for trait",
+                                            trait_m.name);
+
+            infcx.note_type_err(&mut diag,
+                                origin,
+                                trait_err_span.map(|sp| (sp, format!("type in trait"))),
+                                Some(infer::ValuePairs::Types(ExpectedFound {
+                                    expected: trait_fty,
+                                    found: impl_fty,
+                                })),
+                                &terr);
             diag.emit();
-            return
+            return;
         }
 
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
             infcx.report_fulfillment_errors(errors);
-            return
+            return;
         }
 
         // Finally, resolve all regions. This catches wily misuses of
@@ -480,8 +482,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                     impl_generics: &ty::Generics<'tcx>,
                                                     trait_to_skol_substs: &Substs<'tcx>,
                                                     impl_to_skol_substs: &Substs<'tcx>)
-                                                    -> bool
-    {
+                                                    -> bool {
 
         let trait_params = &trait_generics.regions[..];
         let impl_params = &impl_generics.regions[..];
@@ -506,9 +507,12 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         // are zero. Since I don't quite know how to phrase things at
         // the moment, give a kind of vague error message.
         if trait_params.len() != impl_params.len() {
-            struct_span_err!(ccx.tcx.sess, span, E0195,
-                "lifetime parameters or bounds on method `{}` do \
-                 not match the trait declaration",impl_m.name)
+            struct_span_err!(ccx.tcx.sess,
+                             span,
+                             E0195,
+                             "lifetime parameters or bounds on method `{}` do not match the \
+                              trait declaration",
+                             impl_m.name)
                 .span_label(span, &format!("lifetimes do not match trait"))
                 .emit();
             return false;
@@ -524,40 +528,51 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
                                                          impl_sig: ty::FnSig<'tcx>,
                                                          trait_m: &ty::Method,
                                                          trait_sig: ty::FnSig<'tcx>)
-                                                        -> (Span, Option<Span>) {
+                                                         -> (Span, Option<Span>) {
         let tcx = infcx.tcx;
         let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap();
         let (impl_m_output, impl_m_iter) = match tcx.map.expect_impl_item(impl_m_node_id).node {
-            ImplItemKind::Method(ref impl_m_sig, _) =>
-                (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()),
-            _ => bug!("{:?} is not a method", impl_m)
+            ImplItemKind::Method(ref impl_m_sig, _) => {
+                (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter())
+            }
+            _ => bug!("{:?} is not a method", impl_m),
         };
 
         match *terr {
             TypeError::Mutability => {
                 if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                     let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node {
-                        TraitItem_::MethodTraitItem(ref trait_m_sig, _) =>
-                            trait_m_sig.decl.inputs.iter(),
-                        _ => bug!("{:?} is not a MethodTraitItem", trait_m)
+                        TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                            trait_m_sig.decl.inputs.iter()
+                        }
+                        _ => bug!("{:?} is not a MethodTraitItem", trait_m),
                     };
 
-                    impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| {
-                        match (&impl_arg.ty.node, &trait_arg.ty.node) {
-                            (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) |
-                            (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) =>
-                                impl_mt.mutbl != trait_mt.mutbl,
-                            _ => false
-                        }
-                    }).map(|(ref impl_arg, ref trait_arg)| {
-                        match (impl_arg.to_self(), trait_arg.to_self()) {
-                            (Some(impl_self), Some(trait_self)) =>
-                                (impl_self.span, Some(trait_self.span)),
-                            (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)),
-                            _ => bug!("impl and trait fns have different first args, \
-                                       impl: {:?}, trait: {:?}", impl_arg, trait_arg)
-                        }
-                    }).unwrap_or((origin.span(), tcx.map.span_if_local(trait_m.def_id)))
+                    impl_m_iter.zip(trait_m_iter)
+                        .find(|&(ref impl_arg, ref trait_arg)| {
+                            match (&impl_arg.ty.node, &trait_arg.ty.node) {
+                                (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) |
+                                (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) => {
+                                    impl_mt.mutbl != trait_mt.mutbl
+                                }
+                                _ => false,
+                            }
+                        })
+                        .map(|(ref impl_arg, ref trait_arg)| {
+                            match (impl_arg.to_self(), trait_arg.to_self()) {
+                                (Some(impl_self), Some(trait_self)) => {
+                                    (impl_self.span, Some(trait_self.span))
+                                }
+                                (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)),
+                                _ => {
+                                    bug!("impl and trait fns have different first args, impl: \
+                                          {:?}, trait: {:?}",
+                                         impl_arg,
+                                         trait_arg)
+                                }
+                            }
+                        })
+                        .unwrap_or((origin.span(), tcx.map.span_if_local(trait_m.def_id)))
                 } else {
                     (origin.span(), tcx.map.span_if_local(trait_m.def_id))
                 }
@@ -565,25 +580,28 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
             TypeError::Sorts(ExpectedFound { .. }) => {
                 if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                     let (trait_m_output, trait_m_iter) =
-                    match tcx.map.expect_trait_item(trait_m_node_id).node {
-                        TraitItem_::MethodTraitItem(ref trait_m_sig, _) =>
-                            (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter()),
-                        _ => bug!("{:?} is not a MethodTraitItem", trait_m)
-                    };
+                        match tcx.map.expect_trait_item(trait_m_node_id).node {
+                            TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                                (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter())
+                            }
+                            _ => bug!("{:?} is not a MethodTraitItem", trait_m),
+                        };
 
                     let impl_iter = impl_sig.inputs.iter();
                     let trait_iter = trait_sig.inputs.iter();
-                    impl_iter.zip(trait_iter).zip(impl_m_iter).zip(trait_m_iter)
+                    impl_iter.zip(trait_iter)
+                        .zip(impl_m_iter)
+                        .zip(trait_m_iter)
                         .filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| {
                             match infcx.sub_types(true, origin, trait_arg_ty, impl_arg_ty) {
                                 Ok(_) => None,
-                                Err(_) => Some((impl_arg.ty.span, Some(trait_arg.ty.span)))
+                                Err(_) => Some((impl_arg.ty.span, Some(trait_arg.ty.span))),
                             }
                         })
                         .next()
                         .unwrap_or_else(|| {
-                            if infcx.sub_types(false, origin, impl_sig.output,
-                                               trait_sig.output).is_err() {
+                            if infcx.sub_types(false, origin, impl_sig.output, trait_sig.output)
+                                .is_err() {
                                 (impl_m_output.span(), Some(trait_m_output.span()))
                             } else {
                                 (origin.span(), tcx.map.span_if_local(trait_m.def_id))
@@ -593,7 +611,7 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
                     (origin.span(), tcx.map.span_if_local(trait_m.def_id))
                 }
             }
-            _ => (origin.span(), tcx.map.span_if_local(trait_m.def_id))
+            _ => (origin.span(), tcx.map.span_if_local(trait_m.def_id)),
         }
     }
 }
@@ -603,8 +621,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     impl_c_span: Span,
                                     trait_c: &ty::AssociatedConst<'tcx>,
                                     impl_trait_ref: &ty::TraitRef<'tcx>) {
-    debug!("compare_const_impl(impl_trait_ref={:?})",
-           impl_trait_ref);
+    debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
 
     let tcx = ccx.tcx;
     tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
@@ -626,11 +643,12 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let impl_to_skol_substs = &impl_param_env.free_substs;
 
         // Create mapping from trait to skolemized.
-        let trait_to_skol_substs =
-            impl_to_skol_substs.rebase_onto(tcx, impl_c.container.id(),
-                                            trait_to_impl_substs.subst(tcx, impl_to_skol_substs));
+        let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
+                                                                   impl_c.container.id(),
+                                                                   trait_to_impl_substs.subst(tcx,
+                                                                              impl_to_skol_substs));
         debug!("compare_const_impl: trait_to_skol_substs={:?}",
-            trait_to_skol_substs);
+               trait_to_skol_substs);
 
         // Compute skolemized form of impl and trait const tys.
         let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
@@ -639,31 +657,27 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
         let err = infcx.commit_if_ok(|_| {
             // There is no "body" here, so just pass dummy id.
-            let impl_ty =
-                assoc::normalize_associated_types_in(&infcx,
-                                                     &mut fulfillment_cx,
-                                                     impl_c_span,
-                                                     ast::CRATE_NODE_ID,
-                                                     &impl_ty);
-
-            debug!("compare_const_impl: impl_ty={:?}",
-                impl_ty);
-
-            let trait_ty =
-                assoc::normalize_associated_types_in(&infcx,
-                                                     &mut fulfillment_cx,
-                                                     impl_c_span,
-                                                     ast::CRATE_NODE_ID,
-                                                     &trait_ty);
-
-            debug!("compare_const_impl: trait_ty={:?}",
-                trait_ty);
+            let impl_ty = assoc::normalize_associated_types_in(&infcx,
+                                                               &mut fulfillment_cx,
+                                                               impl_c_span,
+                                                               ast::CRATE_NODE_ID,
+                                                               &impl_ty);
+
+            debug!("compare_const_impl: impl_ty={:?}", impl_ty);
+
+            let trait_ty = assoc::normalize_associated_types_in(&infcx,
+                                                                &mut fulfillment_cx,
+                                                                impl_c_span,
+                                                                ast::CRATE_NODE_ID,
+                                                                &trait_ty);
+
+            debug!("compare_const_impl: trait_ty={:?}", trait_ty);
 
             infcx.sub_types(false, origin, impl_ty, trait_ty)
-                 .map(|InferOk { obligations, .. }| {
-                // FIXME(#32730) propagate obligations
-                assert!(obligations.is_empty())
-            })
+                .map(|InferOk { obligations, .. }| {
+                    // FIXME(#32730) propagate obligations
+                    assert!(obligations.is_empty())
+                })
         });
 
         if let Err(terr) = err {
@@ -674,31 +688,31 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             // Locate the Span containing just the type of the offending impl
             match tcx.map.expect_impl_item(impl_c_node_id).node {
                 ImplItemKind::Const(ref ty, _) => origin = TypeOrigin::Misc(ty.span),
-                _ => bug!("{:?} is not a impl const", impl_c)
+                _ => bug!("{:?} is not a impl const", impl_c),
             }
 
-            let mut diag = struct_span_err!(
-                tcx.sess, origin.span(), E0326,
-                "implemented const `{}` has an incompatible type for trait",
-                trait_c.name
-            );
+            let mut diag = struct_span_err!(tcx.sess,
+                                            origin.span(),
+                                            E0326,
+                                            "implemented const `{}` has an incompatible type for \
+                                             trait",
+                                            trait_c.name);
 
             // Add a label to the Span containing just the type of the item
             let trait_c_node_id = tcx.map.as_local_node_id(trait_c.def_id).unwrap();
             let trait_c_span = match tcx.map.expect_trait_item(trait_c_node_id).node {
                 TraitItem_::ConstTraitItem(ref ty, _) => ty.span,
-                _ => bug!("{:?} is not a trait const", trait_c)
+                _ => bug!("{:?} is not a trait const", trait_c),
             };
 
-            infcx.note_type_err(
-                &mut diag,
-                origin,
-                Some((trait_c_span, format!("type in trait"))),
-                Some(infer::ValuePairs::Types(ExpectedFound {
-                    expected: trait_ty,
-                    found: impl_ty
-                })), &terr
-            );
+            infcx.note_type_err(&mut diag,
+                                origin,
+                                Some((trait_c_span, format!("type in trait"))),
+                                Some(infer::ValuePairs::Types(ExpectedFound {
+                                    expected: trait_ty,
+                                    found: impl_ty,
+                                })),
+                                &terr);
             diag.emit();
         }
     });
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 3f7f01a9a3b51708691317dd5ae6686d3e100f25..625acce27bd64bd8bc38ea3798546cb445267e34 100644 (file)
@@ -42,7 +42,7 @@
 #[derive(Copy, Clone)]
 pub struct ConstnessSpace(pub hir::Constness);
 /// Wrapper struct for properly emitting a method declaration.
-pub struct Method<'a>(pub &'a clean::FnDecl);
+pub struct Method<'a>(pub &'a clean::FnDecl, pub &'a str);
 /// Similar to VisSpace, but used for mutability
 #[derive(Copy, Clone)]
 pub struct MutableSpace(pub clean::Mutability);
@@ -84,7 +84,7 @@ impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for (i, item) in self.0.iter().enumerate() {
             if i != 0 { write!(f, ", ")?; }
-            write!(f, "{}", item)?;
+            fmt::Display::fmt(item, f)?;
         }
         Ok(())
     }
@@ -97,7 +97,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             if i > 0 {
                 f.write_str(" + ")?;
             }
-            write!(f, "{}", *bound)?;
+            fmt::Display::fmt(bound, f)?;
         }
         Ok(())
     }
@@ -106,35 +106,51 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl fmt::Display for clean::Generics {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) }
-        f.write_str("&lt;")?;
+        if f.alternate() {
+            f.write_str("<")?;
+        } else {
+            f.write_str("&lt;")?;
+        }
 
         for (i, life) in self.lifetimes.iter().enumerate() {
             if i > 0 {
-                f.write_str(",&nbsp;")?;
+                f.write_str(", ")?;
             }
             write!(f, "{}", *life)?;
         }
 
         if !self.type_params.is_empty() {
             if !self.lifetimes.is_empty() {
-                f.write_str(",&nbsp;")?;
+                f.write_str(", ")?;
             }
             for (i, tp) in self.type_params.iter().enumerate() {
                 if i > 0 {
-                    f.write_str(",&nbsp;")?
+                    f.write_str(", ")?
                 }
                 f.write_str(&tp.name)?;
 
                 if !tp.bounds.is_empty() {
-                    write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?;
+                    if f.alternate() {
+                        write!(f, ": {:#}", TyParamBounds(&tp.bounds))?;
+                    } else {
+                        write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?;
+                    }
                 }
 
                 if let Some(ref ty) = tp.default {
-                    write!(f, "&nbsp;=&nbsp;{}", ty)?;
+                    if f.alternate() {
+                        write!(f, " = {:#}", ty)?;
+                    } else {
+                        write!(f, "&nbsp;=&nbsp;{}", ty)?;
+                    }
                 };
             }
         }
-        f.write_str("&gt;")?;
+        if f.alternate() {
+            f.write_str(">")?;
+        } else {
+            f.write_str("&gt;")?;
+        }
         Ok(())
     }
 }
@@ -145,7 +161,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if gens.where_predicates.is_empty() {
             return Ok(());
         }
-        f.write_str(" <span class='where'>where ")?;
+        if f.alternate() {
+            f.write_str(" ")?;
+        } else {
+            f.write_str(" <span class='where'>where ")?;
+        }
         for (i, pred) in gens.where_predicates.iter().enumerate() {
             if i > 0 {
                 f.write_str(", ")?;
@@ -153,7 +173,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             match pred {
                 &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
                     let bounds = bounds;
-                    write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
+                    if f.alternate() {
+                        write!(f, "{:#}: {:#}", ty, TyParamBounds(bounds))?;
+                    } else {
+                        write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
+                    }
                 }
                 &clean::WherePredicate::RegionPredicate { ref lifetime,
                                                           ref bounds } => {
@@ -167,11 +191,17 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     }
                 }
                 &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
-                    write!(f, "{} == {}", lhs, rhs)?;
+                    if f.alternate() {
+                        write!(f, "{:#} == {:#}", lhs, rhs)?;
+                    } else {
+                        write!(f, "{} == {}", lhs, rhs)?;
+                    }
                 }
             }
         }
-        f.write_str("</span>")?;
+        if !f.alternate() {
+            f.write_str("</span>")?;
+        }
         Ok(())
     }
 }
@@ -186,16 +216,28 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl fmt::Display for clean::PolyTrait {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if !self.lifetimes.is_empty() {
-            f.write_str("for&lt;")?;
+            if f.alternate() {
+                f.write_str("for<")?;
+            } else {
+                f.write_str("for&lt;")?;
+            }
             for (i, lt) in self.lifetimes.iter().enumerate() {
                 if i > 0 {
                     f.write_str(", ")?;
                 }
                 write!(f, "{}", lt)?;
             }
-            f.write_str("&gt; ")?;
+            if f.alternate() {
+                f.write_str("> ")?;
+            } else {
+                f.write_str("&gt; ")?;
+            }
+        }
+        if f.alternate() {
+            write!(f, "{:#}", self.trait_)
+        } else {
+            write!(f, "{}", self.trait_)
         }
-        write!(f, "{}", self.trait_)
     }
 }
 
@@ -210,7 +252,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     hir::TraitBoundModifier::None => "",
                     hir::TraitBoundModifier::Maybe => "?",
                 };
-                write!(f, "{}{}", modifier_str, *ty)
+                if f.alternate() {
+                    write!(f, "{}{:#}", modifier_str, *ty)
+                } else {
+                    write!(f, "{}{}", modifier_str, *ty)
+                }
             }
         }
     }
@@ -223,30 +269,46 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 ref lifetimes, ref types, ref bindings
             } => {
                 if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
-                    f.write_str("&lt;")?;
+                    if f.alternate() {
+                        f.write_str("<")?;
+                    } else {
+                        f.write_str("&lt;")?;
+                    }
                     let mut comma = false;
                     for lifetime in lifetimes {
                         if comma {
-                            f.write_str(",&nbsp;")?;
+                            f.write_str(", ")?;
                         }
                         comma = true;
                         write!(f, "{}", *lifetime)?;
                     }
                     for ty in types {
                         if comma {
-                            f.write_str(",&nbsp;")?;
+                            f.write_str(", ")?;
                         }
                         comma = true;
-                        write!(f, "{}", *ty)?;
+                        if f.alternate() {
+                            write!(f, "{:#}", *ty)?;
+                        } else {
+                            write!(f, "{}", *ty)?;
+                        }
                     }
                     for binding in bindings {
                         if comma {
-                            f.write_str(",&nbsp;")?;
+                            f.write_str(", ")?;
                         }
                         comma = true;
-                        write!(f, "{}", *binding)?;
+                        if f.alternate() {
+                            write!(f, "{:#}", *binding)?;
+                        } else {
+                            write!(f, "{}", *binding)?;
+                        }
+                    }
+                    if f.alternate() {
+                        f.write_str(">")?;
+                    } else {
+                        f.write_str("&gt;")?;
                     }
-                    f.write_str("&gt;")?;
                 }
             }
             clean::PathParameters::Parenthesized { ref inputs, ref output } => {
@@ -257,12 +319,19 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                         f.write_str(", ")?;
                     }
                     comma = true;
-                    write!(f, "{}", *ty)?;
+                    if f.alternate() {
+                        write!(f, "{:#}", *ty)?;
+                    } else {
+                        write!(f, "{}", *ty)?;
+                    }
                 }
                 f.write_str(")")?;
                 if let Some(ref ty) = *output {
-                    f.write_str(" -&gt; ")?;
-                    write!(f, "{}", ty)?;
+                    if f.alternate() {
+                        write!(f, " -> {:#}", ty)?;
+                    } else {
+                        write!(f, " -&gt; {}", ty)?;
+                    }
                 }
             }
         }
@@ -273,7 +342,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl fmt::Display for clean::PathSegment {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&self.name)?;
-        write!(f, "{}", self.params)
+        if f.alternate() {
+            write!(f, "{:#}", self.params)
+        } else {
+            write!(f, "{}", self.params)
+        }
     }
 }
 
@@ -287,7 +360,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             if i > 0 {
                 f.write_str("::")?
             }
-            write!(f, "{}", seg)?;
+            if f.alternate() {
+                write!(f, "{:#}", seg)?;
+            } else {
+                write!(f, "{}", seg)?;
+            }
         }
         Ok(())
     }
@@ -349,7 +426,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
         match rel_root {
             Some(mut root) => {
                 for seg in &path.segments[..amt] {
-                    if "super" == seg.name || "self" == seg.name {
+                    if "super" == seg.name || "self" == seg.name || w.alternate() {
                         write!(w, "{}::", seg.name)?;
                     } else {
                         root.push_str(&seg.name);
@@ -368,7 +445,11 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
             }
         }
     }
-    write!(w, "{}{}", HRef::new(did, &last.name), last.params)?;
+    if w.alternate() {
+        write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
+    } else {
+        write!(w, "{}{}", HRef::new(did, &last.name), last.params)?;
+    }
     Ok(())
 }
 
@@ -377,33 +458,35 @@ fn primitive_link(f: &mut fmt::Formatter,
                   name: &str) -> fmt::Result {
     let m = cache();
     let mut needs_termination = false;
-    match m.primitive_locations.get(&prim) {
-        Some(&LOCAL_CRATE) => {
-            let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
-            let len = if len == 0 {0} else {len - 1};
-            write!(f, "<a class='primitive' href='{}primitive.{}.html'>",
-                   repeat("../").take(len).collect::<String>(),
-                   prim.to_url_str())?;
-            needs_termination = true;
-        }
-        Some(&cnum) => {
-            let loc = match m.extern_locations[&cnum] {
-                (ref cname, render::Remote(ref s)) => Some((cname, s.to_string())),
-                (ref cname, render::Local) => {
-                    let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
-                    Some((cname, repeat("../").take(len).collect::<String>()))
-                }
-                (_, render::Unknown) => None,
-            };
-            if let Some((cname, root)) = loc {
-                write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>",
-                       root,
-                       cname,
+    if !f.alternate() {
+        match m.primitive_locations.get(&prim) {
+            Some(&LOCAL_CRATE) => {
+                let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
+                let len = if len == 0 {0} else {len - 1};
+                write!(f, "<a class='primitive' href='{}primitive.{}.html'>",
+                       repeat("../").take(len).collect::<String>(),
                        prim.to_url_str())?;
                 needs_termination = true;
             }
+            Some(&cnum) => {
+                let loc = match m.extern_locations[&cnum] {
+                    (ref cname, render::Remote(ref s)) => Some((cname, s.to_string())),
+                    (ref cname, render::Local) => {
+                        let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
+                        Some((cname, repeat("../").take(len).collect::<String>()))
+                    }
+                    (_, render::Unknown) => None,
+                };
+                if let Some((cname, root)) = loc {
+                    write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>",
+                           root,
+                           cname,
+                           prim.to_url_str())?;
+                    needs_termination = true;
+                }
+            }
+            None => {}
         }
-        None => {}
     }
     write!(f, "{}", name)?;
     if needs_termination {
@@ -419,7 +502,7 @@ fn tybounds(w: &mut fmt::Formatter,
         Some(ref params) => {
             for param in params {
                 write!(w, " + ")?;
-                write!(w, "{}", *param)?;
+                fmt::Display::fmt(param, w)?;
             }
             Ok(())
         }
@@ -436,10 +519,12 @@ pub fn new(did: DefId, text: &'a str) -> HRef<'a> {
 impl<'a> fmt::Display for HRef<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match href(self.did) {
-            Some((url, shortty, fqp)) => {
+            Some((url, shortty, fqp)) => if !f.alternate() {
                 write!(f, "<a class='{}' href='{}' title='{}'>{}</a>",
                        shortty, url, fqp.join("::"), self.text)
-            }
+            } else {
+                write!(f, "{}", self.text)
+            },
             _ => write!(f, "{}", self.text),
         }
     }
@@ -459,49 +544,68 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             clean::Infer => write!(f, "_"),
             clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()),
             clean::BareFunction(ref decl) => {
-                write!(f, "{}{}fn{}{}",
-                       UnsafetySpace(decl.unsafety),
-                       AbiSpace(decl.abi),
-                       decl.generics,
-                       decl.decl)
+                if f.alternate() {
+                    write!(f, "{}{}fn{:#}{:#}",
+                           UnsafetySpace(decl.unsafety),
+                           AbiSpace(decl.abi),
+                           decl.generics,
+                           decl.decl)
+                } else {
+                    write!(f, "{}{}fn{}{}",
+                           UnsafetySpace(decl.unsafety),
+                           AbiSpace(decl.abi),
+                           decl.generics,
+                           decl.decl)
+                }
             }
             clean::Tuple(ref typs) => {
                 match &typs[..] {
                     &[] => primitive_link(f, PrimitiveType::Tuple, "()"),
                     &[ref one] => {
                         primitive_link(f, PrimitiveType::Tuple, "(")?;
-                        write!(f, "{},", one)?;
-                        primitive_link(f, PrimitiveType::Tuple, ")")
+                        //carry f.alternate() into this display w/o branching manually
+                        fmt::Display::fmt(one, f)?;
+                        primitive_link(f, PrimitiveType::Tuple, ",)")
                     }
                     many => {
                         primitive_link(f, PrimitiveType::Tuple, "(")?;
-                        write!(f, "{}", CommaSep(&many))?;
+                        fmt::Display::fmt(&CommaSep(&many), f)?;
                         primitive_link(f, PrimitiveType::Tuple, ")")
                     }
                 }
             }
             clean::Vector(ref t) => {
                 primitive_link(f, PrimitiveType::Slice, &format!("["))?;
-                write!(f, "{}", t)?;
+                fmt::Display::fmt(t, f)?;
                 primitive_link(f, PrimitiveType::Slice, &format!("]"))
             }
             clean::FixedVector(ref t, ref s) => {
                 primitive_link(f, PrimitiveType::Array, "[")?;
-                write!(f, "{}", t)?;
-                primitive_link(f, PrimitiveType::Array,
-                               &format!("; {}]", Escape(s)))
+                fmt::Display::fmt(t, f)?;
+                if f.alternate() {
+                    primitive_link(f, PrimitiveType::Array,
+                                   &format!("; {}]", s))
+                } else {
+                    primitive_link(f, PrimitiveType::Array,
+                                   &format!("; {}]", Escape(s)))
+                }
             }
             clean::Never => f.write_str("!"),
             clean::RawPointer(m, ref t) => {
                 match **t {
                     clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
-                        primitive_link(f, clean::PrimitiveType::RawPointer,
-                                       &format!("*{}{}", RawMutableSpace(m), t))
+                        if f.alternate() {
+                            primitive_link(f, clean::PrimitiveType::RawPointer,
+                                           &format!("*{}{:#}", RawMutableSpace(m), t))
+                        } else {
+                            primitive_link(f, clean::PrimitiveType::RawPointer,
+                                           &format!("*{}{}", RawMutableSpace(m), t))
+                        }
                     }
                     _ => {
                         primitive_link(f, clean::PrimitiveType::RawPointer,
                                        &format!("*{}", RawMutableSpace(m)))?;
-                        write!(f, "{}", t)
+                        fmt::Display::fmt(t, f)
                     }
                 }
             }
@@ -515,18 +619,33 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T]
                         match **bt {
                             clean::Generic(_) =>
-                                primitive_link(f, PrimitiveType::Slice,
-                                    &format!("&amp;{}{}[{}]", lt, m, **bt)),
+                                if f.alternate() {
+                                    primitive_link(f, PrimitiveType::Slice,
+                                        &format!("&{}{}[{:#}]", lt, m, **bt))
+                                } else {
+                                    primitive_link(f, PrimitiveType::Slice,
+                                        &format!("&amp;{}{}[{}]", lt, m, **bt))
+                                },
                             _ => {
-                                primitive_link(f, PrimitiveType::Slice,
-                                               &format!("&amp;{}{}[", lt, m))?;
-                                write!(f, "{}", **bt)?;
+                                if f.alternate() {
+                                    primitive_link(f, PrimitiveType::Slice,
+                                                   &format!("&{}{}[", lt, m))?;
+                                    write!(f, "{:#}", **bt)?;
+                                } else {
+                                    primitive_link(f, PrimitiveType::Slice,
+                                                   &format!("&amp;{}{}[", lt, m))?;
+                                    write!(f, "{}", **bt)?;
+                                }
                                 primitive_link(f, PrimitiveType::Slice, "]")
                             }
                         }
                     }
                     _ => {
-                        write!(f, "&amp;{}{}{}", lt, m, **ty)
+                        if f.alternate() {
+                            write!(f, "&{}{}{:#}", lt, m, **ty)
+                        } else {
+                            write!(f, "&amp;{}{}{}", lt, m, **ty)
+                        }
                     }
                 }
             }
@@ -535,7 +654,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     if i != 0 {
                         write!(f, " + ")?;
                     }
-                    write!(f, "{}", *bound)?;
+                    if f.alternate() {
+                        write!(f, "{:#}", *bound)?;
+                    } else {
+                        write!(f, "{}", *bound)?;
+                    }
                 }
                 Ok(())
             }
@@ -545,7 +668,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     if i != 0 {
                         write!(f, " + ")?;
                     }
-                    write!(f, "{}", *bound)?;
+                    if f.alternate() {
+                        write!(f, "{:#}", *bound)?;
+                    } else {
+                        write!(f, "{}", *bound)?;
+                    }
                 }
                 Ok(())
             }
@@ -564,7 +691,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 ref self_type,
                 trait_: box clean::ResolvedPath { did, ref typarams, .. },
             } => {
-                write!(f, "{}::", self_type)?;
+                if f.alternate() {
+                    write!(f, "{:#}::", self_type)?;
+                } else {
+                    write!(f, "{}::", self_type)?;
+                }
                 let path = clean::Path::singleton(name.clone());
                 resolved_path(f, did, &path, false)?;
 
@@ -573,7 +704,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 Ok(())
             }
             clean::QPath { ref name, ref self_type, ref trait_ } => {
-                write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
+                if f.alternate() {
+                    write!(f, "<{:#} as {:#}>::{}", self_type, trait_, name)
+                } else {
+                    write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
+                }
             }
             clean::Unique(..) => {
                 panic!("should have been cleaned")
@@ -583,24 +718,30 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
-    write!(f, "impl{} ", i.generics)?;
+    if f.alternate() {
+        write!(f, "impl{:#} ", i.generics)?;
+    } else {
+        write!(f, "impl{} ", i.generics)?;
+    }
     if let Some(ref ty) = i.trait_ {
         write!(f, "{}",
                if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?;
         if link_trait {
-            write!(f, "{}", *ty)?;
+            fmt::Display::fmt(ty, f)?;
         } else {
             match *ty {
                 clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
                     let last = path.segments.last().unwrap();
-                    write!(f, "{}{}", last.name, last.params)?;
+                    fmt::Display::fmt(&last.name, f)?;
+                    fmt::Display::fmt(&last.params, f)?;
                 }
                 _ => unreachable!(),
             }
         }
         write!(f, " for ")?;
     }
-    write!(f, "{}{}", i.for_, WhereClause(&i.generics))?;
+    fmt::Display::fmt(&i.for_, f)?;
+    fmt::Display::fmt(&WhereClause(&i.generics), f)?;
     Ok(())
 }
 
@@ -618,11 +759,15 @@ pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt::
 impl fmt::Display for clean::Arguments {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for (i, input) in self.values.iter().enumerate() {
-            if i > 0 { write!(f, ", ")?; }
             if !input.name.is_empty() {
                 write!(f, "{}: ", input.name)?;
             }
-            write!(f, "{}", input.type_)?;
+            if f.alternate() {
+                write!(f, "{:#}", input.type_)?;
+            } else {
+                write!(f, "{}", input.type_)?;
+            }
+            if i + 1 < self.values.len() { write!(f, ", ")?; }
         }
         Ok(())
     }
@@ -632,6 +777,7 @@ impl fmt::Display for clean::FunctionRetTy {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
+            clean::Return(ref ty) if f.alternate() => write!(f, " -> {:#}", ty),
             clean::Return(ref ty) => write!(f, " -&gt; {}", ty),
             clean::DefaultReturn => Ok(()),
         }
@@ -641,9 +787,17 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl fmt::Display for clean::FnDecl {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.variadic {
-            write!(f, "({args}, ...){arrow}", args = self.inputs, arrow = self.output)
+            if f.alternate() {
+                write!(f, "({args:#}, ...){arrow:#}", args = self.inputs, arrow = self.output)
+            } else {
+                write!(f, "({args}, ...){arrow}", args = self.inputs, arrow = self.output)
+            }
         } else {
-            write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
+            if f.alternate() {
+                write!(f, "({args:#}){arrow:#}", args = self.inputs, arrow = self.output)
+            } else {
+                write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
+            }
         }
     }
 }
@@ -651,30 +805,89 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl<'a> fmt::Display for Method<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let decl = self.0;
+        let indent = self.1;
+        let amp = if f.alternate() { "&" } else { "&amp;" };
         let mut args = String::new();
+        let mut args_plain = String::new();
         for (i, input) in decl.inputs.values.iter().enumerate() {
-            if i > 0 || !args.is_empty() { args.push_str(", "); }
             if let Some(selfty) = input.to_self() {
                 match selfty {
-                    clean::SelfValue => args.push_str("self"),
+                    clean::SelfValue => {
+                        args.push_str("self");
+                        args_plain.push_str("self");
+                    }
                     clean::SelfBorrowed(Some(ref lt), mtbl) => {
-                        args.push_str(&format!("&amp;{} {}self", *lt, MutableSpace(mtbl)));
+                        args.push_str(&format!("{}{} {}self", amp, *lt, MutableSpace(mtbl)));
+                        args_plain.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl)));
                     }
                     clean::SelfBorrowed(None, mtbl) => {
-                        args.push_str(&format!("&amp;{}self", MutableSpace(mtbl)));
+                        args.push_str(&format!("{}{}self", amp, MutableSpace(mtbl)));
+                        args_plain.push_str(&format!("&{}self", MutableSpace(mtbl)));
                     }
                     clean::SelfExplicit(ref typ) => {
-                        args.push_str(&format!("self: {}", *typ));
+                        if f.alternate() {
+                            args.push_str(&format!("self: {:#}", *typ));
+                        } else {
+                            args.push_str(&format!("self: {}", *typ));
+                        }
+                        args_plain.push_str(&format!("self: {:#}", *typ));
                     }
                 }
             } else {
+                if i > 0 {
+                    args.push_str("<br> ");
+                    args_plain.push_str(" ");
+                }
                 if !input.name.is_empty() {
                     args.push_str(&format!("{}: ", input.name));
+                    args_plain.push_str(&format!("{}: ", input.name));
                 }
-                args.push_str(&format!("{}", input.type_));
+
+                if f.alternate() {
+                    args.push_str(&format!("{:#}", input.type_));
+                } else {
+                    args.push_str(&format!("{}", input.type_));
+                }
+                args_plain.push_str(&format!("{:#}", input.type_));
+            }
+            if i + 1 < decl.inputs.values.len() {
+                args.push_str(",");
+                args_plain.push_str(",");
             }
         }
-        write!(f, "({args}){arrow}", args = args, arrow = decl.output)
+
+        if decl.variadic {
+            args.push_str(",<br> ...");
+            args_plain.push_str(", ...");
+        }
+
+        let arrow_plain = format!("{:#}", decl.output);
+        let arrow = if f.alternate() {
+            format!("{:#}", decl.output)
+        } else {
+            format!("{}", decl.output)
+        };
+
+        let mut output: String;
+        let plain: String;
+        if arrow.is_empty() {
+            output = format!("({})", args);
+            plain = format!("{}({})", indent.replace("&nbsp;", " "), args_plain);
+        } else {
+            output = format!("({args})<br>{arrow}", args = args, arrow = arrow);
+            plain = format!("{indent}({args}){arrow}",
+                            indent = indent.replace("&nbsp;", " "),
+                            args = args_plain,
+                            arrow = arrow_plain);
+        }
+
+        if plain.len() > 80 {
+            let pad = format!("<br>{}", indent);
+            output = output.replace("<br>", &pad);
+        } else {
+            output = output.replace("<br>", "");
+        }
+        write!(f, "{}", output)
     }
 }
 
@@ -768,7 +981,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl fmt::Display for clean::TypeBinding {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}={}", self.name, self.ty)
+        if f.alternate() {
+            write!(f, "{}={:#}", self.name, self.ty)
+        } else {
+            write!(f, "{}={}", self.name, self.ty)
+        }
     }
 }
 
@@ -792,10 +1009,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl fmt::Display for AbiSpace {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let quot = if f.alternate() { "\"" } else { "&quot;" };
         match self.0 {
             Abi::Rust => Ok(()),
             Abi::C => write!(f, "extern "),
-            abi => write!(f, "extern &quot;{}&quot; ", abi.name()),
+            abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()),
         }
     }
 }
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 5a6e167188226a660299e4b7593f745af05f0d8b..d8dba00e7d5789f485bcff5c802264c0bbe353fc 100644 (file)
@@ -1967,6 +1967,14 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         UnstableFeatures::Allow => f.constness,
         _ => hir::Constness::NotConst
     };
+    let prefix = format!("{}{}{}{:#}fn {}{:#}",
+                         VisSpace(&it.visibility),
+                         ConstnessSpace(vis_constness),
+                         UnsafetySpace(f.unsafety),
+                         AbiSpace(f.abi),
+                         it.name.as_ref().unwrap(),
+                         f.generics);
+    let indent = repeat("&nbsp;").take(prefix.len()).collect::<String>();
     write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(&it.visibility),
@@ -1976,7 +1984,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
            name = it.name.as_ref().unwrap(),
            generics = f.generics,
            where_clause = WhereClause(&f.generics),
-           decl = f.decl)?;
+           decl = Method(&f.decl, &indent))?;
     document(w, cx, it)
 }
 
@@ -2246,6 +2254,13 @@ fn method(w: &mut fmt::Formatter,
             UnstableFeatures::Allow => constness,
             _ => hir::Constness::NotConst
         };
+        let prefix = format!("{}{}{:#}fn {}{:#}",
+                             ConstnessSpace(vis_constness),
+                             UnsafetySpace(unsafety),
+                             AbiSpace(abi),
+                             name,
+                             *g);
+        let indent = repeat("&nbsp;").take(prefix.len()).collect::<String>();
         write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                ConstnessSpace(vis_constness),
@@ -2254,7 +2269,7 @@ fn method(w: &mut fmt::Formatter,
                href = href,
                name = name,
                generics = *g,
-               decl = Method(d),
+               decl = Method(d, &indent),
                where_clause = WhereClause(g))
     }
     match item.inner {
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 2f2969b110db17a7687b81802ce6409013526277..5bb5183fd6a93b5b3de8fe690e6ca5a3e73c262e 100644 (file)
@@ -1903,6 +1903,130 @@ fn file_test_io_seek_shakedown() {
         check!(fs::remove_file(filename));
     }
 
+    #[test]
+    fn file_test_io_eof() {
+        let tmpdir = tmpdir();
+        let filename = tmpdir.join("file_rt_io_file_test_eof.txt");
+        let mut buf = [0; 256];
+        {
+            let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
+            let mut rw = check!(oo.open(&filename));
+            assert_eq!(check!(rw.read(&mut buf)), 0);
+            assert_eq!(check!(rw.read(&mut buf)), 0);
+        }
+        check!(fs::remove_file(&filename));
+    }
+
+    #[test]
+    #[cfg(unix)]
+    fn file_test_io_read_write_at() {
+        use os::unix::fs::FileExt;
+
+        let tmpdir = tmpdir();
+        let filename = tmpdir.join("file_rt_io_file_test_read_write_at.txt");
+        let mut buf = [0; 256];
+        let write1 = "asdf";
+        let write2 = "qwer-";
+        let write3 = "-zxcv";
+        let content = "qwer-asdf-zxcv";
+        {
+            let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
+            let mut rw = check!(oo.open(&filename));
+            assert_eq!(check!(rw.write_at(write1.as_bytes(), 5)), write1.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(rw.read_at(&mut buf, 5)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(rw.read_at(&mut buf[..write2.len()], 0)), write2.len());
+            assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok("\0\0\0\0\0"));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(rw.write(write2.as_bytes())), write2.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
+            assert_eq!(check!(rw.read(&mut buf)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.read_at(&mut buf[..write2.len()], 0)), write2.len());
+            assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.write_at(write3.as_bytes(), 9)), write3.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+        }
+        {
+            let mut read = check!(File::open(&filename));
+            assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
+            assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(read.read(&mut buf)), write3.len());
+            assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.read_at(&mut buf, 14)), 0);
+            assert_eq!(check!(read.read_at(&mut buf, 15)), 0);
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+        }
+        check!(fs::remove_file(&filename));
+    }
+
+    #[test]
+    #[cfg(windows)]
+    fn file_test_io_seek_read_write() {
+        use os::windows::fs::FileExt;
+
+        let tmpdir = tmpdir();
+        let filename = tmpdir.join("file_rt_io_file_test_seek_read_write.txt");
+        let mut buf = [0; 256];
+        let write1 = "asdf";
+        let write2 = "qwer-";
+        let write3 = "-zxcv";
+        let content = "qwer-asdf-zxcv";
+        {
+            let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
+            let mut rw = check!(oo.open(&filename));
+            assert_eq!(check!(rw.seek_write(write1.as_bytes(), 5)), write1.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.seek_read(&mut buf, 5)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.seek(SeekFrom::Start(0))), 0);
+            assert_eq!(check!(rw.write(write2.as_bytes())), write2.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
+            assert_eq!(check!(rw.read(&mut buf)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.seek_read(&mut buf[..write2.len()], 0)), write2.len());
+            assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
+            assert_eq!(check!(rw.seek_write(write3.as_bytes(), 9)), write3.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 14);
+        }
+        {
+            let mut read = check!(File::open(&filename));
+            assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
+            assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
+            assert_eq!(check!(read.read(&mut buf)), write3.len());
+            assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek_read(&mut buf, 14)), 0);
+            assert_eq!(check!(read.seek_read(&mut buf, 15)), 0);
+        }
+        check!(fs::remove_file(&filename));
+    }
+
     #[test]
     fn file_test_stat_is_correct_on_is_file() {
         let tmpdir = tmpdir();
@@ -2221,8 +2345,8 @@ fn copy_file_preserves_perm_bits() {
         check!(fs::set_permissions(&out, attr.permissions()));
     }
 
-    #[cfg(windows)]
     #[test]
+    #[cfg(windows)]
     fn copy_file_preserves_streams() {
         let tmp = tmpdir();
         check!(check!(File::create(tmp.join("in.txt:bunny"))).write("carrot".as_bytes()));
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 48ecae185f95c37e9e9a54a3e24c121587bb5fcc..f08b7641521447582b4786c64c7db41c3480268a 100644 (file)
@@ -136,6 +136,10 @@ impl<T: ?Sized> RwLock<T> {
     /// This function will return an error if the RwLock is poisoned. An RwLock
     /// is poisoned whenever a writer panics while holding an exclusive lock.
     /// The failure will occur immediately after the lock has been acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by the current thread.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
@@ -188,6 +192,10 @@ pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
     /// This function will return an error if the RwLock is poisoned. An RwLock
     /// is poisoned whenever a writer panics while holding an exclusive lock.
     /// An error will be returned when the lock is acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by the current thread.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
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 abbe3fc1846bdd090953776560123b48162aeb43..10436723a81d0d108f2c65da6c19497addea584d 100644 (file)
 
 #![cfg(target_os = "android")]
 
-use libc::{c_int, sighandler_t};
+use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
+use libc::{ftruncate, pread, pwrite};
 
 use io;
-use sys::cvt_r;
+use super::{cvt, cvt_r};
 
 // The `log2` and `log2f` functions apparently appeared in android-18, or at
 // least you can see they're not present in the android-17 header [1] and they
@@ -96,13 +97,10 @@ pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
 //
 // If it doesn't we just fall back to `ftruncate`, generating an error for
 // too-large values.
+#[cfg(target_pointer_width = "32")]
 pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
     weak!(fn ftruncate64(c_int, i64) -> c_int);
 
-    extern {
-        fn ftruncate(fd: c_int, off: i32) -> c_int;
-    }
-
     unsafe {
         match ftruncate64.get() {
             Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()),
@@ -117,3 +115,56 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
         }
     }
 }
+
+#[cfg(target_pointer_width = "64")]
+pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
+    unsafe {
+        cvt_r(|| ftruncate(fd, size as i64)).map(|_| ())
+    }
+}
+
+#[cfg(target_pointer_width = "32")]
+pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    use convert::TryInto;
+    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
+    pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
+        if let Ok(o) = offset.try_into() {
+            cvt(pread(fd, buf, count, o))
+        } else {
+            Err(io::Error::new(io::ErrorKind::InvalidInput,
+                               "cannot pread >2GB"))
+        }
+    })
+}
+
+#[cfg(target_pointer_width = "32")]
+pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    use convert::TryInto;
+    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
+    pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
+        if let Ok(o) = offset.try_into() {
+            cvt(pwrite(fd, buf, count, o))
+        } else {
+            Err(io::Error::new(io::ErrorKind::InvalidInput,
+                               "cannot pwrite >2GB"))
+        }
+    })
+}
+
+#[cfg(target_pointer_width = "64")]
+pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    cvt(pread(fd, buf, count, offset))
+}
+
+#[cfg(target_pointer_width = "64")]
+pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    cvt(pwrite(fd, buf, count, offset))
+}
index 77587918ac94b0e83d9edb6f912d3227c54f719c..fcfab051588416ce93087ca3456a9fe974c6b5d5 100644 (file)
 use sys_common::{FromInner, AsInner, AsInnerMut};
 use sys::platform::fs::MetadataExt as UnixMetadataExt;
 
+/// Unix-specific extensions to `File`
+#[unstable(feature = "file_offset", issue = "35918")]
+pub trait FileExt {
+    /// Reads a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Note that similar to `File::read`, it is not an error to return with a
+    /// short read.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+
+    /// Writes a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// When writing beyond the end of the file, the file is appropiately
+    /// extended and the intermediate bytes are initialized with the value 0.
+    ///
+    /// Note that similar to `File::write`, it is not an error to return a
+    /// short write.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+}
+
+#[unstable(feature = "file_offset", issue = "35918")]
+impl FileExt for fs::File {
+    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().read_at(buf, offset)
+    }
+    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_at(buf, offset)
+    }
+}
+
 /// Unix-specific extensions to `Permissions`
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
index 1be3d75d866dd7123c663604a142fb9f8ffcfeed..b2483f4e209378094a18ea43a57cdd814b4150fd 100644 (file)
@@ -50,6 +50,8 @@ pub mod prelude {
     pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::fs::DirEntryExt;
+    #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")]
+    pub use super::fs::FileExt;
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::thread::JoinHandleExt;
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
index eadf98867a6b7ad78947b1e61b9ad36022539ad3..41bb96fed16cbcdde027568c572b9d52c4cd2b39 100644 (file)
@@ -50,6 +50,30 @@ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
         (&mut me).read_to_end(buf)
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        #[cfg(target_os = "android")]
+        use super::android::cvt_pread64;
+
+        #[cfg(not(target_os = "android"))]
+        unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
+            -> io::Result<isize>
+        {
+            #[cfg(any(target_os = "linux", target_os = "emscripten"))]
+            use libc::pread64;
+            #[cfg(not(any(target_os = "linux", target_os = "emscripten")))]
+            use libc::pread as pread64;
+            cvt(pread64(fd, buf, count, offset))
+        }
+
+        unsafe {
+            cvt_pread64(self.fd,
+                        buf.as_mut_ptr() as *mut c_void,
+                        buf.len(),
+                        offset as i64)
+                .map(|n| n as usize)
+        }
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::write(self.fd,
@@ -59,6 +83,30 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         Ok(ret as usize)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        #[cfg(target_os = "android")]
+        use super::android::cvt_pwrite64;
+
+        #[cfg(not(target_os = "android"))]
+        unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64)
+            -> io::Result<isize>
+        {
+            #[cfg(any(target_os = "linux", target_os = "emscripten"))]
+            use libc::pwrite64;
+            #[cfg(not(any(target_os = "linux", target_os = "emscripten")))]
+            use libc::pwrite as pwrite64;
+            cvt(pwrite64(fd, buf, count, offset))
+        }
+
+        unsafe {
+            cvt_pwrite64(self.fd,
+                         buf.as_ptr() as *const c_void,
+                         buf.len(),
+                         offset as i64)
+                .map(|n| n as usize)
+        }
+    }
+
     #[cfg(not(any(target_env = "newlib",
                   target_os = "solaris",
                   target_os = "emscripten",
index 606e2c2264ad0ac303553654467de26738ba09a0..fe8cbc84215721bcc1cbdb117b750590f13df47f 100644 (file)
@@ -483,10 +483,18 @@ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
         self.0.read_to_end(buf)
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.0.read_at(buf, offset)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.0.write_at(buf, offset)
+    }
+
     pub fn flush(&self) -> io::Result<()> { Ok(()) }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
index 4388a0bdff2cfb0f7f31920b021cd8221cbae0ea..1e2b8bf38fa719b4300dd59b29f9fc3b7a86a57f 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fs::{OpenOptions, Metadata};
+use fs::{self, OpenOptions, Metadata};
 use io;
 use path::Path;
 use sys;
 use sys_common::{AsInnerMut, AsInner};
 
+/// Windows-specific extensions to `File`
+#[unstable(feature = "file_offset", issue = "35918")]
+pub trait FileExt {
+    /// Seeks to a given position and reads a number of bytes.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor. The current cursor **is** affected by this
+    /// function, it is set to the end of the read.
+    ///
+    /// Reading beyond the end of the file will always return with a length of
+    /// 0.
+    ///
+    /// Note that similar to `File::read`, it is not an error to return with a
+    /// short read. When returning from such a short read, the file pointer is
+    /// still updated.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+
+    /// Seeks to a given position and writes a number of bytes.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor. The current cursor **is** affected by this
+    /// function, it is set to the end of the write.
+    ///
+    /// When writing beyond the end of the file, the file is appropiately
+    /// extended and the intermediate bytes are left uninitialized.
+    ///
+    /// Note that similar to `File::write`, it is not an error to return a
+    /// short write. When returning from such a short write, the file pointer
+    /// is still updated.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+}
+
+#[unstable(feature = "file_offset", issue = "35918")]
+impl FileExt for fs::File {
+    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().read_at(buf, offset)
+    }
+
+    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_at(buf, offset)
+    }
+}
+
 /// Windows-specific extensions to `OpenOptions`
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
index c3578fdfdb16ba452c68051f3ddb1cb7e2ff14fa..932bb5e95640531fdb26ea1f52140944895d0156 100644 (file)
@@ -36,4 +36,6 @@ pub mod prelude {
     pub use super::ffi::{OsStrExt, OsStringExt};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::fs::{OpenOptionsExt, MetadataExt};
+    #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")]
+    pub use super::fs::FileExt;
 }
index 90a16853d56dd43c60894d2648ffd5818b14bc3a..a927eae020dcf9849f5a85d6e1654b3735bc2dc2 100644 (file)
@@ -311,6 +311,10 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.handle.read(buf)
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.handle.read_at(buf, offset)
+    }
+
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
         self.handle.read_to_end(buf)
     }
@@ -319,6 +323,10 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.handle.write(buf)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.handle.write_at(buf, offset)
+    }
+
     pub fn flush(&self) -> io::Result<()> { Ok(()) }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
index 97e746ee345763cc75e3723c5fbfb6f0d7a4deb5..10b86ba44bc793a734e4131e323fd09c261a46e3 100644 (file)
@@ -104,6 +104,23 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         }
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        let mut read = 0;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let res = unsafe {
+            let mut overlapped: c::OVERLAPPED = mem::zeroed();
+            overlapped.Offset = offset as u32;
+            overlapped.OffsetHigh = (offset >> 32) as u32;
+            cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+                            len, &mut read, &mut overlapped))
+        };
+        match res {
+            Ok(_) => Ok(read as usize),
+            Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
+            Err(e) => Err(e),
+        }
+    }
+
     pub unsafe fn read_overlapped(&self,
                                   buf: &mut [u8],
                                   overlapped: *mut c::OVERLAPPED)
@@ -174,6 +191,19 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         Ok(amt as usize)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        let mut written = 0;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        unsafe {
+            let mut overlapped: c::OVERLAPPED = mem::zeroed();
+            overlapped.Offset = offset as u32;
+            overlapped.OffsetHigh = (offset >> 32) as u32;
+            cvt(c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
+                             len, &mut written, &mut overlapped))?;
+        }
+        Ok(written as usize)
+    }
+
     pub fn duplicate(&self, access: c::DWORD, inherit: bool,
                      options: c::DWORD) -> io::Result<Handle> {
         let mut ret = 0 as c::HANDLE;
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 32b66da4d96ceffff3e3dc6fef92336530f04891..792239e7219326d6b233efae7e08dea801491b38 100644 (file)
@@ -125,9 +125,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize) -> String {
-    let n = toks.len();
-    assert_eq!(n, szs.len());
+fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
+    let n = buf.len();
     let mut i = left;
     let mut l = lim;
     let mut s = String::from("[");
@@ -136,7 +135,7 @@ fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize)
         if i != left {
             s.push_str(", ");
         }
-        s.push_str(&format!("{}={}", szs[i], &toks[i]));
+        s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
         i += 1;
         i %= n;
     }
@@ -159,13 +158,9 @@ pub struct PrintStackElem {
 const SIZE_INFINITY: isize = 0xffff;
 
 pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
-    // Yes 55, it makes the ring buffers big enough to never
-    // fall behind.
+    // Yes 55, it makes the ring buffers big enough to never fall behind.
     let n: usize = 55 * linewidth;
     debug!("mk_printer {}", linewidth);
-    let token = vec![Token::Eof; n];
-    let size = vec![0; n];
-    let scan_stack = VecDeque::with_capacity(n);
     Printer {
         out: out,
         buf_len: n,
@@ -173,11 +168,10 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
         space: linewidth as isize,
         left: 0,
         right: 0,
-        token: token,
-        size: size,
+        buf: vec![BufEntry { token: Token::Eof, size: 0 }; n],
         left_total: 0,
         right_total: 0,
-        scan_stack: scan_stack,
+        scan_stack: VecDeque::new(),
         print_stack: Vec::new(),
         pending_indentation: 0
     }
@@ -269,10 +263,8 @@ pub struct Printer<'a> {
     left: usize,
     /// Index of right side of input stream
     right: usize,
-    /// Ring-buffer stream goes through
-    token: Vec<Token> ,
-    /// Ring-buffer of calculated sizes
-    size: Vec<isize> ,
+    /// Ring-buffer of tokens and calculated sizes
+    buf: Vec<BufEntry>,
     /// Running size of stream "...left"
     left_total: isize,
     /// Running size of stream "...right"
@@ -283,20 +275,26 @@ pub struct Printer<'a> {
     /// Begin (if there is any) on top of it. Stuff is flushed off the
     /// bottom as it becomes irrelevant due to the primary ring-buffer
     /// advancing.
-    scan_stack: VecDeque<usize> ,
+    scan_stack: VecDeque<usize>,
     /// Stack of blocks-in-progress being flushed by print
     print_stack: Vec<PrintStackElem> ,
     /// Buffered indentation to avoid writing trailing whitespace
     pending_indentation: isize,
 }
 
+#[derive(Clone)]
+struct BufEntry {
+    token: Token,
+    size: isize,
+}
+
 impl<'a> Printer<'a> {
     pub fn last_token(&mut self) -> Token {
-        self.token[self.right].clone()
+        self.buf[self.right].token.clone()
     }
     // be very careful with this!
     pub fn replace_last_token(&mut self, t: Token) {
-        self.token[self.right] = t;
+        self.buf[self.right].token = t;
     }
     pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
         debug!("pp Vec<{},{}>", self.left, self.right);
@@ -318,8 +316,7 @@ pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
             } else { self.advance_right(); }
             debug!("pp Begin({})/buffer Vec<{},{}>",
                    b.offset, self.left, self.right);
-            self.token[self.right] = token;
-            self.size[self.right] = -self.right_total;
+            self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
             let right = self.right;
             self.scan_push(right);
             Ok(())
@@ -331,8 +328,7 @@ pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
             } else {
                 debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
                 self.advance_right();
-                self.token[self.right] = token;
-                self.size[self.right] = -1;
+                self.buf[self.right] = BufEntry { token: token, size: -1 };
                 let right = self.right;
                 self.scan_push(right);
                 Ok(())
@@ -350,8 +346,7 @@ pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
             self.check_stack(0);
             let right = self.right;
             self.scan_push(right);
-            self.token[self.right] = token;
-            self.size[self.right] = -self.right_total;
+            self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
             self.right_total += b.blank_space;
             Ok(())
           }
@@ -364,8 +359,7 @@ pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
                 debug!("pp String('{}')/buffer Vec<{},{}>",
                        s, self.left, self.right);
                 self.advance_right();
-                self.token[self.right] = Token::String(s, len);
-                self.size[self.right] = len;
+                self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
                 self.right_total += len;
                 self.check_stream()
             }
@@ -381,7 +375,7 @@ pub fn check_stream(&mut self) -> io::Result<()> {
             if Some(&self.left) == self.scan_stack.back() {
                 debug!("setting {} to infinity and popping", self.left);
                 let scanned = self.scan_pop_bottom();
-                self.size[scanned] = SIZE_INFINITY;
+                self.buf[scanned].size = SIZE_INFINITY;
             }
             self.advance_left()?;
             if self.left != self.right {
@@ -410,12 +404,12 @@ pub fn advance_right(&mut self) {
     }
     pub fn advance_left(&mut self) -> io::Result<()> {
         debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
-               self.left, self.size[self.left]);
+               self.left, self.buf[self.left].size);
 
-        let mut left_size = self.size[self.left];
+        let mut left_size = self.buf[self.left].size;
 
         while left_size >= 0 {
-            let left = self.token[self.left].clone();
+            let left = self.buf[self.left].token.clone();
 
             let len = match left {
                 Token::Break(b) => b.blank_space,
@@ -437,7 +431,7 @@ pub fn advance_left(&mut self) -> io::Result<()> {
             self.left += 1;
             self.left %= self.buf_len;
 
-            left_size = self.size[self.left];
+            left_size = self.buf[self.left].size;
         }
 
         Ok(())
@@ -445,23 +439,23 @@ pub fn advance_left(&mut self) -> io::Result<()> {
     pub fn check_stack(&mut self, k: isize) {
         if !self.scan_stack.is_empty() {
             let x = self.scan_top();
-            match self.token[x] {
+            match self.buf[x].token {
                 Token::Begin(_) => {
                     if k > 0 {
                         let popped = self.scan_pop();
-                        self.size[popped] = self.size[x] + self.right_total;
+                        self.buf[popped].size = self.buf[x].size + self.right_total;
                         self.check_stack(k - 1);
                     }
                 }
                 Token::End => {
                     // paper says + not =, but that makes no sense.
                     let popped = self.scan_pop();
-                    self.size[popped] = 1;
+                    self.buf[popped].size = 1;
                     self.check_stack(k + 1);
                 }
                 _ => {
                     let popped = self.scan_pop();
-                    self.size[popped] = self.size[x] + self.right_total;
+                    self.buf[popped].size = self.buf[x].size + self.right_total;
                     if k > 0 {
                         self.check_stack(k);
                     }
@@ -499,8 +493,7 @@ pub fn print_str(&mut self, s: &str) -> io::Result<()> {
     pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
         debug!("print {} {} (remaining line space={})", token, l,
                self.space);
-        debug!("{}", buf_str(&self.token,
-                             &self.size,
+        debug!("{}", buf_str(&self.buf,
                              self.left,
                              self.right,
                              6));
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 4be115b8afdace66329a8d4c5a97b31f32eb3346..b72b5e3b2808bb5998b4d3db121c0abf7e76bbdb 100644 (file)
@@ -15,6 +15,7 @@ fn main() {
         //~^ ERROR E0007
         //~| NOTE binds an already bound by-move value by moving it
         //~| ERROR E0303
+        //~| NOTE not allowed after `@`
         None => {},
     }
 }
index 67947fd087c05d40e99114ce1f55071822c749f4..e631fe2a8a7ccf834f66560db9ec310bbed647ed 100644 (file)
 
 fn main() {
     match Some("hi".to_string()) {
-        ref op_string_ref @ Some(s) => {}, //~ ERROR E0303
-                                           //~^ ERROR E0009
+        ref op_string_ref @ Some(s) => {},
+        //~^ ERROR pattern bindings are not allowed after an `@` [E0303]
+        //~| NOTE not allowed after `@`
+        //~| ERROR E0009
+        //~| NOTE by-move pattern here
+        //~| NOTE both by-ref and by-move used
         None => {},
     }
 }
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/empty-struct-unit-pat-1.rs b/src/test/compile-fail/empty-struct-unit-pat-1.rs
deleted file mode 100644 (file)
index 273cb48..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Can't use unit struct as enum pattern
-
-// aux-build:empty-struct.rs
-
-#![feature(relaxed_adts)]
-
-extern crate empty_struct;
-use empty_struct::*;
-
-struct Empty2;
-
-enum E {
-    Empty4
-}
-
-// remove attribute after warning cycle and promoting warnings to errors
-fn main() {
-    let e2 = Empty2;
-    let e4 = E::Empty4;
-    let xe2 = XEmpty2;
-    let xe4 = XE::XEmpty4;
-
-    match e2 {
-        Empty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
-            //~^ WARNING hard error
-    }
-    match xe2 {
-        XEmpty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
-            //~^ WARNING hard error
-    }
-
-    match e4 {
-        E::Empty4(..) => () //~ ERROR expected tuple struct/variant, found unit variant `E::Empty4`
-            //~^ WARNING hard error
-    }
-    match xe4 {
-        XE::XEmpty4(..) => (),
-            //~^ ERROR expected tuple struct/variant, found unit variant `XE::XEmpty4`
-            //~| WARNING hard error
-        _ => {},
-    }
-}
diff --git a/src/test/compile-fail/empty-struct-unit-pat-2.rs b/src/test/compile-fail/empty-struct-unit-pat-2.rs
deleted file mode 100644 (file)
index 993f10e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Can't use unit struct as enum pattern
-
-// aux-build:empty-struct.rs
-
-#![feature(relaxed_adts)]
-
-extern crate empty_struct;
-use empty_struct::*;
-
-struct Empty2;
-
-enum E {
-    Empty4
-}
-
-fn main() {
-    let e2 = Empty2;
-    let e4 = E::Empty4;
-    let xe2 = XEmpty2;
-    let xe4 = XE::XEmpty4;
-
-    match e2 {
-        Empty2() => ()
-        //~^ ERROR expected tuple struct/variant, found unit struct `Empty2`
-    }
-    match xe2 {
-        XEmpty2() => ()
-        //~^ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
-    }
-
-    match e4 {
-        E::Empty4() => ()
-        //~^ ERROR expected tuple struct/variant, found unit variant `E::Empty4`
-    }
-    match xe4 {
-        XE::XEmpty4() => (),
-        //~^ ERROR expected tuple struct/variant, found unit variant `XE::XEmpty4`
-        _ => {},
-    }
-}
diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs
new file mode 100644 (file)
index 0000000..90f6ae5
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Can't use unit struct as tuple struct pattern
+
+// aux-build:empty-struct.rs
+
+#![feature(relaxed_adts)]
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2;
+
+enum E {
+    Empty4
+}
+
+fn main() {
+    let e2 = Empty2;
+    let e4 = E::Empty4;
+    let xe2 = XEmpty2;
+    let xe4 = XE::XEmpty4;
+
+    match e2 {
+        Empty2() => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
+    }
+    match xe2 {
+        XEmpty2() => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
+    }
+    match e2 {
+        Empty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
+    }
+    match xe2 {
+        XEmpty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
+    }
+
+    match e4 {
+        E::Empty4() => () //~ ERROR expected tuple struct/variant, found unit variant `E::Empty4`
+    }
+    match xe4 {
+        XE::XEmpty4() => (),
+        //~^ ERROR expected tuple struct/variant, found unit variant `XE::XEmpty4`
+        _ => {},
+    }
+    match e4 {
+        E::Empty4(..) => () //~ ERROR expected tuple struct/variant, found unit variant `E::Empty4`
+    }
+    match xe4 {
+        XE::XEmpty4(..) => (),
+        //~^ ERROR expected tuple struct/variant, found unit variant `XE::XEmpty4`
+        _ => {},
+    }
+}
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;
diff --git a/src/test/compile-fail/issue-37026.rs b/src/test/compile-fail/issue-37026.rs
new file mode 100644 (file)
index 0000000..95fd5d1
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// aux-build:empty-struct.rs
+
+extern crate empty_struct;
+
+fn main() {
+    let empty_struct::XEmpty2 = (); //~ ERROR mismatched types
+    let empty_struct::XEmpty6(..) = (); //~ ERROR mismatched types
+}
diff --git a/src/test/compile-fail/issue-pr29383.rs b/src/test/compile-fail/issue-pr29383.rs
new file mode 100644 (file)
index 0000000..b60c537
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum E {
+    A,
+    B,
+}
+
+fn main() {
+    match None {
+        None => {}
+        Some(E::A(..)) => {} //~ ERROR expected tuple struct/variant, found unit variant `E::A`
+        Some(E::B(..)) => {} //~ ERROR expected tuple struct/variant, found unit variant `E::B`
+    }
+}
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;
             }
 
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
new file mode 100644 (file)
index 0000000..10c02d8
--- /dev/null
@@ -0,0 +1,132 @@
+// 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.
+
+
+// This test case tests the incremental compilation hash (ICH) implementation
+// for consts.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// must-compile-successfully
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change const visibility ---------------------------------------------------
+#[cfg(cfail1)]
+const CONST_VISIBILITY: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+pub const CONST_VISIBILITY: u8 = 0;
+
+
+// Change type from i32 to u32 ------------------------------------------------
+#[cfg(cfail1)]
+const CONST_CHANGE_TYPE_1: i32 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+const CONST_CHANGE_TYPE_1: u32 = 0;
+
+
+// Change type from Option<u32> to Option<u64> --------------------------------
+#[cfg(cfail1)]
+const CONST_CHANGE_TYPE_2: Option<u32> = None;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+const CONST_CHANGE_TYPE_2: Option<u64> = None;
+
+
+// Change value between simple literals ---------------------------------------
+#[cfg(cfail1)]
+const CONST_CHANGE_VALUE_1: i16 = 1;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_1: i16 = 2;
+
+
+// Change value between expressions -------------------------------------------
+#[cfg(cfail1)]
+const CONST_CHANGE_VALUE_2: i16 = 1 + 1;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_2: i16 = 1 + 2;
+
+
+#[cfg(cfail1)]
+const CONST_CHANGE_VALUE_3: i16 = 2 + 3;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_3: i16 = 2 * 3;
+
+
+#[cfg(cfail1)]
+const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
+
+
+// Change type indirectly -----------------------------------------------------
+struct ReferencedType1;
+struct ReferencedType2;
+
+mod const_change_type_indirectly {
+    #[cfg(cfail1)]
+    use super::ReferencedType1 as Type;
+
+    #[cfg(not(cfail1))]
+    use super::ReferencedType2 as Type;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    const CONST_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
+}
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
new file mode 100644 (file)
index 0000000..ac67e43
--- /dev/null
@@ -0,0 +1,185 @@
+// 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.
+
+
+// This test case tests the incremental compilation hash (ICH) implementation
+// for statics.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// must-compile-successfully
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(linkage)]
+#![feature(thread_local)]
+#![crate_type="rlib"]
+
+
+// Change static visibility ---------------------------------------------------
+#[cfg(cfail1)]
+static STATIC_VISIBILITY: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+pub static STATIC_VISIBILITY: u8 = 0;
+
+
+// Change static mutability ---------------------------------------------------
+#[cfg(cfail1)]
+static STATIC_MUTABILITY: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static mut STATIC_MUTABILITY: u8 = 0;
+
+
+// Add linkage attribute ------------------------------------------------------
+#[cfg(cfail1)]
+static STATIC_LINKAGE: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[linkage="weak_odr"]
+static STATIC_LINKAGE: u8 = 0;
+
+
+// Add no_mangle attribute ----------------------------------------------------
+#[cfg(cfail1)]
+static STATIC_NO_MANGLE: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[no_mangle]
+static STATIC_NO_MANGLE: u8 = 0;
+
+
+// Add thread_local attribute -------------------------------------------------
+#[cfg(cfail1)]
+static STATIC_THREAD_LOCAL: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+#[thread_local]
+static STATIC_THREAD_LOCAL: u8 = 0;
+
+
+// Change type from i16 to u64 ------------------------------------------------
+#[cfg(cfail1)]
+static STATIC_CHANGE_TYPE_1: i16 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static STATIC_CHANGE_TYPE_1: u64 = 0;
+
+
+// Change type from Option<i8> to Option<u16> ---------------------------------
+#[cfg(cfail1)]
+static STATIC_CHANGE_TYPE_2: Option<i8> = None;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static STATIC_CHANGE_TYPE_2: Option<u16> = None;
+
+
+// Change value between simple literals ---------------------------------------
+#[cfg(cfail1)]
+static STATIC_CHANGE_VALUE_1: i16 = 1;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static STATIC_CHANGE_VALUE_1: i16 = 2;
+
+
+// Change value between expressions -------------------------------------------
+#[cfg(cfail1)]
+static STATIC_CHANGE_VALUE_2: i16 = 1 + 1;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static STATIC_CHANGE_VALUE_2: i16 = 1 + 2;
+
+
+#[cfg(cfail1)]
+static STATIC_CHANGE_VALUE_3: i16 = 2 + 3;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static STATIC_CHANGE_VALUE_3: i16 = 2 * 3;
+
+
+#[cfg(cfail1)]
+static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
+
+
+// Change type indirectly -----------------------------------------------------
+struct ReferencedType1;
+struct ReferencedType2;
+
+mod static_change_type_indirectly {
+    #[cfg(cfail1)]
+    use super::ReferencedType1 as Type;
+
+    #[cfg(not(cfail1))]
+    use super::ReferencedType2 as Type;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
+}
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 58fbdabf87216f692451b9aababc9966c67ae44d..937f053e320f6a7c56d1965b2e68b98a44aac7a3 100644 (file)
@@ -46,16 +46,15 @@ pub trait TraitVisibility { }
 
 
 // Change trait unsafety ----------------------------------------------------------
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitUnsafety { }
+#[cfg(cfail1)]
+trait TraitUnsafety { }
 
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// unsafe trait TraitUnsafety { }
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+unsafe trait TraitUnsafety { }
 
 
 
@@ -178,20 +177,19 @@ trait TraitChangeMethodParameterType {
 
 
 // Change type of method parameter (&i32 => &mut i32) -----------------------------
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitChangeMethodParameterTypeRef {
-//     fn method(a: &i32);
-// }
+#[cfg(cfail1)]
+trait TraitChangeMethodParameterTypeRef {
+    fn method(a: &i32);
+}
 
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// trait TraitChangeMethodParameterTypeRef {
-//     fn method(a: &mut i32);
-// }
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+trait TraitChangeMethodParameterTypeRef {
+    fn method(a: &mut i32);
+}
 
 
 
@@ -249,35 +247,35 @@ trait TraitChangeOrderOfMethods {
 
 
 // Change mode of self parameter --------------------------------------------------
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitChangeModeSelfRefToMut {
-//     fn method(&self);
-// }
-
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// trait TraitChangeModeSelfRefToMut {
-//     fn method(&mut self);
-// }
-
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitChangeModeSelfOwnToMut {
-//     fn method(self);
-// }
-
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// trait TraitChangeModeSelfOwnToMut {
-//     fn method(mut self);
-// }
+#[cfg(cfail1)]
+trait TraitChangeModeSelfRefToMut {
+    fn method(&self);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+trait TraitChangeModeSelfRefToMut {
+    fn method(&mut self);
+}
+
+
+
+#[cfg(cfail1)]
+trait TraitChangeModeSelfOwnToMut {
+    fn method(self);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+trait TraitChangeModeSelfOwnToMut {
+    fn method(mut self);
+}
 
 
 
@@ -298,56 +296,53 @@ trait TraitChangeModeSelfOwnToRef {
 
 
 // Add unsafe modifier to method --------------------------------------------------
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitAddUnsafeModifier {
-//     fn method();
-// }
+#[cfg(cfail1)]
+trait TraitAddUnsafeModifier {
+    fn method();
+}
 
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// trait TraitAddUnsafeModifier {
-//     unsafe fn method();
-// }
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+trait TraitAddUnsafeModifier {
+    unsafe fn method();
+}
 
 
 
 // Add extern modifier to method --------------------------------------------------
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitAddExternModifier {
-//     fn method();
-// }
+#[cfg(cfail1)]
+trait TraitAddExternModifier {
+    fn method();
+}
 
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// trait TraitAddExternModifier {
-//     extern fn method();
-// }
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+trait TraitAddExternModifier {
+    extern fn method();
+}
 
 
 
 // Change extern "C" to extern "rust-intrinsic" -----------------------------------
-// FIXME: this should work but doesn't yet.
-// #[cfg(cfail1)]
-// trait TraitChangeExternCToRustIntrinsic {
-//     extern "C" fn method();
-// }
+#[cfg(cfail1)]
+trait TraitChangeExternCToRustIntrinsic {
+    extern "C" fn method();
+}
 
-// #[cfg(not(cfail1))]
-// #[rustc_dirty(label="Hir", cfg="cfail2")]
-// #[rustc_clean(label="Hir", cfg="cfail3")]
-// #[rustc_metadata_dirty(cfg="cfail2")]
-// #[rustc_metadata_clean(cfg="cfail3")]
-// trait TraitChangeExternCToRustIntrinsic {
-//     extern "rust-intrinsic" fn method();
-// }
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+trait TraitChangeExternCToRustIntrinsic {
+    extern "rust-intrinsic" fn method();
+}
 
 
 
@@ -1118,4 +1113,3 @@ trait TraitChangeTraitBoundWhere<T> where T: Bound {
         fn method(a: T);
     }
 }
-
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;
diff --git a/src/test/run-pass/issue-pr29383.rs b/src/test/run-pass/issue-pr29383.rs
deleted file mode 100644 (file)
index defb2c1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(match_of_unit_variant_via_paren_dotdot)]
-
-enum E {
-    A,
-    B,
-}
-
-fn main() {
-    match None {
-        None => {}
-        Some(E::A(..)) => {}
-        Some(E::B(..)) => {}
-    }
-}
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;
diff --git a/src/test/rustdoc/line-breaks.rs b/src/test/rustdoc/line-breaks.rs
new file mode 100644 (file)
index 0000000..cc608a2
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+#![crate_name = "foo"]
+
+//@count foo/fn.function_with_a_really_long_name.html //pre/br 2
+pub fn function_with_a_really_long_name(parameter_one: i32,
+                                        parameter_two: i32)
+                                        -> Option<i32> {
+    Some(parameter_one + parameter_two)
+}
+
+//@count foo/fn.short_name.html //pre/br 0
+pub fn short_name(param: i32) -> i32 { param + 1 }
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;