]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #48517 - penpalperson:master, r=Mark-Simulacrum
authorkennytm <kennytm@gmail.com>
Sun, 25 Feb 2018 07:54:54 +0000 (15:54 +0800)
committerkennytm <kennytm@gmail.com>
Sun, 25 Feb 2018 13:30:51 +0000 (21:30 +0800)
Added error-format flag to x.py.

Fixes #48475

r? @Mark-Simulacrum

189 files changed:
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/native.rs
src/doc/book
src/doc/unstable-book/src/library-features/entry-and-modify.md [deleted file]
src/liballoc/boxed.rs
src/liballoc/btree/map.rs
src/libcore/iter/iterator.rs
src/libcore/iter/mod.rs
src/libcore/lib.rs
src/libcore/tests/iter.rs
src/libcore/tests/lib.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/prev.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/anon_types/mod.rs
src/librustc/mir/mono.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/ty/instance.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/util.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/powerpc_unknown_netbsd.rs [new file with mode: 0644]
src/librustc_back/target/sparc_unknown_linux_gnu.rs [new file with mode: 0644]
src/librustc_const_eval/_match.rs
src/librustc_data_structures/bitslice.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_driver/driver.rs
src/librustc_driver/test.rs
src/librustc_lint/lib.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/generator.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/diagnostics.rs
src/librustc_passes/lib.rs
src/librustc_passes/static_recursion.rs [deleted file]
src/librustc_resolve/lib.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/span_utils.rs
src/librustc_trans/abi.rs
src/librustc_trans/back/command.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/base.rs
src/librustc_trans/cabi_mips64.rs
src/librustc_trans/cabi_x86_64.rs
src/librustc_trans/callee.rs
src/librustc_trans/common.rs
src/librustc_trans/consts.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/debuginfo/namespace.rs
src/librustc_trans/debuginfo/utils.rs
src/librustc_trans/llvm_util.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/libstd/collections/hash/map.rs
src/libstd/lib.rs
src/libstd/path.rs
src/libstd/process.rs
src/libstd/rt.rs
src/libstd/sync/condvar.rs
src/libstd/termination.rs [deleted file]
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/test.rs
src/libsyntax/visit.rs
src/libtest/lib.rs
src/rt/rust_test_helpers.c [deleted file]
src/test/auxiliary/rust_test_helpers.c [new file with mode: 0644]
src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs
src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs
src/test/compile-fail/const-recursive.rs [deleted file]
src/test/compile-fail/const-size_of-cycle.rs
src/test/compile-fail/cycle-projection-based-on-where-clause.rs
src/test/compile-fail/cycle-trait-default-type-trait.rs
src/test/compile-fail/cycle-trait-supertrait-direct.rs
src/test/compile-fail/dyn-trait-compatibility.rs
src/test/compile-fail/feature-gate-nested_impl_trait.rs [deleted file]
src/test/compile-fail/impl-trait/where-allowed.rs
src/test/compile-fail/infinite-vec-type-recursion.rs
src/test/compile-fail/issue-12997-2.rs
src/test/compile-fail/issue-17252.rs
src/test/compile-fail/issue-17718-recursive.rs [deleted file]
src/test/compile-fail/issue-20772.rs
src/test/compile-fail/issue-20825.rs
src/test/compile-fail/issue-21177.rs
src/test/compile-fail/issue-22673.rs
src/test/compile-fail/issue-26548.rs
src/test/compile-fail/issue-34373.rs
src/test/compile-fail/issue-44415.rs
src/test/compile-fail/issue-48131.rs [new file with mode: 0644]
src/test/compile-fail/macro-at-most-once-rep-ambig.rs [deleted file]
src/test/compile-fail/resolve-self-in-impl.rs
src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs [new file with mode: 0644]
src/test/run-make/atomic-lock-free/Makefile
src/test/run-pass/borrowck/two-phase-bin-ops.rs [new file with mode: 0644]
src/test/run-pass/dyn-trait.rs
src/test/run-pass/impl-trait/lifetimes.rs
src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs [new file with mode: 0644]
src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs [new file with mode: 0644]
src/test/run-pass/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs
src/test/run-pass/rfc-2126-extern-absolute-paths/extern.rs
src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs [new file with mode: 0644]
src/test/run-pass/rfc-2175-or-if-while-let/basic.rs [new file with mode: 0644]
src/test/run-pass/termination-trait-for-result-box-error_ok.rs [deleted file]
src/test/rustdoc/auxiliary/issue-48414.rs [new file with mode: 0644]
src/test/rustdoc/issue-48414.rs [new file with mode: 0644]
src/test/ui/cycle-trait-supertrait-indirect.rs
src/test/ui/cycle-trait-supertrait-indirect.stderr
src/test/ui/error-codes/E0657.rs
src/test/ui/error-codes/E0657.stderr
src/test/ui/feature-gate-if_while_or_patterns.rs [new file with mode: 0644]
src/test/ui/feature-gate-if_while_or_patterns.stderr [new file with mode: 0644]
src/test/ui/impl-trait/auto-trait-leak.rs
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl_trait_projections.rs [new file with mode: 0644]
src/test/ui/impl_trait_projections.stderr [new file with mode: 0644]
src/test/ui/issue-12511.rs
src/test/ui/issue-12511.stderr
src/test/ui/issue-23302-1.rs [new file with mode: 0644]
src/test/ui/issue-23302-1.stderr [new file with mode: 0644]
src/test/ui/issue-23302-2.rs [new file with mode: 0644]
src/test/ui/issue-23302-2.stderr [new file with mode: 0644]
src/test/ui/issue-23302-3.rs [new file with mode: 0644]
src/test/ui/issue-23302-3.stderr [new file with mode: 0644]
src/test/ui/issue-23302.rs [deleted file]
src/test/ui/issue-23302.stderr [deleted file]
src/test/ui/issue-36163.rs
src/test/ui/issue-36163.stderr
src/test/ui/issue-45157.rs [new file with mode: 0644]
src/test/ui/issue-45157.stderr [new file with mode: 0644]
src/test/ui/issue-47706.rs
src/test/ui/issue-47706.stderr
src/test/ui/lint/lint-group-nonstandard-style.rs [new file with mode: 0644]
src/test/ui/lint/lint-group-nonstandard-style.stderr [new file with mode: 0644]
src/test/ui/macros/macro-at-most-once-rep-ambig.rs [new file with mode: 0644]
src/test/ui/macros/macro-at-most-once-rep-ambig.stderr [new file with mode: 0644]
src/test/ui/nested_impl_trait.rs [new file with mode: 0644]
src/test/ui/nested_impl_trait.stderr [new file with mode: 0644]
src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
src/test/ui/resolve/issue-23305.rs
src/test/ui/resolve/issue-23305.stderr
src/test/ui/span/issue-39018.rs
src/test/ui/span/issue-39018.stderr
src/test/ui/unsafe-block-without-braces.rs [new file with mode: 0644]
src/test/ui/unsafe-block-without-braces.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs

index 603a97ddfd412ad23506bc932be645bc5ac65e8b..5966bb65df9c87ebef767ac64d453f185b9ccd98 100644 (file)
@@ -294,7 +294,7 @@ def default_build_triple():
             raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
         # only the n64 ABI is supported, indicate it
         ostype += 'abi64'
-    elif cputype == 'sparcv9' or cputype == 'sparc64':
+    elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64':
         pass
     else:
         err = "unknown cpu type: {}".format(cputype)
index 343d30922fded96028c23c49d9795d849a1c1679..b5946b44e05ef6316ab5881d7250f1e923548b61 100644 (file)
@@ -444,10 +444,11 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
             fn run(self, builder: &Builder) -> Interned<PathBuf> {
                 let compiler = self.compiler;
-                let lib = if compiler.stage >= 1 && builder.build.config.libdir.is_some() {
-                    builder.build.config.libdir.clone().unwrap()
+                let config = &builder.build.config;
+                let lib = if compiler.stage >= 1 && config.libdir_relative().is_some() {
+                    builder.build.config.libdir_relative().unwrap()
                 } else {
-                    PathBuf::from("lib")
+                    Path::new("lib")
                 };
                 let sysroot = builder.sysroot(self.compiler).join(lib)
                     .join("rustlib").join(self.target).join("lib");
index 2dcc0e0e7cd9f0110a583a93ad1450cb7ca3d08a..c85b04ddc02458fb82a63c655ff5db6ebd80ed10 100644 (file)
@@ -516,8 +516,7 @@ fn rustc_cargo_env(build: &Build, cargo: &mut Command) {
          .env("CFG_VERSION", build.rust_version())
          .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
 
-    let libdir_relative =
-        build.config.libdir.clone().unwrap_or(PathBuf::from("lib"));
+    let libdir_relative = build.config.libdir_relative().unwrap_or(Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
 
     // If we're not building a compiler with debugging information then remove
index 70a873043ad326ea15db2aa064ef9a921dcd7e99..6bc20181a0330a5a51eef0ae83defe310cb87e39 100644 (file)
@@ -17,7 +17,7 @@
 use std::env;
 use std::fs::File;
 use std::io::prelude::*;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process;
 use std::cmp;
 
@@ -566,6 +566,17 @@ pub fn parse(args: &[String]) -> Config {
         config
     }
 
+    /// Try to find the relative path of `libdir`.
+    pub fn libdir_relative(&self) -> Option<&Path> {
+        let libdir = self.libdir.as_ref()?;
+        if libdir.is_relative() {
+            Some(libdir)
+        } else {
+            // Try to make it relative to the prefix.
+            libdir.strip_prefix(self.prefix.as_ref()?).ok()
+        }
+    }
+
     pub fn verbose(&self) -> bool {
         self.verbose > 0
     }
index 29cd23bdbb1978398043dd06b45a9d94502b26f1..15dd7fabfa58b5c7303d4170f201f43a3cbdf1ea 100644 (file)
@@ -313,7 +313,7 @@ impl Step for TestHelpers {
     type Output = ();
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        run.path("src/rt/rust_test_helpers.c")
+        run.path("src/test/auxiliary/rust_test_helpers.c")
     }
 
     fn make_run(run: RunConfig) {
@@ -326,7 +326,7 @@ fn run(self, builder: &Builder) {
         let build = builder.build;
         let target = self.target;
         let dst = build.test_helpers_out(target);
-        let src = build.src.join("src/rt/rust_test_helpers.c");
+        let src = build.src.join("src/test/auxiliary/rust_test_helpers.c");
         if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
             return
         }
@@ -353,7 +353,7 @@ fn run(self, builder: &Builder) {
            .opt_level(0)
            .warnings(false)
            .debug(false)
-           .file(build.src.join("src/rt/rust_test_helpers.c"))
+           .file(build.src.join("src/test/auxiliary/rust_test_helpers.c"))
            .compile("rust_test_helpers");
     }
 }
@@ -480,9 +480,11 @@ fn run(self, builder: &Builder) {
             "mips64el-unknown-linux-gnuabi64" => "linux64-mips64",
             "mipsel-unknown-linux-gnu" => "linux-mips32",
             "powerpc-unknown-linux-gnu" => "linux-ppc",
+            "powerpc-unknown-netbsd" => "BSD-generic32",
             "powerpc64-unknown-linux-gnu" => "linux-ppc64",
             "powerpc64le-unknown-linux-gnu" => "linux-ppc64le",
             "s390x-unknown-linux-gnu" => "linux64-s390x",
+            "sparc-unknown-linux-gnu" => "linux-sparcv9",
             "sparc64-unknown-linux-gnu" => "linux64-sparcv9",
             "sparc64-unknown-netbsd" => "BSD-sparc64",
             "x86_64-apple-darwin" => "darwin64-x86_64-cc",
@@ -490,6 +492,7 @@ fn run(self, builder: &Builder) {
             "x86_64-unknown-freebsd" => "BSD-x86_64",
             "x86_64-unknown-dragonfly" => "BSD-x86_64",
             "x86_64-unknown-linux-gnu" => "linux-x86_64",
+            "x86_64-unknown-linux-gnux32" => "linux-x32",
             "x86_64-unknown-linux-musl" => "linux-x86_64",
             "x86_64-unknown-netbsd" => "BSD-x86_64",
             _ => panic!("don't know how to configure OpenSSL for {}", target),
index ec5660820dea91df470dab0b9eb26ef798f20889..98921e9de849acdaeaed08cfad6758bb89769b7d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ec5660820dea91df470dab0b9eb26ef798f20889
+Subproject commit 98921e9de849acdaeaed08cfad6758bb89769b7d
diff --git a/src/doc/unstable-book/src/library-features/entry-and-modify.md b/src/doc/unstable-book/src/library-features/entry-and-modify.md
deleted file mode 100644 (file)
index 1280c71..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-# `entry_and_modify`
-
-The tracking issue for this feature is: [#44733]
-
-[#44733]: https://github.com/rust-lang/rust/issues/44733
-
-------------------------
-
-This introduces a new method for the Entry API of maps
-(`std::collections::HashMap` and `std::collections::BTreeMap`), so that
-occupied entries can be modified before any potential inserts into the
-map.
-
-For example:
-
-```rust
-#![feature(entry_and_modify)]
-# fn main() {
-use std::collections::HashMap;
-
-struct Foo {
-    new: bool,
-}
-
-let mut map: HashMap<&str, Foo> = HashMap::new();
-
-map.entry("quux")
-   .and_modify(|e| e.new = false)
-   .or_insert(Foo { new: true });
-# }
-```
-
-This is not possible with the stable API alone since inserting a default
-_before_ modifying the `new` field would mean we would lose the default state:
-
-```rust
-# fn main() {
-use std::collections::HashMap;
-
-struct Foo {
-    new: bool,
-}
-
-let mut map: HashMap<&str, Foo> = HashMap::new();
-
-map.entry("quux").or_insert(Foo { new: true }).new = false;
-# }
-```
-
-In the above code the `new` field will never be `true`, even though we only
-intended to update that field to `false` for previously extant entries.
-
-To achieve the same effect as `and_modify` we would have to manually match
-against the `Occupied` and `Vacant` variants of the `Entry` enum, which is
-a little less user-friendly, and much more verbose:
-
-```rust
-# fn main() {
-use std::collections::HashMap;
-use std::collections::hash_map::Entry;
-
-struct Foo {
-    new: bool,
-}
-
-let mut map: HashMap<&str, Foo> = HashMap::new();
-
-match map.entry("quux") {
-    Entry::Occupied(entry) => {
-        entry.into_mut().new = false;
-    },
-    Entry::Vacant(entry) => {
-        entry.insert(Foo { new: true });
-    },
-};
-# }
-```
index cdaad973a7123a1aa4830bb896397af5629d3572..75a59de337cef3e01e49eb5a7cb92c0645fe136a 100644 (file)
@@ -359,8 +359,6 @@ pub fn into_unique(b: Box<T>) -> Unique<T> {
     /// Simple usage:
     ///
     /// ```
-    /// #![feature(box_leak)]
-    ///
     /// fn main() {
     ///     let x = Box::new(41);
     ///     let static_ref: &'static mut usize = Box::leak(x);
@@ -372,8 +370,6 @@ pub fn into_unique(b: Box<T>) -> Unique<T> {
     /// Unsized data:
     ///
     /// ```
-    /// #![feature(box_leak)]
-    ///
     /// fn main() {
     ///     let x = vec![1, 2, 3].into_boxed_slice();
     ///     let static_ref = Box::leak(x);
@@ -381,8 +377,7 @@ pub fn into_unique(b: Box<T>) -> Unique<T> {
     ///     assert_eq!(*static_ref, [4, 2, 3]);
     /// }
     /// ```
-    #[unstable(feature = "box_leak", reason = "needs an FCP to stabilize",
-               issue = "46179")]
+    #[stable(feature = "box_leak", since = "1.26.0")]
     #[inline]
     pub fn leak<'a>(b: Box<T>) -> &'a mut T
     where
index b320bed54320a11da4581742c50f7e51e04a794d..618ef81fdd98198c71268a8b08eb257f3ca2feb6 100644 (file)
@@ -2114,7 +2114,6 @@ pub fn key(&self) -> &K {
     /// # Examples
     ///
     /// ```
-    /// #![feature(entry_and_modify)]
     /// use std::collections::BTreeMap;
     ///
     /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
@@ -2129,7 +2128,7 @@ pub fn key(&self) -> &K {
     ///    .or_insert(42);
     /// assert_eq!(map["poneyland"], 43);
     /// ```
-    #[unstable(feature = "entry_and_modify", issue = "44733")]
+    #[stable(feature = "entry_and_modify", since = "1.26.0")]
     pub fn and_modify<F>(self, mut f: F) -> Self
         where F: FnMut(&mut V)
     {
index 877793cb3c57cfd9b1c8a93027cbb5fb2a574191..9d8a71250f88ad508c561d08d05d9e45ea1079e5 100644 (file)
@@ -12,7 +12,8 @@
 use ops::Try;
 
 use super::{AlwaysOk, LoopState};
-use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse};
+use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, Fuse};
+use super::{Flatten, FlatMap, flatten_compat};
 use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
 use super::{Zip, Sum, Product};
 use super::{ChainState, FromIterator, ZipImpl};
@@ -997,11 +998,15 @@ fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
     /// an extra layer of indirection. `flat_map()` will remove this extra layer
     /// on its own.
     ///
+    /// You can think of [`flat_map(f)`][flat_map] as the semantic equivalent
+    /// of [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`.
+    ///
     /// Another way of thinking about `flat_map()`: [`map`]'s closure returns
     /// one item for each element, and `flat_map()`'s closure returns an
     /// iterator for each element.
     ///
     /// [`map`]: #method.map
+    /// [`flatten`]: #method.flatten
     ///
     /// # Examples
     ///
@@ -1021,7 +1026,79 @@ fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
     fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
         where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U,
     {
-        FlatMap{iter: self, f: f, frontiter: None, backiter: None }
+        FlatMap { inner: flatten_compat(self.map(f)) }
+    }
+
+    /// Creates an iterator that flattens nested structure.
+    ///
+    /// This is useful when you have an iterator of iterators or an iterator of
+    /// things that can be turned into iterators and you want to remove one
+    /// level of indirection.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iterator_flatten)]
+    ///
+    /// let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
+    /// let flattened = data.into_iter().flatten().collect::<Vec<u8>>();
+    /// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);
+    /// ```
+    ///
+    /// Mapping and then flattening:
+    ///
+    /// ```
+    /// #![feature(iterator_flatten)]
+    ///
+    /// let words = ["alpha", "beta", "gamma"];
+    ///
+    /// // chars() returns an iterator
+    /// let merged: String = words.iter()
+    ///                           .map(|s| s.chars())
+    ///                           .flatten()
+    ///                           .collect();
+    /// assert_eq!(merged, "alphabetagamma");
+    /// ```
+    ///
+    /// You can also rewrite this in terms of [`flat_map()`] which is preferable
+    /// in this case since that conveys intent clearer:
+    ///
+    /// ```
+    /// let words = ["alpha", "beta", "gamma"];
+    ///
+    /// // chars() returns an iterator
+    /// let merged: String = words.iter()
+    ///                           .flat_map(|s| s.chars())
+    ///                           .collect();
+    /// assert_eq!(merged, "alphabetagamma");
+    /// ```
+    ///
+    /// Flattening once only removes one level of nesting:
+    ///
+    /// ```
+    /// #![feature(iterator_flatten)]
+    ///
+    /// let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
+    ///
+    /// let d2 = d3.iter().flatten().collect::<Vec<_>>();
+    /// assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]);
+    ///
+    /// let d1 = d3.iter().flatten().flatten().collect::<Vec<_>>();
+    /// assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]);
+    /// ```
+    ///
+    /// Here we see that `flatten()` does not perform a "deep" flatten.
+    /// Instead, only one level of nesting is removed. That is, if you
+    /// `flatten()` a three-dimensional array the result will be
+    /// two-dimensional and not one-dimensional. To get a one-dimensional
+    /// structure, you have to `flatten()` again.
+    #[inline]
+    #[unstable(feature = "iterator_flatten", issue = "48213")]
+    fn flatten(self) -> Flatten<Self>
+    where Self: Sized, Self::Item: IntoIterator {
+        Flatten { inner: flatten_compat(self) }
     }
 
     /// Creates an iterator which ends after the first [`None`].
index 1a2da83429af9ef160021d984ef5787cade8ae9f..623cad754dd7274221efea7a9a7a22c4a9b314ba 100644 (file)
@@ -2410,12 +2410,15 @@ fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
 pub struct FlatMap<I, U: IntoIterator, F> {
-    iter: I,
-    f: F,
-    frontiter: Option<U::IntoIter>,
-    backiter: Option<U::IntoIter>,
+    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Clone, U: Clone + IntoIterator, F: Clone> Clone for FlatMap<I, U, F>
+    where <U as IntoIterator>::IntoIter: Clone
+{
+    fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } }
 }
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
@@ -2423,11 +2426,7 @@ impl<I: fmt::Debug, U: IntoIterator, F> fmt::Debug for FlatMap<I, U, F>
     where U::IntoIter: fmt::Debug
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("FlatMap")
-            .field("iter", &self.iter)
-            .field("frontiter", &self.frontiter)
-            .field("backiter", &self.backiter)
-            .finish()
+        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
     }
 }
 
@@ -2437,17 +2436,173 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
 {
     type Item = U::Item;
 
+    #[inline]
+    fn next(&mut self) -> Option<U::Item> { self.inner.next() }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
+        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+    {
+        self.inner.try_fold(init, fold)
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.inner.fold(init, fold)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
+    where F: FnMut(I::Item) -> U,
+          U: IntoIterator,
+          U::IntoIter: DoubleEndedIterator
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
+        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+    {
+        self.inner.try_rfold(init, fold)
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.inner.rfold(init, fold)
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<I, U, F> FusedIterator for FlatMap<I, U, F>
+    where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
+
+/// An iterator that flattens one level of nesting in an iterator of things
+/// that can be turned into iterators.
+///
+/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`flatten`]: trait.Iterator.html#method.flatten
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[unstable(feature = "iterator_flatten", issue = "48213")]
+pub struct Flatten<I: Iterator>
+where I::Item: IntoIterator {
+    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
+}
+
+#[unstable(feature = "iterator_flatten", issue = "48213")]
+impl<I, U> fmt::Debug for Flatten<I>
+    where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Flatten").field("inner", &self.inner).finish()
+    }
+}
+
+#[unstable(feature = "iterator_flatten", issue = "48213")]
+impl<I, U> Clone for Flatten<I>
+    where I: Iterator + Clone, U: Iterator + Clone,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
+{
+    fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
+}
+
+#[unstable(feature = "iterator_flatten", issue = "48213")]
+impl<I, U> Iterator for Flatten<I>
+    where I: Iterator, U: Iterator,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item>
+{
+    type Item = U::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<U::Item> { self.inner.next() }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
+        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+    {
+        self.inner.try_fold(init, fold)
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.inner.fold(init, fold)
+    }
+}
+
+#[unstable(feature = "iterator_flatten", issue = "48213")]
+impl<I, U> DoubleEndedIterator for Flatten<I>
+    where I: DoubleEndedIterator, U: DoubleEndedIterator,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item>
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
+        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+    {
+        self.inner.try_rfold(init, fold)
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.inner.rfold(init, fold)
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<I, U> FusedIterator for Flatten<I>
+    where I: FusedIterator, U: Iterator,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item> {}
+
+/// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
+fn flatten_compat<I, U>(iter: I) -> FlattenCompat<I, U> {
+    FlattenCompat { iter, frontiter: None, backiter: None }
+}
+
+/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
+/// this type.
+#[derive(Clone, Debug)]
+struct FlattenCompat<I, U> {
+    iter: I,
+    frontiter: Option<U>,
+    backiter: Option<U>,
+}
+
+impl<I, U> Iterator for FlattenCompat<I, U>
+    where I: Iterator, U: Iterator,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item>
+{
+    type Item = U::Item;
+
     #[inline]
     fn next(&mut self) -> Option<U::Item> {
         loop {
             if let Some(ref mut inner) = self.frontiter {
-                if let Some(x) = inner.by_ref().next() {
-                    return Some(x)
-                }
+                if let elt@Some(_) = inner.next() { return elt }
             }
-            match self.iter.next().map(&mut self.f) {
+            match self.iter.next() {
                 None => return self.backiter.as_mut().and_then(|it| it.next()),
-                next => self.frontiter = next.map(IntoIterator::into_iter),
+                Some(inner) => self.frontiter = Some(inner.into_iter()),
             }
         }
     }
@@ -2473,10 +2628,9 @@ fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
         self.frontiter = None;
 
         {
-            let f = &mut self.f;
             let frontiter = &mut self.frontiter;
             init = self.iter.try_fold(init, |acc, x| {
-                let mut mid = f(x).into_iter();
+                let mut mid = x.into_iter();
                 let r = mid.try_fold(acc, &mut fold);
                 *frontiter = Some(mid);
                 r
@@ -2497,27 +2651,23 @@ fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
         self.frontiter.into_iter()
-            .chain(self.iter.map(self.f).map(U::into_iter))
+            .chain(self.iter.map(IntoIterator::into_iter))
             .chain(self.backiter)
             .fold(init, |acc, iter| iter.fold(acc, &mut fold))
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> where
-    F: FnMut(I::Item) -> U,
-    U: IntoIterator,
-    U::IntoIter: DoubleEndedIterator
+impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
+    where I: DoubleEndedIterator, U: DoubleEndedIterator,
+          I::Item: IntoIterator<IntoIter = U, Item = U::Item>
 {
     #[inline]
     fn next_back(&mut self) -> Option<U::Item> {
         loop {
             if let Some(ref mut inner) = self.backiter {
-                if let Some(y) = inner.next_back() {
-                    return Some(y)
-                }
+                if let elt@Some(_) = inner.next_back() { return elt }
             }
-            match self.iter.next_back().map(&mut self.f) {
+            match self.iter.next_back() {
                 None => return self.frontiter.as_mut().and_then(|it| it.next_back()),
                 next => self.backiter = next.map(IntoIterator::into_iter),
             }
@@ -2534,10 +2684,9 @@ fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
         self.backiter = None;
 
         {
-            let f = &mut self.f;
             let backiter = &mut self.backiter;
             init = self.iter.try_rfold(init, |acc, x| {
-                let mut mid = f(x).into_iter();
+                let mut mid = x.into_iter();
                 let r = mid.try_rfold(acc, &mut fold);
                 *backiter = Some(mid);
                 r
@@ -2558,16 +2707,12 @@ fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
         where Fold: FnMut(Acc, Self::Item) -> Acc,
     {
         self.frontiter.into_iter()
-            .chain(self.iter.map(self.f).map(U::into_iter))
+            .chain(self.iter.map(IntoIterator::into_iter))
             .chain(self.backiter)
             .rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
-impl<I, U, F> FusedIterator for FlatMap<I, U, F>
-    where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
-
 /// An iterator that yields `None` forever after the underlying iterator
 /// yields `None` once.
 ///
index d2162d307e038e260500d217cc54a9ef541399ff..3dd30ee1c69e235a5ba2ac9685cf4751d0825fa3 100644 (file)
@@ -93,6 +93,7 @@
 #![feature(doc_spotlight)]
 #![feature(rustc_const_unstable)]
 #![feature(iterator_repeat_with)]
+#![feature(iterator_flatten)]
 
 #[prelude_import]
 #[allow(unused)]
index f91c919d7447d6111d258a79532d6ef8fd8c29e1..edd75f7795ed7cf18ec33575b142feff40070367 100644 (file)
@@ -874,6 +874,44 @@ fn test_iterator_flat_map_fold() {
     assert_eq!(i, 0);
 }
 
+#[test]
+fn test_iterator_flatten() {
+    let xs = [0, 3, 6];
+    let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    let it = xs.iter().map(|&x| (x..).step_by(1).take(3)).flatten();
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+/// Test `Flatten::fold` with items already picked off the front and back,
+/// to make sure all parts of the `Flatten` are folded correctly.
+#[test]
+fn test_iterator_flatten_fold() {
+    let xs = [0, 3, 6];
+    let ys = [1, 2, 3, 4, 5, 6, 7];
+    let mut it = xs.iter().map(|&x| x..x+3).flatten();
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next_back(), Some(8));
+    let i = it.fold(0, |i, x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+
+    let mut it = xs.iter().map(|&x| x..x+3).flatten();
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next_back(), Some(8));
+    let i = it.rfold(ys.len(), |i, x| {
+        assert_eq!(x, ys[i - 1]);
+        i - 1
+    });
+    assert_eq!(i, 0);
+}
+
 #[test]
 fn test_inspect() {
     let xs = [1, 2, 3, 4];
@@ -1287,6 +1325,23 @@ fn test_double_ended_flat_map() {
     assert_eq!(it.next_back(), None);
 }
 
+#[test]
+fn test_double_ended_flatten() {
+    let u = [0,1];
+    let v = [5,6,7,8];
+    let mut it = u.iter().map(|x| &v[*x..v.len()]).flatten();
+    assert_eq!(it.next_back().unwrap(), &8);
+    assert_eq!(it.next().unwrap(),      &5);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back().unwrap(), &6);
+    assert_eq!(it.next_back().unwrap(), &8);
+    assert_eq!(it.next().unwrap(),      &6);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back(), None);
+    assert_eq!(it.next(),      None);
+    assert_eq!(it.next_back(), None);
+}
+
 #[test]
 fn test_double_ended_range() {
     assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
@@ -1978,3 +2033,54 @@ fn test_flat_map_try_folds() {
     assert_eq!(iter.try_rfold(0, i8::checked_add), None);
     assert_eq!(iter.next_back(), Some(35));
 }
+
+#[test]
+fn test_flatten_try_folds() {
+    let f = &|acc, x| i32::checked_add(acc*2/3, x);
+    let mr = &|x| (5*x)..(5*x + 5);
+    assert_eq!((0..10).map(mr).flatten().try_fold(7, f), (0..50).try_fold(7, f));
+    assert_eq!((0..10).map(mr).flatten().try_rfold(7, f), (0..50).try_rfold(7, f));
+    let mut iter = (0..10).map(mr).flatten();
+    iter.next(); iter.next_back(); // have front and back iters in progress
+    assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f));
+
+    let mut iter = (0..10).map(|x| (4*x)..(4*x + 4)).flatten();
+    assert_eq!(iter.try_fold(0, i8::checked_add), None);
+    assert_eq!(iter.next(), Some(17));
+    assert_eq!(iter.try_rfold(0, i8::checked_add), None);
+    assert_eq!(iter.next_back(), Some(35));
+}
+
+#[test]
+fn test_functor_laws() {
+    // identity:
+    fn identity<T>(x: T) -> T { x }
+    assert_eq!((0..10).map(identity).sum::<usize>(), (0..10).sum());
+
+    // composition:
+    fn f(x: usize) -> usize { x + 3 }
+    fn g(x: usize) -> usize { x * 2 }
+    fn h(x: usize) -> usize { g(f(x)) }
+    assert_eq!((0..10).map(f).map(g).sum::<usize>(), (0..10).map(h).sum());
+}
+
+#[test]
+fn test_monad_laws_left_identity() {
+    fn f(x: usize) -> impl Iterator<Item = usize> {
+        (0..10).map(move |y| x * y)
+    }
+    assert_eq!(once(42).flat_map(f.clone()).sum::<usize>(), f(42).sum());
+}
+
+#[test]
+fn test_monad_laws_right_identity() {
+    assert_eq!((0..10).flat_map(|x| once(x)).sum::<usize>(), (0..10).sum());
+}
+
+#[test]
+fn test_monad_laws_associativity() {
+    fn f(x: usize) -> impl Iterator<Item = usize> { 0..x }
+    fn g(x: usize) -> impl Iterator<Item = usize> { (0..x).rev() }
+    assert_eq!((0..10).flat_map(f).flat_map(g).sum::<usize>(),
+                (0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>());
+}
index 3e901a9d442ce29bc8460e2c582fa417c859b93e..7954d52f6b1e368f64b4a309fe08b4baea5f6d15 100644 (file)
@@ -25,6 +25,8 @@
 #![feature(inclusive_range)]
 #![feature(inclusive_range_syntax)]
 #![feature(iterator_try_fold)]
+#![feature(iterator_flatten)]
+#![feature(conservative_impl_trait)]
 #![feature(iter_rfind)]
 #![feature(iter_rfold)]
 #![feature(iterator_repeat_with)]
index 4034055d041558f2360e5227c9fdbe3a32451aa1..aa678ba788a5bb9e8d3220d13a4f039638c99beb 100644 (file)
@@ -625,7 +625,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [eval_always] CollectAndPartitionTranslationItems,
     [] ExportName(DefId),
     [] ContainsExternIndicator(DefId),
-    [] IsTranslatedFunction(DefId),
+    [] IsTranslatedItem(DefId),
     [] CodegenUnit(InternedString),
     [] CompileCodegenUnit(InternedString),
     [input] OutputFilenames,
index 55ec8adb5fbf3131ad02837a5da7cdf0b92ed1d0..b77431e806a6d0ef48221b54dee73c4b00ec2397 100644 (file)
@@ -74,7 +74,7 @@ struct DepGraphData {
     /// nodes and edges as well as all fingerprints of nodes that have them.
     previous: PreviousDepGraph,
 
-    colors: RefCell<FxHashMap<DepNode, DepNodeColor>>,
+    colors: RefCell<DepNodeColorMap>,
 
     /// When we load, there may be `.o` files, cached mir, or other such
     /// things available to us. If we find that they are not dirty, we
@@ -97,8 +97,10 @@ pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
         // Pre-allocate the fingerprints array. We over-allocate a little so
         // that we hopefully don't have to re-allocate during this compilation
         // session.
+        let prev_graph_node_count = prev_graph.node_count();
+
         let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO,
-                                                 (prev_graph.node_count() * 115) / 100);
+                                                 (prev_graph_node_count * 115) / 100);
         DepGraph {
             data: Some(Rc::new(DepGraphData {
                 previous_work_products: RefCell::new(FxHashMap()),
@@ -106,7 +108,7 @@ pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
                 dep_node_debug: RefCell::new(FxHashMap()),
                 current: RefCell::new(CurrentDepGraph::new()),
                 previous: prev_graph,
-                colors: RefCell::new(FxHashMap()),
+                colors: RefCell::new(DepNodeColorMap::new(prev_graph_node_count)),
                 loaded_from_cache: RefCell::new(FxHashMap()),
             })),
             fingerprints: Rc::new(RefCell::new(fingerprints)),
@@ -213,8 +215,6 @@ fn with_task_impl<C, A, R, HCX>(&self,
               R: HashStable<HCX>,
     {
         if let Some(ref data) = self.data {
-            debug_assert!(!data.colors.borrow().contains_key(&key));
-
             push(&data.current, key);
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
@@ -254,19 +254,21 @@ fn with_task_impl<C, A, R, HCX>(&self,
             }
 
             // Determine the color of the new DepNode.
-            {
-                let prev_fingerprint = data.previous.fingerprint_of(&key);
+            if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
+                let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
 
-                let color = if Some(current_fingerprint) == prev_fingerprint {
+                let color = if current_fingerprint == prev_fingerprint {
                     DepNodeColor::Green(dep_node_index)
                 } else {
                     DepNodeColor::Red
                 };
 
-                let old_value = data.colors.borrow_mut().insert(key, color);
-                debug_assert!(old_value.is_none(),
+                let mut colors = data.colors.borrow_mut();
+                debug_assert!(colors.get(prev_index).is_none(),
                               "DepGraph::with_task() - Duplicate DepNodeColor \
                                insertion for {:?}", key);
+
+                colors.insert(prev_index, color);
             }
 
             (result, dep_node_index)
@@ -281,9 +283,11 @@ fn with_task_impl<C, A, R, HCX>(&self,
                 let mut fingerprints = self.fingerprints.borrow_mut();
                 let dep_node_index = DepNodeIndex::new(fingerprints.len());
                 fingerprints.push(fingerprint);
+
                 debug_assert!(fingerprints[dep_node_index] == fingerprint,
                               "DepGraph::with_task() - Assigned fingerprint to \
                                unexpected index for {:?}", key);
+
                 (result, dep_node_index)
             } else {
                 (task(cx, arg), DepNodeIndex::INVALID)
@@ -356,6 +360,15 @@ pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex {
             .unwrap()
     }
 
+    #[inline]
+    pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
+        if let Some(ref data) = self.data {
+            data.current.borrow_mut().node_to_node_index.contains_key(dep_node)
+        } else {
+            false
+        }
+    }
+
     #[inline]
     pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
         match self.fingerprints.borrow().get(dep_node_index) {
@@ -495,7 +508,17 @@ pub fn serialize(&self) -> SerializedDepGraph {
     }
 
     pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
-        self.data.as_ref().and_then(|data| data.colors.borrow().get(dep_node).cloned())
+        if let Some(ref data) = self.data {
+            if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) {
+                return data.colors.borrow().get(prev_index)
+            } else {
+                // This is a node that did not exist in the previous compilation
+                // session, so we consider it to be red.
+                return Some(DepNodeColor::Red)
+            }
+        }
+
+        None
     }
 
     pub fn try_mark_green<'tcx>(&self,
@@ -505,7 +528,6 @@ pub fn try_mark_green<'tcx>(&self,
         debug!("try_mark_green({:?}) - BEGIN", dep_node);
         let data = self.data.as_ref().unwrap();
 
-        debug_assert!(!data.colors.borrow().contains_key(dep_node));
         debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
 
         if dep_node.kind.is_input() {
@@ -535,19 +557,22 @@ pub fn try_mark_green<'tcx>(&self,
             }
         };
 
+        debug_assert!(data.colors.borrow().get(prev_dep_node_index).is_none());
+
         let mut current_deps = Vec::new();
 
         for &dep_dep_node_index in prev_deps {
-            let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index);
+            let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
 
-            let dep_dep_node_color = data.colors.borrow().get(dep_dep_node).cloned();
             match dep_dep_node_color {
                 Some(DepNodeColor::Green(node_index)) => {
                     // This dependency has been marked as green before, we are
                     // still fine and can continue with checking the other
                     // dependencies.
                     debug!("try_mark_green({:?}) --- found dependency {:?} to \
-                            be immediately green", dep_node, dep_dep_node);
+                            be immediately green",
+                            dep_node,
+                            data.previous.index_to_node(dep_dep_node_index));
                     current_deps.push(node_index);
                 }
                 Some(DepNodeColor::Red) => {
@@ -556,10 +581,14 @@ pub fn try_mark_green<'tcx>(&self,
                     // mark the DepNode as green and also don't need to bother
                     // with checking any of the other dependencies.
                     debug!("try_mark_green({:?}) - END - dependency {:?} was \
-                            immediately red", dep_node, dep_dep_node);
+                            immediately red",
+                            dep_node,
+                            data.previous.index_to_node(dep_dep_node_index));
                     return None
                 }
                 None => {
+                    let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index);
+
                     // We don't know the state of this dependency. If it isn't
                     // an input node, let's try to mark it green recursively.
                     if !dep_dep_node.kind.is_input() {
@@ -601,10 +630,8 @@ pub fn try_mark_green<'tcx>(&self,
                     debug!("try_mark_green({:?}) --- trying to force \
                             dependency {:?}", dep_node, dep_dep_node);
                     if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
-                        let dep_dep_node_color = data.colors
-                                                     .borrow()
-                                                     .get(dep_dep_node)
-                                                     .cloned();
+                        let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
+
                         match dep_dep_node_color {
                             Some(DepNodeColor::Green(node_index)) => {
                                 debug!("try_mark_green({:?}) --- managed to \
@@ -681,26 +708,21 @@ pub fn try_mark_green<'tcx>(&self,
         }
 
         // ... and finally storing a "Green" entry in the color map.
-        let old_color = data.colors
-                            .borrow_mut()
-                            .insert(*dep_node, DepNodeColor::Green(dep_node_index));
-        debug_assert!(old_color.is_none(),
+        let mut colors = data.colors.borrow_mut();
+        debug_assert!(colors.get(prev_dep_node_index).is_none(),
                       "DepGraph::try_mark_green() - Duplicate DepNodeColor \
                       insertion for {:?}", dep_node);
 
+        colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
+
         debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node);
         Some(dep_node_index)
     }
 
-    // Used in various assertions
-    pub fn is_green(&self, dep_node_index: DepNodeIndex) -> bool {
-        let dep_node = self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index];
-        self.data.as_ref().unwrap().colors.borrow().get(&dep_node).map(|&color| {
-            match color {
-                DepNodeColor::Red => false,
-                DepNodeColor::Green(_) => true,
-            }
-        }).unwrap_or(false)
+    // Returns true if the given node has been marked as green during the
+    // current compilation session. Used in various assertions
+    pub fn is_green(&self, dep_node: &DepNode) -> bool {
+        self.node_color(dep_node).map(|c| c.is_green()).unwrap_or(false)
     }
 
     // This method loads all on-disk cacheable query results into memory, so
@@ -714,20 +736,25 @@ pub fn is_green(&self, dep_node_index: DepNodeIndex) -> bool {
     pub fn exec_cache_promotions<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         let green_nodes: Vec<DepNode> = {
             let data = self.data.as_ref().unwrap();
-            data.colors.borrow().iter().filter_map(|(dep_node, color)| match color {
-                DepNodeColor::Green(_) => {
-                    if dep_node.cache_on_disk(tcx) {
-                        Some(*dep_node)
-                    } else {
+            let colors = data.colors.borrow();
+            colors.values.indices().filter_map(|prev_index| {
+                match colors.get(prev_index) {
+                    Some(DepNodeColor::Green(_)) => {
+                        let dep_node = data.previous.index_to_node(prev_index);
+                        if dep_node.cache_on_disk(tcx) {
+                            Some(dep_node)
+                        } else {
+                            None
+                        }
+                    }
+                    None |
+                    Some(DepNodeColor::Red) => {
+                        // We can skip red nodes because a node can only be marked
+                        // as red if the query result was recomputed and thus is
+                        // already in memory.
                         None
                     }
                 }
-                DepNodeColor::Red => {
-                    // We can skip red nodes because a node can only be marked
-                    // as red if the query result was recomputed and thus is
-                    // already in memory.
-                    None
-                }
             }).collect()
         };
 
@@ -1052,3 +1079,36 @@ enum OpenTask {
         node: DepNode,
     },
 }
+
+// A data structure that stores Option<DepNodeColor> values as a contiguous
+// array, using one u32 per entry.
+struct DepNodeColorMap {
+    values: IndexVec<SerializedDepNodeIndex, u32>,
+}
+
+const COMPRESSED_NONE: u32 = 0;
+const COMPRESSED_RED: u32 = 1;
+const COMPRESSED_FIRST_GREEN: u32 = 2;
+
+impl DepNodeColorMap {
+    fn new(size: usize) -> DepNodeColorMap {
+        DepNodeColorMap {
+            values: IndexVec::from_elem_n(COMPRESSED_NONE, size)
+        }
+    }
+
+    fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
+        match self.values[index] {
+            COMPRESSED_NONE => None,
+            COMPRESSED_RED => Some(DepNodeColor::Red),
+            value => Some(DepNodeColor::Green(DepNodeIndex(value - COMPRESSED_FIRST_GREEN)))
+        }
+    }
+
+    fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
+        self.values[index] = match color {
+            DepNodeColor::Red => COMPRESSED_RED,
+            DepNodeColor::Green(index) => index.0 + COMPRESSED_FIRST_GREEN,
+        }
+    }
+}
index 50e1ee88a4614ce701f9ed34ad7ac02e483175da..504b60e763e23543fc9e5663acbe5bbf6a842429 100644 (file)
@@ -49,6 +49,11 @@ pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
         self.index[dep_node]
     }
 
+    #[inline]
+    pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option<SerializedDepNodeIndex> {
+        self.index.get(dep_node).cloned()
+    }
+
     #[inline]
     pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
         self.index
index e3af285053805e68c768e80a5ff92431eb4d6589..89ed47ea194fb7e51859e9748946561b024046d6 100644 (file)
@@ -2956,7 +2956,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
             // Desugar ExprIfLet
             // From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
-            ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
+            ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => {
                 // to:
                 //
                 //   match <sub_expr> {
@@ -2970,8 +2970,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 {
                     let body = self.lower_block(body, false);
                     let body_expr = P(self.expr_block(body, ThinVec::new()));
-                    let pat = self.lower_pat(pat);
-                    arms.push(self.arm(hir_vec![pat], body_expr));
+                    let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
+                    arms.push(self.arm(pats, body_expr));
                 }
 
                 // _ => [<else_opt>|()]
@@ -3000,7 +3000,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
             // Desugar ExprWhileLet
             // From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
-            ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_label) => {
+            ExprKind::WhileLet(ref pats, ref sub_expr, ref body, opt_label) => {
                 // to:
                 //
                 //   [opt_ident]: loop {
@@ -3021,8 +3021,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 // `<pat> => <body>`
                 let pat_arm = {
                     let body_expr = P(self.expr_block(body, ThinVec::new()));
-                    let pat = self.lower_pat(pat);
-                    self.arm(hir_vec![pat], body_expr)
+                    let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
+                    self.arm(pats, body_expr)
                 };
 
                 // `_ => break`
index b6b3e8955351c48a4a6d7db511e8fd7985162dd2..3799bdada888e84821e8c4a9a8a163cb8cf4a9a1 100644 (file)
@@ -22,6 +22,7 @@
 use syntax::abi::Abi;
 use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
 use syntax::codemap::Spanned;
+use syntax::ext::base::MacroKind;
 use syntax_pos::Span;
 
 use hir::*;
@@ -32,6 +33,7 @@
 use arena::TypedArena;
 use std::cell::RefCell;
 use std::io;
+use ty::TyCtxt;
 
 pub mod blocks;
 mod collector;
@@ -39,6 +41,7 @@
 pub mod definitions;
 mod hir_id_validator;
 
+
 pub const ITEM_LIKE_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::Low;
 pub const REGULAR_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High;
 
@@ -373,6 +376,92 @@ pub fn local_def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
         self.definitions.as_local_node_id(def_id.to_def_id()).unwrap()
     }
 
+    pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
+        let node = if let Some(node) = self.find(node_id) {
+            node
+        } else {
+            return None
+        };
+
+        match node {
+            NodeItem(item) => {
+                let def_id = || {
+                    self.local_def_id(item.id)
+                };
+
+                match item.node {
+                    ItemStatic(_, m, _) => Some(Def::Static(def_id(),
+                                                            m == MutMutable)),
+                    ItemConst(..) => Some(Def::Const(def_id())),
+                    ItemFn(..) => Some(Def::Fn(def_id())),
+                    ItemMod(..) => Some(Def::Mod(def_id())),
+                    ItemGlobalAsm(..) => Some(Def::GlobalAsm(def_id())),
+                    ItemTy(..) => Some(Def::TyAlias(def_id())),
+                    ItemEnum(..) => Some(Def::Enum(def_id())),
+                    ItemStruct(..) => Some(Def::Struct(def_id())),
+                    ItemUnion(..) => Some(Def::Union(def_id())),
+                    ItemTrait(..) => Some(Def::Trait(def_id())),
+                    ItemTraitAlias(..) => {
+                        bug!("trait aliases are not yet implemented (see issue #41517)")
+                    },
+                    ItemExternCrate(_) |
+                    ItemUse(..) |
+                    ItemForeignMod(..) |
+                    ItemImpl(..) => None,
+                }
+            }
+            NodeForeignItem(item) => {
+                let def_id = self.local_def_id(item.id);
+                match item.node {
+                    ForeignItemFn(..) => Some(Def::Fn(def_id)),
+                    ForeignItemStatic(_, m) => Some(Def::Static(def_id, m)),
+                    ForeignItemType => Some(Def::TyForeign(def_id)),
+                }
+            }
+            NodeTraitItem(item) => {
+                let def_id = self.local_def_id(item.id);
+                match item.node {
+                    TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
+                    TraitItemKind::Method(..) => Some(Def::Method(def_id)),
+                    TraitItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
+                }
+            }
+            NodeImplItem(item) => {
+                let def_id = self.local_def_id(item.id);
+                match item.node {
+                    ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
+                    ImplItemKind::Method(..) => Some(Def::Method(def_id)),
+                    ImplItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
+                }
+            }
+            NodeVariant(variant) => {
+                let def_id = self.local_def_id(variant.node.data.id());
+                Some(Def::Variant(def_id))
+            }
+            NodeField(_) |
+            NodeExpr(_) |
+            NodeStmt(_) |
+            NodeTy(_) |
+            NodeTraitRef(_) |
+            NodePat(_) |
+            NodeBinding(_) |
+            NodeStructCtor(_) |
+            NodeLifetime(_) |
+            NodeVisibility(_) |
+            NodeBlock(_) => None,
+            NodeLocal(local) => {
+                Some(Def::Local(local.id))
+            }
+            NodeMacroDef(macro_def) => {
+                Some(Def::Macro(self.local_def_id(macro_def.id),
+                                MacroKind::Bang))
+            }
+            NodeTyParam(param) => {
+                Some(Def::TyParam(self.local_def_id(param.id)))
+            }
+        }
+    }
+
     fn entry_count(&self) -> usize {
         self.map.len()
     }
@@ -1275,3 +1364,12 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
     }
 }
+
+pub fn describe_def(tcx: TyCtxt, def_id: DefId) -> Option<Def> {
+    if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
+        tcx.hir.describe_def(node_id)
+    } else {
+        bug!("Calling local describe_def query provider for upstream DefId: {:?}",
+             def_id)
+    }
+}
index bc03f7ead8187ddf475796e64aa35a41124b945c..0fa1b95d8e7776955bd1923738ac8a2edf2b1b86 100644 (file)
@@ -43,6 +43,7 @@
 use syntax::util::ThinVec;
 use syntax::util::parser::ExprPrecedence;
 use ty::AdtKind;
+use ty::maps::Providers;
 
 use rustc_data_structures::indexed_vec;
 
@@ -2204,3 +2205,8 @@ pub struct TraitCandidate {
 // Map from the NodeId of a glob import to a list of items which are actually
 // imported.
 pub type GlobMap = NodeMap<FxHashSet<Name>>;
+
+
+pub fn provide(providers: &mut Providers) {
+    providers.describe_def = map::describe_def;
+}
index d1e431597e7455237c7683d78dc88115177cf4fa..71a57dbf32fb180b8bac1c01e9e2f1a9a4cf9594 100644 (file)
@@ -56,8 +56,19 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>>
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        self.as_type().hash_stable(hcx, hasher);
-        self.as_region().hash_stable(hcx, hasher);
+        self.unpack().hash_stable(hcx, hasher);
+    }
+}
+
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
+for ty::subst::UnpackedKind<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        match self {
+            ty::subst::UnpackedKind::Lifetime(lt) => lt.hash_stable(hcx, hasher),
+            ty::subst::UnpackedKind::Type(ty) => ty.hash_stable(hcx, hasher),
+        }
     }
 }
 
index f5b88dbc2a9c77aab5b619f5b9a524a80440ae28..a749d0dddd7eeea31863271ecbce1de5f6297008 100644 (file)
@@ -17,7 +17,7 @@
 use ty::{self, Ty};
 use ty::fold::{BottomUpFolder, TypeFoldable};
 use ty::outlives::Component;
-use ty::subst::{Kind, Substs};
+use ty::subst::{Kind, UnpackedKind, Substs};
 use util::nodemap::DefIdMap;
 
 pub type AnonTypeMap<'tcx> = DefIdMap<AnonTypeDecl<'tcx>>;
@@ -321,7 +321,7 @@ fn constrain_anon_type<FRR: FreeRegionRelations<'tcx>>(
             let index = region_def.index as usize;
 
             // Get the value supplied for this region from the substs.
-            let subst_arg = anon_defn.substs[index].as_region().unwrap();
+            let subst_arg = anon_defn.substs.region_at(index);
 
             // Compute the least upper bound of it with the other regions.
             debug!("constrain_anon_types: least_region={:?}", least_region);
@@ -466,7 +466,8 @@ pub fn infer_anon_definition_from_instantiation(
                 // All other regions, we map them appropriately to their adjusted
                 // indices, erroring if we find any lifetimes that were not mapped
                 // into the new set.
-                _ => if let Some(r1) = map.get(&Kind::from(r)).and_then(|k| k.as_region()) {
+                _ => if let Some(UnpackedKind::Lifetime(r1)) = map.get(&r.into())
+                                                                  .map(|k| k.unpack()) {
                     r1
                 } else {
                     // No mapping was found. This means that
index 49e5c0dc21f9ead7954c506cc9db63a6d32f9ef2..7f8f2e9b90603f4a339b91cc96bf74a2bedaed89 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use hir::def_id::DefId;
 use syntax::ast::NodeId;
 use syntax::symbol::InternedString;
 use ty::{Instance, TyCtxt};
@@ -21,7 +22,7 @@
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum MonoItem<'tcx> {
     Fn(Instance<'tcx>),
-    Static(NodeId),
+    Static(DefId),
     GlobalAsm(NodeId),
 }
 
@@ -50,7 +51,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             MonoItem::Fn(ref instance) => {
                 instance.hash_stable(hcx, hasher);
             }
-            MonoItem::Static(node_id)    |
+            MonoItem::Static(def_id) => {
+                def_id.hash_stable(hcx, hasher);
+            }
             MonoItem::GlobalAsm(node_id) => {
                 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                     node_id.hash_stable(hcx, hasher);
index 12d8d6f3d7481f15fa82ec8b42bb493ec21191b6..118d4ddd4457b0daf706ea32362bf589ce022804 100644 (file)
@@ -756,7 +756,7 @@ pub fn report_selection_error(&self,
                         }).collect(),
                     ref sty => vec![ArgKind::Arg("_".to_owned(), format!("{}", sty))],
                 };
-                if found.len()== expected.len() {
+                if found.len() == expected.len() {
                     self.report_closure_arg_mismatch(span,
                                                      found_span,
                                                      found_trait_ref,
@@ -874,6 +874,19 @@ pub fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>
                     _ => ArgKind::Arg("_".to_owned(), "_".to_owned())
                 }).collect::<Vec<ArgKind>>())
             }
+            hir::map::NodeVariant(&hir::Variant {
+                span,
+                node: hir::Variant_ {
+                    data: hir::VariantData::Tuple(ref fields, _),
+                    ..
+                },
+                ..
+            }) => {
+                (self.tcx.sess.codemap().def_span(span),
+                 fields.iter().map(|field| {
+                     ArgKind::Arg(format!("{}", field.name), "_".to_string())
+                 }).collect::<Vec<_>>())
+            }
             _ => panic!("non-FnLike node found: {:?}", node),
         }
     }
index 520b997882e07afe8c5e3c4f2f7673ecd459ea88..49f43b18e61987fd005f1aec103f9fe530cdbc65 100644 (file)
@@ -73,7 +73,7 @@ pub enum IntercrateMode {
 /// either identifying an `impl` (e.g., `impl Eq for int`) that
 /// provides the required vtable, or else finding a bound that is in
 /// scope. The eventual result is usually a `Selection` (defined below).
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct Obligation<'tcx, T> {
     pub cause: ObligationCause<'tcx>,
     pub param_env: ty::ParamEnv<'tcx>,
@@ -85,7 +85,7 @@ pub struct Obligation<'tcx, T> {
 pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 
 /// Why did we incur this obligation? Used for error reporting.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct ObligationCause<'tcx> {
     pub span: Span,
 
@@ -113,7 +113,7 @@ pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from span.
     MiscObligation,
@@ -215,7 +215,7 @@ pub enum ObligationCauseCode<'tcx> {
     BlockTailExpression(ast::NodeId),
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct DerivedObligationCause<'tcx> {
     /// The trait reference of the parent obligation that led to the
     /// current obligation. Note that only trait obligations lead to
@@ -304,7 +304,7 @@ pub enum FulfillmentErrorCode<'tcx> {
 /// ### The type parameter `N`
 ///
 /// See explanation on `VtableImplData`.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum Vtable<'tcx, N> {
     /// Vtable identifying a particular impl.
     VtableImpl(VtableImplData<'tcx, N>),
@@ -374,13 +374,13 @@ pub struct VtableClosureData<'tcx, N> {
     pub nested: Vec<N>
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub struct VtableAutoImplData<N> {
     pub trait_def_id: DefId,
     pub nested: Vec<N>
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub struct VtableBuiltinData<N> {
     pub nested: Vec<N>
 }
index 0d0476e7c21dd44f8d380cc07c8610ad53db5f09..1778a8d693a832fc6c1e9a2a010e12eacca3a8d6 100644 (file)
@@ -16,6 +16,7 @@
 use super::Obligation;
 use super::ObligationCause;
 use super::PredicateObligation;
+use super::Selection;
 use super::SelectionContext;
 use super::SelectionError;
 use super::VtableClosureData;
@@ -101,7 +102,7 @@ pub struct MismatchedProjectionTypes<'tcx> {
     pub err: ty::error::TypeError<'tcx>
 }
 
-#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(PartialEq, Eq, Debug)]
 enum ProjectionTyCandidate<'tcx> {
     // from a where-clause in the env or object type
     ParamEnv(ty::PolyProjectionPredicate<'tcx>),
@@ -110,12 +111,59 @@ enum ProjectionTyCandidate<'tcx> {
     TraitDef(ty::PolyProjectionPredicate<'tcx>),
 
     // from a "impl" (or a "pseudo-impl" returned by select)
-    Select,
+    Select(Selection<'tcx>),
 }
 
-struct ProjectionTyCandidateSet<'tcx> {
-    vec: Vec<ProjectionTyCandidate<'tcx>>,
-    ambiguous: bool
+enum ProjectionTyCandidateSet<'tcx> {
+    None,
+    Single(ProjectionTyCandidate<'tcx>),
+    Ambiguous,
+    Error(SelectionError<'tcx>),
+}
+
+impl<'tcx> ProjectionTyCandidateSet<'tcx> {
+    fn mark_ambiguous(&mut self) {
+        *self = ProjectionTyCandidateSet::Ambiguous;
+    }
+
+    fn mark_error(&mut self, err: SelectionError<'tcx>) {
+        *self = ProjectionTyCandidateSet::Error(err);
+    }
+
+    // Returns true if the push was successful, or false if the candidate
+    // was discarded -- this could be because of ambiguity, or because
+    // a higher-priority candidate is already there.
+    fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
+        use self::ProjectionTyCandidateSet::*;
+        use self::ProjectionTyCandidate::*;
+        match self {
+            None => {
+                *self = Single(candidate);
+                true
+            }
+            Single(current) => {
+                // No duplicates are expected.
+                assert_ne!(current, &candidate);
+                // Prefer where-clauses. As in select, if there are multiple
+                // candidates, we prefer where-clause candidates over impls.  This
+                // may seem a bit surprising, since impls are the source of
+                // "truth" in some sense, but in fact some of the impls that SEEM
+                // applicable are not, because of nested obligations. Where
+                // clauses are the safer choice. See the comment on
+                // `select::SelectionCandidate` and #21974 for more details.
+                match (current, candidate) {
+                    (ParamEnv(..), ParamEnv(..)) => { *self = Ambiguous; }
+                    (ParamEnv(..), _) => {}
+                    (_, ParamEnv(..)) => { unreachable!(); }
+                    (_, _) => { *self = Ambiguous; }
+                }
+                false
+            }
+            Ambiguous | Error(..) => {
+                false
+            }
+        }
+    }
 }
 
 /// Evaluates constraints of the form:
@@ -803,11 +851,11 @@ fn project_type<'cx, 'gcx, 'tcx>(
         return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
     }
 
-    let mut candidates = ProjectionTyCandidateSet {
-        vec: Vec::new(),
-        ambiguous: false,
-    };
+    let mut candidates = ProjectionTyCandidateSet::None;
 
+    // Make sure that the following procedures are kept in order. ParamEnv
+    // needs to be first because it has highest priority, and Select checks
+    // the return value of push_candidate which assumes it's ran at last.
     assemble_candidates_from_param_env(selcx,
                                        obligation,
                                        &obligation_trait_ref,
@@ -818,67 +866,27 @@ fn project_type<'cx, 'gcx, 'tcx>(
                                        &obligation_trait_ref,
                                        &mut candidates);
 
-    if let Err(e) = assemble_candidates_from_impls(selcx,
-                                                   obligation,
-                                                   &obligation_trait_ref,
-                                                   &mut candidates) {
-        return Err(ProjectionTyError::TraitSelectionError(e));
-    }
-
-    debug!("{} candidates, ambiguous={}",
-           candidates.vec.len(),
-           candidates.ambiguous);
-
-    // Inherent ambiguity that prevents us from even enumerating the
-    // candidates.
-    if candidates.ambiguous {
-        return Err(ProjectionTyError::TooManyCandidates);
-    }
-
-    // Drop duplicates.
-    //
-    // Note: `candidates.vec` seems to be on the critical path of the
-    // compiler. Replacing it with an HashSet was also tried, which would
-    // render the following dedup unnecessary. The original comment indicated
-    // that it was 9% slower, but that data is now obsolete and a new
-    // benchmark should be performed.
-    candidates.vec.sort_unstable();
-    candidates.vec.dedup();
-
-    // Prefer where-clauses. As in select, if there are multiple
-    // candidates, we prefer where-clause candidates over impls.  This
-    // may seem a bit surprising, since impls are the source of
-    // "truth" in some sense, but in fact some of the impls that SEEM
-    // applicable are not, because of nested obligations. Where
-    // clauses are the safer choice. See the comment on
-    // `select::SelectionCandidate` and #21974 for more details.
-    if candidates.vec.len() > 1 {
-        debug!("retaining param-env candidates only from {:?}", candidates.vec);
-        candidates.vec.retain(|c| match *c {
-            ProjectionTyCandidate::ParamEnv(..) => true,
-            ProjectionTyCandidate::TraitDef(..) |
-            ProjectionTyCandidate::Select => false,
-        });
-        debug!("resulting candidate set: {:?}", candidates.vec);
-        if candidates.vec.len() != 1 {
-            return Err(ProjectionTyError::TooManyCandidates);
-        }
-    }
-
-    assert!(candidates.vec.len() <= 1);
+    assemble_candidates_from_impls(selcx,
+                                   obligation,
+                                   &obligation_trait_ref,
+                                   &mut candidates);
+
+    match candidates {
+        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
+            confirm_candidate(selcx,
+                              obligation,
+                              &obligation_trait_ref,
+                              candidate))),
+        ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
+            selcx.tcx().mk_projection(
+                obligation.predicate.item_def_id,
+                obligation.predicate.substs))),
+        // Error occurred while trying to processing impls.
+        ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
+        // Inherent ambiguity that prevents us from even enumerating the
+        // candidates.
+        ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
 
-    match candidates.vec.pop() {
-        Some(candidate) => {
-            Ok(ProjectedTy::Progress(
-                confirm_candidate(selcx,
-                                  obligation,
-                                  &obligation_trait_ref,
-                                  candidate)))
-        }
-        None => Ok(ProjectedTy::NoProgress(
-                    selcx.tcx().mk_projection(
-                        obligation.predicate.item_def_id,
-                        obligation.predicate.substs)))
     }
 }
 
@@ -928,7 +936,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
         ty::TyInfer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
-            candidate_set.ambiguous = true;
+            candidate_set.mark_ambiguous();
             return;
         }
         _ => { return; }
@@ -962,7 +970,7 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
         debug!("assemble_candidates_from_predicates: predicate={:?}",
                predicate);
         match predicate {
-            ty::Predicate::Projection(ref data) => {
+            ty::Predicate::Projection(data) => {
                 let same_def_id =
                     data.0.projection_ty.item_def_id == obligation.predicate.item_def_id;
 
@@ -985,10 +993,10 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
                        data, is_match, same_def_id);
 
                 if is_match {
-                    candidate_set.vec.push(ctor(data.clone()));
+                    candidate_set.push_candidate(ctor(data));
                 }
             }
-            _ => { }
+            _ => {}
         }
     }
 }
@@ -998,37 +1006,36 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
-    -> Result<(), SelectionError<'tcx>>
 {
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
     let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
     let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
-    selcx.infcx().probe(|_| {
+    let _ = selcx.infcx().commit_if_ok(|_| {
         let vtable = match selcx.select(&trait_obligation) {
             Ok(Some(vtable)) => vtable,
             Ok(None) => {
-                candidate_set.ambiguous = true;
-                return Ok(());
+                candidate_set.mark_ambiguous();
+                return Err(());
             }
             Err(e) => {
                 debug!("assemble_candidates_from_impls: selection error {:?}",
                        e);
-                return Err(e);
+                candidate_set.mark_error(e);
+                return Err(());
             }
         };
 
-        match vtable {
+        let eligible = match &vtable {
             super::VtableClosure(_) |
             super::VtableGenerator(_) |
             super::VtableFnPointer(_) |
             super::VtableObject(_) => {
                 debug!("assemble_candidates_from_impls: vtable={:?}",
                        vtable);
-
-                candidate_set.vec.push(ProjectionTyCandidate::Select);
+                true
             }
-            super::VtableImpl(ref impl_data) => {
+            super::VtableImpl(impl_data) => {
                 // We have to be careful when projecting out of an
                 // impl because of specialization. If we are not in
                 // trans (i.e., projection mode is not "any"), and the
@@ -1072,27 +1079,25 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                     node_item.item.defaultness.has_value()
                 } else {
                     node_item.item.defaultness.is_default() ||
-                    selcx.tcx().impl_is_default(node_item.node.def_id())
+                        selcx.tcx().impl_is_default(node_item.node.def_id())
                 };
 
                 // Only reveal a specializable default if we're past type-checking
                 // and the obligations is monomorphic, otherwise passes such as
                 // transmute checking and polymorphic MIR optimizations could
                 // get a result which isn't correct for all monomorphizations.
-                let new_candidate = if !is_default {
-                    Some(ProjectionTyCandidate::Select)
+                if !is_default {
+                    true
                 } else if obligation.param_env.reveal == Reveal::All {
                     assert!(!poly_trait_ref.needs_infer());
                     if !poly_trait_ref.needs_subst() {
-                        Some(ProjectionTyCandidate::Select)
+                        true
                     } else {
-                        None
+                        false
                     }
                 } else {
-                    None
-                };
-
-                candidate_set.vec.extend(new_candidate);
+                    false
+                }
             }
             super::VtableParam(..) => {
                 // This case tell us nothing about the value of an
@@ -1120,6 +1125,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 // in the compiler: a trait predicate (`T : SomeTrait`) and a
                 // projection. And the projection where clause is handled
                 // in `assemble_candidates_from_param_env`.
+                false
             }
             super::VtableAutoImpl(..) |
             super::VtableBuiltin(..) => {
@@ -1129,10 +1135,18 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                     "Cannot project an associated type from `{:?}`",
                     vtable);
             }
-        }
+        };
 
-        Ok(())
-    })
+        if eligible {
+            if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) {
+                Ok(())
+            } else {
+                Err(())
+            }
+        } else {
+            Err(())
+        }
+    });
 }
 
 fn confirm_candidate<'cx, 'gcx, 'tcx>(
@@ -1152,8 +1166,8 @@ fn confirm_candidate<'cx, 'gcx, 'tcx>(
             confirm_param_env_candidate(selcx, obligation, poly_projection)
         }
 
-        ProjectionTyCandidate::Select => {
-            confirm_select_candidate(selcx, obligation, obligation_trait_ref)
+        ProjectionTyCandidate::Select(vtable) => {
+            confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable)
         }
     }
 }
@@ -1161,21 +1175,10 @@ fn confirm_candidate<'cx, 'gcx, 'tcx>(
 fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>)
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    vtable: Selection<'tcx>)
     -> Progress<'tcx>
 {
-    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
-    let vtable = match selcx.select(&trait_obligation) {
-        Ok(Some(vtable)) => vtable,
-        _ => {
-            span_bug!(
-                obligation.cause.span,
-                "Failed to select `{:?}`",
-                trait_obligation);
-        }
-    };
-
     match vtable {
         super::VtableImpl(data) =>
             confirm_impl_candidate(selcx, obligation, data),
index cfeb456acefe6b8995168ca59e3e99b71a239e29..9a3738c163d386b2da57f590252e7ae58ab9cb56 100644 (file)
@@ -53,7 +53,7 @@
 use syntax::abi::Abi;
 use hir;
 use lint;
-use util::nodemap::FxHashMap;
+use util::nodemap::{FxHashMap, FxHashSet};
 
 struct InferredObligationsSnapshotVecDelegate<'tcx> {
     phantom: PhantomData<&'tcx i32>,
@@ -584,7 +584,7 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
                     let trait_ref = &mut trait_pred.trait_ref;
                     let unit_substs = trait_ref.substs;
                     let mut never_substs = Vec::with_capacity(unit_substs.len());
-                    never_substs.push(From::from(tcx.types.never));
+                    never_substs.push(tcx.types.never.into());
                     never_substs.extend(&unit_substs[1..]);
                     trait_ref.substs = tcx.intern_substs(&never_substs);
                 }
@@ -2997,7 +2997,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 // unsized parameters is equal to the target.
                 let params = substs_a.iter().enumerate().map(|(i, &k)| {
                     if ty_params.contains(i) {
-                        Kind::from(substs_b.type_at(i))
+                        substs_b.type_at(i).into()
                     } else {
                         k
                     }
@@ -3303,7 +3303,7 @@ fn impl_or_trait_obligations(&mut self,
         // that order.
         let predicates = tcx.predicates_of(def_id);
         assert_eq!(predicates.parent, None);
-        let predicates = predicates.predicates.iter().flat_map(|predicate| {
+        let mut predicates: Vec<_> = predicates.predicates.iter().flat_map(|predicate| {
             let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth,
                                                  &predicate.subst(tcx, substs));
             predicate.obligations.into_iter().chain(
@@ -3314,6 +3314,13 @@ fn impl_or_trait_obligations(&mut self,
                     predicate: predicate.value
                 }))
         }).collect();
+        // We are performing deduplication here to avoid exponential blowups
+        // (#38528) from happening, but the real cause of the duplication is
+        // unknown. What we know is that the deduplication avoids exponential
+        // amount of predicates being propogated when processing deeply nested
+        // types.
+        let mut seen = FxHashSet();
+        predicates.retain(|i| seen.insert(i.clone()));
         self.infcx().plug_leaks(skol_map, snapshot, predicates)
     }
 }
index 63bf52a9bdf786d7603cf2cf43f8e4a012927d0f..f4b5ffbb7dc4044780382598c62258d2e636d425 100644 (file)
@@ -355,10 +355,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let sig = substs.closure_sig(closure_did, tcx);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
-    let substs = tcx.mk_substs([
-                               Kind::from(self_ty),
-                               Kind::from(sig.inputs()[0]),
-    ].iter().cloned());
+    let substs = tcx.mk_substs([Kind::from(self_ty), sig.inputs()[0].into()].iter().cloned());
 
     debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
     Instance { def, substs }
index 21ffe6b895e72cca62aefae16ae84a78a278fab1..be1d255afa1913eb87513881e19a03422671b5f5 100644 (file)
     [] fn export_name: ExportName(DefId) -> Option<Symbol>,
     [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool,
     [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel,
-    [] fn is_translated_function: IsTranslatedFunction(DefId) -> bool,
+    [] fn is_translated_item: IsTranslatedItem(DefId) -> bool,
     [] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
     [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
     [] fn output_filenames: output_filenames_node(CrateNum)
index 56ed0f9106f30d689f08e07eb9e94847f74c3490..17b44f6959f2f88f97dcf278ba139fa1d7e8e881 100644 (file)
@@ -347,22 +347,21 @@ fn load_indexed<'tcx, T>(&self,
             return None
         };
 
-        let mut cnum_map = self.cnum_map.borrow_mut();
-        if cnum_map.is_none() {
+        // Initialize the cnum_map if it is not initialized yet.
+        if self.cnum_map.borrow().is_none() {
+            let mut cnum_map = self.cnum_map.borrow_mut();
             *cnum_map = Some(Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
         }
-
-        let mut synthetic_expansion_infos = self.synthetic_expansion_infos.borrow_mut();
-        let mut file_index_to_file = self.file_index_to_file.borrow_mut();
+        let cnum_map = self.cnum_map.borrow();
 
         let mut decoder = CacheDecoder {
             tcx,
             opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
             codemap: self.codemap,
             cnum_map: cnum_map.as_ref().unwrap(),
-            file_index_to_file: &mut file_index_to_file,
+            file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
-            synthetic_expansion_infos: &mut synthetic_expansion_infos,
+            synthetic_expansion_infos: &self.synthetic_expansion_infos,
         };
 
         match decode_tagged(&mut decoder, dep_node_index) {
@@ -421,21 +420,21 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
     opaque: opaque::Decoder<'x>,
     codemap: &'x CodeMap,
     cnum_map: &'x IndexVec<CrateNum, Option<CrateNum>>,
-    synthetic_expansion_infos: &'x mut FxHashMap<AbsoluteBytePos, SyntaxContext>,
-    file_index_to_file: &'x mut FxHashMap<FileMapIndex, Rc<FileMap>>,
+    synthetic_expansion_infos: &'x RefCell<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
+    file_index_to_file: &'x RefCell<FxHashMap<FileMapIndex, Rc<FileMap>>>,
     file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
 }
 
 impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
-    fn file_index_to_file(&mut self, index: FileMapIndex) -> Rc<FileMap> {
+    fn file_index_to_file(&self, index: FileMapIndex) -> Rc<FileMap> {
         let CacheDecoder {
-            ref mut file_index_to_file,
+            ref file_index_to_file,
             ref file_index_to_stable_id,
             ref codemap,
             ..
         } = *self;
 
-        file_index_to_file.entry(index).or_insert_with(|| {
+        file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
             let stable_id = file_index_to_stable_id[&index];
             codemap.filemap_by_stable_id(stable_id)
                    .expect("Failed to lookup FileMap in new context.")
@@ -572,19 +571,24 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
                 let pos = AbsoluteBytePos::new(self.opaque.position());
                 let expn_info: ExpnInfo = Decodable::decode(self)?;
                 let ctxt = SyntaxContext::allocate_directly(expn_info);
-                self.synthetic_expansion_infos.insert(pos, ctxt);
+                self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
                 ctxt
             }
             TAG_EXPANSION_INFO_SHORTHAND => {
                 let pos = AbsoluteBytePos::decode(self)?;
-                if let Some(ctxt) = self.synthetic_expansion_infos.get(&pos).cloned() {
+                let cached_ctxt = self.synthetic_expansion_infos
+                                      .borrow()
+                                      .get(&pos)
+                                      .cloned();
+
+                if let Some(ctxt) = cached_ctxt {
                     ctxt
                 } else {
                     let expn_info = self.with_position(pos.to_usize(), |this| {
                          ExpnInfo::decode(this)
                     })?;
                     let ctxt = SyntaxContext::allocate_directly(expn_info);
-                    self.synthetic_expansion_infos.insert(pos, ctxt);
+                    self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
                     ctxt
                 }
             }
index f02c7cbd0ea3e8dcf6d36bbd9201cd97e541a44c..b654b6bc42a122896c018319b39efcaf5c0e07da 100644 (file)
@@ -84,7 +84,7 @@ pub(super) fn report_cycle(self, CycleError { span, cycle }: CycleError)
             let span = self.sess.codemap().def_span(span);
             let mut err =
                 struct_span_err!(self.sess, span, E0391,
-                                 "unsupported cyclic reference between types/traits detected");
+                                 "cyclic dependency detected");
             err.span_label(span, "cyclic reference");
 
             err.span_note(self.sess.codemap().def_span(stack[0].0),
@@ -147,7 +147,7 @@ pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option<DepNod
                 }
                 match self.dep_graph.try_mark_green(self.global_tcx(), &dep_node) {
                     Some(dep_node_index) => {
-                        debug_assert!(self.dep_graph.is_green(dep_node_index));
+                        debug_assert!(self.dep_graph.is_green(&dep_node));
                         self.dep_graph.read_index(dep_node_index);
                         Some(dep_node_index)
                     }
@@ -403,7 +403,7 @@ fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                                                   dep_node: &DepNode)
                                                   -> Result<$V, CycleError<'a, $tcx>>
             {
-                debug_assert!(tcx.dep_graph.is_green(dep_node_index));
+                debug_assert!(tcx.dep_graph.is_green(dep_node));
 
                 // First we try to load the result from the on-disk cache
                 let result = if Self::cache_on_disk(key) &&
@@ -491,7 +491,7 @@ fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
                      span: Span,
                      dep_node: DepNode)
                      -> Result<($V, DepNodeIndex), CycleError<'a, $tcx>> {
-                debug_assert!(tcx.dep_graph.node_color(&dep_node).is_none());
+                debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node));
 
                 profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
                 let res = tcx.cycle_check(span, Query::$name(key), || {
@@ -929,7 +929,7 @@ macro_rules! force {
         DepKind::ContainsExternIndicator => {
             force!(contains_extern_indicator, def_id!());
         }
-        DepKind::IsTranslatedFunction => { force!(is_translated_function, def_id!()); }
+        DepKind::IsTranslatedItem => { force!(is_translated_item, def_id!()); }
         DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
 
         DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
index f52f2ea0f9fc8258b9d93964c6694a1da0cb9e9a..3ab2cd274b90ea98ad80a8d4998a9a0f6e00a6ec 100644 (file)
@@ -39,7 +39,6 @@
 use serialize::{self, Encodable, Encoder};
 use std::cell::RefCell;
 use std::cmp;
-use std::cmp::Ordering;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::iter::FromIterator;
@@ -498,20 +497,6 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
-impl<'tcx> Ord for TyS<'tcx> {
-    #[inline]
-    fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
-        // (self as *const _).cmp(other as *const _)
-        (self as *const TyS<'tcx>).cmp(&(other as *const TyS<'tcx>))
-    }
-}
-impl<'tcx> PartialOrd for TyS<'tcx> {
-    #[inline]
-    fn partial_cmp(&self, other: &TyS<'tcx>) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
 impl<'tcx> TyS<'tcx> {
     pub fn is_primitive_ty(&self) -> bool {
         match self.sty {
@@ -581,19 +566,6 @@ fn eq(&self, other: &Slice<T>) -> bool {
 }
 impl<T> Eq for Slice<T> {}
 
-impl<T> Ord for Slice<T> {
-    #[inline]
-    fn cmp(&self, other: &Slice<T>) -> Ordering {
-        (&self.0 as *const [T]).cmp(&(&other.0 as *const [T]))
-    }
-}
-impl<T> PartialOrd for Slice<T> {
-    #[inline]
-    fn partial_cmp(&self, other: &Slice<T>) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
 impl<T> Hash for Slice<T> {
     fn hash<H: Hasher>(&self, s: &mut H) {
         (self.as_ptr(), self.len()).hash(s)
@@ -1128,7 +1100,7 @@ pub struct SubtypePredicate<'tcx> {
 /// equality between arbitrary types. Processing an instance of
 /// Form #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct ProjectionPredicate<'tcx> {
     pub projection_ty: ProjectionTy<'tcx>,
     pub ty: Ty<'tcx>,
@@ -1532,7 +1504,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 pub enum AdtKind { Struct, Union, Enum }
 
 bitflags! {
index a6c72728a51252f1f50a8b1941a607f071b15131..b9927c7eeb2fa491569db9a92557df892948e4fe 100644 (file)
@@ -16,7 +16,7 @@
 use hir::def_id::DefId;
 use middle::const_val::ConstVal;
 use traits::Reveal;
-use ty::subst::{Kind, Substs};
+use ty::subst::{UnpackedKind, Substs};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::{TypeVisitor, TypeFolder};
 use ty::error::{ExpectedFound, TypeError};
@@ -142,12 +142,14 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
 
     let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances.map_or(ty::Invariant, |v| v[i]);
-        if let (Some(a_ty), Some(b_ty)) = (a.as_type(), b.as_type()) {
-            Ok(Kind::from(relation.relate_with_variance(variance, &a_ty, &b_ty)?))
-        } else if let (Some(a_r), Some(b_r)) = (a.as_region(), b.as_region()) {
-            Ok(Kind::from(relation.relate_with_variance(variance, &a_r, &b_r)?))
-        } else {
-            bug!()
+        match (a.unpack(), b.unpack()) {
+            (UnpackedKind::Lifetime(a_lt), UnpackedKind::Lifetime(b_lt)) => {
+                Ok(relation.relate_with_variance(variance, &a_lt, &b_lt)?.into())
+            }
+            (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => {
+                Ok(relation.relate_with_variance(variance, &a_ty, &b_ty)?.into())
+            }
+            (UnpackedKind::Lifetime(_), _) | (UnpackedKind::Type(_), _) => bug!()
         }
     });
 
index 961c2650afdefc995bc256deece40915defc071c..a18e8f578364d21033bc85b458b3bcfadf434b02 100644 (file)
 use middle::const_val::ConstVal;
 use middle::region;
 use rustc_data_structures::indexed_vec::Idx;
-use ty::subst::{Substs, Subst};
+use ty::subst::{Substs, Subst, Kind, UnpackedKind};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
-use ty::subst::Kind;
 
 use std::iter;
 use std::cmp::Ordering;
@@ -297,8 +296,8 @@ fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitClosureSubsts<'tc
         let generics = tcx.generics_of(def_id);
         let parent_len = generics.parent_count();
         SplitClosureSubsts {
-            closure_kind_ty: self.substs[parent_len].as_type().expect("CK should be a type"),
-            closure_sig_ty: self.substs[parent_len + 1].as_type().expect("CS should be a type"),
+            closure_kind_ty: self.substs.type_at(parent_len),
+            closure_sig_ty: self.substs.type_at(parent_len + 1),
             upvar_kinds: &self.substs[parent_len + 2..],
         }
     }
@@ -308,7 +307,13 @@ pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) ->
         impl Iterator<Item=Ty<'tcx>> + 'tcx
     {
         let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
-        upvar_kinds.iter().map(|t| t.as_type().expect("upvar should be type"))
+        upvar_kinds.iter().map(|t| {
+            if let UnpackedKind::Type(ty) = t.unpack() {
+                ty
+            } else {
+                bug!("upvar should be type")
+            }
+        })
     }
 
     /// Returns the closure kind for this closure; may return a type
@@ -620,7 +625,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
         ty::TraitRef {
             def_id: self.def_id,
             substs: tcx.mk_substs(
-                iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned()))
+                iter::once(self_ty.into()).chain(self.substs.iter().cloned()))
         }
     }
 }
@@ -645,7 +650,7 @@ pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a
 /// erase, or otherwise "discharge" these bound regions, we change the
 /// type from `Binder<T>` to just `T` (see
 /// e.g. `liberate_late_bound_regions`).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct Binder<T>(pub T);
 
 impl<T> Binder<T> {
@@ -745,7 +750,7 @@ pub fn split<U,V,F>(self, f: F) -> (Binder<U>, Binder<V>)
 
 /// Represents the projection of an associated type. In explicit UFCS
 /// form this would be written `<T as Trait<..>>::N`.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct ProjectionTy<'tcx> {
     /// The parameters of the associated item.
     pub substs: &'tcx Substs<'tcx>,
@@ -1127,7 +1132,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
             projection_ty: ty::ProjectionTy {
                 item_def_id: self.item_def_id,
                 substs: tcx.mk_substs(
-                iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())),
+                iter::once(self_ty.into()).chain(self.substs.iter().cloned())),
             },
             ty: self.ty,
         }
index 7c167f69ebd8c063c504cd9c671437f212a0175c..5e3417e98c2e9551d42c7a19f58a8f462acfa70b 100644 (file)
@@ -18,6 +18,7 @@
 use syntax_pos::{Span, DUMMY_SP};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
+use core::intrinsics;
 use core::nonzero::NonZero;
 use std::fmt;
 use std::iter;
@@ -29,7 +30,7 @@
 /// To reduce memory usage, a `Kind` is a interned pointer,
 /// with the lowest 2 bits being reserved for a tag to
 /// indicate the type (`Ty` or `Region`) it points to.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Kind<'tcx> {
     ptr: NonZero<usize>,
     marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>)>
@@ -39,15 +40,29 @@ pub struct Kind<'tcx> {
 const TYPE_TAG: usize = 0b00;
 const REGION_TAG: usize = 0b01;
 
-impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
-    fn from(ty: Ty<'tcx>) -> Kind<'tcx> {
-        // Ensure we can use the tag bits.
-        assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
+pub enum UnpackedKind<'tcx> {
+    Lifetime(ty::Region<'tcx>),
+    Type(Ty<'tcx>),
+}
+
+impl<'tcx> UnpackedKind<'tcx> {
+    fn pack(self) -> Kind<'tcx> {
+        let (tag, ptr) = match self {
+            UnpackedKind::Lifetime(lt) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(lt) & TAG_MASK, 0);
+                (REGION_TAG, lt as *const _ as usize)
+            }
+            UnpackedKind::Type(ty) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
+                (TYPE_TAG, ty as *const _ as usize)
+            }
+        };
 
-        let ptr = ty as *const _ as usize;
         Kind {
             ptr: unsafe {
-                NonZero::new_unchecked(ptr | TYPE_TAG)
+                NonZero::new_unchecked(ptr | tag)
             },
             marker: PhantomData
         }
@@ -56,88 +71,60 @@ fn from(ty: Ty<'tcx>) -> Kind<'tcx> {
 
 impl<'tcx> From<ty::Region<'tcx>> for Kind<'tcx> {
     fn from(r: ty::Region<'tcx>) -> Kind<'tcx> {
-        // Ensure we can use the tag bits.
-        assert_eq!(mem::align_of_val(r) & TAG_MASK, 0);
+        UnpackedKind::Lifetime(r).pack()
+    }
+}
 
-        let ptr = r as *const _ as usize;
-        Kind {
-            ptr: unsafe {
-                NonZero::new_unchecked(ptr | REGION_TAG)
-            },
-            marker: PhantomData
-        }
+impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
+    fn from(ty: Ty<'tcx>) -> Kind<'tcx> {
+        UnpackedKind::Type(ty).pack()
     }
 }
 
 impl<'tcx> Kind<'tcx> {
     #[inline]
-    unsafe fn downcast<T>(self, tag: usize) -> Option<&'tcx T> {
+    pub fn unpack(self) -> UnpackedKind<'tcx> {
         let ptr = self.ptr.get();
-        if ptr & TAG_MASK == tag {
-            Some(&*((ptr & !TAG_MASK) as *const _))
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    pub fn as_type(self) -> Option<Ty<'tcx>> {
-        unsafe {
-            self.downcast(TYPE_TAG)
-        }
-    }
-
-    #[inline]
-    pub fn as_region(self) -> Option<ty::Region<'tcx>> {
         unsafe {
-            self.downcast(REGION_TAG)
+            match ptr & TAG_MASK {
+                REGION_TAG => UnpackedKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)),
+                TYPE_TAG => UnpackedKind::Type(&*((ptr & !TAG_MASK) as *const _)),
+                _ => intrinsics::unreachable()
+            }
         }
     }
 }
 
 impl<'tcx> fmt::Debug for Kind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(ty) = self.as_type() {
-            write!(f, "{:?}", ty)
-        } else if let Some(r) = self.as_region() {
-            write!(f, "{:?}", r)
-        } else {
-            write!(f, "<unknown @ {:p}>", self.ptr.get() as *const ())
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => write!(f, "{:?}", lt),
+            UnpackedKind::Type(ty) => write!(f, "{:?}", ty),
         }
     }
 }
 
 impl<'tcx> fmt::Display for Kind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(ty) = self.as_type() {
-            write!(f, "{}", ty)
-        } else if let Some(r) = self.as_region() {
-            write!(f, "{}", r)
-        } else {
-            // FIXME(RFC 2000): extend this if/else chain when we support const generic.
-            unimplemented!();
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => write!(f, "{}", lt),
+            UnpackedKind::Type(ty) => write!(f, "{}", ty),
         }
     }
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        if let Some(ty) = self.as_type() {
-            Kind::from(ty.fold_with(folder))
-        } else if let Some(r) = self.as_region() {
-            Kind::from(r.fold_with(folder))
-        } else {
-            bug!()
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => lt.fold_with(folder).into(),
+            UnpackedKind::Type(ty) => ty.fold_with(folder).into(),
         }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        if let Some(ty) = self.as_type() {
-            ty.visit_with(visitor)
-        } else if let Some(r) = self.as_region() {
-            r.visit_with(visitor)
-        } else {
-            bug!()
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => lt.visit_with(visitor),
+            UnpackedKind::Type(ty) => ty.visit_with(visitor),
         }
     }
 }
@@ -145,16 +132,17 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 impl<'tcx> Encodable for Kind<'tcx> {
     fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_enum("Kind", |e| {
-            if let Some(ty) = self.as_type() {
-                e.emit_enum_variant("Ty", TYPE_TAG, 1, |e| {
-                    e.emit_enum_variant_arg(0, |e| ty.encode(e))
-                })
-            } else if let Some(r) = self.as_region() {
-                e.emit_enum_variant("Region", REGION_TAG, 1, |e| {
-                    e.emit_enum_variant_arg(0, |e| r.encode(e))
-                })
-            } else {
-                bug!()
+            match self.unpack() {
+                UnpackedKind::Lifetime(lt) => {
+                    e.emit_enum_variant("Region", REGION_TAG, 1, |e| {
+                        e.emit_enum_variant_arg(0, |e| lt.encode(e))
+                    })
+                }
+                UnpackedKind::Type(ty) => {
+                    e.emit_enum_variant("Ty", TYPE_TAG, 1, |e| {
+                        e.emit_enum_variant_arg(0, |e| ty.encode(e))
+                    })
+                }
             }
         })
     }
@@ -247,7 +235,7 @@ fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
             let def = types.next().unwrap();
             let ty = mk_type(def, substs);
             assert_eq!(def.index as usize, substs.len());
-            substs.push(Kind::from(ty));
+            substs.push(ty.into());
         }
 
         for def in &defs.regions {
@@ -269,26 +257,42 @@ pub fn is_noop(&self) -> bool {
 
     #[inline]
     pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
-        self.iter().filter_map(|k| k.as_type())
+        self.iter().filter_map(|k| {
+            if let UnpackedKind::Type(ty) = k.unpack() {
+                Some(ty)
+            } else {
+                None
+            }
+        })
     }
 
     #[inline]
     pub fn regions(&'a self) -> impl DoubleEndedIterator<Item=ty::Region<'tcx>> + 'a {
-        self.iter().filter_map(|k| k.as_region())
+        self.iter().filter_map(|k| {
+            if let UnpackedKind::Lifetime(lt) = k.unpack() {
+                Some(lt)
+            } else {
+                None
+            }
+        })
     }
 
     #[inline]
     pub fn type_at(&self, i: usize) -> Ty<'tcx> {
-        self[i].as_type().unwrap_or_else(|| {
+        if let UnpackedKind::Type(ty) = self[i].unpack() {
+            ty
+        } else {
             bug!("expected type for param #{} in {:?}", i, self);
-        })
+        }
     }
 
     #[inline]
     pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
-        self[i].as_region().unwrap_or_else(|| {
+        if let UnpackedKind::Lifetime(lt) = self[i].unpack() {
+            lt
+        } else {
             bug!("expected region for param #{} in {:?}", i, self);
-        })
+        }
     }
 
     #[inline]
@@ -413,13 +417,12 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         // the specialized routine `ty::replace_late_regions()`.
         match *r {
             ty::ReEarlyBound(data) => {
-                let r = self.substs.get(data.index as usize)
-                            .and_then(|k| k.as_region());
+                let r = self.substs.get(data.index as usize).map(|k| k.unpack());
                 match r {
-                    Some(r) => {
-                        self.shift_region_through_binders(r)
+                    Some(UnpackedKind::Lifetime(lt)) => {
+                        self.shift_region_through_binders(lt)
                     }
-                    None => {
+                    _ => {
                         let span = self.span.unwrap_or(DUMMY_SP);
                         span_bug!(
                             span,
@@ -470,11 +473,10 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
 impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
     fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
         // Look up the type in the substitutions. It really should be in there.
-        let opt_ty = self.substs.get(p.idx as usize)
-                         .and_then(|k| k.as_type());
+        let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack());
         let ty = match opt_ty {
-            Some(t) => t,
-            None => {
+            Some(UnpackedKind::Type(ty)) => ty,
+            _ => {
                 let span = self.span.unwrap_or(DUMMY_SP);
                 span_bug!(
                     span,
@@ -600,7 +602,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
             ty::TraitRef {
                 def_id: trait_ref.def_id,
                 substs: tcx.mk_substs(
-                    iter::once(Kind::from(self_ty)).chain(trait_ref.substs.iter().cloned()))
+                    iter::once(self_ty.into()).chain(trait_ref.substs.iter().cloned()))
             }
         })
     }
index 34f05232adcab06d21587ce106a9bdce24015cbd..110808919e905fc65f725e4a8724be03c558f23f 100644 (file)
@@ -19,7 +19,7 @@
 use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::TypeVisitor;
-use ty::subst::{Subst, Kind};
+use ty::subst::{Subst, UnpackedKind};
 use ty::TypeVariants::*;
 use util::common::ErrorReported;
 use middle::lang_items;
@@ -509,16 +509,20 @@ pub fn destructor_constraints(self, def: &'tcx ty::AdtDef)
 
         let result = item_substs.iter().zip(impl_substs.iter())
             .filter(|&(_, &k)| {
-                if let Some(&ty::RegionKind::ReEarlyBound(ref ebr)) = k.as_region() {
-                    !impl_generics.region_param(ebr, self).pure_wrt_drop
-                } else if let Some(&ty::TyS {
-                    sty: ty::TypeVariants::TyParam(ref pt), ..
-                }) = k.as_type() {
-                    !impl_generics.type_param(pt, self).pure_wrt_drop
-                } else {
-                    // not a type or region param - this should be reported
-                    // as an error.
-                    false
+                match k.unpack() {
+                    UnpackedKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => {
+                        !impl_generics.region_param(ebr, self).pure_wrt_drop
+                    }
+                    UnpackedKind::Type(&ty::TyS {
+                        sty: ty::TypeVariants::TyParam(ref pt), ..
+                    }) => {
+                        !impl_generics.type_param(pt, self).pure_wrt_drop
+                    }
+                    UnpackedKind::Lifetime(_) | UnpackedKind::Type(_) => {
+                        // not a type or region param - this should be reported
+                        // as an error.
+                        false
+                    }
                 }
             }).map(|(&item_param, _)| item_param).collect();
         debug!("destructor_constraint({:?}) = {:?}", def.did, result);
@@ -596,7 +600,7 @@ pub fn dtorck_constraint_for_ty(self,
             // Objects must be alive in order for their destructor
             // to be called.
             ty::TyDynamic(..) => Ok(ty::DtorckConstraint {
-                outlives: vec![Kind::from(ty)],
+                outlives: vec![ty.into()],
                 dtorck_types: vec![],
             }),
 
index 21dca99aa500504c8924fae1ee5735ca895a7355..a0f84a6ab04959a23980467c0a049506dca2ada7 100644 (file)
@@ -33,6 +33,7 @@ pub fn opts() -> TargetOptions {
         has_rpath: true,
         pre_link_args: args,
         position_independent_executables: true,
+        eliminate_frame_pointer: false, // FIXME 43575
         relro_level: RelroLevel::Full,
         exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
index 2872c59157d6be1cf1b5d73aec7f39d8e0aa584b..d356105e39314c6aa7d268e67b52a9d9c14ac7e2 100644 (file)
@@ -146,6 +146,7 @@ fn $module() {
     ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
     ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
+    ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
     ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
     ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
@@ -186,6 +187,7 @@ fn $module() {
     ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
 
     ("i686-unknown-netbsd", i686_unknown_netbsd),
+    ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
     ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
     ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
     ("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),
diff --git a/src/librustc_back/target/powerpc_unknown_netbsd.rs b/src/librustc_back/target/powerpc_unknown_netbsd.rs
new file mode 100644 (file)
index 0000000..2c78dbd
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::netbsd_base::opts();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
+    base.max_atomic_width = Some(32);
+
+    // see #36994
+    base.exe_allocation_crate = None;
+
+    Ok(Target {
+        llvm_target: "powerpc-unknown-netbsd".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
+        arch: "powerpc".to_string(),
+        target_os: "netbsd".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/sparc_unknown_linux_gnu.rs b/src/librustc_back/target/sparc_unknown_linux_gnu.rs
new file mode 100644 (file)
index 0000000..a03e693
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_base::opts();
+    base.cpu = "v9".to_string();
+    base.max_atomic_width = Some(64);
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string());
+    base.exe_allocation_crate = None;
+
+    Ok(Target {
+        llvm_target: "sparc-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".to_string(),
+        arch: "sparc".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
index e30f5cb4f12935566b7543397e53aeeae557335e..54e3418d4f0178fb1ba1f93b860b8bb67c2fb4bd 100644 (file)
@@ -878,7 +878,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
         ty::TyAdt(adt, substs) => {
             if adt.is_box() {
                 // Use T as the sub pattern type of Box<T>.
-                vec![substs[0].as_type().unwrap()]
+                vec![substs.type_at(0)]
             } else {
                 adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
index 7665bfd5b1117316c0a758338ad103adca34e2b5..2678861be0634e3588510406bc2f403ac40a5c6e 100644 (file)
@@ -24,6 +24,7 @@ pub trait BitSlice {
 
 impl BitSlice for [Word] {
     /// Clears bit at `idx` to 0; returns true iff this changed `self.`
+    #[inline]
     fn clear_bit(&mut self, idx: usize) -> bool {
         let words = self;
         debug!("clear_bit: words={} idx={}",
@@ -37,6 +38,7 @@ fn clear_bit(&mut self, idx: usize) -> bool {
     }
 
     /// Sets bit at `idx` to 1; returns true iff this changed `self.`
+    #[inline]
     fn set_bit(&mut self, idx: usize) -> bool {
         let words = self;
         debug!("set_bit: words={} idx={}",
@@ -50,6 +52,7 @@ fn set_bit(&mut self, idx: usize) -> bool {
     }
 
     /// Extracts value of bit at `idx` in `self`.
+    #[inline]
     fn get_bit(&self, idx: usize) -> bool {
         let words = self;
         let BitLookup { word, bit_mask, .. } = bit_lookup(idx);
index 3e94b3f4d302a95029b495b1887b65e6573a753e..11c2bd7368760b90f99fa8d98a1ebcf945376735 100644 (file)
@@ -29,12 +29,16 @@ pub trait Idx: Copy + 'static + Eq + Debug {
 }
 
 impl Idx for usize {
+    #[inline]
     fn new(idx: usize) -> Self { idx }
+    #[inline]
     fn index(self) -> usize { self }
 }
 
 impl Idx for u32 {
+    #[inline]
     fn new(idx: usize) -> Self { assert!(idx <= u32::MAX as usize); idx as u32 }
+    #[inline]
     fn index(self) -> usize { self as usize }
 }
 
@@ -73,11 +77,13 @@ macro_rules! newtype_index {
         pub struct $type($($pub)* u32);
 
         impl Idx for $type {
+            #[inline]
             fn new(value: usize) -> Self {
                 assert!(value < ($max) as usize);
                 $type(value as u32)
             }
 
+            #[inline]
             fn index(self) -> usize {
                 self.0 as usize
             }
index eb67c9ce4b7d8be2e614f59df1ff71bb87823e11..b03108ed807da0060ecf67e8c37db32cf901ef0f 100644 (file)
@@ -36,7 +36,7 @@
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
-use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
+use rustc_passes::{self, ast_validation, loops, consts, hir_stats};
 use rustc_const_eval::{self, check_match};
 use super::Compilation;
 
@@ -818,7 +818,8 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
                                          &mut resolver,
                                          sess.opts.test,
                                          krate,
-                                         sess.diagnostic())
+                                         sess.diagnostic(),
+                                         &sess.features.borrow())
     });
 
     // If we're actually rustdoc then there's no need to actually compile
@@ -931,6 +932,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
 }
 
 pub fn default_provide(providers: &mut ty::maps::Providers) {
+    hir::provide(providers);
     borrowck::provide(providers);
     mir::provide(providers);
     reachable::provide(providers);
@@ -990,10 +992,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
          "loop checking",
          || loops::check_crate(sess, &hir_map));
 
-    time(time_passes,
-              "static item recursion checking",
-              || static_recursion::check_crate(sess, &hir_map))?;
-
     let mut local_providers = ty::maps::Providers::default();
     default_provide(&mut local_providers);
     trans.provide(&mut local_providers);
index 306e7e9c16dce2c5b05611fcad78ba6f9b4e9036..35d2205cf33f3cea858e9e58c8dfd12ad4892be4 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
 use rustc::middle::region;
-use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::subst::Subst;
 use rustc::traits::{ObligationCause, Reveal};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::maps::OnDiskCache;
@@ -468,7 +468,7 @@ fn subst_ty_renumber_bound() {
             env.t_fn(&[t_param], env.t_nil())
         };
 
-        let substs = env.infcx.tcx.intern_substs(&[Kind::from(t_rptr_bound1)]);
+        let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]);
         let t_substituted = t_source.subst(env.infcx.tcx, substs);
 
         // t_expected = fn(&'a isize)
@@ -503,7 +503,7 @@ fn subst_ty_renumber_some_bounds() {
             env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil()))
         };
 
-        let substs = env.infcx.tcx.intern_substs(&[Kind::from(t_rptr_bound1)]);
+        let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]);
         let t_substituted = t_source.subst(env.infcx.tcx, substs);
 
         // t_expected = (&'a isize, fn(&'a isize))
@@ -565,7 +565,7 @@ fn subst_region_renumber_region() {
             env.t_fn(&[env.t_rptr(re_early)], env.t_nil())
         };
 
-        let substs = env.infcx.tcx.intern_substs(&[Kind::from(re_bound1)]);
+        let substs = env.infcx.tcx.intern_substs(&[re_bound1.into()]);
         let t_substituted = t_source.subst(env.infcx.tcx, substs);
 
         // t_expected = fn(&'a isize)
index 699765dde03ffa50070e8636501c14682dc8295c..f3c6ff2f2b3a10ba8aeb720eb8adabb67e4bc157 100644 (file)
@@ -152,6 +152,12 @@ macro_rules! add_lint_group {
                     NON_SNAKE_CASE,
                     NON_UPPER_CASE_GLOBALS);
 
+    add_lint_group!(sess,
+                    "nonstandard_style",
+                    NON_CAMEL_CASE_TYPES,
+                    NON_SNAKE_CASE,
+                    NON_UPPER_CASE_GLOBALS);
+
     add_lint_group!(sess,
                     "unused",
                     UNUSED_IMPORTS,
index 7ca8d0bdd500bb841a8dc849ce5b5ed4909d900d..d57b8e78f18a9b1ebbfd090ecfd1798096514a74 100644 (file)
@@ -1585,6 +1585,12 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &
         let id = tcx.hir.as_local_node_id(def_id).unwrap();
         debug!("run_pass: {:?}", def_id);
 
+        // When NLL is enabled, the borrow checker runs the typeck
+        // itself, so we don't need this MIR pass anymore.
+        if tcx.sess.nll() {
+            return;
+        }
+
         if tcx.sess.err_count() > 0 {
             // compiling a broken program can obviously result in a
             // broken MIR, so try not to report duplicate errors.
index 635d99e7737a97467025175374c2b11837bea2d9..d6f419f6cfb41d5eb68ac5428fbd62aaf95d9263 100644 (file)
@@ -353,9 +353,12 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
                 self.gather_move(&Place::Local(RETURN_PLACE));
             }
 
-            TerminatorKind::Assert { .. } |
-            TerminatorKind::SwitchInt { .. } => {
-                // branching terminators - these don't move anything
+            TerminatorKind::Assert { ref cond, .. } => {
+                self.gather_operand(cond);
+            }
+
+            TerminatorKind::SwitchInt { ref discr, .. } => {
+                self.gather_operand(discr);
             }
 
             TerminatorKind::Yield { ref value, .. } => {
index 3578164feb7c5796f5dcd628f0e44d0e5b186989..08c16fed5dd3fd074a0c75e42a2924128bb68681 100644 (file)
@@ -7,7 +7,7 @@
 use rustc::mir;
 use rustc::traits::Reveal;
 use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
-use rustc::ty::subst::{Subst, Substs, Kind};
+use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax::codemap::{self, DUMMY_SP};
@@ -1663,6 +1663,6 @@ pub fn resolve_drop_in_place<'a, 'tcx>(
     ty: Ty<'tcx>,
 ) -> ty::Instance<'tcx> {
     let def_id = tcx.require_lang_item(::rustc::middle::lang_items::DropInPlaceFnLangItem);
-    let substs = tcx.intern_substs(&[Kind::from(ty)]);
+    let substs = tcx.intern_substs(&[ty.into()]);
     ty::Instance::resolve(tcx, ty::ParamEnv::empty(Reveal::All), def_id, substs).unwrap()
 }
index a80dfaef0dab1b276ff74892f80facd2c3d879b9..eb4ba21489c3dc310d66eeae8b7c00bfbaf0190d 100644 (file)
@@ -368,8 +368,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let recursion_depth_reset;
 
     match starting_point {
-        MonoItem::Static(node_id) => {
-            let def_id = tcx.hir.local_def_id(node_id);
+        MonoItem::Static(def_id) => {
             let instance = Instance::mono(tcx, def_id);
 
             // Sanity check whether this ended up being collected accidentally
@@ -652,8 +651,7 @@ fn visit_static(&mut self,
         let tcx = self.tcx;
         let instance = Instance::mono(tcx, static_.def_id);
         if should_monomorphize_locally(tcx, &instance) {
-            let node_id = tcx.hir.as_local_node_id(static_.def_id).unwrap();
-            self.output.push(MonoItem::Static(node_id));
+            self.output.push(MonoItem::Static(static_.def_id));
         }
 
         self.super_static(static_, context, location);
@@ -946,10 +944,10 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                 self.output.push(MonoItem::GlobalAsm(item.id));
             }
             hir::ItemStatic(..) => {
+                let def_id = self.tcx.hir.local_def_id(item.id);
                 debug!("RootCollector: ItemStatic({})",
-                       def_id_to_string(self.tcx,
-                                        self.tcx.hir.local_def_id(item.id)));
-                self.output.push(MonoItem::Static(item.id));
+                       def_id_to_string(self.tcx, def_id));
+                self.output.push(MonoItem::Static(def_id));
             }
             hir::ItemConst(..) => {
                 // const items only generate mono items if they are
index a5078187a57e30d14e60a7981487ce0d942f08ce..549919a2c891925d620aae621f8a85ae2ed80a56 100644 (file)
@@ -97,8 +97,7 @@ fn is_generic_fn(&self) -> bool {
     fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
         match *self.as_mono_item() {
             MonoItem::Fn(instance) => tcx.symbol_name(instance),
-            MonoItem::Static(node_id) => {
-                let def_id = tcx.hir.local_def_id(node_id);
+            MonoItem::Static(def_id) => {
                 tcx.symbol_name(Instance::mono(tcx, def_id))
             }
             MonoItem::GlobalAsm(node_id) => {
@@ -159,7 +158,7 @@ fn instantiation_mode(&self,
     fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Linkage> {
         let def_id = match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => instance.def_id(),
-            MonoItem::Static(node_id) => tcx.hir.local_def_id(node_id),
+            MonoItem::Static(def_id) => def_id,
             MonoItem::GlobalAsm(..) => return None,
         };
 
@@ -209,7 +208,7 @@ fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
         debug!("is_instantiable({:?})", self);
         let (def_id, substs) = match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
-            MonoItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
+            MonoItem::Static(def_id) => (def_id, Substs::empty()),
             // global asm never has predicates
             MonoItem::GlobalAsm(..) => return true
         };
@@ -218,14 +217,11 @@ fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
     }
 
     fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
-        let hir_map = &tcx.hir;
-
         return match *self.as_mono_item() {
             MonoItem::Fn(instance) => {
                 to_string_internal(tcx, "fn ", instance)
             },
-            MonoItem::Static(node_id) => {
-                let def_id = hir_map.local_def_id(node_id);
+            MonoItem::Static(def_id) => {
                 let instance = Instance::new(def_id, tcx.intern_substs(&[]));
                 to_string_internal(tcx, "static ", instance)
             },
@@ -251,7 +247,9 @@ fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
             MonoItem::Fn(Instance { def, .. }) => {
                 tcx.hir.as_local_node_id(def.def_id())
             }
-            MonoItem::Static(node_id) |
+            MonoItem::Static(def_id) => {
+                tcx.hir.as_local_node_id(def_id)
+            }
             MonoItem::GlobalAsm(node_id) => {
                 Some(node_id)
             }
index 95ebb6c970a588ec4c3758818f4bd7ff88bec703..2ca6c76a8009a058e18f8bdc1c2e33f958544f8e 100644 (file)
@@ -92,7 +92,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
         Kind::from(self_ty),
-        Kind::from(sig.inputs()[0]),
+        sig.inputs()[0].into(),
     ].iter().cloned());
 
     debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
@@ -153,7 +153,7 @@ pub fn resolve_drop_in_place<'a, 'tcx>(
     -> ty::Instance<'tcx>
 {
     let def_id = tcx.require_lang_item(DropInPlaceFnLangItem);
-    let substs = tcx.intern_substs(&[Kind::from(ty)]);
+    let substs = tcx.intern_substs(&[ty.into()]);
     Instance::resolve(tcx, ty::ParamEnv::empty(traits::Reveal::All), def_id, substs).unwrap()
 }
 
index e9471cdb4f9497658b91a27108906d88f72e98dc..2b558e71483c67e893317c7130ab220066ff0f62 100644 (file)
@@ -180,7 +180,9 @@ fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         }
                     }
                 }
-                MonoItem::Static(node_id) |
+                MonoItem::Static(def_id) => {
+                    tcx.hir.as_local_node_id(def_id)
+                }
                 MonoItem::GlobalAsm(node_id) => {
                     Some(node_id)
                 }
@@ -382,7 +384,15 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         };
                         (Linkage::External, visibility)
                     }
-                    MonoItem::Static(node_id) |
+                    MonoItem::Static(def_id) => {
+                        let visibility = if tcx.is_exported_symbol(def_id) {
+                            can_be_internalized = false;
+                            default_visibility(def_id)
+                        } else {
+                            Visibility::Hidden
+                        };
+                        (Linkage::External, visibility)
+                    }
                     MonoItem::GlobalAsm(node_id) => {
                         let def_id = tcx.hir.local_def_id(node_id);
                         let visibility = if tcx.is_exported_symbol(def_id) {
@@ -643,7 +653,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             Some(def_id)
         }
-        MonoItem::Static(node_id) |
+        MonoItem::Static(def_id) => Some(def_id),
         MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
     }
 }
index bbc7803b84d8e1a87e68b52102533d4a32ed3134..3524255e03772328311120212f8c7fee12933e11 100644 (file)
@@ -386,10 +386,13 @@ fn is_enclosed(tcx: TyCtxt,
         if used_unsafe.contains(&parent_id) {
             Some(("block".to_string(), parent_id))
         } else if let Some(hir::map::NodeItem(&hir::Item {
-            node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
+            node: hir::ItemFn(_, fn_unsafety, _, _, _, _),
             ..
         })) = tcx.hir.find(parent_id) {
-            Some(("fn".to_string(), parent_id))
+            match fn_unsafety {
+                hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)),
+                hir::Unsafety::Normal => None,
+            }
         } else {
             is_enclosed(tcx, used_unsafe, parent_id)
         }
index 812665f5fa49804d3b2648206e50496bce011977..04ebaa031fe5a305548574865e2c1724fe61dac1 100644 (file)
@@ -65,7 +65,7 @@
 use rustc::mir::*;
 use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
-use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::subst::Substs;
 use util::dump_mir;
 use util::liveness::{self, LivenessMode};
 use rustc_const_math::ConstInt;
@@ -858,8 +858,8 @@ fn run_pass<'a, 'tcx>(&self,
         // Compute GeneratorState<yield_ty, return_ty>
         let state_did = tcx.lang_items().gen_state().unwrap();
         let state_adt_ref = tcx.adt_def(state_did);
-        let state_substs = tcx.mk_substs([Kind::from(yield_ty),
-            Kind::from(mir.return_ty())].iter());
+        let state_substs = tcx.mk_substs([yield_ty.into(),
+            mir.return_ty().into()].iter());
         let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
         // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
index bb6dbe632e3168d1f57317f019ab4a508ac37d3c..a5dd8f1558e4392b8e59c5d9a045bbc44803fe79 100644 (file)
@@ -419,6 +419,141 @@ fn visit_pat(&mut self, pat: &'a Pat) {
     }
 }
 
+// Bans nested `impl Trait`, e.g. `impl Into<impl Debug>`.
+// Nested `impl Trait` _is_ allowed in associated type position,
+// e.g `impl Iterator<Item=impl Debug>`
+struct NestedImplTraitVisitor<'a> {
+    session: &'a Session,
+    outer_impl_trait: Option<Span>,
+}
+
+impl<'a> NestedImplTraitVisitor<'a> {
+    fn with_impl_trait<F>(&mut self, outer_impl_trait: Option<Span>, f: F)
+        where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
+    {
+        let old_outer_impl_trait = self.outer_impl_trait;
+        self.outer_impl_trait = outer_impl_trait;
+        f(self);
+        self.outer_impl_trait = old_outer_impl_trait;
+    }
+}
+
+
+impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
+    fn visit_ty(&mut self, t: &'a Ty) {
+        if let TyKind::ImplTrait(_) = t.node {
+            if let Some(outer_impl_trait) = self.outer_impl_trait {
+                struct_span_err!(self.session, t.span, E0666,
+                                 "nested `impl Trait` is not allowed")
+                    .span_label(outer_impl_trait, "outer `impl Trait`")
+                    .span_label(t.span, "nested `impl Trait` here")
+                    .emit();
+
+            }
+            self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t));
+        } else {
+            visit::walk_ty(self, t);
+        }
+    }
+    fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a PathParameters) {
+        match *path_parameters {
+            PathParameters::AngleBracketed(ref params) => {
+                for type_ in &params.types {
+                    self.visit_ty(type_);
+                }
+                for type_binding in &params.bindings {
+                    // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
+                    // are allowed to contain nested `impl Trait`.
+                    self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty));
+                }
+            }
+            PathParameters::Parenthesized(ref params) => {
+                for type_ in &params.inputs {
+                    self.visit_ty(type_);
+                }
+                if let Some(ref type_) = params.output {
+                    // `-> Foo` syntax is essentially an associated type binding,
+                    // so it is also allowed to contain nested `impl Trait`.
+                    self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
+                }
+            }
+        }
+    }
+}
+
+// Bans `impl Trait` in path projections like `<impl Iterator>::Item` or `Foo::Bar<impl Trait>`.
+struct ImplTraitProjectionVisitor<'a> {
+    session: &'a Session,
+    is_banned: bool,
+}
+
+impl<'a> ImplTraitProjectionVisitor<'a> {
+    fn with_ban<F>(&mut self, f: F)
+        where F: FnOnce(&mut ImplTraitProjectionVisitor<'a>)
+    {
+        let old_is_banned = self.is_banned;
+        self.is_banned = true;
+        f(self);
+        self.is_banned = old_is_banned;
+    }
+}
+
+impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
+    fn visit_ty(&mut self, t: &'a Ty) {
+        match t.node {
+            TyKind::ImplTrait(_) => {
+                if self.is_banned {
+                    struct_span_err!(self.session, t.span, E0667,
+                                 "`impl Trait` is not allowed in path parameters")
+                        .emit();
+                }
+            }
+            TyKind::Path(ref qself, ref path) => {
+                // We allow these:
+                //  - `Option<impl Trait>`
+                //  - `option::Option<impl Trait>`
+                //  - `option::Option<T>::Foo<impl Trait>
+                //
+                // But not these:
+                //  - `<impl Trait>::Foo`
+                //  - `option::Option<impl Trait>::Foo`.
+                //
+                // To implement this, we disallow `impl Trait` from `qself`
+                // (for cases like `<impl Trait>::Foo>`)
+                // but we allow `impl Trait` in `PathParameters`
+                // iff there are no more PathSegments.
+                if let Some(ref qself) = *qself {
+                    // `impl Trait` in `qself` is always illegal
+                    self.with_ban(|this| this.visit_ty(&qself.ty));
+                }
+
+                for (i, segment) in path.segments.iter().enumerate() {
+                    // Allow `impl Trait` iff we're on the final path segment
+                    if i == (path.segments.len() - 1) {
+                        visit::walk_path_segment(self, path.span, segment);
+                    } else {
+                        self.with_ban(|this|
+                            visit::walk_path_segment(this, path.span, segment));
+                    }
+                }
+            }
+            _ => visit::walk_ty(self, t),
+        }
+    }
+}
+
 pub fn check_crate(session: &Session, krate: &Crate) {
+    visit::walk_crate(
+        &mut NestedImplTraitVisitor {
+            session,
+            outer_impl_trait: None,
+        }, krate);
+
+    visit::walk_crate(
+        &mut ImplTraitProjectionVisitor {
+            session,
+            is_banned: false,
+        }, krate);
+
     visit::walk_crate(&mut AstValidator { session: session }, krate)
 }
index 743f7b7326e9e5c2526d4a09949fba928f549544..184fab778c60191d13dea1b8c3ba404188cde694 100644 (file)
@@ -128,22 +128,6 @@ impl !Enterprise for Foo { }
 Please note that negative impls are only allowed for auto traits.
 "##,
 
-E0265: r##"
-This error indicates that a static or constant references itself.
-All statics and constants need to resolve to a value in an acyclic manner.
-
-For example, neither of the following can be sensibly compiled:
-
-```compile_fail,E0265
-const X: u32 = X;
-```
-
-```compile_fail,E0265
-const X: u32 = Y;
-const Y: u32 = X;
-```
-"##,
-
 E0267: r##"
 This error indicates the use of a loop keyword (`break` or `continue`) inside a
 closure but outside of any loop. Erroneous code example:
@@ -320,4 +304,6 @@ fn foo() {}
     E0567, // auto traits can not have generic parameters
     E0568, // auto traits can not have super traits
     E0642, // patterns aren't allowed in methods without bodies
+    E0666, // nested `impl Trait` is illegal
+    E0667, // `impl Trait` in projections
 }
index 7db1f5665fbe5f83473b2b2984361fe7e503e7e1..6b9f407cbdb4da742317383d34db0adff6c30d57 100644 (file)
@@ -42,7 +42,6 @@
 pub mod hir_stats;
 pub mod loops;
 mod mir_stats;
-pub mod static_recursion;
 
 __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
 
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
deleted file mode 100644 (file)
index 987243b..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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 compiler pass detects constants that refer to themselves
-// recursively.
-
-use rustc::hir::map as hir_map;
-use rustc::session::Session;
-use rustc::hir::def::{Def, CtorKind};
-use rustc::util::common::ErrorReported;
-use rustc::util::nodemap::{NodeMap, NodeSet};
-
-use syntax::ast;
-use syntax_pos::Span;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir;
-
-struct CheckCrateVisitor<'a, 'hir: 'a> {
-    sess: &'a Session,
-    hir_map: &'a hir_map::Map<'hir>,
-    // `discriminant_map` is a cache that associates the `NodeId`s of local
-    // variant definitions with the discriminant expression that applies to
-    // each one. If the variant uses the default values (starting from `0`),
-    // then `None` is stored.
-    discriminant_map: NodeMap<Option<hir::BodyId>>,
-    detected_recursive_ids: NodeSet,
-}
-
-impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_item(&mut self, it: &'hir hir::Item) {
-        match it.node {
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) => {
-                let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
-                recursion_visitor.visit_item(it);
-            }
-            hir::ItemEnum(ref enum_def, ref generics) => {
-                // We could process the whole enum, but handling the variants
-                // with discriminant expressions one by one gives more specific,
-                // less redundant output.
-                for variant in &enum_def.variants {
-                    if let Some(_) = variant.node.disr_expr {
-                        let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
-                        recursion_visitor.populate_enum_discriminants(enum_def);
-                        recursion_visitor.visit_variant(variant, generics, it.id);
-                    }
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_item(self, it)
-    }
-
-    fn visit_trait_item(&mut self, ti: &'hir hir::TraitItem) {
-        match ti.node {
-            hir::TraitItemKind::Const(_, ref default) => {
-                if let Some(_) = *default {
-                    let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
-                    recursion_visitor.visit_trait_item(ti);
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_trait_item(self, ti)
-    }
-
-    fn visit_impl_item(&mut self, ii: &'hir hir::ImplItem) {
-        match ii.node {
-            hir::ImplItemKind::Const(..) => {
-                let mut recursion_visitor = CheckItemRecursionVisitor::new(self);
-                recursion_visitor.visit_impl_item(ii);
-            }
-            _ => {}
-        }
-        intravisit::walk_impl_item(self, ii)
-    }
-}
-
-pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>)
-                         -> Result<(), ErrorReported>
-{
-    let mut visitor = CheckCrateVisitor {
-        sess,
-        hir_map,
-        discriminant_map: NodeMap(),
-        detected_recursive_ids: NodeSet(),
-    };
-    sess.track_errors(|| {
-        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
-        hir_map.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
-    })
-}
-
-struct CheckItemRecursionVisitor<'a, 'b: 'a, 'hir: 'b> {
-    sess: &'b Session,
-    hir_map: &'b hir_map::Map<'hir>,
-    discriminant_map: &'a mut NodeMap<Option<hir::BodyId>>,
-    idstack: Vec<ast::NodeId>,
-    detected_recursive_ids: &'a mut NodeSet,
-}
-
-impl<'a, 'b: 'a, 'hir: 'b> CheckItemRecursionVisitor<'a, 'b, 'hir> {
-    fn new(v: &'a mut CheckCrateVisitor<'b, 'hir>) -> Self {
-        CheckItemRecursionVisitor {
-            sess: v.sess,
-            hir_map: v.hir_map,
-            discriminant_map: &mut v.discriminant_map,
-            idstack: Vec::new(),
-            detected_recursive_ids: &mut v.detected_recursive_ids,
-        }
-    }
-    fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F, span: Span)
-        where F: Fn(&mut Self)
-    {
-        if self.idstack.iter().any(|&x| x == id) {
-            if self.detected_recursive_ids.contains(&id) {
-                return;
-            }
-            self.detected_recursive_ids.insert(id);
-            let any_static = self.idstack.iter().any(|&x| {
-                if let hir_map::NodeItem(item) = self.hir_map.get(x) {
-                    if let hir::ItemStatic(..) = item.node {
-                        true
-                    } else {
-                        false
-                    }
-                } else {
-                    false
-                }
-            });
-            if !any_static {
-                struct_span_err!(self.sess, span, E0265, "recursive constant")
-                    .span_label(span, "recursion not allowed in constant")
-                    .emit();
-            }
-            return;
-        }
-        self.idstack.push(id);
-        f(self);
-        self.idstack.pop();
-    }
-    // If a variant has an expression specifying its discriminant, then it needs
-    // to be checked just like a static or constant. However, if there are more
-    // variants with no explicitly specified discriminant, those variants will
-    // increment the same expression to get their values.
-    //
-    // So for every variant, we need to track whether there is an expression
-    // somewhere in the enum definition that controls its discriminant. We do
-    // this by starting from the end and searching backward.
-    fn populate_enum_discriminants(&mut self, enum_definition: &'hir hir::EnumDef) {
-        // Get the map, and return if we already processed this enum or if it
-        // has no variants.
-        match enum_definition.variants.first() {
-            None => {
-                return;
-            }
-            Some(variant) if self.discriminant_map.contains_key(&variant.node.data.id()) => {
-                return;
-            }
-            _ => {}
-        }
-
-        // Go through all the variants.
-        let mut variant_stack: Vec<ast::NodeId> = Vec::new();
-        for variant in enum_definition.variants.iter().rev() {
-            variant_stack.push(variant.node.data.id());
-            // When we find an expression, every variant currently on the stack
-            // is affected by that expression.
-            if let Some(expr) = variant.node.disr_expr {
-                for id in &variant_stack {
-                    self.discriminant_map.insert(*id, Some(expr));
-                }
-                variant_stack.clear()
-            }
-        }
-        // If we are at the top, that always starts at 0, so any variant on the
-        // stack has a default value and does not need to be checked.
-        for id in &variant_stack {
-            self.discriminant_map.insert(*id, None);
-        }
-    }
-}
-
-impl<'a, 'b: 'a, 'hir: 'b> Visitor<'hir> for CheckItemRecursionVisitor<'a, 'b, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
-        NestedVisitorMap::OnlyBodies(&self.hir_map)
-    }
-    fn visit_item(&mut self, it: &'hir hir::Item) {
-        self.with_item_id_pushed(it.id, |v| intravisit::walk_item(v, it), it.span);
-    }
-
-    fn visit_enum_def(&mut self,
-                      enum_definition: &'hir hir::EnumDef,
-                      generics: &'hir hir::Generics,
-                      item_id: ast::NodeId,
-                      _: Span) {
-        self.populate_enum_discriminants(enum_definition);
-        intravisit::walk_enum_def(self, enum_definition, generics, item_id);
-    }
-
-    fn visit_variant(&mut self,
-                     variant: &'hir hir::Variant,
-                     _: &'hir hir::Generics,
-                     _: ast::NodeId) {
-        let variant_id = variant.node.data.id();
-        let maybe_expr = *self.discriminant_map.get(&variant_id).unwrap_or_else(|| {
-            span_bug!(variant.span,
-                      "`check_static_recursion` attempted to visit \
-                      variant with unknown discriminant")
-        });
-        // If `maybe_expr` is `None`, that's because no discriminant is
-        // specified that affects this variant. Thus, no risk of recursion.
-        if let Some(expr) = maybe_expr {
-            let expr = &self.hir_map.body(expr).value;
-            self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr), expr.span);
-        }
-    }
-
-    fn visit_trait_item(&mut self, ti: &'hir hir::TraitItem) {
-        self.with_item_id_pushed(ti.id, |v| intravisit::walk_trait_item(v, ti), ti.span);
-    }
-
-    fn visit_impl_item(&mut self, ii: &'hir hir::ImplItem) {
-        self.with_item_id_pushed(ii.id, |v| intravisit::walk_impl_item(v, ii), ii.span);
-    }
-
-    fn visit_path(&mut self, path: &'hir hir::Path, _: ast::NodeId) {
-        match path.def {
-            Def::Static(def_id, _) |
-            Def::AssociatedConst(def_id) |
-            Def::Const(def_id) => {
-                if let Some(node_id) = self.hir_map.as_local_node_id(def_id) {
-                    match self.hir_map.get(node_id) {
-                        hir_map::NodeItem(item) => self.visit_item(item),
-                        hir_map::NodeTraitItem(item) => self.visit_trait_item(item),
-                        hir_map::NodeImplItem(item) => self.visit_impl_item(item),
-                        hir_map::NodeForeignItem(_) => {}
-                        _ => {
-                            span_bug!(path.span,
-                                      "expected item, found {}",
-                                      self.hir_map.node_to_string(node_id));
-                        }
-                    }
-                }
-            }
-            // For variants, we only want to check expressions that
-            // affect the specific variant used, but we need to check
-            // the whole enum definition to see what expression that
-            // might be (if any).
-            Def::VariantCtor(variant_id, CtorKind::Const) => {
-                if let Some(variant_id) = self.hir_map.as_local_node_id(variant_id) {
-                    let variant = self.hir_map.expect_variant(variant_id);
-                    let enum_id = self.hir_map.get_parent(variant_id);
-                    let enum_item = self.hir_map.expect_item(enum_id);
-                    if let hir::ItemEnum(ref enum_def, ref generics) = enum_item.node {
-                        self.populate_enum_discriminants(enum_def);
-                        self.visit_variant(variant, generics, enum_id);
-                    } else {
-                        span_bug!(path.span,
-                                  "`check_static_recursion` found \
-                                    non-enum in Def::VariantCtor");
-                    }
-                }
-            }
-            _ => (),
-        }
-        intravisit::walk_path(self, path);
-    }
-}
index e6b9150fa3aec0d1e52c2d95fdd102704750e2a9..e4e9ee58330cc58b775692491e72a68164b0b412 100644 (file)
@@ -59,6 +59,7 @@
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
 use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue};
 use syntax::parse::token;
+use syntax::ptr::P;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use errors::{DiagnosticBuilder, DiagnosticId};
@@ -2329,17 +2330,17 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
 
     // check that all of the arms in an or-pattern have exactly the
     // same set of bindings, with the same binding modes for each.
-    fn check_consistent_bindings(&mut self, arm: &Arm) {
-        if arm.pats.is_empty() {
+    fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) {
+        if pats.is_empty() {
             return;
         }
 
         let mut missing_vars = FxHashMap();
         let mut inconsistent_vars = FxHashMap();
-        for (i, p) in arm.pats.iter().enumerate() {
+        for (i, p) in pats.iter().enumerate() {
             let map_i = self.binding_mode_map(&p);
 
-            for (j, q) in arm.pats.iter().enumerate() {
+            for (j, q) in pats.iter().enumerate() {
                 if i == j {
                     continue;
                 }
@@ -2404,9 +2405,8 @@ fn resolve_arm(&mut self, arm: &Arm) {
             self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list);
         }
 
-        // This has to happen *after* we determine which
-        // pat_idents are variants
-        self.check_consistent_bindings(arm);
+        // This has to happen *after* we determine which pat_idents are variants
+        self.check_consistent_bindings(&arm.pats);
 
         walk_list!(self, visit_expr, &arm.guard);
         self.visit_expr(&arm.body);
@@ -2490,7 +2490,9 @@ fn fresh_binding(&mut self,
                         &ident.node.name.as_str())
                 );
             }
-            Some(..) if pat_src == PatternSource::Match => {
+            Some(..) if pat_src == PatternSource::Match ||
+                        pat_src == PatternSource::IfLet ||
+                        pat_src == PatternSource::WhileLet => {
                 // `Variant1(a) | Variant2(a)`, ok
                 // Reuse definition from the first `a`.
                 def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node];
@@ -3480,11 +3482,16 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 visit::walk_expr(self, expr);
             }
 
-            ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
+            ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => {
                 self.visit_expr(subexpression);
 
                 self.ribs[ValueNS].push(Rib::new(NormalRibKind));
-                self.resolve_pattern(pattern, PatternSource::IfLet, &mut FxHashMap());
+                let mut bindings_list = FxHashMap();
+                for pat in pats {
+                    self.resolve_pattern(pat, PatternSource::IfLet, &mut bindings_list);
+                }
+                // This has to happen *after* we determine which pat_idents are variants
+                self.check_consistent_bindings(pats);
                 self.visit_block(if_block);
                 self.ribs[ValueNS].pop();
 
@@ -3500,11 +3507,16 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 });
             }
 
-            ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
+            ExprKind::WhileLet(ref pats, ref subexpression, ref block, label) => {
                 self.with_resolved_label(label, expr.id, |this| {
                     this.visit_expr(subexpression);
                     this.ribs[ValueNS].push(Rib::new(NormalRibKind));
-                    this.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap());
+                    let mut bindings_list = FxHashMap();
+                    for pat in pats {
+                        this.resolve_pattern(pat, PatternSource::WhileLet, &mut bindings_list);
+                    }
+                    // This has to happen *after* we determine which pat_idents are variants
+                    this.check_consistent_bindings(pats);
                     this.visit_block(block);
                     this.ribs[ValueNS].pop();
                 });
index bf82b0774238bf4879273b5c9df5c94d4ba6dea4..6e98604101345a6796fd526a08955020ee430ea8 100644 (file)
@@ -1031,6 +1031,81 @@ fn process_pat(&mut self, p: &'l ast::Pat) {
         }
     }
 
+    fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
+        let mut collector = PathCollector::new();
+        for pattern in pats {
+            // collect paths from the arm's patterns
+            collector.visit_pat(&pattern);
+            self.visit_pat(&pattern);
+        }
+
+        // process collected paths
+        for (id, i, sp, immut) in collector.collected_idents {
+            match self.save_ctxt.get_path_def(id) {
+                HirDef::Local(id) => {
+                    let mut value = if immut == ast::Mutability::Immutable {
+                        self.span.snippet(sp).to_string()
+                    } else {
+                        "<mutable>".to_string()
+                    };
+                    let hir_id = self.tcx.hir.node_to_hir_id(id);
+                    let typ = self.save_ctxt
+                        .tables
+                        .node_id_to_type_opt(hir_id)
+                        .map(|t| t.to_string())
+                        .unwrap_or(String::new());
+                    value.push_str(": ");
+                    value.push_str(&typ);
+
+                    if !self.span.filter_generated(Some(sp), sp) {
+                        let qualname = format!("{}${}", i.to_string(), id);
+                        let id = ::id_from_node_id(id, &self.save_ctxt);
+                        let span = self.span_from_span(sp);
+
+                        self.dumper.dump_def(
+                            &Access {
+                                public: false,
+                                reachable: false,
+                            },
+                            Def {
+                                kind: DefKind::Local,
+                                id,
+                                span,
+                                name: i.to_string(),
+                                qualname,
+                                value: typ,
+                                parent: None,
+                                children: vec![],
+                                decl_id: None,
+                                docs: String::new(),
+                                sig: None,
+                                attributes: vec![],
+                            },
+                        );
+                    }
+                }
+                HirDef::StructCtor(..) |
+                HirDef::VariantCtor(..) |
+                HirDef::Const(..) |
+                HirDef::AssociatedConst(..) |
+                HirDef::Struct(..) |
+                HirDef::Variant(..) |
+                HirDef::TyAlias(..) |
+                HirDef::AssociatedTy(..) |
+                HirDef::SelfTy(..) => {
+                    self.dump_path_ref(id, &ast::Path::from_ident(sp, i));
+                }
+                def => error!(
+                    "unexpected definition kind when processing collected idents: {:?}",
+                    def
+                ),
+            }
+        }
+
+        for (id, ref path) in collector.collected_paths {
+            self.process_path(id, path);
+        }
+    }
 
     fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
         // The local could declare multiple new vars, we must walk the
@@ -1622,17 +1697,21 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                     v.nest_scope(ex.id, |v| v.visit_expr(body))
                 });
             }
-            ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) |
-            ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => {
+            ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) => {
                 let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
                 debug!("for loop, walk sub-expr: {:?}", subexpression.node);
                 self.visit_expr(subexpression);
                 visit::walk_block(self, block);
             }
-            ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => {
-                let value = self.span.snippet(subexpression.span);
-                self.process_var_decl(pattern, value);
+            ast::ExprKind::WhileLet(ref pats, ref subexpression, ref block, _) => {
+                self.process_var_decl_multi(pats);
+                debug!("for loop, walk sub-expr: {:?}", subexpression.node);
+                self.visit_expr(subexpression);
+                visit::walk_block(self, block);
+            }
+            ast::ExprKind::IfLet(ref pats, ref subexpression, ref block, ref opt_else) => {
+                self.process_var_decl_multi(pats);
                 self.visit_expr(subexpression);
                 visit::walk_block(self, block);
                 opt_else.as_ref().map(|el| self.visit_expr(el));
@@ -1661,79 +1740,7 @@ fn visit_pat(&mut self, p: &'l ast::Pat) {
     }
 
     fn visit_arm(&mut self, arm: &'l ast::Arm) {
-        let mut collector = PathCollector::new();
-        for pattern in &arm.pats {
-            // collect paths from the arm's patterns
-            collector.visit_pat(&pattern);
-            self.visit_pat(&pattern);
-        }
-
-        // process collected paths
-        for (id, i, sp, immut) in collector.collected_idents {
-            match self.save_ctxt.get_path_def(id) {
-                HirDef::Local(id) => {
-                    let mut value = if immut == ast::Mutability::Immutable {
-                        self.span.snippet(sp).to_string()
-                    } else {
-                        "<mutable>".to_string()
-                    };
-                    let hir_id = self.tcx.hir.node_to_hir_id(id);
-                    let typ = self.save_ctxt
-                        .tables
-                        .node_id_to_type_opt(hir_id)
-                        .map(|t| t.to_string())
-                        .unwrap_or(String::new());
-                    value.push_str(": ");
-                    value.push_str(&typ);
-
-                    if !self.span.filter_generated(Some(sp), sp) {
-                        let qualname = format!("{}${}", i.to_string(), id);
-                        let id = ::id_from_node_id(id, &self.save_ctxt);
-                        let span = self.span_from_span(sp);
-
-                        self.dumper.dump_def(
-                            &Access {
-                                public: false,
-                                reachable: false,
-                            },
-                            Def {
-                                kind: DefKind::Local,
-                                id,
-                                span,
-                                name: i.to_string(),
-                                qualname,
-                                value: typ,
-                                parent: None,
-                                children: vec![],
-                                decl_id: None,
-                                docs: String::new(),
-                                sig: None,
-                                attributes: vec![],
-                            },
-                        );
-                    }
-                }
-                HirDef::StructCtor(..) |
-                HirDef::VariantCtor(..) |
-                HirDef::Const(..) |
-                HirDef::AssociatedConst(..) |
-                HirDef::Struct(..) |
-                HirDef::Variant(..) |
-                HirDef::TyAlias(..) |
-                HirDef::AssociatedTy(..) |
-                HirDef::SelfTy(..) => {
-                    self.dump_path_ref(id, &ast::Path::from_ident(sp, i));
-                }
-                def => error!(
-                    "unexpected definition kind when processing collected idents: {:?}",
-                    def
-                ),
-            }
-        }
-
-        for (id, ref path) in collector.collected_paths {
-            self.process_path(id, path);
-        }
+        self.process_var_decl_multi(&arm.pats);
         walk_list!(self, visit_expr, &arm.guard);
         self.visit_expr(&arm.body);
     }
index 25e81e6f326e1c8ae04318828c5cac3295b43ee7..d5a58c08cbe5a0d950c2ae9bb89b94ea5f5d3737 100644 (file)
@@ -115,7 +115,7 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
         // We keep track of the following two counts - the depth of nesting of
         // angle brackets, and the depth of nesting of square brackets. For the
         // angle bracket count, we only count tokens which occur outside of any
-        // square brackets (i.e. bracket_count == 0). The intutition here is
+        // square brackets (i.e. bracket_count == 0). The intuition here is
         // that we want to count angle brackets in the type, but not any which
         // could be in expression context (because these could mean 'less than',
         // etc.).
@@ -151,18 +151,20 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
             }
             prev = next;
         }
-        if angle_count != 0 || bracket_count != 0 {
-            let loc = self.sess.codemap().lookup_char_pos(span.lo());
-            span_bug!(
-                span,
-                "Mis-counted brackets when breaking path? Parsing '{}' \
-                 in {}, line {}",
-                self.snippet(span),
-                loc.file.name,
-                loc.line
-            );
+        #[cfg(debug_assertions)] {
+            if angle_count != 0 || bracket_count != 0 {
+                let loc = self.sess.codemap().lookup_char_pos(span.lo());
+                span_bug!(
+                    span,
+                    "Mis-counted brackets when breaking path? Parsing '{}' \
+                     in {}, line {}",
+                    self.snippet(span),
+                    loc.file.name,
+                    loc.line
+                );
+            }
         }
-        if result.is_none() && prev.tok.is_ident() && angle_count == 0 {
+        if result.is_none() && prev.tok.is_ident() {
             return Some(prev.sp);
         }
         result
index 12698964d2e65ec7dc76f9b40c4754323d0e926a..ee0f2415bd80861626584d3e61bb92b7b76eb15c 100644 (file)
@@ -40,7 +40,7 @@
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
 
 use libc::c_uint;
-use std::{cmp, iter};
+use std::cmp;
 
 pub use syntax::abi::Abi;
 pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
@@ -279,30 +279,6 @@ impl Uniform {
     pub fn align(&self, cx: &CodegenCx) -> Align {
         self.unit.align(cx)
     }
-
-    pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
-        let llunit = self.unit.llvm_type(cx);
-
-        if self.total <= self.unit.size {
-            return llunit;
-        }
-
-        let count = self.total.bytes() / self.unit.size.bytes();
-        let rem_bytes = self.total.bytes() % self.unit.size.bytes();
-
-        if rem_bytes == 0 {
-            return Type::array(&llunit, count);
-        }
-
-        // Only integers can be really split further.
-        assert_eq!(self.unit.kind, RegKind::Integer);
-
-        let args: Vec<_> = (0..count).map(|_| llunit)
-            .chain(iter::once(Type::ix(cx, rem_bytes * 8)))
-            .collect();
-
-        Type::struct_(cx, &args, false)
-    }
 }
 
 pub trait LayoutExt<'tcx> {
@@ -405,55 +381,81 @@ fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg> {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum CastTarget {
-    Uniform(Uniform),
-    Pair(Reg, Reg)
+pub struct CastTarget {
+    pub prefix: [Option<RegKind>; 8],
+    pub prefix_chunk: Size,
+    pub rest: Uniform,
 }
 
 impl From<Reg> for CastTarget {
     fn from(unit: Reg) -> CastTarget {
-        CastTarget::Uniform(Uniform::from(unit))
+        CastTarget::from(Uniform::from(unit))
     }
 }
 
 impl From<Uniform> for CastTarget {
     fn from(uniform: Uniform) -> CastTarget {
-        CastTarget::Uniform(uniform)
+        CastTarget {
+            prefix: [None; 8],
+            prefix_chunk: Size::from_bytes(0),
+            rest: uniform
+        }
     }
 }
 
 impl CastTarget {
-    pub fn size(&self, cx: &CodegenCx) -> Size {
-        match *self {
-            CastTarget::Uniform(u) => u.total,
-            CastTarget::Pair(a, b) => {
-                (a.size.abi_align(a.align(cx)) + b.size)
-                    .abi_align(self.align(cx))
-            }
+    pub fn pair(a: Reg, b: Reg) -> CastTarget {
+        CastTarget {
+            prefix: [Some(a.kind), None, None, None, None, None, None, None],
+            prefix_chunk: a.size,
+            rest: Uniform::from(b)
         }
     }
 
+    pub fn size(&self, cx: &CodegenCx) -> Size {
+        (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
+            .abi_align(self.rest.align(cx)) + self.rest.total
+    }
+
     pub fn align(&self, cx: &CodegenCx) -> Align {
-        match *self {
-            CastTarget::Uniform(u) => u.align(cx),
-            CastTarget::Pair(a, b) => {
-                cx.data_layout().aggregate_align
-                    .max(a.align(cx))
-                    .max(b.align(cx))
-            }
-        }
+        self.prefix.iter()
+            .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx)))
+            .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)),
+                |acc, align| acc.max(align))
     }
 
     pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
-        match *self {
-            CastTarget::Uniform(u) => u.llvm_type(cx),
-            CastTarget::Pair(a, b) => {
-                Type::struct_(cx, &[
-                    a.llvm_type(cx),
-                    b.llvm_type(cx)
-                ], false)
+        let rest_ll_unit = self.rest.unit.llvm_type(cx);
+        let rest_count = self.rest.total.bytes() / self.rest.unit.size.bytes();
+        let rem_bytes = self.rest.total.bytes() % self.rest.unit.size.bytes();
+
+        if self.prefix.iter().all(|x| x.is_none()) {
+            // Simplify to a single unit when there is no prefix and size <= unit size
+            if self.rest.total <= self.rest.unit.size {
+                return rest_ll_unit;
+            }
+
+            // Simplify to array when all chunks are the same size and type
+            if rem_bytes == 0 {
+                return Type::array(&rest_ll_unit, rest_count);
             }
         }
+
+        // Create list of fields in the main structure
+        let mut args: Vec<_> =
+            self.prefix.iter().flat_map(|option_kind| option_kind.map(
+                    |kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)))
+            .chain((0..rest_count).map(|_| rest_ll_unit))
+            .collect();
+
+        // Append final integer
+        if rem_bytes != 0 {
+            // Only integers can be really split further.
+            assert_eq!(self.rest.unit.kind, RegKind::Integer);
+            args.push(Type::ix(cx, rem_bytes * 8));
+        }
+
+        Type::struct_(cx, &args, false)
     }
 }
 
index 3b765a493e0e79a15d98982f4fbb986d7fa0b0be..0bccef1e62a8e186126bd6cc4593d806e3d6064f 100644 (file)
@@ -109,6 +109,10 @@ pub fn command(&self) -> process::Command {
 
     // extensions
 
+    pub fn get_args(&self) -> &[OsString] {
+        &self.args
+    }
+
     pub fn take_args(&mut self) -> Vec<OsString> {
         mem::replace(&mut self.args, Vec::new())
     }
index 4fe294a790fc4467edaedbd686672d48535e3f09..d7c75dea8d04eb021275c541018f1c4f727ee4e6 100644 (file)
@@ -700,9 +700,6 @@ fn link_natively(sess: &Session,
         prog = time(sess.time_passes(), "running linker", || {
             exec_linker(sess, &mut cmd, tmpdir)
         });
-        if !retry_on_segfault || i > 3 {
-            break
-        }
         let output = match prog {
             Ok(ref output) => output,
             Err(_) => break,
@@ -713,6 +710,31 @@ fn link_natively(sess: &Session,
         let mut out = output.stderr.clone();
         out.extend(&output.stdout);
         let out = String::from_utf8_lossy(&out);
+
+        // Check to see if the link failed with "unrecognized command line option:
+        // '-no-pie'" for gcc or "unknown argument: '-no-pie'" for clang. If so,
+        // reperform the link step without the -no-pie option. This is safe because
+        // if the linker doesn't support -no-pie then it should not default to
+        // linking executables as pie. Different versions of gcc seem to use
+        // different quotes in the error message so don't check for them.
+        if sess.target.target.options.linker_is_gnu &&
+           (out.contains("unrecognized command line option") ||
+            out.contains("unknown argument")) &&
+           out.contains("-no-pie") &&
+           cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") {
+            info!("linker output: {:?}", out);
+            warn!("Linker does not support -no-pie command line option. Retrying without.");
+            for arg in cmd.take_args() {
+                if arg.to_string_lossy() != "-no-pie" {
+                    cmd.arg(arg);
+                }
+            }
+            info!("{:?}", &cmd);
+            continue;
+        }
+        if !retry_on_segfault || i > 3 {
+            break
+        }
         let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
         let msg_bus  = "clang: error: unable to execute command: Bus error: 10";
         if !(out.contains(msg_segv) || out.contains(msg_bus)) {
@@ -949,16 +971,30 @@ fn link_args(cmd: &mut Linker,
 
     let used_link_args = &trans.crate_info.link_args;
 
-    if crate_type == config::CrateTypeExecutable &&
-       t.options.position_independent_executables {
-        let empty_vec = Vec::new();
-        let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
-        let more_args = &sess.opts.cg.link_arg;
-        let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
-
-        if get_reloc_model(sess) == llvm::RelocMode::PIC
-            && !sess.crt_static() && !args.any(|x| *x == "-static") {
+    if crate_type == config::CrateTypeExecutable {
+        let mut position_independent_executable = false;
+
+        if t.options.position_independent_executables {
+            let empty_vec = Vec::new();
+            let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
+            let more_args = &sess.opts.cg.link_arg;
+            let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
+
+            if get_reloc_model(sess) == llvm::RelocMode::PIC
+                && !sess.crt_static() && !args.any(|x| *x == "-static") {
+                position_independent_executable = true;
+            }
+        }
+
+        if position_independent_executable {
             cmd.position_independent_executable();
+        } else {
+            // recent versions of gcc can be configured to generate position
+            // independent executables by default. We have to pass -no-pie to
+            // explicitly turn that off.
+            if sess.target.target.options.linker_is_gnu {
+                cmd.no_position_independent_executable();
+            }
         }
     }
 
index aa29c3cc120584477a47f45f1cb1c56f70d086be..7e7811c56c74e39f1b9a476a235637920476cda2 100644 (file)
@@ -105,6 +105,7 @@ pub trait Linker {
     fn add_object(&mut self, path: &Path);
     fn gc_sections(&mut self, keep_metadata: bool);
     fn position_independent_executable(&mut self);
+    fn no_position_independent_executable(&mut self);
     fn partial_relro(&mut self);
     fn full_relro(&mut self);
     fn optimize(&mut self);
@@ -179,6 +180,7 @@ impl<'a> Linker for GccLinker<'a> {
     fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
     fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
     fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
+    fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); }
     fn partial_relro(&mut self) { self.linker_arg("-z,relro"); }
     fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); }
     fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
@@ -439,6 +441,10 @@ fn position_independent_executable(&mut self) {
         // noop
     }
 
+    fn no_position_independent_executable(&mut self) {
+        // noop
+    }
+
     fn partial_relro(&mut self) {
         // noop
     }
@@ -647,6 +653,10 @@ fn position_independent_executable(&mut self) {
         // noop
     }
 
+    fn no_position_independent_executable(&mut self) {
+        // noop
+    }
+
     fn partial_relro(&mut self) {
         // noop
     }
index 466a86e7ea5584d221eb13e17d71ca043d3ab09f..c0785f5393716a7d7b9e90b70a3f4f506b80a017 100644 (file)
@@ -1004,6 +1004,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
     let translation_items: DefIdSet = items.iter().filter_map(|trans_item| {
         match *trans_item {
             MonoItem::Fn(ref instance) => Some(instance.def_id()),
+            MonoItem::Static(def_id) => Some(def_id),
             _ => None,
         }
     }).collect();
@@ -1107,7 +1108,7 @@ pub fn new(tcx: TyCtxt) -> CrateInfo {
     }
 }
 
-fn is_translated_function(tcx: TyCtxt, id: DefId) -> bool {
+fn is_translated_item(tcx: TyCtxt, id: DefId) -> bool {
     let (all_trans_items, _) =
         tcx.collect_and_partition_translation_items(LOCAL_CRATE);
     all_trans_items.contains(&id)
@@ -1222,7 +1223,7 @@ pub fn provide(providers: &mut Providers) {
     providers.collect_and_partition_translation_items =
         collect_and_partition_translation_items;
 
-    providers.is_translated_function = is_translated_function;
+    providers.is_translated_item = is_translated_item;
 
     providers.codegen_unit = |tcx, name| {
         let (_, all) = tcx.collect_and_partition_translation_items(LOCAL_CRATE);
index e44063faab8105e3160432b67e97c3aea46ea1df..94bf53cee1edbd67b90885dccc28d44ecb482268 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
+use abi::{ArgAttribute, ArgType, CastTarget, FnType, LayoutExt, PassMode, Reg, RegKind, Uniform};
 use context::CodegenCx;
+use rustc::ty::layout::{self, Size};
 
-use rustc::ty::layout::Size;
+fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
+    // Always sign extend u32 values on 64-bit mips
+    if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
+        if let layout::Int(i, signed) = scalar.value {
+            if !signed && i.size().bits() == 32 {
+                if let PassMode::Direct(ref mut attrs) = arg.mode {
+                    attrs.set(ArgAttribute::SExt);
+                    return;
+                }
+            }
+        }
+    }
+
+    arg.extend_integer_width_to(bits);
+}
+
+fn bits_to_int_reg(bits: u64) -> Reg {
+    if bits <= 8 {
+        Reg::i8()
+    } else if bits <= 16 {
+        Reg::i16()
+    } else if bits <= 32 {
+        Reg::i32()
+    } else {
+        Reg::i64()
+    }
+}
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                             ret: &mut ArgType<'tcx>,
-                             offset: &mut Size) {
+fn float_reg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &ArgType<'tcx>, i: usize) -> Option<Reg> {
+    match ret.layout.field(cx, i).abi {
+        layout::Abi::Scalar(ref scalar) => match scalar.value {
+            layout::F32 => Some(Reg::f32()),
+            layout::F64 => Some(Reg::f64()),
+            _ => None
+        },
+        _ => None
+    }
+}
+
+fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
     if !ret.layout.is_aggregate() {
-        ret.extend_integer_width_to(64);
+        extend_integer_width_mips(ret, 64);
+        return;
+    }
+
+    let size = ret.layout.size;
+    let bits = size.bits();
+    if bits <= 128 {
+        // Unlike other architectures which return aggregates in registers, MIPS n64 limits the
+        // use of float registers to structures (not unions) containing exactly one or two
+        // float fields.
+
+        if let layout::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
+            if ret.layout.fields.count() == 1 {
+                if let Some(reg) = float_reg(cx, ret, 0) {
+                    ret.cast_to(reg);
+                    return;
+                }
+            } else if ret.layout.fields.count() == 2 {
+                if let Some(reg0) = float_reg(cx, ret, 0) {
+                    if let Some(reg1) = float_reg(cx, ret, 1) {
+                        ret.cast_to(CastTarget::pair(reg0, reg1));
+                        return;
+                    }
+                }
+            }
+        }
+
+        // Cast to a uniform int structure
+        ret.cast_to(Uniform {
+            unit: bits_to_int_reg(bits),
+            total: size
+        });
     } else {
         ret.make_indirect();
-        *offset += cx.tcx.data_layout.pointer_size;
     }
 }
 
-fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
+fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+    if !arg.layout.is_aggregate() {
+        extend_integer_width_mips(arg, 64);
+        return;
+    }
+
     let dl = &cx.tcx.data_layout;
     let size = arg.layout.size;
-    let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
+    let mut prefix = [None; 8];
+    let mut prefix_index = 0;
 
-    if arg.layout.is_aggregate() {
-        arg.cast_to(Uniform {
-            unit: Reg::i64(),
-            total: size
-        });
-        if !offset.is_abi_aligned(align) {
-            arg.pad_with(Reg::i64());
+    match arg.layout.fields {
+        layout::FieldPlacement::Array { .. } => {
+            // Arrays are passed indirectly
+            arg.make_indirect();
+            return;
         }
-    } else {
-        arg.extend_integer_width_to(64);
-    }
+        layout::FieldPlacement::Union(_) => {
+            // Unions and are always treated as a series of 64-bit integer chunks
+        },
+        layout::FieldPlacement::Arbitrary { .. } => {
+            // Structures are split up into a series of 64-bit integer chunks, but any aligned
+            // doubles not part of another aggregate are passed as floats.
+            let mut last_offset = Size::from_bytes(0);
+
+            for i in 0..arg.layout.fields.count() {
+                let field = arg.layout.field(cx, i);
+                let offset = arg.layout.fields.offset(i);
+
+                // We only care about aligned doubles
+                if let layout::Abi::Scalar(ref scalar) = field.abi {
+                    if let layout::F64 = scalar.value {
+                        if offset.is_abi_aligned(dl.f64_align) {
+                            // Insert enough integers to cover [last_offset, offset)
+                            assert!(last_offset.is_abi_aligned(dl.f64_align));
+                            for _ in 0..((offset - last_offset).bits() / 64)
+                                .min((prefix.len() - prefix_index) as u64) {
+
+                                prefix[prefix_index] = Some(RegKind::Integer);
+                                prefix_index += 1;
+                            }
+
+                            if prefix_index == prefix.len() {
+                                break;
+                            }
+
+                            prefix[prefix_index] = Some(RegKind::Float);
+                            prefix_index += 1;
+                            last_offset = offset + Reg::f64().size;
+                        }
+                    }
+                }
+            }
+        }
+    };
 
-    *offset = offset.abi_align(align) + size.abi_align(align);
+    // Extract first 8 chunks as the prefix
+    let rest_size = size - Size::from_bytes(8) * prefix_index as u64;
+    arg.cast_to(CastTarget {
+        prefix: prefix,
+        prefix_chunk: Size::from_bytes(8),
+        rest: Uniform { unit: Reg::i64(), total: rest_size }
+    });
 }
 
 pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
-    let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
-        classify_ret_ty(cx, &mut fty.ret, &mut offset);
+        classify_ret_ty(cx, &mut fty.ret);
     }
 
     for arg in &mut fty.args {
         if arg.is_ignore() { continue; }
-        classify_arg_ty(cx, arg, &mut offset);
+        classify_arg_ty(cx, arg);
     }
 }
index b8144a3ca7a3ee2ddb87745011bd33e6f7fe9022..7eadaa7f493a3f52b63c9699123f5e08c478b097 100644 (file)
@@ -171,7 +171,7 @@ fn cast_target(cls: &[Option<Class>], size: Size) -> CastTarget {
     let mut target = CastTarget::from(lo);
     if size > offset {
         if let Some(hi) = reg_component(cls, &mut i, size - offset) {
-            target = CastTarget::Pair(lo, hi);
+            target = CastTarget::pair(lo, hi);
         }
     }
     assert_eq!(reg_component(cls, &mut i, Size::from_bytes(0)), None);
index c3d5e08c73e7ec88d1a6f6448f40915287c83d6d..8c40aa6a2acba5d2e374ce86304ed7cac5b77930 100644 (file)
@@ -149,7 +149,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         unsafe {
             llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
 
-            if cx.tcx.is_translated_function(instance_def_id) {
+            if cx.tcx.is_translated_item(instance_def_id) {
                 if instance_def_id.is_local() {
                     if !cx.tcx.is_exported_symbol(instance_def_id) {
                         llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
index 9e745c3a1f5dd77d46c38b4c5c34832a5801d9b4..37bd225a7d9cbd304286290c80835eac3e3b9880 100644 (file)
@@ -28,7 +28,6 @@
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
-use rustc::ty::subst::Kind;
 use rustc::hir;
 
 use libc::{c_uint, c_char};
@@ -413,8 +412,8 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             sig.map_bound(|sig| {
                 let state_did = tcx.lang_items().gen_state().unwrap();
                 let state_adt_ref = tcx.adt_def(state_did);
-                let state_substs = tcx.mk_substs([Kind::from(sig.yield_ty),
-                    Kind::from(sig.return_ty)].iter());
+                let state_substs = tcx.mk_substs([sig.yield_ty.into(),
+                    sig.return_ty.into()].iter());
                 let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
                 tcx.mk_fn_sig(iter::once(env_ty),
index d5b33d837c5bd92e4440fd2440e26839a0a368c9..1608c4a87bf5c16ca3eab8df49129cb5b5685f56 100644 (file)
@@ -16,7 +16,7 @@
 use rustc::middle::const_val::ConstEvalErr;
 use debuginfo;
 use base;
-use monomorphize::{MonoItem, MonoItemExt};
+use monomorphize::MonoItem;
 use common::{CodegenCx, val_ty};
 use declare;
 use monomorphize::Instance;
@@ -110,7 +110,17 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
         return g;
     }
 
+    let defined_in_current_codegen_unit = cx.codegen_unit
+                                            .items()
+                                            .contains_key(&MonoItem::Static(def_id));
+    assert!(!defined_in_current_codegen_unit,
+            "consts::get_static() should always hit the cache for \
+             statics defined in the same CGU, but did not for `{:?}`",
+             def_id);
+
     let ty = instance.ty(cx.tcx);
+    let sym = cx.tcx.symbol_name(instance);
+
     let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
 
         let llty = cx.layout_of(ty).llvm_type(cx);
@@ -118,13 +128,6 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
             hir_map::NodeItem(&hir::Item {
                 ref attrs, span, node: hir::ItemStatic(..), ..
             }) => {
-                let sym = MonoItem::Static(id).symbol_name(cx.tcx);
-
-                let defined_in_current_codegen_unit = cx.codegen_unit
-                                                         .items()
-                                                         .contains_key(&MonoItem::Static(id));
-                assert!(!defined_in_current_codegen_unit);
-
                 if declare::get_declared_value(cx, &sym[..]).is_some() {
                     span_bug!(span, "trans: Conflicting symbol names for static?");
                 }
@@ -143,7 +146,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
             hir_map::NodeForeignItem(&hir::ForeignItem {
                 ref attrs, span, node: hir::ForeignItemStatic(..), ..
             }) => {
-                let sym = cx.tcx.symbol_name(instance);
+
                 let g = if let Some(name) =
                         attr::first_attr_value_str_by_name(&attrs, "linkage") {
                     // If this is a static with a linkage specified, then we need to handle
@@ -203,8 +206,6 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
 
         g
     } else {
-        let sym = cx.tcx.symbol_name(instance);
-
         // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
         // FIXME(nagisa): investigate whether it can be changed into define_global
         let g = declare::declare_global(cx, &sym, cx.layout_of(ty).llvm_type(cx));
@@ -225,8 +226,15 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
             // statically in the final application, we always mark such symbols as 'dllimport'.
             // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs to
             // make things work.
-            unsafe {
-                llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+            //
+            // However, in some scenarios we defer emission of statics to downstream
+            // crates, so there are cases where a static with an upstream DefId
+            // is actually present in the current crate. We can find out via the
+            // is_translated_item query.
+            if !cx.tcx.is_translated_item(def_id) {
+                unsafe {
+                    llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+                }
             }
         }
         g
@@ -245,12 +253,11 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
 }
 
 pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                              m: hir::Mutability,
-                              id: ast::NodeId,
+                              def_id: DefId,
+                              is_mutable: bool,
                               attrs: &[ast::Attribute])
                               -> Result<ValueRef, ConstEvalErr<'tcx>> {
     unsafe {
-        let def_id = cx.tcx.hir.local_def_id(id);
         let g = get_static(cx, def_id);
 
         let v = ::mir::trans_static_initializer(cx, def_id)?;
@@ -298,13 +305,13 @@ pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
-        if m != hir::MutMutable {
+        if !is_mutable {
             if cx.type_is_freeze(ty) {
                 llvm::LLVMSetGlobalConstant(g, llvm::True);
             }
         }
 
-        debuginfo::create_global_var_metadata(cx, id, g);
+        debuginfo::create_global_var_metadata(cx, def_id, g);
 
         if attr::contains_name(attrs, "thread_local") {
             llvm::set_thread_local_mode(g, cx.tls_model);
index 62ba91840d95e4c4281fd36566742acc881725b6..2c430d03c968ec02d46b05ff75b5513c3dd06200 100644 (file)
@@ -14,7 +14,7 @@
 
 use super::utils::{debug_context, DIB, span_start,
                    get_namespace_for_item, create_DIArray, is_node_local_to_unit};
-use super::namespace::mangled_name_of_item;
+use super::namespace::mangled_name_of_instance;
 use super::type_names::compute_debuginfo_type_name;
 use super::{CrateDebugContext};
 use abi;
@@ -1634,19 +1634,18 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
 pub fn create_global_var_metadata(cx: &CodegenCx,
-                                  node_id: ast::NodeId,
+                                  def_id: DefId,
                                   global: ValueRef) {
     if cx.dbg_cx.is_none() {
         return;
     }
 
     let tcx = cx.tcx;
-    let node_def_id = tcx.hir.local_def_id(node_id);
-    let no_mangle = attr::contains_name(&tcx.get_attrs(node_def_id), "no_mangle");
+    let no_mangle = attr::contains_name(&tcx.get_attrs(def_id), "no_mangle");
     // We may want to remove the namespace scope if we're in an extern block, see:
     // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
-    let var_scope = get_namespace_for_item(cx, node_def_id);
-    let span = cx.tcx.def_span(node_def_id);
+    let var_scope = get_namespace_for_item(cx, def_id);
+    let span = cx.tcx.def_span(def_id);
 
     let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP {
         let loc = span_start(cx, span);
@@ -1655,15 +1654,15 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
         (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
     };
 
-    let is_local_to_unit = is_node_local_to_unit(cx, node_id);
-    let variable_type = Instance::mono(cx.tcx, node_def_id).ty(cx.tcx);
+    let is_local_to_unit = is_node_local_to_unit(cx, def_id);
+    let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx);
     let type_metadata = type_metadata(cx, variable_type, span);
-    let var_name = tcx.item_name(node_def_id).to_string();
+    let var_name = tcx.item_name(def_id).to_string();
     let var_name = CString::new(var_name).unwrap();
     let linkage_name = if no_mangle {
         None
     } else {
-        let linkage_name = mangled_name_of_item(cx, node_id);
+        let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
         Some(CString::new(linkage_name.to_string()).unwrap())
     };
 
index 9071eb776d5295dc25231789591d74dae9ad5251..16279f31836a984c2e6cd78ae7ff278310ea1b15 100644 (file)
@@ -254,14 +254,14 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let linkage_name = mangled_name_of_instance(cx, instance);
 
     let scope_line = span_start(cx, span).line;
-
-    let local_id = cx.tcx.hir.as_local_node_id(instance.def_id());
-    let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id));
+    let is_local_to_unit = is_node_local_to_unit(cx, def_id);
 
     let function_name = CString::new(name).unwrap();
     let linkage_name = CString::new(linkage_name.to_string()).unwrap();
 
     let mut flags = DIFlags::FlagPrototyped;
+
+    let local_id = cx.tcx.hir.as_local_node_id(def_id);
     match *cx.sess().entry_fn.borrow() {
         Some((id, _)) => {
             if local_id == Some(id) {
index 46067a4330396e384b9d25871ef2270f7d459ad0..891bf649c388a02aa7a6549408cf0113f5817439 100644 (file)
@@ -14,7 +14,6 @@
 use super::utils::{DIB, debug_context};
 use monomorphize::Instance;
 use rustc::ty;
-use syntax::ast;
 
 use llvm;
 use llvm::debuginfo::DIScope;
@@ -33,16 +32,6 @@ pub fn mangled_name_of_instance<'a, 'tcx>(
      tcx.symbol_name(instance)
 }
 
-pub fn mangled_name_of_item<'a, 'tcx>(
-    cx: &CodegenCx<'a, 'tcx>,
-    node_id: ast::NodeId,
-) -> ty::SymbolName {
-    let tcx = cx.tcx;
-    let node_def_id = tcx.hir.local_def_id(node_id);
-    let instance = Instance::mono(tcx, node_def_id);
-    tcx.symbol_name(instance)
-}
-
 pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
     if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) {
         return scope;
index c571b84b8e9edd64c8268f5ec9f6be5490c3343f..9559cd4d9ea2d52e2088bc147eb27446cb0b65d9 100644 (file)
@@ -21,9 +21,8 @@
 use common::{CodegenCx};
 
 use syntax_pos::{self, Span};
-use syntax::ast;
 
-pub fn is_node_local_to_unit(cx: &CodegenCx, node_id: ast::NodeId) -> bool
+pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool
 {
     // The is_local_to_unit flag indicates whether a function is local to the
     // current compilation unit (i.e. if it is *static* in the C-sense). The
@@ -33,7 +32,6 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, node_id: ast::NodeId) -> bool
     // visible). It might better to use the `exported_items` set from
     // `driver::CrateAnalysis` in the future, but (atm) this set is not
     // available in the translation pass.
-    let def_id = cx.tcx.hir.local_def_id(node_id);
     !cx.tcx.is_exported_symbol(def_id)
 }
 
index b25562252e72e86cc70585acd9ac74a24faf7986..6271dcdfb2433c42aafb9580a274eca15c44bf77 100644 (file)
@@ -75,26 +75,25 @@ unsafe fn configure_llvm(sess: &Session) {
                                  llvm_args.as_ptr());
 }
 
-// WARNING: the features must be known to LLVM or the feature
-// detection code will walk past the end of the feature array,
-// leading to crashes.
+// WARNING: the features after applying `to_llvm_feature` must be known
+// to LLVM or the feature detection code will walk past the end of the feature
+// array, leading to crashes.
 
 const ARM_WHITELIST: &'static [&'static str] = &["neon", "v7", "vfp2", "vfp3", "vfp4"];
 
 const AARCH64_WHITELIST: &'static [&'static str] = &["neon", "v7"];
 
-const X86_WHITELIST: &'static [&'static str] = &["avx", "avx2", "bmi", "bmi2", "sse",
-                                                 "sse2", "sse3", "sse4.1", "sse4.2",
-                                                 "ssse3", "tbm", "lzcnt", "popcnt",
-                                                 "sse4a", "rdrnd", "rdseed", "fma",
-                                                 "xsave", "xsaveopt", "xsavec",
-                                                 "xsaves", "aes", "pclmulqdq",
-                                                 "avx512bw", "avx512cd",
-                                                 "avx512dq", "avx512er",
-                                                 "avx512f", "avx512ifma",
-                                                 "avx512pf", "avx512vbmi",
-                                                 "avx512vl", "avx512vpopcntdq",
-                                                 "mmx", "fxsr"];
+const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw",
+                                                 "avx512cd", "avx512dq", "avx512er",
+                                                 "avx512f", "avx512ifma", "avx512pf",
+                                                 "avx512vbmi", "avx512vl", "avx512vpopcntdq",
+                                                 "bmi", "bmi2", "fma", "fxsr",
+                                                 "lzcnt", "mmx", "pclmulqdq",
+                                                 "popcnt", "rdrand", "rdseed",
+                                                 "sse", "sse2", "sse3", "sse4.1",
+                                                 "sse4.2", "sse4a", "ssse3",
+                                                 "tbm", "xsave", "xsavec",
+                                                 "xsaveopt", "xsaves"];
 
 const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx", "hvx-double"];
 
@@ -108,6 +107,7 @@ unsafe fn configure_llvm(sess: &Session) {
 pub fn to_llvm_feature(s: &str) -> &str {
     match s {
         "pclmulqdq" => "pclmul",
+        "rdrand" => "rdrnd",
         s => s,
     }
 }
index 5eb6679fe252c0480d176e2419f90595d2840dc7..91c1097fc7f8a5dc733384495effaf6c587440ca 100644 (file)
 use monomorphize::Instance;
 use type_of::LayoutLlvmExt;
 use rustc::hir;
+use rustc::hir::def::Def;
+use rustc::hir::def_id::DefId;
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::TypeFoldable;
 use rustc::ty::layout::LayoutOf;
-use syntax::ast;
 use syntax::attr;
 use std::fmt;
 
@@ -44,19 +45,25 @@ fn define(&self, cx: &CodegenCx<'a, 'tcx>) {
                cx.codegen_unit.name());
 
         match *self.as_mono_item() {
-            MonoItem::Static(node_id) => {
+            MonoItem::Static(def_id) => {
                 let tcx = cx.tcx;
-                let item = tcx.hir.expect_item(node_id);
-                if let hir::ItemStatic(_, m, _) = item.node {
-                    match consts::trans_static(&cx, m, item.id, &item.attrs) {
-                        Ok(_) => { /* Cool, everything's alright. */ },
-                        Err(err) => {
-                            err.report(tcx, item.span, "static");
-                        }
-                    };
-                } else {
-                    span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
-                }
+                let is_mutable = match tcx.describe_def(def_id) {
+                    Some(Def::Static(_, is_mutable)) => is_mutable,
+                    Some(other) => {
+                        bug!("Expected Def::Static, found {:?}", other)
+                    }
+                    None => {
+                        bug!("Expected Def::Static for {:?}, found nothing", def_id)
+                    }
+                };
+                let attrs = tcx.get_attrs(def_id);
+
+                match consts::trans_static(&cx, def_id, is_mutable, &attrs) {
+                    Ok(_) => { /* Cool, everything's alright. */ },
+                    Err(err) => {
+                        err.report(tcx, tcx.def_span(def_id), "static");
+                    }
+                };
             }
             MonoItem::GlobalAsm(node_id) => {
                 let item = cx.tcx.hir.expect_item(node_id);
@@ -91,8 +98,8 @@ fn predefine(&self,
         debug!("symbol {}", &symbol_name);
 
         match *self.as_mono_item() {
-            MonoItem::Static(node_id) => {
-                predefine_static(cx, node_id, linkage, visibility, &symbol_name);
+            MonoItem::Static(def_id) => {
+                predefine_static(cx, def_id, linkage, visibility, &symbol_name);
             }
             MonoItem::Fn(instance) => {
                 predefine_fn(cx, instance, linkage, visibility, &symbol_name);
@@ -126,17 +133,16 @@ fn to_raw_string(&self) -> String {
 impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {}
 
 fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                              node_id: ast::NodeId,
+                              def_id: DefId,
                               linkage: Linkage,
                               visibility: Visibility,
                               symbol_name: &str) {
-    let def_id = cx.tcx.hir.local_def_id(node_id);
     let instance = Instance::mono(cx.tcx, def_id);
     let ty = instance.ty(cx.tcx);
     let llty = cx.layout_of(ty).llvm_type(cx);
 
     let g = declare::define_global(cx, symbol_name, llty).unwrap_or_else(|| {
-        cx.sess().span_fatal(cx.tcx.hir.span(node_id),
+        cx.sess().span_fatal(cx.tcx.def_span(def_id),
             &format!("symbol `{}` is already defined", symbol_name))
     });
 
index 1139ea5fbd364074c33abdf2c47d2fe2b12388e8..650e530519887a71de58fd81c538aa7cf303ae39 100644 (file)
@@ -19,7 +19,7 @@
 use hir::def_id::DefId;
 use middle::resolve_lifetime as rl;
 use namespace::Namespace;
-use rustc::ty::subst::{Kind, Subst, Substs};
+use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
@@ -1136,7 +1136,7 @@ pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) ->
 
             // Replace all lifetimes with 'static
             for subst in &mut substs {
-                if let Some(_) = subst.as_region() {
+                if let UnpackedKind::Lifetime(_) = subst.unpack() {
                     *subst = Kind::from(&RegionKind::ReStatic);
                 }
             }
@@ -1146,8 +1146,7 @@ pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) ->
 
         // Fill in our own generics with the resolved lifetimes
         assert_eq!(lifetimes.len(), generics.own_count());
-        substs.extend(lifetimes.iter().map(|lt|
-            Kind::from(self.ast_region_to_region(lt, None))));
+        substs.extend(lifetimes.iter().map(|lt| Kind::from(self.ast_region_to_region(lt, None))));
 
         debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
 
index bf253a88d27c2e270f5da4f44f29e7e605ef817f..427641aaf0951a3eb1dd91831d132eed16cbf4ca 100644 (file)
@@ -151,6 +151,19 @@ pub fn check_pat_walk(
                     err.emit();
                 }
             }
+        } else if let PatKind::Ref(..) = pat.node {
+            // When you encounter a `&pat` pattern, reset to "by
+            // value". This is so that `x` and `y` here are by value,
+            // as they appear to be:
+            //
+            // ```
+            // match &(&22, &44) {
+            //   (&x, &y) => ...
+            // }
+            // ```
+            //
+            // cc #46688
+            def_bm = ty::BindByValue(hir::MutImmutable);
         }
 
         // Lose mutability now that we know binding mode and discriminant type.
index 4aed688027f767783bc65355b87936b28cade11a..039669a62e104ab6491651ad645610fa68c75e8f 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::infer::{self, InferOk};
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::middle::region;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::{self, Reveal, ObligationCause};
 use util::common::ErrorReported;
@@ -331,10 +331,9 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
         }
 
         for outlive in outlives {
-            if let Some(r) = outlive.as_region() {
-                rcx.sub_regions(origin(), parent_scope, r);
-            } else if let Some(ty) = outlive.as_type() {
-                rcx.type_must_outlive(origin(), ty, parent_scope);
+            match outlive.unpack() {
+                UnpackedKind::Lifetime(lt) => rcx.sub_regions(origin(), parent_scope, lt),
+                UnpackedKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope),
             }
         }
     }
index a6776a0fe8612f75d7776a772f0d11f6b9496d3c..a28625be2c73963e3e09465dc4328150a0ddac0d 100644 (file)
@@ -13,7 +13,7 @@
 use super::{FnCtxt, Needs};
 use super::method::MethodCallee;
 use rustc::ty::{self, Ty, TypeFoldable, TypeVariants};
-use rustc::ty::TypeVariants::{TyStr, TyRef};
+use rustc::ty::TypeVariants::{TyStr, TyRef, TyAdt};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use errors;
@@ -201,10 +201,9 @@ fn check_overloaded_binop(&self,
                         let mutbl = match mt.mutbl {
                             hir::MutImmutable => AutoBorrowMutability::Immutable,
                             hir::MutMutable => AutoBorrowMutability::Mutable {
-                                // For initial two-phase borrow
-                                // deployment, conservatively omit
-                                // overloaded binary ops.
-                                allow_two_phase_borrow: false,
+                                // Allow two-phase borrows for binops in initial deployment
+                                // since they desugar to methods
+                                allow_two_phase_borrow: true,
                             }
                         };
                         let autoref = Adjustment {
@@ -219,10 +218,9 @@ fn check_overloaded_binop(&self,
                         let mutbl = match mt.mutbl {
                             hir::MutImmutable => AutoBorrowMutability::Immutable,
                             hir::MutMutable => AutoBorrowMutability::Mutable {
-                                // For initial two-phase borrow
-                                // deployment, conservatively omit
-                                // overloaded binary ops.
-                                allow_two_phase_borrow: false,
+                                // Allow two-phase borrows for binops in initial deployment
+                                // since they desugar to methods
+                                allow_two_phase_borrow: true,
                             }
                         };
                         let autoref = Adjustment {
@@ -301,7 +299,7 @@ fn check_overloaded_binop(&self,
 
                         if let Some(missing_trait) = missing_trait {
                             if missing_trait == "std::ops::Add" &&
-                                self.check_str_addition(expr, lhs_expr, lhs_ty,
+                                self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
                                                         rhs_ty, &mut err) {
                                 // This has nothing here because it means we did string
                                 // concatenation (e.g. "Hello " + "World!"). This means
@@ -330,37 +328,54 @@ fn check_overloaded_binop(&self,
     fn check_str_addition(&self,
                           expr: &'gcx hir::Expr,
                           lhs_expr: &'gcx hir::Expr,
+                          rhs_expr: &'gcx hir::Expr,
                           lhs_ty: Ty<'tcx>,
                           rhs_ty: Ty<'tcx>,
                           err: &mut errors::DiagnosticBuilder) -> bool {
+        let codemap = self.tcx.sess.codemap();
+        let msg = "`to_owned()` can be used to create an owned `String` \
+                   from a string reference. String concatenation \
+                   appends the string on the right to the string \
+                   on the left and may require reallocation. This \
+                   requires ownership of the string on the left";
         // If this function returns true it means a note was printed, so we don't need
         // to print the normal "implementation of `std::ops::Add` might be missing" note
-        let mut is_string_addition = false;
-        if let TyRef(_, l_ty) = lhs_ty.sty {
-            if let TyRef(_, r_ty) = rhs_ty.sty {
-                if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr {
-                    err.span_label(expr.span,
-                        "`+` can't be used to concatenate two `&str` strings");
-                    let codemap = self.tcx.sess.codemap();
-                    let suggestion =
-                        match codemap.span_to_snippet(lhs_expr.span) {
-                            Ok(lstring) => format!("{}.to_owned()", lstring),
-                            _ => format!("<expression>")
-                        };
-                    err.span_suggestion(lhs_expr.span,
-                        &format!("`to_owned()` can be used to create an owned `String` \
-                                  from a string reference. String concatenation \
-                                  appends the string on the right to the string \
-                                  on the left and may require reallocation. This \
-                                  requires ownership of the string on the left"), suggestion);
-                    is_string_addition = true;
-                }
-
+        match (&lhs_ty.sty, &rhs_ty.sty) {
+            (&TyRef(_, ref l_ty), &TyRef(_, ref r_ty))
+            if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr => {
+                err.span_label(expr.span,
+                    "`+` can't be used to concatenate two `&str` strings");
+                match codemap.span_to_snippet(lhs_expr.span) {
+                    Ok(lstring) => err.span_suggestion(lhs_expr.span,
+                                                       msg,
+                                                       format!("{}.to_owned()", lstring)),
+                    _ => err.help(msg),
+                };
+                true
             }
-
+            (&TyRef(_, ref l_ty), &TyAdt(..))
+            if l_ty.ty.sty == TyStr && &format!("{:?}", rhs_ty) == "std::string::String" => {
+                err.span_label(expr.span,
+                    "`+` can't be used to concatenate a `&str` with a `String`");
+                match codemap.span_to_snippet(lhs_expr.span) {
+                    Ok(lstring) => err.span_suggestion(lhs_expr.span,
+                                                       msg,
+                                                       format!("{}.to_owned()", lstring)),
+                    _ => err.help(msg),
+                };
+                match codemap.span_to_snippet(rhs_expr.span) {
+                    Ok(rstring) => {
+                        err.span_suggestion(rhs_expr.span,
+                                            "you also need to borrow the `String` on the right to \
+                                             get a `&str`",
+                                            format!("&{}", rstring));
+                    }
+                    _ => {}
+                };
+                true
+            }
+            _ => false,
         }
-
-        is_string_addition
     }
 
     pub fn check_user_unop(&self,
index f7e10a4a47d37733677da801410cecdb062dbe5d..44ac7a10e8287634637b692237a1fcbcf01095c1 100644 (file)
@@ -14,7 +14,7 @@
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Substs, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
 use syntax::ast;
 use rustc::hir;
@@ -381,12 +381,13 @@ fn add_constraints_from_substs(&mut self,
             debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
                    variance_decl,
                    variance_i);
-            if let Some(ty) = k.as_type() {
-                self.add_constraints_from_ty(current, ty, variance_i);
-            } else if let Some(r) = k.as_region() {
-                self.add_constraints_from_region(current, r, variance_i);
-            } else {
-                bug!();
+            match k.unpack() {
+                UnpackedKind::Lifetime(lt) => {
+                    self.add_constraints_from_region(current, lt, variance_i)
+                }
+                UnpackedKind::Type(ty) => {
+                    self.add_constraints_from_ty(current, ty, variance_i)
+                }
             }
         }
     }
index d4233309627f5844874b4ab3c66f7b26f53de400..b382ba7f22da713bfa20fb37c662fab4e6461282 100644 (file)
@@ -512,7 +512,16 @@ fn separate_supertrait_bounds(mut g: clean::Generics)
 }
 
 pub fn record_extern_trait(cx: &DocContext, did: DefId) {
-    cx.external_traits.borrow_mut().entry(did).or_insert_with(|| {
-        build_external_trait(cx, did)
-    });
+    if cx.external_traits.borrow().contains_key(&did) ||
+        cx.active_extern_traits.borrow().contains(&did)
+    {
+        return;
+    }
+
+    cx.active_extern_traits.borrow_mut().push(did);
+
+    let trait_ = build_external_trait(cx, did);
+
+    cx.external_traits.borrow_mut().insert(did, trait_);
+    cx.active_extern_traits.borrow_mut().remove_item(&did);
 }
index df7371cdf817b805c6d5e7c2a8f958bd003b26be..9ee0937f425c90cbbb0a88125c16c2cae4ac47ec 100644 (file)
@@ -61,6 +61,9 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
     pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
+    /// Used while populating `external_traits` to ensure we don't process the same trait twice at
+    /// the same time.
+    pub active_extern_traits: RefCell<Vec<DefId>>,
     // The current set of type and lifetime substitutions,
     // for expanding type aliases at the HIR level:
 
@@ -253,6 +256,7 @@ pub fn run_core(search_paths: SearchPaths,
             populated_all_crate_impls: Cell::new(false),
             access_levels: RefCell::new(access_levels),
             external_traits: Default::default(),
+            active_extern_traits: Default::default(),
             renderinfo: Default::default(),
             ty_substs: Default::default(),
             lt_substs: Default::default(),
index a82ff915093c6ca0952bee2f672bb4cbb7e85df2..4dfdc23ebee53120ac1d225d6fa10f5d2ca7c950 100644 (file)
@@ -2082,7 +2082,6 @@ pub fn key(&self) -> &K {
     /// # Examples
     ///
     /// ```
-    /// #![feature(entry_and_modify)]
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<&str, u32> = HashMap::new();
@@ -2097,7 +2096,7 @@ pub fn key(&self) -> &K {
     ///    .or_insert(42);
     /// assert_eq!(map["poneyland"], 43);
     /// ```
-    #[unstable(feature = "entry_and_modify", issue = "44733")]
+    #[stable(feature = "entry_and_modify", since = "1.26.0")]
     pub fn and_modify<F>(self, mut f: F) -> Self
         where F: FnMut(&mut V)
     {
index 854cefcb59725a4098891180287c0736380506b7..d7d856fe3ad068e096ce60ab329f9bcca3c4e327 100644 (file)
 // The runtime entry point and a few unstable public functions used by the
 // compiler
 pub mod rt;
-// The trait to support returning arbitrary types in the main function
-mod termination;
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-pub use self::termination::Termination;
 
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
index e03a182653e5a451810c99820ed16ea8b1de4fe5..4bbad30a5a3152cac16732144274c154196b6bf1 100644 (file)
@@ -1825,7 +1825,7 @@ pub fn parent(&self) -> Option<&Path> {
     /// If the path is a normal file, this is the file name. If it's the path of a directory, this
     /// is the directory name.
     ///
-    /// Returns [`None`] If the path terminates in `..`.
+    /// Returns [`None`] if the path terminates in `..`.
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
index 9b2f815b71383b0e6fdca479ecee7ded45264321..e25599b8bd8712e6c13fafbf9ec27fe93509d329 100644 (file)
@@ -1392,6 +1392,73 @@ pub fn id() -> u32 {
     ::sys::os::getpid()
 }
 
+#[cfg(target_arch = "wasm32")]
+mod exit {
+    pub const SUCCESS: i32 = 0;
+    pub const FAILURE: i32 = 1;
+}
+#[cfg(not(target_arch = "wasm32"))]
+mod exit {
+    use libc;
+    pub const SUCCESS: i32 = libc::EXIT_SUCCESS;
+    pub const FAILURE: i32 = libc::EXIT_FAILURE;
+}
+
+/// A trait for implementing arbitrary return types in the `main` function.
+///
+/// The c-main function only supports to return integers as return type.
+/// So, every type implementing the `Termination` trait has to be converted
+/// to an integer.
+///
+/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
+/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
+#[cfg_attr(not(test), lang = "termination")]
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[rustc_on_unimplemented =
+  "`main` can only return types that implement {Termination}, not `{Self}`"]
+pub trait Termination {
+    /// Is called to get the representation of the value as status code.
+    /// This status code is returned to the operating system.
+    fn report(self) -> i32;
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for () {
+    fn report(self) -> i32 { exit::SUCCESS }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl<T: Termination, E: fmt::Debug> Termination for Result<T, E> {
+    fn report(self) -> i32 {
+        match self {
+            Ok(val) => val.report(),
+            Err(err) => {
+                eprintln!("Error: {:?}", err);
+                exit::FAILURE
+            }
+        }
+    }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for ! {
+    fn report(self) -> i32 { unreachable!(); }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for bool {
+    fn report(self) -> i32 {
+        if self { exit::SUCCESS } else { exit::FAILURE }
+    }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for i32 {
+    fn report(self) -> i32 {
+        self
+    }
+}
+
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
index 9dbaf784f89e0b7e2f6bb6d88b366f91c925c976..e1392762a59dc7c76e5b73142b11b05a9702bae7 100644 (file)
@@ -68,7 +68,7 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
 
 #[cfg(not(test))]
 #[lang = "start"]
-fn lang_start<T: ::termination::Termination + 'static>
+fn lang_start<T: ::process::Termination + 'static>
     (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
 {
     lang_start_internal(&move || main().report(), argc, argv)
index 54bb65136508b5eab83d75f0bfa455ba56f191dd..3014283da5b271edc067f78d4c0df488a36e617a 100644 (file)
@@ -14,7 +14,7 @@
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
 use sys_common::poison::{self, LockResult};
-use time::Duration;
+use time::{Duration, Instant};
 
 /// A type indicating whether a timed wait on a condition variable returned
 /// due to a time out or not.
@@ -221,6 +221,64 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
         }
     }
 
+    /// Blocks the current thread until this condition variable receives a
+    /// notification and the required condition is met. Spurious wakeups are
+    /// ignored and this function will only return once the condition has been
+    /// met.
+    ///
+    /// This function will atomically unlock the mutex specified (represented by
+    /// `guard`) and block the current thread. This means that any calls
+    /// to [`notify_one`] or [`notify_all`] which happen logically after the
+    /// mutex is unlocked are candidates to wake this thread up. When this
+    /// function call returns, the lock specified will have been re-acquired.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the mutex being waited on is
+    /// poisoned when this thread re-acquires the lock. For more information,
+    /// see information about [poisoning] on the [`Mutex`] type.
+    ///
+    /// [`notify_one`]: #method.notify_one
+    /// [`notify_all`]: #method.notify_all
+    /// [poisoning]: ../sync/struct.Mutex.html#poisoning
+    /// [`Mutex`]: ../sync/struct.Mutex.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(wait_until)]
+    ///
+    /// use std::sync::{Arc, Mutex, Condvar};
+    /// use std::thread;
+    ///
+    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+    /// let pair2 = pair.clone();
+    ///
+    /// thread::spawn(move|| {
+    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let mut started = lock.lock().unwrap();
+    ///     *started = true;
+    ///     // We notify the condvar that the value has changed.
+    ///     cvar.notify_one();
+    /// });
+    ///
+    /// // Wait for the thread to start up.
+    /// let &(ref lock, ref cvar) = &*pair;
+    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
+    /// ```
+    #[unstable(feature = "wait_until", issue = "47960")]
+    pub fn wait_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
+                                mut condition: F)
+                                -> LockResult<MutexGuard<'a, T>>
+                                where F: FnMut(&mut T) -> bool {
+        while !condition(&mut *guard) {
+            guard = self.wait(guard)?;
+        }
+        Ok(guard)
+    }
+
+
     /// Waits on this condition variable for a notification, timing out after a
     /// specified duration.
     ///
@@ -295,7 +353,15 @@ pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
     ///
     /// Note that the best effort is made to ensure that the time waited is
     /// measured with a monotonic clock, and not affected by the changes made to
-    /// the system time.
+    /// the system time.  This function is susceptible to spurious wakeups.
+    /// Condition variables normally have a boolean predicate associated with
+    /// them, and the predicate must always be checked each time this function
+    /// returns to protect against spurious wakeups.  Additionally, it is
+    /// typically desirable for the time-out to not exceed some duration in
+    /// spite of spurious wakes, thus the sleep-duration is decremented by the
+    /// amount slept.  Alternatively, use the `wait_timeout_until` method
+    /// to wait until a condition is met with a total time-out regardless
+    /// of spurious wakes.
     ///
     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
     /// known to have elapsed.
@@ -304,6 +370,7 @@ pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
     /// returns, regardless of whether the timeout elapsed or not.
     ///
     /// [`wait`]: #method.wait
+    /// [`wait_timeout_until`]: #method.wait_timeout_until
     /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
     ///
     /// # Examples
@@ -355,6 +422,80 @@ pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
         }
     }
 
+    /// Waits on this condition variable for a notification, timing out after a
+    /// specified duration.  Spurious wakes will not cause this function to
+    /// return.
+    ///
+    /// The semantics of this function are equivalent to [`wait_until`] except
+    /// that the thread will be blocked for roughly no longer than `dur`. This
+    /// method should not be used for precise timing due to anomalies such as
+    /// preemption or platform differences that may not cause the maximum
+    /// amount of time waited to be precisely `dur`.
+    ///
+    /// Note that the best effort is made to ensure that the time waited is
+    /// measured with a monotonic clock, and not affected by the changes made to
+    /// the system time.
+    ///
+    /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
+    /// known to have elapsed without the condition being met.
+    ///
+    /// Like [`wait_until`], the lock specified will be re-acquired when this
+    /// function returns, regardless of whether the timeout elapsed or not.
+    ///
+    /// [`wait_until`]: #method.wait_until
+    /// [`wait_timeout`]: #method.wait_timeout
+    /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(wait_timeout_until)]
+    ///
+    /// use std::sync::{Arc, Mutex, Condvar};
+    /// use std::thread;
+    /// use std::time::Duration;
+    ///
+    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+    /// let pair2 = pair.clone();
+    ///
+    /// thread::spawn(move|| {
+    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let mut started = lock.lock().unwrap();
+    ///     *started = true;
+    ///     // We notify the condvar that the value has changed.
+    ///     cvar.notify_one();
+    /// });
+    ///
+    /// // wait for the thread to start up
+    /// let &(ref lock, ref cvar) = &*pair;
+    /// let result = cvar.wait_timeout_until(
+    ///     lock.lock().unwrap(),
+    ///     Duration::from_millis(100),
+    ///     |&mut started| started,
+    /// ).unwrap();
+    /// if result.1.timed_out() {
+    ///     // timed-out without the condition ever evaluating to true.
+    /// }
+    /// // access the locked mutex via result.0
+    /// ```
+    #[unstable(feature = "wait_timeout_until", issue = "47960")]
+    pub fn wait_timeout_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
+                                        dur: Duration, mut condition: F)
+                                        -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
+                                        where F: FnMut(&mut T) -> bool {
+        let start = Instant::now();
+        loop {
+            if condition(&mut *guard) {
+                return Ok((guard, WaitTimeoutResult(false)));
+            }
+            let timeout = match dur.checked_sub(start.elapsed()) {
+                Some(timeout) => timeout,
+                None => return Ok((guard, WaitTimeoutResult(true))),
+            };
+            guard = self.wait_timeout(guard, timeout)?.0;
+        }
+    }
+
     /// Wakes up one blocked thread on this condvar.
     ///
     /// If there is a blocked thread on this condition variable, then it will
@@ -480,6 +621,7 @@ fn drop(&mut self) {
 
 #[cfg(test)]
 mod tests {
+    /// #![feature(wait_until)]
     use sync::mpsc::channel;
     use sync::{Condvar, Mutex, Arc};
     use sync::atomic::{AtomicBool, Ordering};
@@ -548,6 +690,29 @@ fn notify_all() {
         }
     }
 
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_until() {
+        let pair = Arc::new((Mutex::new(false), Condvar::new()));
+        let pair2 = pair.clone();
+
+        // Inside of our lock, spawn a new thread, and then wait for it to start.
+        thread::spawn(move|| {
+            let &(ref lock, ref cvar) = &*pair2;
+            let mut started = lock.lock().unwrap();
+            *started = true;
+            // We notify the condvar that the value has changed.
+            cvar.notify_one();
+        });
+
+        // Wait for the thread to start up.
+        let &(ref lock, ref cvar) = &*pair;
+        let guard = cvar.wait_until(lock.lock().unwrap(), |started| {
+            *started
+        });
+        assert!(*guard.unwrap());
+    }
+
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     fn wait_timeout_wait() {
@@ -567,6 +732,53 @@ fn wait_timeout_wait() {
         }
     }
 
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_timeout_until_wait() {
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
+
+        let g = m.lock().unwrap();
+        let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| { false }).unwrap();
+        // no spurious wakeups. ensure it timed-out
+        assert!(wait.timed_out());
+    }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_timeout_until_instant_satisfy() {
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
+
+        let g = m.lock().unwrap();
+        let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| { true }).unwrap();
+        // ensure it didn't time-out even if we were not given any time.
+        assert!(!wait.timed_out());
+    }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_timeout_until_wake() {
+        let pair = Arc::new((Mutex::new(false), Condvar::new()));
+        let pair_copy = pair.clone();
+
+        let &(ref m, ref c) = &*pair;
+        let g = m.lock().unwrap();
+        let _t = thread::spawn(move || {
+            let &(ref lock, ref cvar) = &*pair_copy;
+            let mut started = lock.lock().unwrap();
+            thread::sleep(Duration::from_millis(1));
+            *started = true;
+            cvar.notify_one();
+        });
+        let (g2, wait) = c.wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| {
+            notified
+        }).unwrap();
+        // ensure it didn't time-out even if we were not given any time.
+        assert!(!wait.timed_out());
+        assert!(*g2);
+    }
+
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     fn wait_timeout_wake() {
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
deleted file mode 100644 (file)
index dc7fa53..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use fmt::Debug;
-#[cfg(target_arch = "wasm32")]
-mod exit {
-    pub const SUCCESS: i32 = 0;
-    pub const FAILURE: i32 = 1;
-}
-#[cfg(not(target_arch = "wasm32"))]
-mod exit {
-    use libc;
-    pub const SUCCESS: i32 = libc::EXIT_SUCCESS;
-    pub const FAILURE: i32 = libc::EXIT_FAILURE;
-}
-
-/// A trait for implementing arbitrary return types in the `main` function.
-///
-/// The c-main function only supports to return integers as return type.
-/// So, every type implementing the `Termination` trait has to be converted
-/// to an integer.
-///
-/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
-/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
-#[cfg_attr(not(test), lang = "termination")]
-#[unstable(feature = "termination_trait", issue = "43301")]
-#[rustc_on_unimplemented =
-  "`main` can only return types that implement {Termination}, not `{Self}`"]
-pub trait Termination {
-    /// Is called to get the representation of the value as status code.
-    /// This status code is returned to the operating system.
-    fn report(self) -> i32;
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for () {
-    fn report(self) -> i32 { exit::SUCCESS }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl<T: Termination, E: Debug> Termination for Result<T, E> {
-    fn report(self) -> i32 {
-        match self {
-            Ok(val) => val.report(),
-            Err(err) => {
-                eprintln!("Error: {:?}", err);
-                exit::FAILURE
-            }
-        }
-    }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for ! {
-    fn report(self) -> i32 { unreachable!(); }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for bool {
-    fn report(self) -> i32 {
-        if self { exit::SUCCESS } else { exit::FAILURE }
-    }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for i32 {
-    fn report(self) -> i32 {
-        self
-    }
-}
index c7ce7fffaa21b2e3fd72043a8542ce7ae918eeaf..6609b77b132c62f27dec7f5c3ea4c61c182a1bc9 100644 (file)
@@ -1085,7 +1085,7 @@ pub enum ExprKind {
     /// `if let pat = expr { block } else { expr }`
     ///
     /// This is desugared to a `match` expression.
-    IfLet(P<Pat>, P<Expr>, P<Block>, Option<P<Expr>>),
+    IfLet(Vec<P<Pat>>, P<Expr>, P<Block>, Option<P<Expr>>),
     /// A while loop, with an optional label
     ///
     /// `'label: while expr { block }`
@@ -1095,7 +1095,7 @@ pub enum ExprKind {
     /// `'label: while let pat = expr { block }`
     ///
     /// This is desugared to a combination of `loop` and `match` expressions.
-    WhileLet(P<Pat>, P<Expr>, P<Block>, Option<Label>),
+    WhileLet(Vec<P<Pat>>, P<Expr>, P<Block>, Option<Label>),
     /// A for loop, with an optional label
     ///
     /// `'label: for pat in expr { block }`
index 7681f55bd8ccb4f96c4b6422c272c46c6cd7be90..b88e064e7e56dd059c8d54290a9cd005c3a9d6f7 100644 (file)
@@ -319,14 +319,8 @@ fn path_all(&self,
                 types: Vec<P<ast::Ty>>,
                 bindings: Vec<ast::TypeBinding> )
                 -> ast::Path {
-        use syntax::parse::token;
-
         let last_identifier = idents.pop().unwrap();
         let mut segments: Vec<ast::PathSegment> = Vec::new();
-        if global &&
-           !idents.first().map_or(false, |&ident| token::Ident(ident).is_path_segment_keyword()) {
-            segments.push(ast::PathSegment::crate_root(span));
-        }
 
         segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, span)));
         let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
@@ -335,7 +329,9 @@ fn path_all(&self,
             None
         };
         segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
-        ast::Path { span, segments }
+        let path = ast::Path { span, segments };
+
+        if global { path.default_to_global() } else { path }
     }
 
     /// Constructs a qualified path.
index f7cebed5f62cd078045be870344e8d4aa0369f79..1ebf52e9fe8c016a43512c48e545e10d563a9d48 100644 (file)
@@ -432,9 +432,6 @@ pub fn new() -> Features {
     // `foo.rs` as an alternative to `foo/mod.rs`
     (active, non_modrs_mods, "1.24.0", Some(44660)),
 
-    // Nested `impl Trait`
-    (active, nested_impl_trait, "1.24.0", Some(34511)),
-
     // Termination trait in main (RFC 1937)
     (active, termination_trait, "1.24.0", Some(43301)),
 
@@ -449,6 +446,9 @@ pub fn new() -> Features {
 
     // Use `?` as the Kleene "at most one" operator
     (active, macro_at_most_once_rep, "1.25.0", Some(48075)),
+
+    // Multiple patterns with `|` in `if let` and `while let`
+    (active, if_while_or_patterns, "1.26.0", Some(48215)),
 );
 
 declare_features! (
@@ -1352,73 +1352,8 @@ fn contains_novel_literal(item: &ast::MetaItem) -> bool {
     }
 }
 
-// Bans nested `impl Trait`, e.g. `impl Into<impl Debug>`.
-// Nested `impl Trait` _is_ allowed in associated type position,
-// e.g `impl Iterator<Item=impl Debug>`
-struct NestedImplTraitVisitor<'a> {
-    context: &'a Context<'a>,
-    is_in_impl_trait: bool,
-}
-
-impl<'a> NestedImplTraitVisitor<'a> {
-    fn with_impl_trait<F>(&mut self, is_in_impl_trait: bool, f: F)
-        where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
-    {
-        let old_is_in_impl_trait = self.is_in_impl_trait;
-        self.is_in_impl_trait = is_in_impl_trait;
-        f(self);
-        self.is_in_impl_trait = old_is_in_impl_trait;
-    }
-}
-
-
-impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
-    fn visit_ty(&mut self, t: &'a ast::Ty) {
-        if let ast::TyKind::ImplTrait(_) = t.node {
-            if self.is_in_impl_trait {
-                gate_feature_post!(&self, nested_impl_trait, t.span,
-                    "nested `impl Trait` is experimental"
-                );
-            }
-            self.with_impl_trait(true, |this| visit::walk_ty(this, t));
-        } else {
-            visit::walk_ty(self, t);
-        }
-    }
-    fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a ast::PathParameters) {
-        match *path_parameters {
-            ast::PathParameters::AngleBracketed(ref params) => {
-                for type_ in &params.types {
-                    self.visit_ty(type_);
-                }
-                for type_binding in &params.bindings {
-                    // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
-                    // are allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(false, |this| visit::walk_ty(this, &type_binding.ty));
-                }
-            }
-            ast::PathParameters::Parenthesized(ref params) => {
-                for type_ in &params.inputs {
-                    self.visit_ty(type_);
-                }
-                if let Some(ref type_) = params.output {
-                    // `-> Foo` syntax is essentially an associated type binding,
-                    // so it is also allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(false, |this| visit::walk_ty(this, type_));
-                }
-            }
-        }
-    }
-}
-
 impl<'a> PostExpansionVisitor<'a> {
-    fn whole_crate_feature_gates(&mut self, krate: &ast::Crate) {
-        visit::walk_crate(
-            &mut NestedImplTraitVisitor {
-                context: self.context,
-                is_in_impl_trait: false,
-            }, krate);
-
+    fn whole_crate_feature_gates(&mut self, _krate: &ast::Crate) {
         for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() {
             if !span.allows_unstable() {
                 let cx = &self.context;
@@ -1686,6 +1621,12 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
             ast::ExprKind::Catch(_) => {
                 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
             }
+            ast::ExprKind::IfLet(ref pats, ..) | ast::ExprKind::WhileLet(ref pats, ..) => {
+                if pats.len() > 1 {
+                    gate_feature_post!(&self, if_while_or_patterns, e.span,
+                                    "multiple patterns in `if let` and `while let` are unstable");
+                }
+            }
             _ => {}
         }
         visit::walk_expr(self, e);
index 1a2025b073b2b85081f96883242dda1909531f13..e8eb75f5e6018e6e97e1c39d6cdbd1caf8d79130 100644 (file)
@@ -1210,8 +1210,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                        folder.fold_block(tr),
                        fl.map(|x| folder.fold_expr(x)))
             }
-            ExprKind::IfLet(pat, expr, tr, fl) => {
-                ExprKind::IfLet(folder.fold_pat(pat),
+            ExprKind::IfLet(pats, expr, tr, fl) => {
+                ExprKind::IfLet(pats.move_map(|pat| folder.fold_pat(pat)),
                           folder.fold_expr(expr),
                           folder.fold_block(tr),
                           fl.map(|x| folder.fold_expr(x)))
@@ -1221,8 +1221,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                           folder.fold_block(body),
                           opt_label.map(|label| folder.fold_label(label)))
             }
-            ExprKind::WhileLet(pat, expr, body, opt_label) => {
-                ExprKind::WhileLet(folder.fold_pat(pat),
+            ExprKind::WhileLet(pats, expr, body, opt_label) => {
+                ExprKind::WhileLet(pats.move_map(|pat| folder.fold_pat(pat)),
                              folder.fold_expr(expr),
                              folder.fold_block(body),
                              opt_label.map(|label| folder.fold_label(label)))
index 1a33de844298290f11b3b8dc9f4c50112e6a6a6f..4d457f4864af0050587f86a75a52a0e953441ab4 100644 (file)
@@ -405,11 +405,14 @@ fn to_string(&self) -> String {
     }
 }
 
-// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
-// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
-fn can_continue_type_after_ident(t: &token::Token) -> bool {
+/// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
+/// `IDENT<<u8 as Trait>::AssocTy>`.
+///
+/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
+/// that IDENT is not the ident of a fn trait
+fn can_continue_type_after_non_fn_ident(t: &token::Token) -> bool {
     t == &token::ModSep || t == &token::Lt ||
-    t == &token::BinOp(token::Shl) || t == &token::OpenDelim(token::Paren)
+    t == &token::BinOp(token::Shl)
 }
 
 /// Information about the path to a module.
@@ -1321,7 +1324,7 @@ pub fn diagnostic(&self) -> &'a errors::Handler {
     pub fn token_is_bare_fn_keyword(&mut self) -> bool {
         self.check_keyword(keywords::Fn) ||
             self.check_keyword(keywords::Unsafe) ||
-            self.check_keyword(keywords::Extern)
+            self.check_keyword(keywords::Extern) && self.is_extern_non_path()
     }
 
     fn eat_label(&mut self) -> Option<Label> {
@@ -1619,7 +1622,8 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
             impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
             TyKind::ImplTrait(bounds)
         } else if self.check_keyword(keywords::Dyn) &&
-                  self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_ident(t)) {
+                  self.look_ahead(1, |t| t.can_begin_bound() &&
+                                         !can_continue_type_after_non_fn_ident(t)) {
             self.bump(); // `dyn`
             // Always parse bounds greedily for better error recovery.
             let bounds = self.parse_ty_param_bounds()?;
@@ -3224,7 +3228,7 @@ pub fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>)
                              -> PResult<'a, P<Expr>> {
         let lo = self.prev_span;
         self.expect_keyword(keywords::Let)?;
-        let pat = self.parse_pat()?;
+        let pats = self.parse_pats()?;
         self.expect(&token::Eq)?;
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
         let thn = self.parse_block()?;
@@ -3234,7 +3238,7 @@ pub fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>)
         } else {
             (thn.span, None)
         };
-        Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pat, expr, thn, els), attrs))
+        Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs))
     }
 
     // `move |args| expr`
@@ -3325,13 +3329,13 @@ pub fn parse_while_let_expr(&mut self, opt_label: Option<Label>,
                                 span_lo: Span,
                                 mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         self.expect_keyword(keywords::Let)?;
-        let pat = self.parse_pat()?;
+        let pats = self.parse_pats()?;
         self.expect(&token::Eq)?;
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         let span = span_lo.to(body.span);
-        return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_label), attrs));
+        return Ok(self.mk_expr(span, ExprKind::WhileLet(pats, expr, body, opt_label), attrs));
     }
 
     // parse `loop {...}`, `loop` token already eaten
@@ -6482,6 +6486,8 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
             // UNSAFE FUNCTION ITEM
             self.bump(); // `unsafe`
+            // `{` is also expected after `unsafe`, in case of error, include it in the diagnostic
+            self.check(&token::OpenDelim(token::Brace));
             let abi = if self.eat_keyword(keywords::Extern) {
                 self.parse_opt_abi()?.unwrap_or(Abi::C)
             } else {
index 3dfe3c9e5b990590e12c1e8efe97a45163eb1875..9cad9f46e98cfef05af3906fc9d24a2a763a16d5 100644 (file)
@@ -1767,11 +1767,11 @@ fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
                         self.print_else(e.as_ref().map(|e| &**e))
                     }
                     // "another else-if-let"
-                    ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => {
+                    ast::ExprKind::IfLet(ref pats, ref expr, ref then, ref e) => {
                         self.cbox(INDENT_UNIT - 1)?;
                         self.ibox(0)?;
                         self.s.word(" else if let ")?;
-                        self.print_pat(pat)?;
+                        self.print_pats(pats)?;
                         self.s.space()?;
                         self.word_space("=")?;
                         self.print_expr_as_cond(expr)?;
@@ -1805,10 +1805,10 @@ pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
         self.print_else(elseopt)
     }
 
-    pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block,
+    pub fn print_if_let(&mut self, pats: &[P<ast::Pat>], expr: &ast::Expr, blk: &ast::Block,
                         elseopt: Option<&ast::Expr>) -> io::Result<()> {
         self.head("if let")?;
-        self.print_pat(pat)?;
+        self.print_pats(pats)?;
         self.s.space()?;
         self.word_space("=")?;
         self.print_expr_as_cond(expr)?;
@@ -2109,8 +2109,8 @@ fn print_expr_outer_attr_style(&mut self,
             ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
                 self.print_if(test, blk, elseopt.as_ref().map(|e| &**e))?;
             }
-            ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
-                self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?;
+            ast::ExprKind::IfLet(ref pats, ref expr, ref blk, ref elseopt) => {
+                self.print_if_let(pats, expr, blk, elseopt.as_ref().map(|e| &**e))?;
             }
             ast::ExprKind::While(ref test, ref blk, opt_label) => {
                 if let Some(label) = opt_label {
@@ -2122,13 +2122,13 @@ fn print_expr_outer_attr_style(&mut self,
                 self.s.space()?;
                 self.print_block_with_attrs(blk, attrs)?;
             }
-            ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_label) => {
+            ast::ExprKind::WhileLet(ref pats, ref expr, ref blk, opt_label) => {
                 if let Some(label) = opt_label {
                     self.print_ident(label.ident)?;
                     self.word_space(":")?;
                 }
                 self.head("while let")?;
-                self.print_pat(pat)?;
+                self.print_pats(pats)?;
                 self.s.space()?;
                 self.word_space("=")?;
                 self.print_expr_as_cond(expr)?;
@@ -2664,6 +2664,20 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
         self.ann.post(self, NodePat(pat))
     }
 
+    fn print_pats(&mut self, pats: &[P<ast::Pat>]) -> io::Result<()> {
+        let mut first = true;
+        for p in pats {
+            if first {
+                first = false;
+            } else {
+                self.s.space()?;
+                self.word_space("|")?;
+            }
+            self.print_pat(p)?;
+        }
+        Ok(())
+    }
+
     fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
         // I have no idea why this check is necessary, but here it
         // is :(
@@ -2674,16 +2688,7 @@ fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
         self.ibox(0)?;
         self.maybe_print_comment(arm.pats[0].span.lo())?;
         self.print_outer_attributes(&arm.attrs)?;
-        let mut first = true;
-        for p in &arm.pats {
-            if first {
-                first = false;
-            } else {
-                self.s.space()?;
-                self.word_space("|")?;
-            }
-            self.print_pat(p)?;
-        }
+        self.print_pats(&arm.pats)?;
         self.s.space()?;
         if let Some(ref e) = arm.guard {
             self.word_space("if")?;
index 7b119c576db5821e33e7d42642bda77e29c09944..e732ac3a635ba1475de4d3a41c4ad5da2ccd7fbb 100644 (file)
@@ -32,6 +32,7 @@
 use ext::expand::ExpansionConfig;
 use ext::hygiene::{Mark, SyntaxContext};
 use fold::Folder;
+use feature_gate::Features;
 use util::move_map::MoveMap;
 use fold;
 use parse::{token, ParseSess};
@@ -63,6 +64,7 @@ struct TestCtxt<'a> {
     reexport_test_harness_main: Option<Symbol>,
     is_libtest: bool,
     ctxt: SyntaxContext,
+    features: &'a Features,
 
     // top-level re-export submodule, filled out after folding is finished
     toplevel_reexport: Option<Ident>,
@@ -74,7 +76,8 @@ pub fn modify_for_testing(sess: &ParseSess,
                           resolver: &mut Resolver,
                           should_test: bool,
                           krate: ast::Crate,
-                          span_diagnostic: &errors::Handler) -> ast::Crate {
+                          span_diagnostic: &errors::Handler,
+                          features: &Features) -> ast::Crate {
     // Check for #[reexport_test_harness_main = "some_name"] which
     // creates a `use some_name = __test::main;`. This needs to be
     // unconditional, so that the attribute is still marked as used in
@@ -84,7 +87,8 @@ pub fn modify_for_testing(sess: &ParseSess,
                                            "reexport_test_harness_main");
 
     if should_test {
-        generate_test_harness(sess, resolver, reexport_test_harness_main, krate, span_diagnostic)
+        generate_test_harness(sess, resolver, reexport_test_harness_main,
+                              krate, span_diagnostic, features)
     } else {
         krate
     }
@@ -265,16 +269,20 @@ fn generate_test_harness(sess: &ParseSess,
                          resolver: &mut Resolver,
                          reexport_test_harness_main: Option<Symbol>,
                          krate: ast::Crate,
-                         sd: &errors::Handler) -> ast::Crate {
+                         sd: &errors::Handler,
+                         features: &Features) -> ast::Crate {
     // Remove the entry points
     let mut cleaner = EntryPointCleaner { depth: 0 };
     let krate = cleaner.fold_crate(krate);
 
     let mark = Mark::fresh(Mark::root());
 
+    let mut econfig = ExpansionConfig::default("test".to_string());
+    econfig.features = Some(features);
+
     let cx = TestCtxt {
         span_diagnostic: sd,
-        ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver),
+        ext_cx: ExtCtxt::new(sess, econfig, resolver),
         path: Vec::new(),
         testfns: Vec::new(),
         reexport_test_harness_main,
@@ -282,6 +290,7 @@ fn generate_test_harness(sess: &ParseSess,
         is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false),
         toplevel_reexport: None,
         ctxt: SyntaxContext::empty().apply_mark(mark),
+        features,
     };
 
     mark.set_expn_info(ExpnInfo {
@@ -318,71 +327,105 @@ enum HasTestSignature {
 fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_test_attr = attr::contains_name(&i.attrs, "test");
 
-    fn has_test_signature(i: &ast::Item) -> HasTestSignature {
+    fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
         match i.node {
-          ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
-            let no_output = match decl.output {
-                ast::FunctionRetTy::Default(..) => true,
-                ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
-                _ => false
-            };
-            if decl.inputs.is_empty()
-                   && no_output
-                   && !generics.is_parameterized() {
-                Yes
-            } else {
-                No
+            ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
+                // If the termination trait is active, the compiler will check that the output
+                // type implements the `Termination` trait as `libtest` enforces that.
+                let output_matches = if cx.features.termination_trait {
+                    true
+                } else {
+                    let no_output = match decl.output {
+                        ast::FunctionRetTy::Default(..) => true,
+                        ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
+                        _ => false
+                    };
+
+                    no_output && !generics.is_parameterized()
+                };
+
+                if decl.inputs.is_empty() && output_matches {
+                    Yes
+                } else {
+                    No
+                }
             }
-          }
-          _ => NotEvenAFunction,
+            _ => NotEvenAFunction,
         }
     }
 
-    if has_test_attr {
+    let has_test_signature = if has_test_attr {
         let diag = cx.span_diagnostic;
-        match has_test_signature(i) {
-            Yes => {},
-            No => diag.span_err(i.span, "functions used as tests must have signature fn() -> ()"),
-            NotEvenAFunction => diag.span_err(i.span,
-                                              "only functions may be used as tests"),
+        match has_test_signature(cx, i) {
+            Yes => true,
+            No => {
+                if cx.features.termination_trait {
+                    diag.span_err(i.span, "functions used as tests can not have any arguments");
+                } else {
+                    diag.span_err(i.span, "functions used as tests must have signature fn() -> ()");
+                }
+                false
+            },
+            NotEvenAFunction => {
+                diag.span_err(i.span, "only functions may be used as tests");
+                false
+            },
         }
-    }
+    } else {
+        false
+    };
 
-    has_test_attr && has_test_signature(i) == Yes
+    has_test_attr && has_test_signature
 }
 
 fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_bench_attr = attr::contains_name(&i.attrs, "bench");
 
-    fn has_test_signature(i: &ast::Item) -> bool {
+    fn has_bench_signature(cx: &TestCtxt, i: &ast::Item) -> bool {
         match i.node {
             ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
                 let input_cnt = decl.inputs.len();
-                let no_output = match decl.output {
-                    ast::FunctionRetTy::Default(..) => true,
-                    ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
-                    _ => false
+
+                // If the termination trait is active, the compiler will check that the output
+                // type implements the `Termination` trait as `libtest` enforces that.
+                let output_matches = if cx.features.termination_trait {
+                    true
+                } else {
+                    let no_output = match decl.output {
+                        ast::FunctionRetTy::Default(..) => true,
+                        ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
+                        _ => false
+                    };
+                    let tparm_cnt = generics.params.iter()
+                        .filter(|param| param.is_type_param())
+                        .count();
+
+                    no_output && tparm_cnt == 0
                 };
-                let tparm_cnt = generics.params.iter()
-                    .filter(|param| param.is_type_param())
-                    .count();
 
                 // NB: inadequate check, but we're running
                 // well before resolve, can't get too deep.
-                input_cnt == 1
-                    && no_output && tparm_cnt == 0
+                input_cnt == 1 && output_matches
             }
           _ => false
         }
     }
 
-    if has_bench_attr && !has_test_signature(i) {
+    let has_bench_signature = has_bench_signature(cx, i);
+
+    if has_bench_attr && !has_bench_signature {
         let diag = cx.span_diagnostic;
-        diag.span_err(i.span, "functions used as benches must have signature \
-                      `fn(&mut Bencher) -> ()`");
+
+        if cx.features.termination_trait {
+            diag.span_err(i.span, "functions used as benches must have signature \
+                                   `fn(&mut Bencher) -> impl Termination`");
+        } else {
+            diag.span_err(i.span, "functions used as benches must have signature \
+                                   `fn(&mut Bencher) -> ()`");
+        }
     }
 
-    has_bench_attr && has_test_signature(i)
+    has_bench_attr && has_bench_signature
 }
 
 fn is_ignored(i: &ast::Item) -> bool {
@@ -690,9 +733,12 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
              field("should_panic", fail_expr),
              field("allow_fail", allow_fail_expr)]);
 
-
-    let mut visible_path = match cx.toplevel_reexport {
-        Some(id) => vec![id],
+    let mut visible_path = vec![];
+    if cx.features.extern_absolute_paths {
+        visible_path.push(keywords::Crate.ident());
+    }
+    match cx.toplevel_reexport {
+        Some(id) => visible_path.push(id),
         None => {
             let diag = cx.span_diagnostic;
             diag.bug("expected to find top-level re-export name, but found None");
@@ -700,9 +746,64 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     };
     visible_path.extend(path);
 
-    let fn_expr = ecx.expr_path(ecx.path_global(span, visible_path));
+    // Rather than directly give the test function to the test
+    // harness, we create a wrapper like one of the following:
+    //
+    //     || test::assert_test_result(real_function()) // for test
+    //     |b| test::assert_test_result(real_function(b)) // for bench
+    //
+    // this will coerce into a fn pointer that is specialized to the
+    // actual return type of `real_function` (Typically `()`, but not always).
+    let fn_expr = {
+        // construct `real_function()` (this will be inserted into the overall expr)
+        let real_function_expr = ecx.expr_path(ecx.path_global(span, visible_path));
+        // construct path `test::assert_test_result`
+        let assert_test_result = test_path("assert_test_result");
+        if test.bench {
+            // construct `|b| {..}`
+            let b_ident = Ident::with_empty_ctxt(Symbol::gensym("b"));
+            let b_expr = ecx.expr_ident(span, b_ident);
+            ecx.lambda(
+                span,
+                vec![b_ident],
+                // construct `assert_test_result(..)`
+                ecx.expr_call(
+                    span,
+                    ecx.expr_path(assert_test_result),
+                    vec![
+                        // construct `real_function(b)`
+                        ecx.expr_call(
+                            span,
+                            real_function_expr,
+                            vec![b_expr],
+                        )
+                    ],
+                ),
+            )
+        } else {
+            // construct `|| {..}`
+            ecx.lambda(
+                span,
+                vec![],
+                // construct `assert_test_result(..)`
+                ecx.expr_call(
+                    span,
+                    ecx.expr_path(assert_test_result),
+                    vec![
+                        // construct `real_function()`
+                        ecx.expr_call(
+                            span,
+                            real_function_expr,
+                            vec![],
+                        )
+                    ],
+                ),
+            )
+        }
+    };
 
     let variant_name = if test.bench { "StaticBenchFn" } else { "StaticTestFn" };
+
     // self::test::$variant_name($fn_expr)
     let testfn_expr = ecx.expr_call(span, ecx.expr_path(test_path(variant_name)), vec![fn_expr]);
 
index 4691ddafa36e8480f2463ad81caffe85245bf214..640f90ecb4a4367e57d9b4b32b4f1bf1966f6279 100644 (file)
@@ -705,15 +705,15 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_block(block);
         }
-        ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
-            visitor.visit_pat(pattern);
+        ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => {
+            walk_list!(visitor, visit_pat, pats);
             visitor.visit_expr(subexpression);
             visitor.visit_block(if_block);
             walk_list!(visitor, visit_expr, optional_else);
         }
-        ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_label) => {
+        ExprKind::WhileLet(ref pats, ref subexpression, ref block, ref opt_label) => {
             walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_pat(pattern);
+            walk_list!(visitor, visit_pat, pats);
             visitor.visit_expr(subexpression);
             visitor.visit_block(block);
         }
index 9ea5f39b71feecca2ae04b27164c8c1bc2cbb6b3..82077bc4cd4822319346c0632df8a1bc941ecad3 100644 (file)
@@ -40,6 +40,7 @@
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
+#![feature(termination_trait_lib)]
 
 extern crate getopts;
 extern crate term;
@@ -67,6 +68,7 @@
 use std::io;
 use std::iter::repeat;
 use std::path::PathBuf;
+use std::process::Termination;
 use std::sync::mpsc::{channel, Sender};
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -81,8 +83,8 @@
 pub mod test {
     pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed,
              TrFailedMsg, TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName,
-             DynTestName, DynTestFn, run_test, test_main, test_main_static, filter_tests,
-             parse_opts, StaticBenchFn, ShouldPanic, Options};
+             DynTestName, DynTestFn, assert_test_result, run_test, test_main, test_main_static,
+             filter_tests, parse_opts, StaticBenchFn, ShouldPanic, Options};
 }
 
 pub mod stats;
@@ -322,6 +324,13 @@ pub fn test_main_static(tests: &[TestDescAndFn]) {
     test_main(&args, owned_tests, Options::new())
 }
 
+/// Invoked when unit tests terminate. Should panic if the unit
+/// test is considered a failure. By default, invokes `report()`
+/// and checks for a `0` result.
+pub fn assert_test_result<T: Termination>(result: T) {
+    assert_eq!(result.report(), 0);
+}
+
 #[derive(Copy, Clone, Debug)]
 pub enum ColorConfig {
     AutoColor,
diff --git a/src/rt/rust_test_helpers.c b/src/rt/rust_test_helpers.c
deleted file mode 100644 (file)
index 2a14b3d..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright 2013 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.
-
-// Helper functions used only in tests
-
-#include <stdint.h>
-#include <assert.h>
-#include <stdarg.h>
-
-// These functions are used in the unit tests for C ABI calls.
-
-uint32_t
-rust_dbg_extern_identity_u32(uint32_t u) {
-    return u;
-}
-
-uint64_t
-rust_dbg_extern_identity_u64(uint64_t u) {
-    return u;
-}
-
-double
-rust_dbg_extern_identity_double(double u) {
-    return u;
-}
-
-char
-rust_dbg_extern_identity_u8(char u) {
-    return u;
-}
-
-typedef void *(*dbg_callback)(void*);
-
-void *
-rust_dbg_call(dbg_callback cb, void *data) {
-    return cb(data);
-}
-
-void rust_dbg_do_nothing() { }
-
-struct TwoU8s {
-    uint8_t one;
-    uint8_t two;
-};
-
-struct TwoU8s
-rust_dbg_extern_return_TwoU8s() {
-    struct TwoU8s s;
-    s.one = 10;
-    s.two = 20;
-    return s;
-}
-
-struct TwoU8s
-rust_dbg_extern_identity_TwoU8s(struct TwoU8s u) {
-    return u;
-}
-
-struct TwoU16s {
-    uint16_t one;
-    uint16_t two;
-};
-
-struct TwoU16s
-rust_dbg_extern_return_TwoU16s() {
-    struct TwoU16s s;
-    s.one = 10;
-    s.two = 20;
-    return s;
-}
-
-struct TwoU16s
-rust_dbg_extern_identity_TwoU16s(struct TwoU16s u) {
-    return u;
-}
-
-struct TwoU32s {
-    uint32_t one;
-    uint32_t two;
-};
-
-struct TwoU32s
-rust_dbg_extern_return_TwoU32s() {
-    struct TwoU32s s;
-    s.one = 10;
-    s.two = 20;
-    return s;
-}
-
-struct TwoU32s
-rust_dbg_extern_identity_TwoU32s(struct TwoU32s u) {
-    return u;
-}
-
-struct TwoU64s {
-    uint64_t one;
-    uint64_t two;
-};
-
-struct TwoU64s
-rust_dbg_extern_return_TwoU64s() {
-    struct TwoU64s s;
-    s.one = 10;
-    s.two = 20;
-    return s;
-}
-
-struct TwoU64s
-rust_dbg_extern_identity_TwoU64s(struct TwoU64s u) {
-    return u;
-}
-
-struct TwoDoubles {
-    double one;
-    double two;
-};
-
-struct TwoDoubles
-rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
-    return u;
-}
-
-struct ManyInts {
-    int8_t arg1;
-    int16_t arg2;
-    int32_t arg3;
-    int16_t arg4;
-    int8_t arg5;
-    struct TwoU8s arg6;
-};
-
-// MSVC doesn't allow empty structs or unions
-#ifndef _MSC_VER
-struct Empty {
-};
-
-void
-rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts v2) {
-    assert(v1.arg1 == v2.arg1 + 1);
-    assert(v1.arg2 == v2.arg2 + 1);
-    assert(v1.arg3 == v2.arg3 + 1);
-    assert(v1.arg4 == v2.arg4 + 1);
-    assert(v1.arg5 == v2.arg5 + 1);
-    assert(v1.arg6.one == v2.arg6.one + 1);
-    assert(v1.arg6.two == v2.arg6.two + 1);
-}
-#endif
-
-intptr_t
-rust_get_test_int() {
-  return 1;
-}
-
-char *
-rust_get_null_ptr() {
-    return 0;
-}
-
-/* Debug helpers strictly to verify ABI conformance.
- *
- * FIXME (#2665): move these into a testcase when the testsuite
- * understands how to have explicit C files included.
- */
-
-struct quad {
-    uint64_t a;
-    uint64_t b;
-    uint64_t c;
-    uint64_t d;
-};
-
-struct floats {
-    double a;
-    uint8_t b;
-    double c;
-};
-
-struct quad
-rust_dbg_abi_1(struct quad q) {
-    struct quad qq = { q.c + 1,
-                       q.d - 1,
-                       q.a + 1,
-                       q.b - 1 };
-    return qq;
-}
-
-struct floats
-rust_dbg_abi_2(struct floats f) {
-    struct floats ff = { f.c + 1.0,
-                         0xff,
-                         f.a - 1.0 };
-    return ff;
-}
-
-int
-rust_dbg_static_mut = 3;
-
-void
-rust_dbg_static_mut_check_four() {
-    assert(rust_dbg_static_mut == 4);
-}
-
-struct S {
-    uint64_t x;
-    uint64_t y;
-    uint64_t z;
-};
-
-uint64_t get_x(struct S s) {
-    return s.x;
-}
-
-uint64_t get_y(struct S s) {
-    return s.y;
-}
-
-uint64_t get_z(struct S s) {
-    return s.z;
-}
-
-uint64_t get_c_many_params(void *a, void *b, void *c, void *d, struct quad f) {
-    return f.c;
-}
-
-// Calculates the average of `(x + y) / n` where x: i64, y: f64. There must be exactly n pairs
-// passed as variadic arguments.
-double rust_interesting_average(uint64_t n, ...) {
-    va_list pairs;
-    double sum = 0.0;
-    int i;
-    va_start(pairs, n);
-    for(i = 0; i < n; i += 1) {
-        sum += (double)va_arg(pairs, int64_t);
-        sum += va_arg(pairs, double);
-    }
-    va_end(pairs);
-    return sum / n;
-}
-
-int32_t rust_int8_to_int32(int8_t x) {
-    return (int32_t)x;
-}
-
-typedef union LARGE_INTEGER {
-  struct {
-    uint32_t LowPart;
-    uint32_t HighPart;
-  };
-  struct {
-    uint32_t LowPart;
-    uint32_t HighPart;
-  } u;
-  uint64_t QuadPart;
-} LARGE_INTEGER;
-
-LARGE_INTEGER increment_all_parts(LARGE_INTEGER li) {
-    li.LowPart += 1;
-    li.HighPart += 1;
-    li.u.LowPart += 1;
-    li.u.HighPart += 1;
-    li.QuadPart += 1;
-    return li;
-}
-
-#if __SIZEOF_INT128__ == 16
-
-unsigned __int128 identity(unsigned __int128 a) {
-    return a;
-}
-
-__int128 square(__int128 a) {
-    return a * a;
-}
-
-__int128 sub(__int128 a, __int128 b) {
-    return a - b;
-}
-
-#endif
diff --git a/src/test/auxiliary/rust_test_helpers.c b/src/test/auxiliary/rust_test_helpers.c
new file mode 100644 (file)
index 0000000..2a14b3d
--- /dev/null
@@ -0,0 +1,286 @@
+// Copyright 2013 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.
+
+// Helper functions used only in tests
+
+#include <stdint.h>
+#include <assert.h>
+#include <stdarg.h>
+
+// These functions are used in the unit tests for C ABI calls.
+
+uint32_t
+rust_dbg_extern_identity_u32(uint32_t u) {
+    return u;
+}
+
+uint64_t
+rust_dbg_extern_identity_u64(uint64_t u) {
+    return u;
+}
+
+double
+rust_dbg_extern_identity_double(double u) {
+    return u;
+}
+
+char
+rust_dbg_extern_identity_u8(char u) {
+    return u;
+}
+
+typedef void *(*dbg_callback)(void*);
+
+void *
+rust_dbg_call(dbg_callback cb, void *data) {
+    return cb(data);
+}
+
+void rust_dbg_do_nothing() { }
+
+struct TwoU8s {
+    uint8_t one;
+    uint8_t two;
+};
+
+struct TwoU8s
+rust_dbg_extern_return_TwoU8s() {
+    struct TwoU8s s;
+    s.one = 10;
+    s.two = 20;
+    return s;
+}
+
+struct TwoU8s
+rust_dbg_extern_identity_TwoU8s(struct TwoU8s u) {
+    return u;
+}
+
+struct TwoU16s {
+    uint16_t one;
+    uint16_t two;
+};
+
+struct TwoU16s
+rust_dbg_extern_return_TwoU16s() {
+    struct TwoU16s s;
+    s.one = 10;
+    s.two = 20;
+    return s;
+}
+
+struct TwoU16s
+rust_dbg_extern_identity_TwoU16s(struct TwoU16s u) {
+    return u;
+}
+
+struct TwoU32s {
+    uint32_t one;
+    uint32_t two;
+};
+
+struct TwoU32s
+rust_dbg_extern_return_TwoU32s() {
+    struct TwoU32s s;
+    s.one = 10;
+    s.two = 20;
+    return s;
+}
+
+struct TwoU32s
+rust_dbg_extern_identity_TwoU32s(struct TwoU32s u) {
+    return u;
+}
+
+struct TwoU64s {
+    uint64_t one;
+    uint64_t two;
+};
+
+struct TwoU64s
+rust_dbg_extern_return_TwoU64s() {
+    struct TwoU64s s;
+    s.one = 10;
+    s.two = 20;
+    return s;
+}
+
+struct TwoU64s
+rust_dbg_extern_identity_TwoU64s(struct TwoU64s u) {
+    return u;
+}
+
+struct TwoDoubles {
+    double one;
+    double two;
+};
+
+struct TwoDoubles
+rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
+    return u;
+}
+
+struct ManyInts {
+    int8_t arg1;
+    int16_t arg2;
+    int32_t arg3;
+    int16_t arg4;
+    int8_t arg5;
+    struct TwoU8s arg6;
+};
+
+// MSVC doesn't allow empty structs or unions
+#ifndef _MSC_VER
+struct Empty {
+};
+
+void
+rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts v2) {
+    assert(v1.arg1 == v2.arg1 + 1);
+    assert(v1.arg2 == v2.arg2 + 1);
+    assert(v1.arg3 == v2.arg3 + 1);
+    assert(v1.arg4 == v2.arg4 + 1);
+    assert(v1.arg5 == v2.arg5 + 1);
+    assert(v1.arg6.one == v2.arg6.one + 1);
+    assert(v1.arg6.two == v2.arg6.two + 1);
+}
+#endif
+
+intptr_t
+rust_get_test_int() {
+  return 1;
+}
+
+char *
+rust_get_null_ptr() {
+    return 0;
+}
+
+/* Debug helpers strictly to verify ABI conformance.
+ *
+ * FIXME (#2665): move these into a testcase when the testsuite
+ * understands how to have explicit C files included.
+ */
+
+struct quad {
+    uint64_t a;
+    uint64_t b;
+    uint64_t c;
+    uint64_t d;
+};
+
+struct floats {
+    double a;
+    uint8_t b;
+    double c;
+};
+
+struct quad
+rust_dbg_abi_1(struct quad q) {
+    struct quad qq = { q.c + 1,
+                       q.d - 1,
+                       q.a + 1,
+                       q.b - 1 };
+    return qq;
+}
+
+struct floats
+rust_dbg_abi_2(struct floats f) {
+    struct floats ff = { f.c + 1.0,
+                         0xff,
+                         f.a - 1.0 };
+    return ff;
+}
+
+int
+rust_dbg_static_mut = 3;
+
+void
+rust_dbg_static_mut_check_four() {
+    assert(rust_dbg_static_mut == 4);
+}
+
+struct S {
+    uint64_t x;
+    uint64_t y;
+    uint64_t z;
+};
+
+uint64_t get_x(struct S s) {
+    return s.x;
+}
+
+uint64_t get_y(struct S s) {
+    return s.y;
+}
+
+uint64_t get_z(struct S s) {
+    return s.z;
+}
+
+uint64_t get_c_many_params(void *a, void *b, void *c, void *d, struct quad f) {
+    return f.c;
+}
+
+// Calculates the average of `(x + y) / n` where x: i64, y: f64. There must be exactly n pairs
+// passed as variadic arguments.
+double rust_interesting_average(uint64_t n, ...) {
+    va_list pairs;
+    double sum = 0.0;
+    int i;
+    va_start(pairs, n);
+    for(i = 0; i < n; i += 1) {
+        sum += (double)va_arg(pairs, int64_t);
+        sum += va_arg(pairs, double);
+    }
+    va_end(pairs);
+    return sum / n;
+}
+
+int32_t rust_int8_to_int32(int8_t x) {
+    return (int32_t)x;
+}
+
+typedef union LARGE_INTEGER {
+  struct {
+    uint32_t LowPart;
+    uint32_t HighPart;
+  };
+  struct {
+    uint32_t LowPart;
+    uint32_t HighPart;
+  } u;
+  uint64_t QuadPart;
+} LARGE_INTEGER;
+
+LARGE_INTEGER increment_all_parts(LARGE_INTEGER li) {
+    li.LowPart += 1;
+    li.HighPart += 1;
+    li.u.LowPart += 1;
+    li.u.HighPart += 1;
+    li.QuadPart += 1;
+    return li;
+}
+
+#if __SIZEOF_INT128__ == 16
+
+unsigned __int128 identity(unsigned __int128 a) {
+    return a;
+}
+
+__int128 square(__int128 a) {
+    return a * a;
+}
+
+__int128 sub(__int128 a, __int128 b) {
+    return a - b;
+}
+
+#endif
index 795d45a776db595489dc8d76b6d26b5a6ba83beb..f4c36157fe98a431ea7cd7d760555882e4617954 100644 (file)
@@ -30,8 +30,6 @@
 // #![feature(rustc_attrs)]
 
 use std::ops::{Index, IndexMut};
-use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
-use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
 
 // This is case outlined by Niko that we want to ensure we reject
 // (at least initially).
@@ -105,14 +103,10 @@ fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
         //[lxl]~^^^           ERROR use of moved value: `*f`
         //[nll]~^^^^          ERROR cannot move a value of type
         //[nll]~^^^^^         ERROR cannot move a value of type
-        //[nll]~^^^^^^        ERROR cannot move a value of type
-        //[nll]~^^^^^^^       ERROR cannot move a value of type
-        //[nll]~^^^^^^^^      ERROR use of moved value: `*f`
-        //[g2p]~^^^^^^^^^     ERROR cannot move a value of type
-        //[g2p]~^^^^^^^^^^    ERROR cannot move a value of type
-        //[g2p]~^^^^^^^^^^^   ERROR cannot move a value of type
-        //[g2p]~^^^^^^^^^^^^  ERROR cannot move a value of type
-        //[g2p]~^^^^^^^^^^^^^ ERROR use of moved value: `*f`
+        //[nll]~^^^^^^        ERROR use of moved value: `*f`
+        //[g2p]~^^^^^^^       ERROR cannot move a value of type
+        //[g2p]~^^^^^^^^      ERROR cannot move a value of type
+        //[g2p]~^^^^^^^^^     ERROR use of moved value: `*f`
     }
 
     twice_ten_sm(&mut |x| x + 1);
@@ -186,56 +180,6 @@ fn coerce_index_op() {
     //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
 }
 
-struct A(i32);
-
-macro_rules! trivial_binop {
-    ($Trait:ident, $m:ident) => {
-        impl $Trait<i32> for A { fn $m(&mut self, rhs: i32) { self.0 = rhs; } }
-    }
-}
-
-trivial_binop!(AddAssign, add_assign);
-trivial_binop!(SubAssign, sub_assign);
-trivial_binop!(MulAssign, mul_assign);
-trivial_binop!(DivAssign, div_assign);
-trivial_binop!(RemAssign, rem_assign);
-trivial_binop!(BitAndAssign, bitand_assign);
-trivial_binop!(BitOrAssign, bitor_assign);
-trivial_binop!(BitXorAssign, bitxor_assign);
-trivial_binop!(ShlAssign, shl_assign);
-trivial_binop!(ShrAssign, shr_assign);
-
-fn overloaded_binops() {
-    let mut a = A(10);
-    a += a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a -= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a *= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a /= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a &= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a |= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a ^= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a <<= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-    a >>= a.0;
-    //[lxl]~^   ERROR cannot use `a.0` because it was mutably borrowed
-    //[nll]~^^  ERROR cannot use `a.0` because it was mutably borrowed
-}
-
 fn main() {
 
     // As a reminder, this is the basic case we want to ensure we handle.
@@ -256,5 +200,4 @@ fn main() {
 
     coerce_unsized();
     coerce_index_op();
-    overloaded_binops();
 }
index 5d7f33967402c217b27edb2b860b3c188e7179bb..2f4d82e2ef514a43868df734d9ebf23677f7d675 100644 (file)
@@ -17,7 +17,7 @@
 #![feature(specialization)]
 
 trait Trait<T> { type Assoc; }
-//~^ unsupported cyclic reference between types/traits detected [E0391]
+//~^ cyclic dependency detected [E0391]
 
 impl<T> Trait<T> for Vec<T> {
     type Assoc = ();
diff --git a/src/test/compile-fail/const-recursive.rs b/src/test/compile-fail/const-recursive.rs
deleted file mode 100644 (file)
index 7c05a81..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-const a: isize = b; //~ ERROR recursive constant
-const b: isize = a; //~ ERROR recursive constant
-
-fn main() {
-}
index cbeafdfe6acc97eeb74a2b337920af6c177299bf..6218dcbf5f2c54ec5f86e5cd27db7fd5c105a372 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unsupported cyclic reference between types/traits detected
+// error-pattern: cyclic dependency detected
 
 #![feature(const_fn)]
 
index 7af2f11bd281506d11174fb7a3e40e9469961882..ee4722c010f1660fe8e01555649da6c38e99cfef 100644 (file)
@@ -25,7 +25,7 @@
 struct A<T>
     where T : Trait,
           T : Add<T::Item>
-    //~^ ERROR unsupported cyclic reference between types/traits detected
+    //~^ ERROR cyclic dependency detected
     //~| ERROR associated type `Item` not found for `T`
 {
     data: T
index e6caeb34a8c8f30fddd833c1140200f73f2ea113..88672088bcb4c279eb412c6a77f9ed3c77ff7bb5 100644 (file)
@@ -12,7 +12,7 @@
 // again references the trait.
 
 trait Foo<X = Box<Foo>> {
-    //~^ ERROR unsupported cyclic reference
+    //~^ ERROR cyclic dependency detected
 }
 
 fn main() { }
index ef3fead18f6aa1d34f99450012f30764b77ad116..626567ccc0ead54616644092ad8e295411cd9153 100644 (file)
@@ -11,7 +11,7 @@
 // Test a supertrait cycle where a trait extends itself.
 
 trait Chromosome: Chromosome {
-    //~^ ERROR unsupported cyclic reference
+    //~^ ERROR cyclic dependency detected
 }
 
 fn main() { }
index a7cfda504c75382a20ada7c28d518915990066ed..454b6d2f566eb3cad53e027ba0c43359c5b52766 100644 (file)
 //~^ ERROR cannot find type `dyn` in this scope
 //~| ERROR cannot find type `dyn` in this scope
 //~| ERROR Use of undeclared type or module `dyn`
-type A4 = dyn(dyn, dyn) -> dyn;
-//~^ ERROR cannot find type `dyn` in this scope
-//~| ERROR cannot find type `dyn` in this scope
-//~| ERROR cannot find type `dyn` in this scope
-//~| ERROR cannot find type `dyn` in this scope
 
 fn main() {}
diff --git a/src/test/compile-fail/feature-gate-nested_impl_trait.rs b/src/test/compile-fail/feature-gate-nested_impl_trait.rs
deleted file mode 100644 (file)
index 7c35263..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-#![feature(conservative_impl_trait, universal_impl_trait)]
-
-use std::fmt::Debug;
-
-fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
-
-fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-//~^ ERROR nested `impl Trait` is experimental
-
-fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
-//~^ ERROR nested `impl Trait` is experimental
-
-fn bad_in_arg_position(_: impl Into<impl Debug>) { }
-//~^ ERROR nested `impl Trait` is experimental
-
-struct X;
-impl X {
-    fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-    //~^ ERROR nested `impl Trait` is experimental
-}
-
-fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
-    vec![|| println!("woot")].into_iter()
-}
-
-fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
-    || 5
-}
-
-fn main() {}
index a9fe1e04664e9d4980293bb8f77c3a5e2ff8a7da..52c5471681df300eef53c500bc6cb6a07df7b90e 100644 (file)
@@ -10,7 +10,7 @@
 
 //! A simple test for testing many permutations of allowedness of
 //! impl Trait
-#![feature(conservative_impl_trait, nested_impl_trait, universal_impl_trait, dyn_trait)]
+#![feature(conservative_impl_trait, universal_impl_trait, dyn_trait)]
 use std::fmt::Debug;
 
 // Allowed
@@ -60,6 +60,7 @@ fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
 // Disallowed
 fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
 //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^^ ERROR nested `impl Trait` is not allowed
 
 // Disallowed
 fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
@@ -68,6 +69,7 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
 // Disallowed
 fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
 //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+//~^^ ERROR nested `impl Trait` is not allowed
 
 // Disallowed
 fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
index e5120840f7672a6d19ad8fae9faa4d87f29504df..25d0590db1b75dbd296bf1e91bf61692346a6639 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 type x = Vec<x>;
-//~^ ERROR unsupported cyclic reference
+//~^ ERROR cyclic dependency detected
 
 fn main() { let b: x = Vec::new(); }
index 85d91bb2db202dd6dcb1681cb4ed1e1ef8fe4505..8d3df68577bab14f1d2518d02fd495acf220e63c 100644 (file)
@@ -15,6 +15,3 @@
 #[bench]
 fn bar(x: isize) { }
 //~^ ERROR mismatched types
-//~| expected type `for<'r> fn(&'r mut __test::test::Bencher)`
-//~| found type `fn(isize) {bar}`
-//~| expected mutable reference, found isize
index 0c04e295e1458cb24738f68a7c186e846ba30150..1c3e6890c8e2e17ea112daa8dff4ea0f0be348fc 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-const FOO: usize = FOO; //~ ERROR recursive constant
+const FOO: usize = FOO; //~ ERROR E0391
 
 fn main() {
     let _x: [u8; FOO]; // caused stack overflow prior to fix
     let _y: usize = 1 + {
-        const BAR: usize = BAR; //~ ERROR recursive constant
+        const BAR: usize = BAR;
         let _z: [u8; BAR]; // caused stack overflow prior to fix
         1
     };
diff --git a/src/test/compile-fail/issue-17718-recursive.rs b/src/test/compile-fail/issue-17718-recursive.rs
deleted file mode 100644 (file)
index 9959b0c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-const A: usize = B; //~ ERROR: recursive constant
-const B: usize = A; //~ ERROR: recursive constant
-
-fn main() {}
index 7ae4250d4203bac9f6274cd297433762c90c2d0f..88395e5f1eafa1240f99b1bf099a20829fa82538 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 trait T : Iterator<Item=Self::Item>
-//~^ ERROR unsupported cyclic reference between types/traits detected
+//~^ ERROR cyclic dependency detected
 //~| ERROR associated type `Item` not found for `Self`
 {}
 
index 7d082a3148f76bace6157f882736a7b079ce5466..aeb798b382875a5a740297723b9160282a405498 100644 (file)
@@ -13,7 +13,7 @@ pub trait Subscriber {
 }
 
 pub trait Processor: Subscriber<Input = Self::Input> {
-    //~^ ERROR unsupported cyclic reference between types/traits detected [E0391]
+    //~^ ERROR cyclic dependency detected [E0391]
     type Input;
 }
 
index f49b71953835b28ac50d8b058f39901c2d601fb8..40c95b98f1264d4f9311cf5364a414c8e8b72a89 100644 (file)
@@ -14,7 +14,7 @@ trait Trait {
 }
 
 fn foo<T: Trait<A = T::B>>() { }
-//~^ ERROR unsupported cyclic reference between types/traits detected
+//~^ ERROR cyclic dependency detected
 //~| ERROR associated type `B` not found for `T`
 
 fn main() { }
index 442e6bcda5a092f855dc8577e805f339ee07d925..fde2d001542b84a1eda160b7fb62488440189fdb 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 trait Expr : PartialEq<Self::Item> {
-    //~^ ERROR: unsupported cyclic reference between types/traits detected
+    //~^ ERROR: cyclic dependency detected
     type Item;
 }
 
index 39c6e97268f980e3d9aebdcd8a33ba64256be49e..16a650cc6d88632ed57d1c809377e756036f8773 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unsupported cyclic reference between types/traits detected
+// error-pattern: cyclic dependency detected
 // note-pattern: the cycle begins when computing layout of
 // note-pattern: ...which then requires computing layout of
 // note-pattern: ...which then again requires computing layout of
index 7bbc680197e8499f1fc783bd7e6e78eeb0657f37..b18e05af47c97266521065b5711c08e234b64aee 100644 (file)
@@ -15,7 +15,7 @@ fn foo(_: T) {}
 }
 
 pub struct Foo<T = Box<Trait<DefaultFoo>>>;
-type DefaultFoo = Foo; //~ ERROR unsupported cyclic reference
+type DefaultFoo = Foo; //~ ERROR cyclic dependency detected
 
 fn main() {
 }
index 3b7089f497526aaac1ed0d24587a73c49e39fd9a..930a427e9a5e0ec7c58261bfb7516de5bb442b23 100644 (file)
@@ -15,7 +15,7 @@
 
 struct Foo {
     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-    //~^ ERROR unsupported cyclic reference between types/traits detected
+    //~^ ERROR cyclic dependency detected
     x: usize,
 }
 
diff --git a/src/test/compile-fail/issue-48131.rs b/src/test/compile-fail/issue-48131.rs
new file mode 100644 (file)
index 0000000..9eb567a
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This note is annotated because the purpose of the test
+// is to ensure that certain other notes are not generated.
+#![deny(unused_unsafe)] //~ NOTE
+
+// (test that no note is generated on this unsafe fn)
+pub unsafe fn a() {
+    fn inner() {
+        unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe`
+                                     //~^ NOTE
+    }
+
+    inner()
+}
+
+pub fn b() {
+    // (test that no note is generated on this unsafe block)
+    unsafe {
+        fn inner() {
+            unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe`
+                                         //~^ NOTE
+        }
+
+        let () = ::std::mem::uninitialized();
+
+        inner()
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/macro-at-most-once-rep-ambig.rs b/src/test/compile-fail/macro-at-most-once-rep-ambig.rs
deleted file mode 100644 (file)
index a5660f8..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// The logic for parsing Kleene operators in macros has a special case to disambiguate `?`.
-// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the
-// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to
-// exercise that logic in the macro parser.
-//
-// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but
-// included for consistency with `+` and `*`.
-//
-// This test focuses on error cases.
-
-#![feature(macro_at_most_once_rep)]
-
-macro_rules! foo {
-    ($(a)?) => {}
-}
-
-macro_rules! baz {
-    ($(a),?) => {} // comma separator is meaningless for `?`
-}
-
-macro_rules! barplus {
-    ($(a)?+) => {}
-}
-
-macro_rules! barstar {
-    ($(a)?*) => {}
-}
-
-pub fn main() {
-    foo!(a?a?a); //~ ERROR no rules expected the token `?`
-    foo!(a?a); //~ ERROR no rules expected the token `?`
-    foo!(a?); //~ ERROR no rules expected the token `?`
-    baz!(a?a?a); //~ ERROR no rules expected the token `?`
-    baz!(a?a); //~ ERROR no rules expected the token `?`
-    baz!(a?); //~ ERROR no rules expected the token `?`
-    baz!(a,); //~ ERROR unexpected end of macro invocation
-    baz!(a?a?a,); //~ ERROR no rules expected the token `?`
-    baz!(a?a,); //~ ERROR no rules expected the token `?`
-    baz!(a?,); //~ ERROR no rules expected the token `?`
-    barplus!(); //~ ERROR unexpected end of macro invocation
-    barplus!(a?); //~ ERROR unexpected end of macro invocation
-    barstar!(a?); //~ ERROR unexpected end of macro invocation
-}
index 55ae37404a9fa11d6b1bba7a43ed6cd052109fe8..7210c857125d6d9e026acdc9273fed733dc26d95 100644 (file)
@@ -21,10 +21,10 @@ impl Tr for S where Self: Copy {} // OK
 impl Tr for S where S<Self>: Copy {} // OK
 impl Tr for S where Self::A: Copy {} // OK
 
-impl Tr for Self {} //~ ERROR unsupported cyclic reference between types/traits detected
-impl Tr for S<Self> {} //~ ERROR unsupported cyclic reference between types/traits detected
-impl Self {} //~ ERROR unsupported cyclic reference between types/traits detected
-impl S<Self> {} //~ ERROR unsupported cyclic reference between types/traits detected
-impl Tr<Self::A> for S {} //~ ERROR unsupported cyclic reference between types/traits detected
+impl Tr for Self {} //~ ERROR cyclic dependency detected
+impl Tr for S<Self> {} //~ ERROR cyclic dependency detected
+impl Self {} //~ ERROR cyclic dependency detected
+impl S<Self> {} //~ ERROR cyclic dependency detected
+impl Tr<Self::A> for S {} //~ ERROR cyclic dependency detected
 
 fn main() {}
index a63162cf73d1c4171f3c0f93f29126df96c719e3..93e2561adf753fed810ab5ffddeb9295130ecac0 100644 (file)
@@ -10,6 +10,6 @@
 #![feature(termination_trait)]
 
 fn main() -> char {
-//~^ ERROR: the trait bound `char: std::Termination` is not satisfied
+//~^ ERROR: the trait bound `char: std::process::Termination` is not satisfied
     ' '
 }
index 788c38c55be0a65bd167226d9a7342e84f4fddcd..e87e0ceebf1b1a1263bcca8da59dba65d40919a7 100644 (file)
@@ -12,6 +12,6 @@
 
 struct ReturnType {}
 
-fn main() -> ReturnType { //~ ERROR `ReturnType: std::Termination` is not satisfied
+fn main() -> ReturnType { //~ ERROR `ReturnType: std::process::Termination` is not satisfied
     ReturnType {}
 }
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs
new file mode 100644 (file)
index 0000000..c1dd44a
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(termination_trait)]
+
+// error-pattern:oh, dear
+
+fn main() -> ! {
+    panic!("oh, dear");
+}
index 4849b0307423d5517f260c820cf4e04d2f2cc64f..63b8608afc7638b24ec45d24cae3a230d65ced3a 100644 (file)
@@ -36,6 +36,8 @@ ifeq ($(filter powerpc,$(LLVM_COMPONENTS)),powerpc)
        nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
        $(RUSTC) --target=powerpc64le-unknown-linux-gnu atomic_lock_free.rs
        nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
+endif
+ifeq ($(filter systemz,$(LLVM_COMPONENTS)),systemz)
        $(RUSTC) --target=s390x-unknown-linux-gnu atomic_lock_free.rs
        nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
 endif
diff --git a/src/test/run-pass/borrowck/two-phase-bin-ops.rs b/src/test/run-pass/borrowck/two-phase-bin-ops.rs
new file mode 100644 (file)
index 0000000..1b2529d
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: lxl nll
+
+#![cfg_attr(nll, feature(nll))]
+
+use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
+use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
+
+struct A(i32);
+
+macro_rules! trivial_binop {
+    ($Trait:ident, $m:ident) => {
+        impl $Trait<i32> for A { fn $m(&mut self, rhs: i32) { self.0 = rhs; } }
+    }
+}
+
+trivial_binop!(AddAssign, add_assign);
+trivial_binop!(SubAssign, sub_assign);
+trivial_binop!(MulAssign, mul_assign);
+trivial_binop!(DivAssign, div_assign);
+trivial_binop!(RemAssign, rem_assign);
+trivial_binop!(BitAndAssign, bitand_assign);
+trivial_binop!(BitOrAssign, bitor_assign);
+trivial_binop!(BitXorAssign, bitxor_assign);
+trivial_binop!(ShlAssign, shl_assign);
+trivial_binop!(ShrAssign, shr_assign);
+
+fn main() {
+    let mut a = A(10);
+    a += a.0;
+    a -= a.0;
+    a *= a.0;
+    a /= a.0;
+    a &= a.0;
+    a |= a.0;
+    a ^= a.0;
+    a <<= a.0;
+    a >>= a.0;
+}
index 91930852a57f64c9f489002c47159346ceb7b975..fdec6a26ac945bace66b4fefb6303c506d9a6529 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-pretty `dyn ::foo` parses differently in the current epoch
+
 #![feature(dyn_trait)]
 
 use std::fmt::Display;
@@ -17,6 +19,8 @@
 fn main() {
     let x: &(dyn 'static + Display) = &BYTE;
     let y: Box<dyn Display + 'static> = Box::new(BYTE);
+    let _: &dyn (Display) = &BYTE;
+    let _: &dyn (::std::fmt::Display) = &BYTE;
     let xstr = format!("{}", x);
     let ystr = format!("{}", y);
     assert_eq!(xstr, "33");
index 213a46ded8e765d6ea782b4ed54de1b59de1eec1..2d5dfb045dbac32ca8e2dec32432135b514dc5c9 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, underscore_lifetimes, universal_impl_trait, nested_impl_trait)]
+#![feature(conservative_impl_trait, underscore_lifetimes, universal_impl_trait)]
 #![allow(warnings)]
 
 use std::fmt::Debug;
@@ -63,12 +63,11 @@ fn pass_through_elision_with_fn_ptr(x: &fn(&u32) -> &u32) -> impl Into<&fn(&u32)
 
 fn pass_through_elision_with_fn_path<T: Fn(&u32) -> &u32>(
     x: &T
-) -> impl Into<&impl Fn(&u32) -> &u32> { x }
+) -> &impl Fn(&u32) -> &u32 { x }
 
-fn foo(x: &impl Debug) -> impl Into<&impl Debug> { x }
-fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> impl Into<&'a impl Debug> { x }
-fn foo_no_outer_impl(x: &impl Debug) -> &impl Debug { x }
-fn foo_explicit_arg<T: Debug>(x: &T) -> impl Into<&impl Debug> { x }
+fn foo(x: &impl Debug) -> &impl Debug { x }
+fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> &'a impl Debug { x }
+fn foo_explicit_arg<T: Debug>(x: &T) -> &impl Debug { x }
 
 fn mixed_lifetimes<'a>() -> impl for<'b: 'a> Fn(&'b u32) { |_| () }
 fn mixed_as_static() -> impl Fn(&'static u32) { mixed_lifetimes() }
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs
new file mode 100644 (file)
index 0000000..494500d
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --test
+
+#![feature(termination_trait)]
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+fn is_a_num() -> Result<(), ParseIntError> {
+    let _: u32 = "22".parse()?;
+    Ok(())
+}
+
+#[test]
+#[should_panic]
+fn not_a_num() -> Result<(), ParseIntError> {
+    let _: u32 = "abc".parse()?;
+    Ok(())
+}
+
+#[bench]
+fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+    Ok(())
+}
+
+#[bench]
+#[should_panic]
+fn test_a_neg_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+    let _: u32 = "abc".parse()?;
+    Ok(())
+}
diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs b/src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs
new file mode 100644 (file)
index 0000000..f980ef0
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(match_default_bindings)]
+
+// Test that we "reset" the mode as we pass through a `&` pattern.
+//
+// cc #46688
+
+fn surprise(x: i32) {
+    assert_eq!(x, 2);
+}
+
+fn main() {
+    let x = &(1, &2);
+    let (_, &b) = x;
+    surprise(b);
+}
index c3da4a518720d4e8ccdc8efcfe7e4b254e6d93da..a5214d796cd6253291f9b66867517bc029c6a518 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 pub struct S;
 
 #[derive(Debug)]
 pub struct Z;
+
+pub trait Tr<'a> {}
index 52b52b23c874abf2a67f5a68e1603c54fd8a886c..15b754e1fe6b2ae500fe83289ec2b299421c9c3e 100644 (file)
@@ -14,6 +14,9 @@
 
 use extern::xcrate::Z;
 
+type A = extern::xcrate::S;
+type B = for<'a> extern::xcrate::Tr<'a>;
+
 fn f() {
     use extern::xcrate;
     use extern::xcrate as ycrate;
@@ -28,4 +31,5 @@ fn main() {
     assert_eq!(format!("{:?}", s), "S");
     let z = Z;
     assert_eq!(format!("{:?}", z), "Z");
+    assert_eq!(A {}, extern::xcrate::S {});
 }
diff --git a/src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs b/src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs
new file mode 100644 (file)
index 0000000..796f652
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that `#[test]` works with extern-absolute-paths enabled.
+//
+// Regression test for #47075.
+
+// compile-flags: --test
+
+#![feature(extern_absolute_paths)]
+
+#[test]
+fn test() {
+}
diff --git a/src/test/run-pass/rfc-2175-or-if-while-let/basic.rs b/src/test/run-pass/rfc-2175-or-if-while-let/basic.rs
new file mode 100644 (file)
index 0000000..a516a3e
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(if_while_or_patterns)]
+
+enum E {
+    V(u8),
+    U(u8),
+    W,
+}
+use E::*;
+
+fn main() {
+    let mut e = V(10);
+
+    if let V(x) | U(x) = e {
+        assert_eq!(x, 10);
+    }
+    while let V(x) | U(x) = e {
+        assert_eq!(x, 10);
+        e = W;
+    }
+}
diff --git a/src/test/run-pass/termination-trait-for-result-box-error_ok.rs b/src/test/run-pass/termination-trait-for-result-box-error_ok.rs
deleted file mode 100644 (file)
index 269ac45..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(termination_trait)]
-
-use std::io::Error;
-
-fn main() -> Result<(), Box<Error>> {
-    Ok(())
-}
diff --git a/src/test/rustdoc/auxiliary/issue-48414.rs b/src/test/rustdoc/auxiliary/issue-48414.rs
new file mode 100644 (file)
index 0000000..7e0edf7
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+/// Woah, this trait links to [OtherTrait](OtherTrait)!
+pub trait SomeTrait {}
+
+/// Woah, this trait links to [SomeTrait](SomeTrait)!
+pub trait OtherTrait {}
diff --git a/src/test/rustdoc/issue-48414.rs b/src/test/rustdoc/issue-48414.rs
new file mode 100644 (file)
index 0000000..0136f9c
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// aux-build:issue-48414.rs
+
+// ICE when resolving paths for a trait that linked to another trait, when both were in an external
+// crate
+
+#![crate_name = "base"]
+
+extern crate issue_48414;
+
+#[doc(inline)]
+pub use issue_48414::{SomeTrait, OtherTrait};
index c3b0276bcf9cba078af046eaf9515c84d901f72f..447505e886f81ef07a4684d351d78167fa6f9686 100644 (file)
@@ -18,7 +18,7 @@ trait B: C {
 }
 
 trait C: B { }
-    //~^ ERROR unsupported cyclic reference
+    //~^ ERROR cyclic dependency detected
     //~| cyclic reference
 
 fn main() { }
index 107644037a9caac62dfde589335872fe253551f8..a01565546462d3463b106d8246ad4a97d3123fb3 100644 (file)
@@ -1,4 +1,4 @@
-error[E0391]: unsupported cyclic reference between types/traits detected
+error[E0391]: cyclic dependency detected
   --> $DIR/cycle-trait-supertrait-indirect.rs:20:1
    |
 20 | trait C: B { }
index 4595e413081a525ef6b4b84b7858ac884507456b..31b3acd86ef555b25070599d051d8a46ab388eb0 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 #![allow(warnings)]
-#![feature(conservative_impl_trait, nested_impl_trait)]
+#![feature(conservative_impl_trait)]
 
 trait Id<T> {}
 trait Lt<'a> {}
@@ -17,7 +17,7 @@ impl<'a> Lt<'a> for () {}
 impl<T> Id<T> for T {}
 
 fn free_fn_capture_hrtb_in_impl_trait()
-    -> impl for<'a> Id<impl Lt<'a>>
+    -> Box<for<'a> Id<impl Lt<'a>>>
         //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657]
 {
     ()
@@ -26,7 +26,7 @@ fn free_fn_capture_hrtb_in_impl_trait()
 struct Foo;
 impl Foo {
     fn impl_fn_capture_hrtb_in_impl_trait()
-        -> impl for<'a> Id<impl Lt<'a>>
+        -> Box<for<'a> Id<impl Lt<'a>>>
             //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
     {
         ()
index d3b53d37a30a03eed3c6f090080109e7062d30a6..e039d645fa6dbab51778fb1f2660c22ee0ad9aae 100644 (file)
@@ -1,14 +1,14 @@
 error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
-  --> $DIR/E0657.rs:20:32
+  --> $DIR/E0657.rs:20:31
    |
-20 |     -> impl for<'a> Id<impl Lt<'a>>
-   |                                ^^
+20 |     -> Box<for<'a> Id<impl Lt<'a>>>
+   |                               ^^
 
 error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
-  --> $DIR/E0657.rs:29:36
+  --> $DIR/E0657.rs:29:35
    |
-29 |         -> impl for<'a> Id<impl Lt<'a>>
-   |                                    ^^
+29 |         -> Box<for<'a> Id<impl Lt<'a>>>
+   |                                   ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gate-if_while_or_patterns.rs b/src/test/ui/feature-gate-if_while_or_patterns.rs
new file mode 100644 (file)
index 0000000..3df140c
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    if let 0 | 1 = 0 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
+        ;
+    }
+    while let 0 | 1 = 1 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
+        break;
+    }
+}
diff --git a/src/test/ui/feature-gate-if_while_or_patterns.stderr b/src/test/ui/feature-gate-if_while_or_patterns.stderr
new file mode 100644 (file)
index 0000000..c906fa5
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0658]: multiple patterns in `if let` and `while let` are unstable (see issue #48215)
+  --> $DIR/feature-gate-if_while_or_patterns.rs:12:5
+   |
+12 | /     if let 0 | 1 = 0 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
+13 | |         ;
+14 | |     }
+   | |_____^
+   |
+   = help: add #![feature(if_while_or_patterns)] to the crate attributes to enable
+
+error[E0658]: multiple patterns in `if let` and `while let` are unstable (see issue #48215)
+  --> $DIR/feature-gate-if_while_or_patterns.rs:15:5
+   |
+15 | /     while let 0 | 1 = 1 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
+16 | |         break;
+17 | |     }
+   | |_____^
+   |
+   = help: add #![feature(if_while_or_patterns)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
index 705390e3b969c7625be0d7d863073436e9339fce..5a6aac43ec770d26655b1c7e411f2ebf33cc433f 100644 (file)
@@ -42,7 +42,7 @@ fn after() -> impl Fn(i32) {
 // independently resolved and only require the concrete
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
-    //~^ ERROR unsupported cyclic reference between types/traits detected
+    //~^ ERROR cyclic dependency detected
     //~| cyclic reference
     send(cycle2().clone());
 
index 838a3002e3aa7b9872d4c3efdb28e76d9b8f85b8..d6e31ba1e1f9c67ee0a99b75625209250fda65bd 100644 (file)
@@ -28,7 +28,7 @@ note: required by `send`
 24 | fn send<T: Send>(_: T) {}
    | ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0391]: unsupported cyclic reference between types/traits detected
+error[E0391]: cyclic dependency detected
   --> $DIR/auto-trait-leak.rs:44:1
    |
 44 | fn cycle1() -> impl Clone {
diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs
new file mode 100644 (file)
index 0000000..f69a78b
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(dyn_trait, conservative_impl_trait, universal_impl_trait)]
+
+use std::fmt::Debug;
+use std::option;
+
+fn parametrized_type_is_allowed() -> Option<impl Debug> {
+    Some(5i32)
+}
+
+fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> {
+    Some(5i32)
+}
+
+fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+//~^ ERROR `impl Trait` is not allowed in path parameters
+//~^^ ERROR ambiguous associated type
+    x.next().unwrap()
+}
+
+fn projection_with_named_trait_is_disallowed(x: impl Iterator)
+    -> <impl Iterator as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+    x.next().unwrap()
+}
+
+fn projection_with_named_trait_inside_path_is_disallowed()
+    -> <::std::ops::Range<impl Debug> as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+    (1i32..100).next().unwrap()
+}
+
+fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
+    -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+    panic!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr
new file mode 100644 (file)
index 0000000..08de0eb
--- /dev/null
@@ -0,0 +1,34 @@
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:23:51
+   |
+23 | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+   |                                                   ^^^^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:30:9
+   |
+30 |     -> <impl Iterator as Iterator>::Item
+   |         ^^^^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:37:27
+   |
+37 |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
+   |                           ^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:44:29
+   |
+44 |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
+   |                             ^^^^^^^^^^
+
+error[E0223]: ambiguous associated type
+  --> $DIR/impl_trait_projections.rs:23:50
+   |
+23 | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
+   |
+   = note: specify the type using the syntax `<impl std::iter::Iterator as Trait>::Item`
+
+error: aborting due to 5 previous errors
+
index e1335c7d558e11d2d1284ed81164a99f0b346645..e4d6076868717f0678b6b31924327cae4b2a0e50 100644 (file)
@@ -12,7 +12,7 @@ trait t1 : t2 {
 }
 
 trait t2 : t1 {
-//~^ ERROR unsupported cyclic reference between types/traits detected
+//~^ ERROR cyclic dependency detected
 //~| cyclic reference
 }
 
index cbf005a70b028ee2270c082ca029e0b3e608ba3f..aec828a90d1a7c6958ef561656aaa24d7e225eb2 100644 (file)
@@ -1,4 +1,4 @@
-error[E0391]: unsupported cyclic reference between types/traits detected
+error[E0391]: cyclic dependency detected
   --> $DIR/issue-12511.rs:14:1
    |
 14 | trait t2 : t1 {
diff --git a/src/test/ui/issue-23302-1.rs b/src/test/ui/issue-23302-1.rs
new file mode 100644 (file)
index 0000000..10a5383
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that an enum with recursion in the discriminant throws
+// the appropriate error (rather than, say, blowing the stack).
+enum X {
+    A = X::A as isize, //~ ERROR E0391
+}
+
+fn main() { }
diff --git a/src/test/ui/issue-23302-1.stderr b/src/test/ui/issue-23302-1.stderr
new file mode 100644 (file)
index 0000000..0658c07
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0391]: cyclic dependency detected
+  --> $DIR/issue-23302-1.rs:14:9
+   |
+14 |     A = X::A as isize, //~ ERROR E0391
+   |         ^^^^^^^^^^^^^ cyclic reference
+   |
+note: the cycle begins when const-evaluating `X::A::{{initializer}}`...
+  --> $DIR/issue-23302-1.rs:14:5
+   |
+14 |     A = X::A as isize, //~ ERROR E0391
+   |     ^^^^^^^^^^^^^^^^^
+   = note: ...which then again requires const-evaluating `X::A::{{initializer}}`, completing the cycle.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-23302-2.rs b/src/test/ui/issue-23302-2.rs
new file mode 100644 (file)
index 0000000..d1af19e
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// Since `Y::B` here defaults to `Y::A+1`, this is also a
+// recursive definition.
+enum Y {
+    A = Y::B as isize, //~ ERROR E0391
+    B,
+}
+
+fn main() { }
diff --git a/src/test/ui/issue-23302-2.stderr b/src/test/ui/issue-23302-2.stderr
new file mode 100644 (file)
index 0000000..c4a1c4f
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0391]: cyclic dependency detected
+  --> $DIR/issue-23302-2.rs:14:9
+   |
+14 |     A = Y::B as isize, //~ ERROR E0391
+   |         ^^^^^^^^^^^^^ cyclic reference
+   |
+note: the cycle begins when const-evaluating `Y::A::{{initializer}}`...
+  --> $DIR/issue-23302-2.rs:14:5
+   |
+14 |     A = Y::B as isize, //~ ERROR E0391
+   |     ^^^^^^^^^^^^^^^^^
+   = note: ...which then again requires const-evaluating `Y::A::{{initializer}}`, completing the cycle.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-23302-3.rs b/src/test/ui/issue-23302-3.rs
new file mode 100644 (file)
index 0000000..1d750b0
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+const A: i32 = B; //~ ERROR E0391
+
+const B: i32 = A;
+
+fn main() { }
diff --git a/src/test/ui/issue-23302-3.stderr b/src/test/ui/issue-23302-3.stderr
new file mode 100644 (file)
index 0000000..76f543c
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0391]: cyclic dependency detected
+  --> $DIR/issue-23302-3.rs:11:16
+   |
+11 | const A: i32 = B; //~ ERROR E0391
+   |                ^ cyclic reference
+   |
+note: the cycle begins when processing `B`...
+  --> $DIR/issue-23302-3.rs:13:1
+   |
+13 | const B: i32 = A;
+   | ^^^^^^^^^^^^^^^^^
+note: ...which then requires processing `A`...
+  --> $DIR/issue-23302-3.rs:13:16
+   |
+13 | const B: i32 = A;
+   |                ^
+   = note: ...which then again requires processing `B`, completing the cycle.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-23302.rs b/src/test/ui/issue-23302.rs
deleted file mode 100644 (file)
index 2d93ab0..0000000
+++ /dev/null
@@ -1,28 +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.
-
-// Check that an enum with recursion in the discriminant throws
-// the appropriate error (rather than, say, blowing the stack).
-enum X {
-    A = X::A as isize, //~ ERROR E0265
-}
-
-// Since `Y::B` here defaults to `Y::A+1`, this is also a
-// recursive definition.
-enum Y {
-    A = Y::B as isize, //~ ERROR E0265
-    B,
-}
-
-const A: i32 = B; //~ ERROR E0265
-
-const B: i32 = A; //~ ERROR E0265
-
-fn main() { }
diff --git a/src/test/ui/issue-23302.stderr b/src/test/ui/issue-23302.stderr
deleted file mode 100644 (file)
index 4e93809..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error[E0265]: recursive constant
-  --> $DIR/issue-23302.rs:14:9
-   |
-14 |     A = X::A as isize, //~ ERROR E0265
-   |         ^^^^^^^^^^^^^ recursion not allowed in constant
-
-error[E0265]: recursive constant
-  --> $DIR/issue-23302.rs:20:9
-   |
-20 |     A = Y::B as isize, //~ ERROR E0265
-   |         ^^^^^^^^^^^^^ recursion not allowed in constant
-
-error[E0265]: recursive constant
-  --> $DIR/issue-23302.rs:24:1
-   |
-24 | const A: i32 = B; //~ ERROR E0265
-   | ^^^^^^^^^^^^^^^^^ recursion not allowed in constant
-
-error[E0265]: recursive constant
-  --> $DIR/issue-23302.rs:26:1
-   |
-26 | const B: i32 = A; //~ ERROR E0265
-   | ^^^^^^^^^^^^^^^^^ recursion not allowed in constant
-
-error: aborting due to 4 previous errors
-
index 2337f82afa49fc30d2ef181d8dffe2f49843816c..4c74d9d9173d8c3e5906f7c4f2f082768928e052 100644 (file)
@@ -8,16 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-const A: i32 = Foo::B; //~ ERROR E0265
+const A: isize = Foo::B as isize;
 
 enum Foo {
-    B = A, //~ ERROR E0265
+    B = A, //~ ERROR E0391
 }
 
-enum Bar {
-    C = Bar::C, //~ ERROR E0265
-}
-
-const D: i32 = A;
-
 fn main() {}
index 5a107d88f2e4f2e32293fbde72dee74775fd0159..d0337fc32b03e1a2a64b41d9b8e690bd078fad50 100644 (file)
@@ -1,20 +1,20 @@
-error[E0265]: recursive constant
-  --> $DIR/issue-36163.rs:11:1
-   |
-11 | const A: i32 = Foo::B; //~ ERROR E0265
-   | ^^^^^^^^^^^^^^^^^^^^^^ recursion not allowed in constant
-
-error[E0265]: recursive constant
+error[E0391]: cyclic dependency detected
   --> $DIR/issue-36163.rs:14:9
    |
-14 |     B = A, //~ ERROR E0265
-   |         ^ recursion not allowed in constant
-
-error[E0265]: recursive constant
-  --> $DIR/issue-36163.rs:18:9
+14 |     B = A, //~ ERROR E0391
+   |         ^ cyclic reference
+   |
+note: the cycle begins when const-evaluating `Foo::B::{{initializer}}`...
+  --> $DIR/issue-36163.rs:14:5
+   |
+14 |     B = A, //~ ERROR E0391
+   |     ^^^^^
+note: ...which then requires const-evaluating `A`...
+  --> $DIR/issue-36163.rs:14:9
    |
-18 |     C = Bar::C, //~ ERROR E0265
-   |         ^^^^^^ recursion not allowed in constant
+14 |     B = A, //~ ERROR E0391
+   |         ^
+   = note: ...which then again requires const-evaluating `Foo::B::{{initializer}}`, completing the cycle.
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-45157.rs b/src/test/ui/issue-45157.rs
new file mode 100644 (file)
index 0000000..cff338f
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused)]
+#![feature(nll)]
+
+#[derive(Clone, Copy, Default)]
+struct S {
+    a: u8,
+    b: u8,
+}
+#[derive(Clone, Copy, Default)]
+struct Z {
+    c: u8,
+    d: u8,
+}
+
+union U {
+    s: S,
+    z: Z,
+}
+
+fn main() {
+    unsafe {
+        let mut u = U { s: Default::default() };
+
+        let mref = &mut u.s.a;
+        *mref = 22;
+
+        let nref = &u.z.c;
+        //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
+        println!("{} {}", mref, nref)
+        //~^ ERROR cannot borrow `u.s.a` as mutable because it is also borrowed as immutable [E0502]
+    }
+}
+
diff --git a/src/test/ui/issue-45157.stderr b/src/test/ui/issue-45157.stderr
new file mode 100644 (file)
index 0000000..e133aab
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0502]: cannot borrow `u.z.c` as immutable because it is also borrowed as mutable
+  --> $DIR/issue-45157.rs:37:20
+   |
+34 |         let mref = &mut u.s.a;
+   |                    ---------- mutable borrow occurs here
+...
+37 |         let nref = &u.z.c;
+   |                    ^^^^^^ immutable borrow occurs here
+
+error[E0502]: cannot borrow `u.s.a` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-45157.rs:39:27
+   |
+37 |         let nref = &u.z.c;
+   |                    ------ immutable borrow occurs here
+38 |         //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
+39 |         println!("{} {}", mref, nref)
+   |                           ^^^^ mutable borrow occurs here
+
+error: aborting due to 2 previous errors
+
index 24a0f66f5b1c445514c09fc4605cb2baa445b032..9c521dd6479636a8cf0ae29352d4e6a685040060 100644 (file)
@@ -22,3 +22,18 @@ pub fn map(self) -> Option<Foo> {
     }
     //~^^ ERROR function is expected to take 1 argument, but it takes 2 arguments [E0593]
 }
+
+enum Qux {
+    Bar(i32),
+}
+
+fn foo<F>(f: F)
+where
+    F: Fn(),
+{
+}
+
+fn main() {
+    foo(Qux::Bar);
+}
+//~^^ ERROR function is expected to take 0 arguments, but it takes 1 argument [E0593]
index 0916dc64292e3ae0c2b370dbb68ffdae0518661a..e197c09062d1c904048ffebc9bc530c23eea78f2 100644 (file)
@@ -1,5 +1,3 @@
-error[E0601]: main function not found
-
 error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
   --> $DIR/issue-47706.rs:21:18
    |
@@ -9,5 +7,24 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
 21 |         self.foo.map(Foo::new)
    |                  ^^^ expected function that takes 1 argument
 
+error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
+  --> $DIR/issue-47706.rs:37:5
+   |
+27 |     Bar(i32),
+   |     -------- takes 1 argument
+...
+37 |     foo(Qux::Bar);
+   |     ^^^ expected function that takes 0 arguments
+   |
+note: required by `foo`
+  --> $DIR/issue-47706.rs:30:1
+   |
+30 | / fn foo<F>(f: F)
+31 | | where
+32 | |     F: Fn(),
+33 | | {
+34 | | }
+   | |_^
+
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.rs b/src/test/ui/lint/lint-group-nonstandard-style.rs
new file mode 100644 (file)
index 0000000..55d6168
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(nonstandard_style)]
+#![allow(dead_code)]
+
+fn CamelCase() {} //~ ERROR should have a snake
+
+#[allow(nonstandard_style)]
+mod test {
+    fn CamelCase() {}
+
+    #[forbid(nonstandard_style)]
+    mod bad {
+        fn CamelCase() {} //~ ERROR should have a snake
+
+        static bad: isize = 1; //~ ERROR should have an upper
+    }
+
+    mod warn {
+        #![warn(nonstandard_style)]
+
+        fn CamelCase() {} //~ WARN should have a snake
+
+        struct snake_case; //~ WARN should have a camel
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr
new file mode 100644 (file)
index 0000000..b0ce19e
--- /dev/null
@@ -0,0 +1,67 @@
+error: function `CamelCase` should have a snake case name such as `camel_case`
+  --> $DIR/lint-group-nonstandard-style.rs:14:1
+   |
+14 | fn CamelCase() {} //~ ERROR should have a snake
+   | ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:11:9
+   |
+11 | #![deny(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^
+   = note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)]
+
+error: function `CamelCase` should have a snake case name such as `camel_case`
+  --> $DIR/lint-group-nonstandard-style.rs:22:9
+   |
+22 |         fn CamelCase() {} //~ ERROR should have a snake
+   |         ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:20:14
+   |
+20 |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)]
+
+error: static variable `bad` should have an upper case name such as `BAD`
+  --> $DIR/lint-group-nonstandard-style.rs:24:9
+   |
+24 |         static bad: isize = 1; //~ ERROR should have an upper
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:20:14
+   |
+20 |     #[forbid(nonstandard_style)]
+   |              ^^^^^^^^^^^^^^^^^
+   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)]
+
+warning: function `CamelCase` should have a snake case name such as `camel_case`
+  --> $DIR/lint-group-nonstandard-style.rs:30:9
+   |
+30 |         fn CamelCase() {} //~ WARN should have a snake
+   |         ^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:28:17
+   |
+28 |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_snake_case)] implied by #[warn(nonstandard_style)]
+
+warning: type `snake_case` should have a camel case name such as `SnakeCase`
+  --> $DIR/lint-group-nonstandard-style.rs:32:9
+   |
+32 |         struct snake_case; //~ WARN should have a camel
+   |         ^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/lint-group-nonstandard-style.rs:28:17
+   |
+28 |         #![warn(nonstandard_style)]
+   |                 ^^^^^^^^^^^^^^^^^
+   = note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)]
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/macros/macro-at-most-once-rep-ambig.rs b/src/test/ui/macros/macro-at-most-once-rep-ambig.rs
new file mode 100644 (file)
index 0000000..a5660f8
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// The logic for parsing Kleene operators in macros has a special case to disambiguate `?`.
+// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the
+// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to
+// exercise that logic in the macro parser.
+//
+// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but
+// included for consistency with `+` and `*`.
+//
+// This test focuses on error cases.
+
+#![feature(macro_at_most_once_rep)]
+
+macro_rules! foo {
+    ($(a)?) => {}
+}
+
+macro_rules! baz {
+    ($(a),?) => {} // comma separator is meaningless for `?`
+}
+
+macro_rules! barplus {
+    ($(a)?+) => {}
+}
+
+macro_rules! barstar {
+    ($(a)?*) => {}
+}
+
+pub fn main() {
+    foo!(a?a?a); //~ ERROR no rules expected the token `?`
+    foo!(a?a); //~ ERROR no rules expected the token `?`
+    foo!(a?); //~ ERROR no rules expected the token `?`
+    baz!(a?a?a); //~ ERROR no rules expected the token `?`
+    baz!(a?a); //~ ERROR no rules expected the token `?`
+    baz!(a?); //~ ERROR no rules expected the token `?`
+    baz!(a,); //~ ERROR unexpected end of macro invocation
+    baz!(a?a?a,); //~ ERROR no rules expected the token `?`
+    baz!(a?a,); //~ ERROR no rules expected the token `?`
+    baz!(a?,); //~ ERROR no rules expected the token `?`
+    barplus!(); //~ ERROR unexpected end of macro invocation
+    barplus!(a?); //~ ERROR unexpected end of macro invocation
+    barstar!(a?); //~ ERROR unexpected end of macro invocation
+}
diff --git a/src/test/ui/macros/macro-at-most-once-rep-ambig.stderr b/src/test/ui/macros/macro-at-most-once-rep-ambig.stderr
new file mode 100644 (file)
index 0000000..67a77e0
--- /dev/null
@@ -0,0 +1,80 @@
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:40:11
+   |
+40 |     foo!(a?a?a); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:41:11
+   |
+41 |     foo!(a?a); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:42:11
+   |
+42 |     foo!(a?); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:43:11
+   |
+43 |     baz!(a?a?a); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:44:11
+   |
+44 |     baz!(a?a); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:45:11
+   |
+45 |     baz!(a?); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-ambig.rs:46:11
+   |
+46 |     baz!(a,); //~ ERROR unexpected end of macro invocation
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:47:11
+   |
+47 |     baz!(a?a?a,); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:48:11
+   |
+48 |     baz!(a?a,); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:49:11
+   |
+49 |     baz!(a?,); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-ambig.rs:50:5
+   |
+50 |     barplus!(); //~ ERROR unexpected end of macro invocation
+   |     ^^^^^^^^^^^
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-ambig.rs:51:15
+   |
+51 |     barplus!(a?); //~ ERROR unexpected end of macro invocation
+   |               ^
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-ambig.rs:52:15
+   |
+52 |     barstar!(a?); //~ ERROR unexpected end of macro invocation
+   |               ^
+
+error: aborting due to 13 previous errors
+
diff --git a/src/test/ui/nested_impl_trait.rs b/src/test/ui/nested_impl_trait.rs
new file mode 100644 (file)
index 0000000..f6302c0
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(conservative_impl_trait, universal_impl_trait)]
+
+use std::fmt::Debug;
+
+fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
+
+fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+//~^ ERROR nested `impl Trait` is not allowed
+
+fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+//~^ ERROR nested `impl Trait` is not allowed
+//~^^ `impl Trait` not allowed
+
+fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+//~^ ERROR nested `impl Trait` is not allowed
+
+struct X;
+impl X {
+    fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+    //~^ ERROR nested `impl Trait` is not allowed
+}
+
+fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
+    vec![|| println!("woot")].into_iter()
+}
+
+fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+//~^ `impl Trait` not allowed
+    || 5
+}
+
+fn main() {}
diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/nested_impl_trait.stderr
new file mode 100644 (file)
index 0000000..0949261
--- /dev/null
@@ -0,0 +1,50 @@
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:16:56
+   |
+16 | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                              ----------^^^^^^^^^^-
+   |                                              |         |
+   |                                              |         nested `impl Trait` here
+   |                                              outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:19:42
+   |
+19 | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+   |                                ----------^^^^^^^^^^-
+   |                                |         |
+   |                                |         nested `impl Trait` here
+   |                                outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:23:37
+   |
+23 | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+   |                           ----------^^^^^^^^^^-
+   |                           |         |
+   |                           |         nested `impl Trait` here
+   |                           outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/nested_impl_trait.rs:28:44
+   |
+28 |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                  ----------^^^^^^^^^^-
+   |                                  |         |
+   |                                  |         nested `impl Trait` here
+   |                                  outer `impl Trait`
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/nested_impl_trait.rs:19:32
+   |
+19 | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+   |                                ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
+  --> $DIR/nested_impl_trait.rs:36:42
+   |
+36 | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+   |                                          ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
index b2e98b7c2f6a45be62f0962342b7e467de50c295..30669dc4c2f8c1e9e5b2b772d5974e7d6cf7741c 100644 (file)
@@ -25,53 +25,6 @@ note: External requirements
    = note: number of external vids: 3
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
-note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:46:23
-   |
-46 |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:18 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
-               i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#2r>
-           ]
-   = note: number of external vids: 3
-   = note: where <T as std::iter::Iterator>::Item: '_#2r
-
-note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:54:23
-   |
-54 |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:22 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
-           ]
-   = note: number of external vids: 4
-   = note: where <T as std::iter::Iterator>::Item: '_#3r
-
-note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:65:23
-   |
-65 |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:26 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
-           ]
-   = note: number of external vids: 4
-   = note: where <T as std::iter::Iterator>::Item: '_#3r
-
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
   --> $DIR/projection-no-regions-closure.rs:36:23
    |
@@ -97,6 +50,21 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:46:23
+   |
+46 |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:18 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#2r>
+           ]
+   = note: number of external vids: 3
+   = note: where <T as std::iter::Iterator>::Item: '_#2r
+
 note: No external requirements
   --> $DIR/projection-no-regions-closure.rs:42:1
    |
@@ -113,6 +81,22 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:54:23
+   |
+54 |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:22 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
+           ]
+   = note: number of external vids: 4
+   = note: where <T as std::iter::Iterator>::Item: '_#3r
+
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
   --> $DIR/projection-no-regions-closure.rs:54:23
    |
@@ -139,6 +123,22 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-no-regions-closure.rs:65:23
+   |
+65 |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:26 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
+           ]
+   = note: number of external vids: 4
+   = note: where <T as std::iter::Iterator>::Item: '_#3r
+
 note: No external requirements
   --> $DIR/projection-no-regions-closure.rs:60:1
    |
index bfe408342a868d73b5b5b8a770e5cd4c221c7f68..946c1a8f3723503517e078a9c5a806f65a3663d3 100644 (file)
@@ -32,57 +32,6 @@ note: External requirements
    = note: where T: '_#2r
    = note: where '_#1r: '_#2r
 
-note: External requirements
-  --> $DIR/projection-one-region-closure.rs:68:29
-   |
-68 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:23 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-   = note: number of external vids: 4
-   = note: where T: '_#3r
-   = note: where '_#2r: '_#3r
-
-note: External requirements
-  --> $DIR/projection-one-region-closure.rs:90:29
-   |
-90 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:27 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-   = note: number of external vids: 4
-   = note: where T: '_#3r
-   = note: where '_#2r: '_#3r
-
-note: External requirements
-   --> $DIR/projection-one-region-closure.rs:103:29
-    |
-103 |     with_signature(cell, t, |cell, t| require(cell, t));
-    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: defining type: DefId(0/1:31 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
-                '_#1r,
-                '_#2r,
-                T,
-                i32,
-                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-            ]
-    = note: number of external vids: 4
-    = note: where T: '_#3r
-    = note: where '_#2r: '_#3r
-
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:56:29
    |
@@ -114,6 +63,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-one-region-closure.rs:68:29
+   |
+68 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:23 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+   = note: where '_#2r: '_#3r
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:68:29
    |
@@ -146,6 +112,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-one-region-closure.rs:90:29
+   |
+90 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+   = note: where '_#2r: '_#3r
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:90:29
    |
@@ -178,6 +161,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+   --> $DIR/projection-one-region-closure.rs:103:29
+    |
+103 |     with_signature(cell, t, |cell, t| require(cell, t));
+    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = note: defining type: DefId(0/1:31 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+                '_#1r,
+                '_#2r,
+                T,
+                i32,
+                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+            ]
+    = note: number of external vids: 4
+    = note: where T: '_#3r
+    = note: where '_#2r: '_#3r
+
 note: No external requirements
    --> $DIR/projection-one-region-closure.rs:97:1
     |
index 6cb54170d7a90170ab888599405188536e42f08e..b26fa96fe638902dc74c7533e07b27966026ae2b 100644 (file)
@@ -31,69 +31,6 @@ note: External requirements
    = note: number of external vids: 3
    = note: where '_#1r: '_#2r
 
-note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:29
-   |
-59 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-   = note: number of external vids: 4
-   = note: where '_#2r: '_#3r
-
-note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:29
-   |
-80 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-   = note: number of external vids: 4
-   = note: where '_#2r: '_#3r
-
-note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:91:29
-   |
-91 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-   = note: number of external vids: 4
-   = note: where '_#2r: '_#3r
-
-note: External requirements
-   --> $DIR/projection-one-region-trait-bound-closure.rs:103:29
-    |
-103 |     with_signature(cell, t, |cell, t| require(cell, t));
-    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
-                '_#1r,
-                T,
-                i32,
-                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
-            ]
-    = note: number of external vids: 3
-    = note: where '_#1r: '_#2r
-
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
   --> $DIR/projection-one-region-trait-bound-closure.rs:48:20
    |
@@ -117,6 +54,22 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:59:29
+   |
+59 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where '_#2r: '_#3r
+
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
   --> $DIR/projection-one-region-trait-bound-closure.rs:59:20
    |
@@ -141,6 +94,22 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:80:29
+   |
+80 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where '_#2r: '_#3r
+
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
   --> $DIR/projection-one-region-trait-bound-closure.rs:80:20
    |
@@ -165,6 +134,22 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-one-region-trait-bound-closure.rs:91:29
+   |
+91 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where '_#2r: '_#3r
+
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:86:1
    |
@@ -183,6 +168,21 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+   --> $DIR/projection-one-region-trait-bound-closure.rs:103:29
+    |
+103 |     with_signature(cell, t, |cell, t| require(cell, t));
+    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
+                '_#1r,
+                T,
+                i32,
+                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+            ]
+    = note: number of external vids: 3
+    = note: where '_#1r: '_#2r
+
 note: No external requirements
    --> $DIR/projection-one-region-trait-bound-closure.rs:95:1
     |
index 986676d28d9209108d17d5ce412bb45750339f0e..98b033b6a06725b134c06eed63d3417d3340c4d3 100644 (file)
@@ -12,40 +12,28 @@ note: No external requirements
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:56:29
-   |
-56 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-
-note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:75:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:43:1
    |
-75 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+43 | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+44 | | where
+45 | |     T: Anything<'b>,
+46 | | {
+47 | |     with_signature(cell, t, |cell, t| require(cell, t));
+48 | | }
+   | |_^
    |
-   = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [
                '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               T
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:84:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:56:29
    |
-84 |     with_signature(cell, t, |cell, t| require(cell, t));
+56 |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: DefId(0/1:23 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
                '_#1r,
                '_#2r,
                T,
@@ -53,35 +41,6 @@ note: No external requirements
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
            ]
 
-note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:96:29
-   |
-96 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
-           ]
-
-note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:43:1
-   |
-43 | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
-44 | | where
-45 | |     T: Anything<'b>,
-46 | | {
-47 | |     with_signature(cell, t, |cell, t| require(cell, t));
-48 | | }
-   | |_^
-   |
-   = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [
-               '_#1r,
-               T
-           ]
-
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:51:1
    |
@@ -100,6 +59,20 @@ note: No external requirements
                T
            ]
 
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:75:29
+   |
+75 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:60:1
    |
@@ -118,6 +91,20 @@ note: No external requirements
                T
            ]
 
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:84:29
+   |
+84 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:31 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:79:1
    |
@@ -136,6 +123,19 @@ note: No external requirements
                T
            ]
 
+note: No external requirements
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:96:29
+   |
+96 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:34 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+           ]
+
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:88:1
    |
index 21487899d3ba6c44683526dd059758073ca0e3ab..78775ce94adddfd6dd806f794bc7ed927a91a9c7 100644 (file)
@@ -38,120 +38,6 @@ note: External requirements
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
-note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
-   |
-60 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:27 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
-           ]
-   = note: number of external vids: 5
-   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
-
-note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
-   |
-81 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:32 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
-           ]
-   = note: number of external vids: 5
-   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
-
-note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:92:29
-   |
-92 |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:37 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
-           ]
-   = note: number of external vids: 5
-   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
-
-note: External requirements
-   --> $DIR/projection-two-region-trait-bound-closure.rs:101:29
-    |
-101 |     with_signature(cell, t, |cell, t| require(cell, t));
-    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: defining type: DefId(0/1:42 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [
-                '_#1r,
-                '_#2r,
-                '_#3r,
-                T,
-                i32,
-                extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
-            ]
-    = note: number of external vids: 5
-    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
-
-note: External requirements
-   --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
-    |
-109 |     with_signature(cell, t, |cell, t| require(cell, t));
-    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: defining type: DefId(0/1:46 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [
-                '_#1r,
-                T,
-                i32,
-                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
-            ]
-    = note: number of external vids: 3
-    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
-
-note: External requirements
-   --> $DIR/projection-two-region-trait-bound-closure.rs:120:29
-    |
-120 |     with_signature(cell, t, |cell, t| require(cell, t));
-    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: defining type: DefId(0/1:50 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [
-                '_#1r,
-                '_#2r,
-                T,
-                i32,
-                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-            ]
-    = note: number of external vids: 4
-    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
-
-note: External requirements
-   --> $DIR/projection-two-region-trait-bound-closure.rs:132:29
-    |
-132 |     with_signature(cell, t, |cell, t| require(cell, t));
-    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: defining type: DefId(0/1:53 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
-                '_#1r,
-                T,
-                i32,
-                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
-            ]
-    = note: number of external vids: 3
-    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
-
 error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:49:29
    |
@@ -178,6 +64,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
+   |
+60 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:27 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
    |
@@ -205,6 +108,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
+   |
+81 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:32 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
    |
@@ -232,6 +152,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/projection-two-region-trait-bound-closure.rs:92:29
+   |
+92 |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:37 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               '_#3r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+           ]
+   = note: number of external vids: 5
+   = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
 note: No external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:87:1
    |
@@ -251,6 +188,23 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+   --> $DIR/projection-two-region-trait-bound-closure.rs:101:29
+    |
+101 |     with_signature(cell, t, |cell, t| require(cell, t));
+    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = note: defining type: DefId(0/1:42 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [
+                '_#1r,
+                '_#2r,
+                '_#3r,
+                T,
+                i32,
+                extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+            ]
+    = note: number of external vids: 5
+    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
+
 note: No external requirements
    --> $DIR/projection-two-region-trait-bound-closure.rs:96:1
     |
@@ -270,6 +224,21 @@ note: No external requirements
                 T
             ]
 
+note: External requirements
+   --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
+    |
+109 |     with_signature(cell, t, |cell, t| require(cell, t));
+    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = note: defining type: DefId(0/1:46 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [
+                '_#1r,
+                T,
+                i32,
+                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+            ]
+    = note: number of external vids: 3
+    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
+
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))`
    --> $DIR/projection-two-region-trait-bound-closure.rs:109:20
     |
@@ -293,6 +262,22 @@ note: No external requirements
                 T
             ]
 
+note: External requirements
+   --> $DIR/projection-two-region-trait-bound-closure.rs:120:29
+    |
+120 |     with_signature(cell, t, |cell, t| require(cell, t));
+    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = note: defining type: DefId(0/1:50 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [
+                '_#1r,
+                '_#2r,
+                T,
+                i32,
+                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+            ]
+    = note: number of external vids: 4
+    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
+
 note: No external requirements
    --> $DIR/projection-two-region-trait-bound-closure.rs:115:1
     |
@@ -311,6 +296,21 @@ note: No external requirements
                 T
             ]
 
+note: External requirements
+   --> $DIR/projection-two-region-trait-bound-closure.rs:132:29
+    |
+132 |     with_signature(cell, t, |cell, t| require(cell, t));
+    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+    = note: defining type: DefId(0/1:53 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
+                '_#1r,
+                T,
+                i32,
+                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+            ]
+    = note: number of external vids: 3
+    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
+
 note: No external requirements
    --> $DIR/projection-two-region-trait-bound-closure.rs:124:1
     |
index 023b58c927d865b49fd9767fda9f94f0e55ded10..f68a76c3d0de5790d2411abbbf6980efd52c0ccf 100644 (file)
@@ -30,20 +30,6 @@ note: External requirements
    = note: number of external vids: 2
    = note: where T: '_#1r
 
-note: External requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
-   |
-43 |     twice(cell, value, |a, b| invoke(a, b));
-   |                        ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
-               T,
-               i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) T))
-           ]
-   = note: number of external vids: 2
-   = note: where T: '_#1r
-
 note: No external requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:33:1
    |
@@ -60,6 +46,20 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+   |
+43 |     twice(cell, value, |a, b| invoke(a, b));
+   |                        ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
+               T,
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) T))
+           ]
+   = note: number of external vids: 2
+   = note: where T: '_#1r
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
    |
index 2dd13810ae48a09092380d90591bbd9cdbb0d3c3..ed4d4b1e68f7f81070f9314a0b8155d13300df55 100644 (file)
@@ -31,69 +31,6 @@ note: External requirements
    = note: number of external vids: 2
    = note: where T: '_#1r
 
-note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:55:26
-   |
-55 |       with_signature(a, b, |x, y| {
-   |  __________________________^
-56 | |         // Key point of this test:
-57 | |         //
-58 | |         // The *closure* is being type-checked with all of its free
-...  |
-67 | |         require(&x, &y)
-68 | |     })
-   | |_____^
-   |
-   = note: defining type: DefId(0/1:19 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
-           ]
-   = note: number of external vids: 3
-   = note: where T: '_#2r
-
-note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
-   |
-76 |       with_signature(a, b, |x, y| {
-   |  __________________________^
-77 | |         //~^ ERROR the parameter type `T` may not live long enough
-78 | |         // See `correct_region`
-79 | |         require(&x, &y)
-80 | |         //~^ WARNING not reporting region error due to -Znll
-81 | |     })
-   | |_____^
-   |
-   = note: defining type: DefId(0/1:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
-           ]
-   = note: number of external vids: 3
-   = note: where T: '_#2r
-
-note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:90:26
-   |
-90 |       with_signature(a, b, |x, y| {
-   |  __________________________^
-91 | |         // See `correct_region`
-92 | |         require(&x, &y)
-93 | |     })
-   | |_____^
-   |
-   = note: defining type: DefId(0/1:27 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
-               i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
-           ]
-   = note: number of external vids: 4
-   = note: where T: '_#3r
-
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
    |
@@ -125,6 +62,28 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:55:26
+   |
+55 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+56 | |         // Key point of this test:
+57 | |         //
+58 | |         // The *closure* is being type-checked with all of its free
+...  |
+67 | |         require(&x, &y)
+68 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:19 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
 note: No external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:51:1
    |
@@ -142,6 +101,27 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+   |
+76 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+77 | |         //~^ ERROR the parameter type `T` may not live long enough
+78 | |         // See `correct_region`
+79 | |         require(&x, &y)
+80 | |         //~^ WARNING not reporting region error due to -Znll
+81 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
    |
@@ -173,6 +153,26 @@ note: No external requirements
                T
            ]
 
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:90:26
+   |
+90 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+91 | |         // See `correct_region`
+92 | |         require(&x, &y)
+93 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:27 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+
 note: No external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:85:1
    |
index f249e0e1127ee8af4ca9240668f3627c607ffe55..34f8a0a48431c8f36d3205dcf617ad86e36d6973 100644 (file)
@@ -13,6 +13,6 @@ pub trait ToNbt<T> {
 }
 
 impl ToNbt<Self> {}
-//~^ ERROR unsupported cyclic reference
+//~^ ERROR cyclic dependency detected
 
 fn main() {}
index 5bba9fc41e276f359a9ba2e7316c85739d10c1ce..a0b4d424ec968b409d332c6273472d2248bf24ee 100644 (file)
@@ -1,4 +1,4 @@
-error[E0391]: unsupported cyclic reference between types/traits detected
+error[E0391]: cyclic dependency detected
   --> $DIR/issue-23305.rs:15:12
    |
 15 | impl ToNbt<Self> {}
index 4c9d10ba46bc858db86fb79f815eeb0b421c7f32..7b3288fd29cc190d956279022591c27d755a8800 100644 (file)
@@ -17,6 +17,9 @@ pub fn main() {
     // that won't output for the above string concatenation
     let y = World::Hello + World::Goodbye;
     //~^ ERROR cannot be applied to type
+
+    let x = "Hello " + "World!".to_owned();
+    //~^ ERROR cannot be applied to type
 }
 
 enum World {
index db662a1df5972ad6b3d8eb01847b6ecd05b29c48..70f8ecf42cb2d91f5afbab1ffc69179a2dba0d72 100644 (file)
@@ -16,5 +16,19 @@ error[E0369]: binary operation `+` cannot be applied to type `World`
    |
    = note: an implementation of `std::ops::Add` might be missing for `World`
 
-error: aborting due to 2 previous errors
+error[E0369]: binary operation `+` cannot be applied to type `&str`
+  --> $DIR/issue-39018.rs:21:13
+   |
+21 |     let x = "Hello " + "World!".to_owned();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `+` can't be used to concatenate a `&str` with a `String`
+help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
+   |
+21 |     let x = "Hello ".to_owned() + "World!".to_owned();
+   |             ^^^^^^^^^^^^^^^^^^^
+help: you also need to borrow the `String` on the right to get a `&str`
+   |
+21 |     let x = "Hello " + &"World!".to_owned();
+   |                        ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/unsafe-block-without-braces.rs b/src/test/ui/unsafe-block-without-braces.rs
new file mode 100644 (file)
index 0000000..b6fb3ec
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    unsafe //{
+        std::mem::transmute::<f32, u32>(1.0);
+    //}
+}
+//~^^^ ERROR expected one of `extern`, `fn`, or `{`, found `std`
diff --git a/src/test/ui/unsafe-block-without-braces.stderr b/src/test/ui/unsafe-block-without-braces.stderr
new file mode 100644 (file)
index 0000000..fc6ddba
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected one of `extern`, `fn`, or `{`, found `std`
+  --> $DIR/unsafe-block-without-braces.rs:13:9
+   |
+12 |     unsafe //{
+   |           - expected one of `extern`, `fn`, or `{` here
+13 |         std::mem::transmute::<f32, u32>(1.0);
+   |         ^^^ unexpected token
+
+error: aborting due to previous error
+
index 4113f8fd124c7090344189eb1d02176b827d772b..0845179532224f68f7ee66160a6768620c59ea4c 100644 (file)
@@ -86,6 +86,7 @@
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
     "s390x-unknown-linux-gnu",
+    "sparc-unknown-linux-gnu",
     "sparc64-unknown-linux-gnu",
     "sparcv9-sun-solaris",
     "wasm32-unknown-emscripten",