]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #49210 - oli-obk:pango_crash, r=eddyb
authorbors <bors@rust-lang.org>
Thu, 22 Mar 2018 20:02:14 +0000 (20:02 +0000)
committerbors <bors@rust-lang.org>
Thu, 22 Mar 2018 20:02:14 +0000 (20:02 +0000)
Fix the conversion between bit representations and i128 representations

fixes #49181

the `Discr` type now encodes the bit representation instead of `i128` or `u128` casted to `u128`.

r? @eddyb

88 files changed:
.travis.yml
RELEASES.md
config.toml.example
src/bootstrap/bin/rustc.rs
src/bootstrap/builder.rs
src/bootstrap/config.rs
src/ci/init_repo.sh
src/ci/run.sh
src/liballoc/tests/slice.rs
src/libcore/convert.rs
src/libcore/iter/mod.rs
src/libcore/num/mod.rs
src/libcore/str/mod.rs
src/libcore/sync/atomic.rs
src/libcore/tests/ascii.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/prev.rs
src/librustc/dep_graph/serialized.rs
src/librustc/diagnostics.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_hir.rs
src/librustc/infer/anon_types/mod.rs
src/librustc/infer/canonical.rs
src/librustc/lib.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/util/captures.rs [new file with mode: 0644]
src/librustc_data_structures/indexed_vec.rs
src/librustc_incremental/persist/save.rs
src/librustc_metadata/decoder.rs
src/librustc_mir/build/block.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_traits/lowering.rs
src/librustc_trans/attributes.rs
src/librustc_trans/builder.rs
src/librustc_trans/llvm_util.rs
src/librustc_trans_utils/symbol_names_test.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/markdown.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/libstd/ascii.rs
src/libstd/error.rs
src/libstd/num.rs
src/libstd/sys/windows/process.rs
src/libstd/sys_common/wtf8.rs
src/libsyntax/parse/mod.rs
src/libsyntax/test.rs
src/stdsimd
src/test/codegen/abi-main-signature-16bit-c-int.rs
src/test/codegen/fastcall-inreg.rs
src/test/codegen/global_asm.rs
src/test/codegen/global_asm_include.rs
src/test/codegen/global_asm_x2.rs
src/test/codegen/repr-transparent-aggregates-1.rs
src/test/mir-opt/end_region_8.rs
src/test/run-make/tools.mk
src/test/run-pass/issue-10683.rs
src/test/run-pass/issue-27889.rs
src/test/run-pass/issue-28561.rs
src/test/rustdoc/check-styled-link.rs [new file with mode: 0644]
src/test/rustdoc/doc-cfg.rs
src/test/ui/chalkify/lower_trait.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_trait.stderr [new file with mode: 0644]
src/test/ui/generator/auto-trait-regions.stderr
src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound.stderr [new file with mode: 0644]
src/test/ui/type-dependent-def-issue-49241.rs [new file with mode: 0644]
src/test/ui/type-dependent-def-issue-49241.stderr [new file with mode: 0644]
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs

index b2aba305aedc4347a66dc626d5270bcc34071e33..41ea0c9afa87cc97c93973e6f3ad5109031393fc 100644 (file)
@@ -318,8 +318,6 @@ before_deploy:
 
 deploy:
   - provider: s3
-    edge:
-      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
@@ -336,8 +334,6 @@ deploy:
   # this is the same as the above deployment provider except that it uploads to
   # a slightly different directory and has a different trigger
   - provider: s3
-    edge:
-      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
@@ -355,8 +351,6 @@ deploy:
   # try branch. Travis does not appear to provide a way to use "or" in these
   # conditions.
   - provider: s3
-    edge:
-      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
@@ -371,8 +365,6 @@ deploy:
       condition: $DEPLOY = 1
 
   - provider: s3
-    edge:
-      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
index 64e2145e0f37b444953dfef48c7f1f28f6f69cfd..51c36c99858b8851892bcc103109944f94545d43 100644 (file)
@@ -1,3 +1,103 @@
+Version 1.25.0 (2018-03-29)
+==========================
+
+Language
+--------
+- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358]
+- [You can now use nested groups of imports.][47948]
+  e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};`
+- [You can now have `|` at the start of a match arm.][47947] e.g.
+```rust
+enum Foo { A, B, C }
+
+fn main() {
+    let x = Foo::A;
+    match x {
+        | Foo::A
+        | Foo::B => println!("AB"),
+        | Foo::C => println!("C"),
+    }
+}
+```
+
+Compiler
+--------
+- [Upgraded to LLVM 6.][47828]
+- [Added `-C lto=val` option.][47521]
+- [Added `i586-unknown-linux-musl` target][47282]
+
+Libraries
+---------
+- [Impl Send for `process::Command` on Unix.][47760]
+- [Impl PartialEq and Eq for `ParseCharError`.][47790]
+- [`UnsafeCell::into_inner` is now safe.][47204]
+- [Implement libstd for CloudABI.][47268]
+- [`Float::{from_bits, to_bits}` is now available in libcore.][46931]
+- [Implement `AsRef<Path>` for Component][46985]
+- [Implemented `Write` for `Cursor<&mut Vec<T>>`][46830]
+- [Moved `Duration` to libcore.][46666]
+
+Stabilized APIs
+---------------
+- [`Location::column`]
+- [`ptr::NonNull`]
+
+The following functions can now be used in a constant expression.
+eg. `static MINUTE: Duration = Duration::from_secs(60);`
+- [`Duration::new`][47300]
+- [`Duration::from_secs`][47300]
+- [`Duration::from_millis`][47300]
+- [`Duration::from_micros`][47300]
+- [`Duration::from_nanos`][47300]
+
+Cargo
+-----
+- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013]
+- [`cargo new` now defaults to creating a binary crate, instead of a
+  library crate.][cargo/5029]
+
+Misc
+----
+- [Rust by example is now shipped with new releases][46196]
+
+Compatibility Notes
+-------------------
+- [Deprecated `net::lookup_host`.][47510]
+- [`rustdoc` has switched to pulldown as the default markdown renderer.][47398]
+- The borrow checker was sometimes incorrectly permitting overlapping borrows
+  around indexing operations (see [#47349][47349]). This has been fixed (which also
+  enabled some correct code that used to cause errors (e.g. [#33903][33903] and [#46095][46095]).
+- [Removed deprecated unstable attribute `#[simd]`.][47251]
+
+[33903]: https://github.com/rust-lang/rust/pull/33903
+[47947]: https://github.com/rust-lang/rust/pull/47947
+[47948]: https://github.com/rust-lang/rust/pull/47948
+[47760]: https://github.com/rust-lang/rust/pull/47760
+[47790]: https://github.com/rust-lang/rust/pull/47790
+[47828]: https://github.com/rust-lang/rust/pull/47828
+[47398]: https://github.com/rust-lang/rust/pull/47398
+[47510]: https://github.com/rust-lang/rust/pull/47510
+[47521]: https://github.com/rust-lang/rust/pull/47521
+[47204]: https://github.com/rust-lang/rust/pull/47204
+[47251]: https://github.com/rust-lang/rust/pull/47251
+[47268]: https://github.com/rust-lang/rust/pull/47268
+[47282]: https://github.com/rust-lang/rust/pull/47282
+[47300]: https://github.com/rust-lang/rust/pull/47300
+[47349]: https://github.com/rust-lang/rust/pull/47349
+[46931]: https://github.com/rust-lang/rust/pull/46931
+[46985]: https://github.com/rust-lang/rust/pull/46985
+[47006]: https://github.com/rust-lang/rust/pull/47006
+[46830]: https://github.com/rust-lang/rust/pull/46830
+[46095]: https://github.com/rust-lang/rust/pull/46095
+[46666]: https://github.com/rust-lang/rust/pull/46666
+[46196]: https://github.com/rust-lang/rust/pull/46196
+[cargo/5013]: https://github.com/rust-lang/cargo/pull/5013
+[cargo/5029]: https://github.com/rust-lang/cargo/pull/5029
+[RFC 1358]: https://github.com/rust-lang/rfcs/pull/1358
+[`Location::column`]: https://doc.rust-lang.org/std/panic/struct.Location.html#method.column
+[`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html
+
+
 Version 1.24.0 (2018-02-15)
 ==========================
 
index de7036db29f4afa5883a39e467731f8da575b764..c9a7b57438ae944f8a5dc29b26e7fe30d3f32071 100644 (file)
 # essentially skipping stage0 as the local compiler is recompiling itself again.
 #local-rebuild = false
 
+# Print out how long each rustbuild step took (mostly intended for CI and
+# tracking over time)
+#print-step-timings = false
+
 # =============================================================================
 # General install configuration options
 # =============================================================================
index 4be16475590f4fdf946019953785b881a141e607..6701f58ba8e92593589679caf6772aeb6c1d9395 100644 (file)
 
 use std::env;
 use std::ffi::OsString;
-use std::str::FromStr;
+use std::io;
 use std::path::PathBuf;
-use std::process::{Command, ExitStatus};
+use std::process::Command;
+use std::str::FromStr;
+use std::time::Instant;
 
 fn main() {
     let mut args = env::args_os().skip(1).collect::<Vec<_>>();
@@ -90,7 +92,7 @@ fn main() {
     };
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
     let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
-    let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
+    let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
 
     let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
     let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -103,6 +105,7 @@ fn main() {
         .arg(format!("stage{}", stage))
         .env(bootstrap::util::dylib_path_var(),
              env::join_paths(&dylib_path).unwrap());
+    let mut maybe_crate = None;
 
     if let Some(target) = target {
         // The stage0 compiler has a special sysroot distinct from what we
@@ -134,6 +137,7 @@ fn main() {
             .find(|a| &*a[0] == "--crate-name")
             .unwrap();
         let crate_name = &*crate_name[1];
+        maybe_crate = Some(crate_name);
 
         // If we're compiling specifically the `panic_abort` crate then we pass
         // the `-C panic=abort` option. Note that we do not do this for any
@@ -281,31 +285,52 @@ fn main() {
         eprintln!("libdir: {:?}", libdir);
     }
 
-    // Actually run the compiler!
-    std::process::exit(if let Some(ref mut on_fail) = on_fail {
-        match cmd.status() {
-            Ok(s) if s.success() => 0,
-            _ => {
-                println!("\nDid not run successfully:\n{:?}\n-------------", cmd);
-                exec_cmd(on_fail).expect("could not run the backup command");
-                1
+    if let Some(mut on_fail) = on_fail {
+        let e = match cmd.status() {
+            Ok(s) if s.success() => std::process::exit(0),
+            e => e,
+        };
+        println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd);
+        exec_cmd(&mut on_fail).expect("could not run the backup command");
+        std::process::exit(1);
+    }
+
+    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
+        if let Some(krate) = maybe_crate {
+            let start = Instant::now();
+            let status = cmd
+                .status()
+                .expect(&format!("\n\n failed to run {:?}", cmd));
+            let dur = start.elapsed();
+
+            let is_test = args.iter().any(|a| a == "--test");
+            eprintln!("[RUSTC-TIMING] {} test:{} {}.{:03}",
+                      krate.to_string_lossy(),
+                      is_test,
+                      dur.as_secs(),
+                      dur.subsec_nanos() / 1_000_000);
+
+            match status.code() {
+                Some(i) => std::process::exit(i),
+                None => {
+                    eprintln!("rustc exited with {}", status);
+                    std::process::exit(0xfe);
+                }
             }
         }
-    } else {
-        std::process::exit(match exec_cmd(&mut cmd) {
-            Ok(s) => s.code().unwrap_or(0xfe),
-            Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
-        })
-    })
+    }
+
+    let code = exec_cmd(&mut cmd).expect(&format!("\n\n failed to run {:?}", cmd));
+    std::process::exit(code);
 }
 
 #[cfg(unix)]
-fn exec_cmd(cmd: &mut Command) -> ::std::io::Result<ExitStatus> {
+fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
     use std::os::unix::process::CommandExt;
     Err(cmd.exec())
 }
 
 #[cfg(not(unix))]
-fn exec_cmd(cmd: &mut Command) -> ::std::io::Result<ExitStatus> {
-    cmd.status()
+fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
+    cmd.status().map(|status| status.code().unwrap())
 }
index 675d3dd437eef9deb3cc60d7956b038628c81e05..a398bcc973746fffb4595ba726a2c1d7630f9365 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::any::Any;
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
 use std::env;
 use std::fmt::Debug;
@@ -18,6 +18,7 @@
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::process::Command;
+use std::time::{Instant, Duration};
 
 use compile;
 use install;
@@ -40,6 +41,7 @@ pub struct Builder<'a> {
     pub kind: Kind,
     cache: Cache,
     stack: RefCell<Vec<Box<Any>>>,
+    time_spent_on_dependencies: Cell<Duration>,
 }
 
 impl<'a> Deref for Builder<'a> {
@@ -308,12 +310,14 @@ macro_rules! describe {
                 test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps,
                 test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty,
                 test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty,
-                test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake,
+                test::RunPassFullDepsPretty, test::RunFailFullDepsPretty,
                 test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck,
                 test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
                 test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
                 test::TheBook, test::UnstableBook,
-                test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
+                test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
+                // Run run-make last, since these won't pass without make on Windows
+                test::RunMake),
             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
@@ -343,6 +347,7 @@ pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
             kind,
             cache: Cache::new(),
             stack: RefCell::new(Vec::new()),
+            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
         };
 
         let builder = &builder;
@@ -383,6 +388,7 @@ pub fn run(build: &Build) {
             kind,
             cache: Cache::new(),
             stack: RefCell::new(Vec::new()),
+            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
         };
 
         if kind == Kind::Dist {
@@ -662,6 +668,10 @@ pub fn cargo(&self,
             cargo.env("RUSTC_ON_FAIL", on_fail);
         }
 
+        if self.config.print_step_timings {
+            cargo.env("RUSTC_PRINT_STEP_TIMINGS", "1");
+        }
+
         cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
 
         // Throughout the build Cargo can execute a number of build scripts
@@ -818,7 +828,24 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
             self.build.verbose(&format!("{}> {:?}", "  ".repeat(stack.len()), step));
             stack.push(Box::new(step.clone()));
         }
-        let out = step.clone().run(self);
+
+        let (out, dur) = {
+            let start = Instant::now();
+            let zero = Duration::new(0, 0);
+            let parent = self.time_spent_on_dependencies.replace(zero);
+            let out = step.clone().run(self);
+            let dur = start.elapsed();
+            let deps = self.time_spent_on_dependencies.replace(parent + dur);
+            (out, dur - deps)
+        };
+
+        if self.build.config.print_step_timings && dur > Duration::from_millis(100) {
+            println!("[TIMING] {:?} -- {}.{:03}",
+                     step,
+                     dur.as_secs(),
+                     dur.subsec_nanos() / 1_000_000);
+        }
+
         {
             let mut stack = self.stack.borrow_mut();
             let cur_step = stack.pop().expect("step stack empty");
index 920a8ffc2fc860e1981fe053d451cb07f3c9f2dc..3ef4b0f8ae7ac0bf0d9c32f4c48f4340860f0806 100644 (file)
@@ -121,6 +121,7 @@ pub struct Config {
     pub quiet_tests: bool,
     pub test_miri: bool,
     pub save_toolstates: Option<PathBuf>,
+    pub print_step_timings: bool,
 
     // Fallback musl-root for all targets
     pub musl_root: Option<PathBuf>,
@@ -204,6 +205,7 @@ struct Build {
     openssl_static: Option<bool>,
     configure_args: Option<Vec<String>>,
     local_rebuild: Option<bool>,
+    print_step_timings: Option<bool>,
 }
 
 /// TOML representation of various global install decisions.
@@ -413,6 +415,7 @@ pub fn parse(args: &[String]) -> Config {
         set(&mut config.openssl_static, build.openssl_static);
         set(&mut config.configure_args, build.configure_args);
         set(&mut config.local_rebuild, build.local_rebuild);
+        set(&mut config.print_step_timings, build.print_step_timings);
         config.verbose = cmp::max(config.verbose, flags.verbose);
 
         if let Some(ref install) = toml.install {
index 8ab4276fa3b059b38f1a3aba9479c89eba4e4603..f2664e6d196c7afcab810ab0ee15f5e30b14eb64 100755 (executable)
@@ -17,6 +17,7 @@ ci_dir=$(cd $(dirname $0) && pwd)
 . "$ci_dir/shared.sh"
 
 travis_fold start init_repo
+travis_time_start
 
 REPO_DIR="$1"
 CACHE_DIR="$2"
@@ -42,54 +43,39 @@ if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then
   git fetch origin --unshallow beta master
 fi
 
-travis_fold start update_cache
-travis_time_start
-
-# Update the cache (a pristine copy of the rust source master)
-retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
-    git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir"
-if [ -d $cache_src_dir/src/llvm ]; then
-  (cd $cache_src_dir && git rm src/llvm)
-fi
-if [ -d $cache_src_dir/src/llvm-emscripten ]; then
-  (cd $cache_src_dir && git rm src/llvm-emscripten)
-fi
-retry sh -c "cd $cache_src_dir && \
-    git submodule deinit -f . && git submodule sync && git submodule update --init"
-
-travis_fold end update_cache
-travis_time_finish
+function fetch_submodule {
+    local module=$1
+    local cached="download-${module//\//-}.tar.gz"
+    retry sh -c "rm -f $cached && \
+        curl -sSL -o $cached $2"
+    mkdir $module
+    touch "$module/.git"
+    tar -C $module --strip-components=1 -xf $cached
+    rm $cached
+}
 
-travis_fold start update_submodules
-travis_time_start
-
-# Update the submodules of the repo we're in, using the pristine repo as
-# a cache for any object files
-# No, `git submodule foreach` won't work:
-# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
+included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example"
 modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
-for module in $modules; do
-    if [ "$module" = src/llvm ] || [ "$module" = src/llvm-emscripten ]; then
+modules=($modules)
+use_git=""
+urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)"
+urls=($urls)
+for i in ${!modules[@]}; do
+    module=${modules[$i]}
+    if [[ " $included " = *" $module "* ]]; then
         commit="$(git ls-tree HEAD $module | awk '{print $3}')"
         git rm $module
-        retry sh -c "rm -f $commit.tar.gz && \
-            curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
-        tar -C src/ -xf "$commit.tar.gz"
-        rm "$commit.tar.gz"
-        mv "src/llvm-$commit" $module
-        continue
-    fi
-    if [ ! -e "$cache_src_dir/$module/.git" ]; then
-        echo "WARNING: $module not found in pristine repo"
-        retry sh -c "git submodule deinit -f $module && \
-            git submodule update --init --recursive $module"
+        url=${urls[$i]}
+        url=${url/\.git/}
+        fetch_submodule $module "$url/archive/$commit.tar.gz" &
         continue
+    else
+        use_git="$use_git $module"
     fi
-    retry sh -c "git submodule deinit -f $module && \
-        git submodule update --init --recursive --reference $cache_src_dir/$module $module"
 done
-
-travis_fold end update_submodules
-travis_time_finish
-
+retry sh -c "git submodule deinit -f $use_git && \
+    git submodule sync && \
+    git submodule update -j 16 --init --recursive $use_git"
+wait
 travis_fold end init_repo
+travis_time_finish
index afa6d1fa0aea5e9d38aaecf67617dc3194528607..9a26043c92c13a34508af873771f2da3dc5ec578 100755 (executable)
@@ -25,6 +25,8 @@ source "$ci_dir/shared.sh"
 
 if [ "$TRAVIS" == "true" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-quiet-tests"
+else
+    RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings"
 fi
 
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"
@@ -105,15 +107,7 @@ fi
 travis_fold end log-system-info
 
 if [ ! -z "$SCRIPT" ]; then
-  # FIXME(#49246): Re-enable these tools after #49246 has been merged and thus fixing the cache.
-  if [ "$DEPLOY_ALT" = 1 ]; then
-    sh -x -c "$SCRIPT \
-       --exclude src/tools/rls \
-       --exclude src/tools/rustfmt \
-       --exclude src/tools/clippy"
-  else
-    sh -x -c "$SCRIPT"
-  fi
+  sh -x -c "$SCRIPT"
 else
   do_make() {
     travis_fold start "make-$1"
index d9e9d91cea88a06d5a39d74363610a3991945477..3f679d81f08de9bd59a5019ddfd12033ebd59310 100644 (file)
@@ -1351,7 +1351,7 @@ fn test_copy_from_slice_dst_shorter() {
 const MAX_LEN: usize = 80;
 
 static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
-    // FIXME #5244: AtomicUsize is not Copy.
+    // FIXME(RFC 1109): AtomicUsize is not Copy.
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
index d3a83dc795c8577040b83b1c0e0440b826bf2880..7324df95bc5d5691306ba78924148e593abb4ed4 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fmt;
-
-/// A type used as the error type for implementations of fallible conversion
-/// traits in cases where conversions cannot actually fail.
-///
-/// Because `Infallible` has no variants, a value of this type can never exist.
-/// It is used only to satisfy trait signatures that expect an error type, and
-/// signals to both the compiler and the user that the error case is impossible.
-#[unstable(feature = "try_from", issue = "33417")]
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub enum Infallible {}
-
-#[unstable(feature = "try_from", issue = "33417")]
-impl fmt::Display for Infallible {
-    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-        }
-    }
-}
 /// A cheap reference-to-reference conversion. Used to convert a value to a
 /// reference value within generic code.
 ///
@@ -382,7 +363,7 @@ fn as_ref(&self) -> &U {
     }
 }
 
-// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
+// FIXME (#45742): replace the above impls for &/&mut with the following more general one:
 // // As lifts over Deref
 // impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
 //     fn as_ref(&self) -> &U {
@@ -399,7 +380,7 @@ fn as_mut(&mut self) -> &mut U {
     }
 }
 
-// FIXME (#23442): replace the above impl for &mut with the following more general one:
+// FIXME (#45742): replace the above impl for &mut with the following more general one:
 // // AsMut lifts over DerefMut
 // impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
 //     fn as_mut(&mut self) -> &mut U {
@@ -438,7 +419,7 @@ fn try_into(self) -> Result<U, U::Error> {
 // with an uninhabited error type.
 #[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryFrom<U> for T where T: From<U> {
-    type Error = Infallible;
+    type Error = !;
 
     fn try_from(value: U) -> Result<Self, Self::Error> {
         Ok(T::from(value))
index b1b783b47c72b1b19dc0a70834c020e6aaf2cd69..1e8476d3880c8a4fc197c0c95e647ebca69ccf62 100644 (file)
@@ -1872,7 +1872,7 @@ fn count(mut self) -> usize {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        // FIXME(#6393): merge these when borrow-checking gets better.
+        // FIXME(#43234): merge these when borrow-checking gets better.
         if n == 0 {
             match self.peeked.take() {
                 Some(v) => v,
index 09ab7060d37db8420162350925900891dbb2e5b5..4583e45bb12ebeebe3008fc1eeaaa8cd2941f737 100644 (file)
@@ -12,7 +12,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use convert::{Infallible, TryFrom};
+use convert::TryFrom;
 use fmt;
 use intrinsics;
 use ops;
@@ -3596,10 +3596,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[unstable(feature = "try_from", issue = "33417")]
-impl From<Infallible> for TryFromIntError {
-    fn from(infallible: Infallible) -> TryFromIntError {
-        match infallible {
-        }
+impl From<!> for TryFromIntError {
+    fn from(never: !) -> TryFromIntError {
+        never
     }
 }
 
@@ -3608,7 +3607,7 @@ macro_rules! try_from_unbounded {
     ($source:ty, $($target:ty),*) => {$(
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
-            type Error = Infallible;
+            type Error = !;
 
             #[inline]
             fn try_from(value: $source) -> Result<Self, Self::Error> {
@@ -3719,7 +3718,7 @@ macro_rules! rev {
 #[cfg(target_pointer_width = "16")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::{Infallible, TryFrom};
+    use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8);
     try_from_unbounded!(usize, u16, u32, u64, u128);
@@ -3745,7 +3744,7 @@ mod ptr_try_from_impls {
 #[cfg(target_pointer_width = "32")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::{Infallible, TryFrom};
+    use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8, u16);
     try_from_unbounded!(usize, u32, u64, u128);
@@ -3771,7 +3770,7 @@ mod ptr_try_from_impls {
 #[cfg(target_pointer_width = "64")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::{Infallible, TryFrom};
+    use convert::TryFrom;
 
     try_from_upper_bounded!(usize, u8, u16, u32);
     try_from_unbounded!(usize, u64, u128);
index 9cf862bd93625f9e2604eef7abcc3eb685a40758..1185b7acaae1f3101d34307983185843208ae8f0 100644 (file)
@@ -165,6 +165,37 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 ///
 /// [`String`]: ../../std/string/struct.String.html#method.from_utf8
 /// [`&str`]: ../../std/str/fn.from_utf8.html
+///
+/// # Examples
+///
+/// This error type’s methods can be used to create functionality
+/// similar to `String::from_utf8_lossy` without allocating heap memory:
+///
+/// ```
+/// fn from_utf8_lossy<F>(mut input: &[u8], mut push: F) where F: FnMut(&str) {
+///     loop {
+///         match ::std::str::from_utf8(input) {
+///             Ok(valid) => {
+///                 push(valid);
+///                 break
+///             }
+///             Err(error) => {
+///                 let (valid, after_valid) = input.split_at(error.valid_up_to());
+///                 unsafe {
+///                     push(::std::str::from_utf8_unchecked(valid))
+///                 }
+///                 push("\u{FFFD}");
+///
+///                 if let Some(invalid_sequence_length) = error.error_len() {
+///                     input = &after_valid[invalid_sequence_length..]
+///                 } else {
+///                     break
+///                 }
+///             }
+///         }
+///     }
+/// }
+/// ```
 #[derive(Copy, Eq, PartialEq, Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Utf8Error {
index 25827edee7d9343c0719fc30c4ebad784c35992e..fe5ed5d49422439147d860657366c6d16b061cd8 100644 (file)
@@ -948,6 +948,7 @@ macro_rules! atomic_int {
      $stable_from:meta,
      $stable_nand:meta,
      $s_int_type:expr, $int_ref:expr,
+     $extra_feature:expr,
      $int_type:ident $atomic_type:ident $atomic_init:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
@@ -959,12 +960,7 @@ macro_rules! atomic_int {
         /// ). For more about the differences between atomic types and
         /// non-atomic types, please see the [module-level documentation].
         ///
-        /// Please note that examples are shared between atomic variants of
-        /// primitive integer types, so it's normal that they are all
-        /// demonstrating [`AtomicIsize`].
-        ///
         /// [module-level documentation]: index.html
-        /// [`AtomicIsize`]: struct.AtomicIsize.html
         #[$stable]
         pub struct $atomic_type {
             v: UnsafeCell<$int_type>,
@@ -1001,395 +997,426 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe impl Sync for $atomic_type {}
 
         impl $atomic_type {
-            /// Creates a new atomic integer.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::AtomicIsize;
-            ///
-            /// let atomic_forty_two  = AtomicIsize::new(42);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub const fn new(v: $int_type) -> Self {
-                $atomic_type {v: UnsafeCell::new(v)}
+            doc_comment! {
+                concat!("Creates a new atomic integer.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+
+let atomic_forty_two = ", stringify!($atomic_type), "::new(42);
+```"),
+                #[inline]
+                #[$stable]
+                pub const fn new(v: $int_type) -> Self {
+                    $atomic_type {v: UnsafeCell::new(v)}
+                }
             }
 
-            /// Returns a mutable reference to the underlying integer.
-            ///
-            /// This is safe because the mutable reference guarantees that no other threads are
-            /// concurrently accessing the atomic data.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let mut some_isize = AtomicIsize::new(10);
-            /// assert_eq!(*some_isize.get_mut(), 10);
-            /// *some_isize.get_mut() = 5;
-            /// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
-            /// ```
-            #[inline]
-            #[$stable_access]
-            pub fn get_mut(&mut self) -> &mut $int_type {
-                unsafe { &mut *self.v.get() }
+            doc_comment! {
+                concat!("Returns a mutable reference to the underlying integer.
+
+This is safe because the mutable reference guarantees that no other threads are
+concurrently accessing the atomic data.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let mut some_var = ", stringify!($atomic_type), "::new(10);
+assert_eq!(*some_var.get_mut(), 10);
+*some_var.get_mut() = 5;
+assert_eq!(some_var.load(Ordering::SeqCst), 5);
+```"),
+                #[inline]
+                #[$stable_access]
+                pub fn get_mut(&mut self) -> &mut $int_type {
+                    unsafe { &mut *self.v.get() }
+                }
             }
 
-            /// Consumes the atomic and returns the contained value.
-            ///
-            /// This is safe because passing `self` by value guarantees that no other threads are
-            /// concurrently accessing the atomic data.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::AtomicIsize;
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            /// assert_eq!(some_isize.into_inner(), 5);
-            /// ```
-            #[inline]
-            #[$stable_access]
-            pub fn into_inner(self) -> $int_type {
-                self.v.into_inner()
+            doc_comment! {
+                concat!("Consumes the atomic and returns the contained value.
+
+This is safe because passing `self` by value guarantees that no other threads are
+concurrently accessing the atomic data.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+assert_eq!(some_var.into_inner(), 5);
+```"),
+                #[inline]
+                #[$stable_access]
+                pub fn into_inner(self) -> $int_type {
+                    self.v.into_inner()
+                }
             }
 
-            /// Loads a value from the atomic integer.
-            ///
-            /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// # Panics
-            ///
-            /// Panics if `order` is [`Release`] or [`AcqRel`].
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn load(&self, order: Ordering) -> $int_type {
-                unsafe { atomic_load(self.v.get(), order) }
+            doc_comment! {
+                concat!("Loads a value from the atomic integer.
+
+`load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+# Panics
+
+Panics if `order` is [`Release`] or [`AcqRel`].
+
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.load(Ordering::Relaxed), 5);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn load(&self, order: Ordering) -> $int_type {
+                    unsafe { atomic_load(self.v.get(), order) }
+                }
             }
 
-            /// Stores a value into the atomic integer.
-            ///
-            /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// some_isize.store(10, Ordering::Relaxed);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            ///
-            /// # Panics
-            ///
-            /// Panics if `order` is [`Acquire`] or [`AcqRel`].
-            ///
-            /// [`Acquire`]: enum.Ordering.html#variant.Acquire
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            #[inline]
-            #[$stable]
-            pub fn store(&self, val: $int_type, order: Ordering) {
-                unsafe { atomic_store(self.v.get(), val, order); }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer.
+
+`store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+some_var.store(10, Ordering::Relaxed);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```
+
+# Panics
+
+Panics if `order` is [`Acquire`] or [`AcqRel`].
+
+[`Acquire`]: enum.Ordering.html#variant.Acquire
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel"),
+                #[inline]
+                #[$stable]
+                pub fn store(&self, val: $int_type, order: Ordering) {
+                    unsafe { atomic_store(self.v.get(), val, order); }
+                }
             }
 
-            /// Stores a value into the atomic integer, returning the previous value.
-            ///
-            /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_swap(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer, returning the previous value.
+
+`swap` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_swap(self.v.get(), val, order) }
+                }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// The return value is always the previous value. If it is equal to `current`, then the
-            /// value was updated.
-            ///
-            /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
-            /// ordering of this operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            ///
-            /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn compare_and_swap(&self,
-                                    current: $int_type,
-                                    new: $int_type,
-                                    order: Ordering) -> $int_type {
-                match self.compare_exchange(current,
-                                            new,
-                                            order,
-                                            strongest_failure_ordering(order)) {
-                    Ok(x) => x,
-                    Err(x) => x,
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+The return value is always the previous value. If it is equal to `current`, then the
+value was updated.
+
+`compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+
+assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn compare_and_swap(&self,
+                                        current: $int_type,
+                                        new: $int_type,
+                                        order: Ordering) -> $int_type {
+                    match self.compare_exchange(current,
+                                                new,
+                                                order,
+                                                strongest_failure_ordering(order)) {
+                        Ok(x) => x,
+                        Err(x) => x,
+                    }
                 }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// The return value is a result indicating whether the new value was written and
-            /// containing the previous value. On success this value is guaranteed to be equal to
-            /// `current`.
-            ///
-            /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
-            /// ordering of this operation. The first describes the required ordering if
-            /// the operation succeeds while the second describes the required ordering when
-            /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
-            /// must be equivalent or weaker than the success ordering.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.compare_exchange(5, 10,
-            ///                                        Ordering::Acquire,
-            ///                                        Ordering::Relaxed),
-            ///            Ok(5));
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            ///
-            /// assert_eq!(some_isize.compare_exchange(6, 12,
-            ///                                        Ordering::SeqCst,
-            ///                                        Ordering::Acquire),
-            ///            Err(10));
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            #[inline]
-            #[$stable_cxchg]
-            pub fn compare_exchange(&self,
-                                    current: $int_type,
-                                    new: $int_type,
-                                    success: Ordering,
-                                    failure: Ordering) -> Result<$int_type, $int_type> {
-                unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+The return value is a result indicating whether the new value was written and
+containing the previous value. On success this value is guaranteed to be equal to
+`current`.
+
+`compare_exchange` takes two [`Ordering`] arguments to describe the memory
+ordering of this operation. The first describes the required ordering if
+the operation succeeds while the second describes the required ordering when
+the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+must be equivalent or weaker than the success ordering.
+
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.compare_exchange(5, 10,
+                                     Ordering::Acquire,
+                                     Ordering::Relaxed),
+           Ok(5));
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+
+assert_eq!(some_var.compare_exchange(6, 12,
+                                     Ordering::SeqCst,
+                                     Ordering::Acquire),
+           Err(10));
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```"),
+                #[inline]
+                #[$stable_cxchg]
+                pub fn compare_exchange(&self,
+                                        current: $int_type,
+                                        new: $int_type,
+                                        success: Ordering,
+                                        failure: Ordering) -> Result<$int_type, $int_type> {
+                    unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+                }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
-            /// when the comparison succeeds, which can result in more efficient code on some
-            /// platforms. The return value is a result indicating whether the new value was
-            /// written and containing the previous value.
-            ///
-            /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
-            /// ordering of this operation. The first describes the required ordering if the
-            /// operation succeeds while the second describes the required ordering when the
-            /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
-            /// must be equivalent or weaker than the success ordering.
-            ///
-            /// [`compare_exchange`]: #method.compare_exchange
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let val = AtomicIsize::new(4);
-            ///
-            /// let mut old = val.load(Ordering::Relaxed);
-            /// loop {
-            ///     let new = old * 2;
-            ///     match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
-            ///         Ok(_) => break,
-            ///         Err(x) => old = x,
-            ///     }
-            /// }
-            /// ```
-            #[inline]
-            #[$stable_cxchg]
-            pub fn compare_exchange_weak(&self,
-                                         current: $int_type,
-                                         new: $int_type,
-                                         success: Ordering,
-                                         failure: Ordering) -> Result<$int_type, $int_type> {
-                unsafe {
-                    atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+Unlike [`compare_exchange`], this function is allowed to spuriously fail even
+when the comparison succeeds, which can result in more efficient code on some
+platforms. The return value is a result indicating whether the new value was
+written and containing the previous value.
+
+`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
+ordering of this operation. The first describes the required ordering if the
+operation succeeds while the second describes the required ordering when the
+operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+must be equivalent or weaker than the success ordering.
+
+[`compare_exchange`]: #method.compare_exchange
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let val = ", stringify!($atomic_type), "::new(4);
+
+let mut old = val.load(Ordering::Relaxed);
+loop {
+    let new = old * 2;
+    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+        Ok(_) => break,
+        Err(x) => old = x,
+    }
+}
+```"),
+                #[inline]
+                #[$stable_cxchg]
+                pub fn compare_exchange_weak(&self,
+                                             current: $int_type,
+                                             new: $int_type,
+                                             success: Ordering,
+                                             failure: Ordering) -> Result<$int_type, $int_type> {
+                    unsafe {
+                        atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+                    }
                 }
             }
 
-            /// Adds to the current value, returning the previous value.
-            ///
-            /// This operation wraps around on overflow.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0);
-            /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_add(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Adds to the current value, returning the previous value.
+
+This operation wraps around on overflow.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0);
+assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
+assert_eq!(foo.load(Ordering::SeqCst), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_add(self.v.get(), val, order) }
+                }
             }
 
-            /// Subtracts from the current value, returning the previous value.
-            ///
-            /// This operation wraps around on overflow.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0);
-            /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
-            /// assert_eq!(foo.load(Ordering::SeqCst), -10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_sub(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Subtracts from the current value, returning the previous value.
+
+This operation wraps around on overflow.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(20);
+assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
+assert_eq!(foo.load(Ordering::SeqCst), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_sub(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "and" with the current value.
-            ///
-            /// Performs a bitwise "and" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
-            #[inline]
-            #[$stable]
-            pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_and(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"and\" with the current value.
+
+Performs a bitwise \"and\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_and(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "nand" with the current value.
-            ///
-            /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// #![feature(atomic_nand)]
-            ///
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0xf731);
-            /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731);
-            /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f));
-            #[inline]
-            #[$stable_nand]
-            pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_nand(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"nand\" with the current value.
+
+Performs a bitwise \"nand\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "#![feature(atomic_nand)]
+
+use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0x13);
+assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
+assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
+```"),
+                #[inline]
+                #[$stable_nand]
+                pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_nand(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "or" with the current value.
-            ///
-            /// Performs a bitwise "or" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
-            #[inline]
-            #[$stable]
-            pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_or(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"or\" with the current value.
+
+Performs a bitwise \"or\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_or(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "xor" with the current value.
-            ///
-            /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
-            #[inline]
-            #[$stable]
-            pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_xor(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"xor\" with the current value.
+
+Performs a bitwise \"xor\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_xor(self.v.get(), val, order) }
+                }
             }
         }
     }
@@ -1404,6 +1431,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i8", "../../../std/primitive.i8.html",
+    "#![feature(integer_atomics)]\n\n",
     i8 AtomicI8 ATOMIC_I8_INIT
 }
 #[cfg(target_has_atomic = "8")]
@@ -1415,6 +1443,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u8", "../../../std/primitive.u8.html",
+    "#![feature(integer_atomics)]\n\n",
     u8 AtomicU8 ATOMIC_U8_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1426,6 +1455,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i16", "../../../std/primitive.i16.html",
+    "#![feature(integer_atomics)]\n\n",
     i16 AtomicI16 ATOMIC_I16_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1437,6 +1467,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u16", "../../../std/primitive.u16.html",
+    "#![feature(integer_atomics)]\n\n",
     u16 AtomicU16 ATOMIC_U16_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1448,6 +1479,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i32", "../../../std/primitive.i32.html",
+    "#![feature(integer_atomics)]\n\n",
     i32 AtomicI32 ATOMIC_I32_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1459,6 +1491,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u32", "../../../std/primitive.u32.html",
+    "#![feature(integer_atomics)]\n\n",
     u32 AtomicU32 ATOMIC_U32_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1470,6 +1503,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i64", "../../../std/primitive.i64.html",
+    "#![feature(integer_atomics)]\n\n",
     i64 AtomicI64 ATOMIC_I64_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1481,6 +1515,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u64", "../../../std/primitive.u64.html",
+    "#![feature(integer_atomics)]\n\n",
     u64 AtomicU64 ATOMIC_U64_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1492,6 +1527,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     stable(feature = "atomic_from", since = "1.23.0"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "isize", "../../../std/primitive.isize.html",
+    "",
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1503,6 +1539,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     stable(feature = "atomic_from", since = "1.23.0"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "usize", "../../../std/primitive.usize.html",
+    "",
     usize AtomicUsize ATOMIC_USIZE_INIT
 }
 
index 4d43067ad2cf3e7b4467581b0d2e190af19d0a59..950222dbcfa3fe8d303097e6832e0af6af648196 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use core::char::from_u32;
-use std::ascii::AsciiExt;
 
 #[test]
 fn test_is_ascii() {
@@ -143,8 +142,6 @@ macro_rules! assert_all {
                            stringify!($what), b);
                 }
             }
-            assert!($str.$what());
-            assert!($str.as_bytes().$what());
         )+
     }};
     ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
index 744e3a5eaabccb4c2dd346506152aecf55c64b79..1e2e4e5a69fa1ad0b9ef05757976eabc03b236bc 100644 (file)
@@ -579,6 +579,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] GetPanicStrategy(CrateNum),
     [] IsNoBuiltins(CrateNum),
     [] ImplDefaultness(DefId),
+    [] CheckItemWellFormed(DefId),
+    [] CheckTraitItemWellFormed(DefId),
+    [] CheckImplItemWellFormed(DefId),
     [] ReachableNonGenerics(CrateNum),
     [] NativeLibraries(CrateNum),
     [] PluginRegistrarFn(CrateNum),
index 0ad79eacd2b03f9a04981bf5d2a4e9db918b7089..d60c22064d3a0cd0ee3900a1dec51d175e28ea58 100644 (file)
@@ -476,10 +476,8 @@ pub fn serialize(&self) -> SerializedDepGraph {
             fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO);
         }
 
-        let nodes: IndexVec<_, (DepNode, Fingerprint)> =
-            current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| {
-            (dep_node, fingerprints[idx])
-        }).collect();
+        let fingerprints = fingerprints.clone().convert_index_type();
+        let nodes = current_dep_graph.nodes.clone().convert_index_type();
 
         let total_edge_count: usize = current_dep_graph.edges.iter()
                                                              .map(|v| v.len())
@@ -503,6 +501,7 @@ pub fn serialize(&self) -> SerializedDepGraph {
 
         SerializedDepGraph {
             nodes,
+            fingerprints,
             edge_list_indices,
             edge_list_data,
         }
index 504b60e763e23543fc9e5663acbe5bbf6a842429..669a99019aa60176de63f093266766a75d8638a4 100644 (file)
@@ -23,7 +23,7 @@ impl PreviousDepGraph {
     pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
         let index: FxHashMap<_, _> = data.nodes
             .iter_enumerated()
-            .map(|(idx, &(dep_node, _))| (dep_node, idx))
+            .map(|(idx, &dep_node)| (dep_node, idx))
             .collect();
         PreviousDepGraph { data, index }
     }
@@ -41,7 +41,7 @@ pub fn edges_from(&self,
 
     #[inline]
     pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode {
-        self.data.nodes[dep_node_index].0
+        self.data.nodes[dep_node_index]
     }
 
     #[inline]
@@ -58,14 +58,14 @@ pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option<SerializedDepNodeI
     pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
         self.index
             .get(dep_node)
-            .map(|&node_index| self.data.nodes[node_index].1)
+            .map(|&node_index| self.data.fingerprints[node_index])
     }
 
     #[inline]
     pub fn fingerprint_by_index(&self,
                                 dep_node_index: SerializedDepNodeIndex)
                                 -> Fingerprint {
-        self.data.nodes[dep_node_index].1
+        self.data.fingerprints[dep_node_index]
     }
 
     pub fn node_count(&self) -> usize {
index c96040ab9b6e3eab996aafdb875c90fc6d3217a4..60fc813a25d51eda38da1293b1a8943a89c35225 100644 (file)
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedDepGraph {
     /// The set of all DepNodes in the graph
-    pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>,
+    pub nodes: IndexVec<SerializedDepNodeIndex, DepNode>,
+    /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
+    /// the DepNode at the same index in the nodes vector.
+    pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
     /// For each DepNode, stores the list of edges originating from that
     /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
     /// which holds the actual DepNodeIndices of the target nodes.
@@ -35,6 +38,7 @@ impl SerializedDepGraph {
     pub fn new() -> SerializedDepGraph {
         SerializedDepGraph {
             nodes: IndexVec::new(),
+            fingerprints: IndexVec::new(),
             edge_list_indices: IndexVec::new(),
             edge_list_data: Vec::new(),
         }
index b3a904f2f5fec520598714aee8882b5642f33c12..2fd875c3447677b4d841b320535abbfe543b6917 100644 (file)
@@ -2074,6 +2074,58 @@ struct Foo {
 transparent wrapper around a float. This can make a difference for the ABI.
 "##,
 
+E0909: r##"
+The `impl Trait` return type captures lifetime parameters that do not
+appear within the `impl Trait` itself.
+
+Erroneous code example:
+
+```compile-fail,E0909
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a, 'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
+where 'x: 'y
+{
+    x
+}
+```
+
+Here, the function `foo` returns a value of type `Cell<&'x u32>`,
+which references the lifetime `'x`. However, the return type is
+declared as `impl Trait<'y>` -- this indicates that `foo` returns
+"some type that implements `Trait<'y>`", but it also indicates that
+the return type **only captures data referencing the lifetime `'y`**.
+In this case, though, we are referencing data with lifetime `'x`, so
+this function is in error.
+
+To fix this, you must reference the lifetime `'x` from the return
+type. For example, changing the return type to `impl Trait<'y> + 'x`
+would work:
+
+```
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a,'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
+where 'x: 'y
+{
+    x
+}
+```
+"##,
+
+
 }
 
 
index 1439410f7e9aa2ac025f2d23b92363cc77a1f9ff..f6bdfde15fc5ff962cf7f6f12ab90e49a0febe64 100644 (file)
@@ -809,7 +809,7 @@ fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>)
         }
     }
 
-    fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
+    fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
         attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into()
     }
 
@@ -1019,6 +1019,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                             span,
                             pure_wrt_drop: false,
                             synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+                            attrs: P::new(),
                         });
 
                         hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
@@ -1585,6 +1586,7 @@ fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::
                                .filter(|attr| attr.check_name("rustc_synthetic"))
                                .map(|_| hir::SyntheticTyParamKind::ImplTrait)
                                .nth(0),
+            attrs: self.lower_attrs(&tp.attrs),
         }
     }
 
index 61fae4609d54fe7813b76857c5baa5fb6e48ed09..e8bcbfbb77a1791cb03d6d65352566accc740c8a 100644 (file)
@@ -962,6 +962,7 @@ pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] {
             Some(NodeField(ref f)) => Some(&f.attrs[..]),
             Some(NodeExpr(ref e)) => Some(&*e.attrs),
             Some(NodeStmt(ref s)) => Some(s.node.attrs()),
+            Some(NodeTyParam(tp)) => Some(&tp.attrs[..]),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
             Some(NodeStructCtor(_)) => {
index 5ae84f5685eafca61a09c0716dd2de7ff76d7a56..d6810b2468bccbed8dc1d332e42847db7b3da388 100644 (file)
@@ -414,6 +414,7 @@ pub struct TyParam {
     pub span: Span,
     pub pure_wrt_drop: bool,
     pub synthetic: Option<SyntheticTyParamKind>,
+    pub attrs: HirVec<Attribute>,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
index e764cedd658b5df4070f031fcd0f5bc33c26c663..774b1442b7101cd0da9aea15ede223d57231ed9b 100644 (file)
@@ -203,7 +203,8 @@ fn hash_stable<W: StableHasherResult>(&self,
     default,
     span,
     pure_wrt_drop,
-    synthetic
+    synthetic,
+    attrs
 });
 
 impl_stable_hash_for!(enum hir::GenericParam {
index eb26f0c1188bf639bf8c0b31aa40a8c85e7cdf40..93e8745af1b57731318feea40405c51953944899 100644 (file)
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast;
 use traits::{self, PredicateObligation};
-use ty::{self, Ty};
-use ty::fold::{BottomUpFolder, TypeFoldable};
+use ty::{self, Ty, TyCtxt};
+use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
 use ty::outlives::Component;
-use ty::subst::{Kind, UnpackedKind, Substs};
+use ty::subst::{Kind, Substs, UnpackedKind};
 use util::nodemap::DefIdMap;
 
 pub type AnonTypeMap<'tcx> = DefIdMap<AnonTypeDecl<'tcx>>;
@@ -113,10 +113,7 @@ pub fn instantiate_anon_types<T: TypeFoldable<'tcx>>(
     ) -> InferOk<'tcx, (T, AnonTypeMap<'tcx>)> {
         debug!(
             "instantiate_anon_types(value={:?}, parent_def_id={:?}, body_id={:?}, param_env={:?})",
-            value,
-            parent_def_id,
-            body_id,
-            param_env,
+            value, parent_def_id, body_id, param_env,
         );
         let mut instantiator = Instantiator {
             infcx: self,
@@ -458,55 +455,184 @@ pub fn infer_anon_definition_from_instantiation(
         // Convert the type from the function into a type valid outside
         // the function, by replacing invalid regions with 'static,
         // after producing an error for each of them.
-        let definition_ty = gcx.fold_regions(&instantiated_ty, &mut false, |r, _| {
-            match *r {
-                // 'static and early-bound regions are valid.
-                ty::ReStatic | ty::ReEmpty => r,
-
-                // 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(UnpackedKind::Lifetime(r1)) = map.get(&r.into())
-                                                                  .map(|k| k.unpack()) {
-                    r1
-                } else {
-                    // No mapping was found. This means that
-                    // it is either a disallowed lifetime,
-                    // which will be caught by regionck, or it
-                    // is a region in a non-upvar closure
-                    // generic, which is explicitly
-                    // allowed. If that surprises you, read
-                    // on.
-                    //
-                    // The case of closure is a somewhat
-                    // subtle (read: hacky) consideration. The
-                    // problem is that our closure types
-                    // currently include all the lifetime
-                    // parameters declared on the enclosing
-                    // function, even if they are unused by
-                    // the closure itself. We can't readily
-                    // filter them out, so here we replace
-                    // those values with `'empty`. This can't
-                    // really make a difference to the rest of
-                    // the compiler; those regions are ignored
-                    // for the outlives relation, and hence
-                    // don't affect trait selection or auto
-                    // traits, and they are erased during
-                    // trans.
-                    gcx.types.re_empty
-                },
-            }
-        });
-
+        let definition_ty =
+            instantiated_ty.fold_with(&mut ReverseMapper::new(
+                self.tcx,
+                self.is_tainted_by_errors(),
+                def_id,
+                map,
+                instantiated_ty,
+            ));
         debug!(
             "infer_anon_definition_from_instantiation: definition_ty={:?}",
             definition_ty
         );
 
+        // We can unwrap here because our reverse mapper always
+        // produces things with 'gcx lifetime, though the type folder
+        // obscures that.
+        let definition_ty = gcx.lift(&definition_ty).unwrap();
+
         definition_ty
     }
 }
 
+struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+
+    /// If errors have already been reported in this fn, we suppress
+    /// our own errors because they are sometimes derivative.
+    tainted_by_errors: bool,
+
+    anon_type_def_id: DefId,
+    map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
+    map_missing_regions_to_empty: bool,
+
+    /// initially `Some`, set to `None` once error has been reported
+    hidden_ty: Option<Ty<'tcx>>,
+}
+
+impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> {
+    fn new(
+        tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+        tainted_by_errors: bool,
+        anon_type_def_id: DefId,
+        map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
+        hidden_ty: Ty<'tcx>,
+    ) -> Self {
+        Self {
+            tcx,
+            tainted_by_errors,
+            anon_type_def_id,
+            map,
+            map_missing_regions_to_empty: false,
+            hidden_ty: Some(hidden_ty),
+        }
+    }
+
+    fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
+        assert!(!self.map_missing_regions_to_empty);
+        self.map_missing_regions_to_empty = true;
+        let kind = kind.fold_with(self);
+        self.map_missing_regions_to_empty = false;
+        kind
+    }
+
+    fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
+        assert!(!self.map_missing_regions_to_empty);
+        kind.fold_with(self)
+    }
+}
+
+impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
+        self.tcx
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match r {
+            // ignore bound regions that appear in the type (e.g., this
+            // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
+            ty::ReLateBound(..) => return r,
+
+            // ignore `'static`, as that can appear anywhere
+            ty::ReStatic => return r,
+
+            _ => { }
+        }
+
+        match self.map.get(&r.into()).map(|k| k.unpack()) {
+            Some(UnpackedKind::Lifetime(r1)) => r1,
+            Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
+            None => {
+                if !self.map_missing_regions_to_empty && !self.tainted_by_errors {
+                    if let Some(hidden_ty) = self.hidden_ty.take() {
+                        let span = self.tcx.def_span(self.anon_type_def_id);
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0909,
+                            "hidden type for `impl Trait` captures lifetime that \
+                             does not appear in bounds",
+                        );
+
+                        // Assuming regionck succeeded, then we must
+                        // be capturing *some* region from the fn
+                        // header, and hence it must be free, so it's
+                        // ok to invoke this fn (which doesn't accept
+                        // all regions, and would ICE if an
+                        // inappropriate region is given). We check
+                        // `is_tainted_by_errors` by errors above, so
+                        // we don't get in here unless regionck
+                        // succeeded. (Note also that if regionck
+                        // failed, then the regions we are attempting
+                        // to map here may well be giving errors
+                        // *because* the constraints were not
+                        // satisfiable.)
+                        self.tcx.note_and_explain_free_region(
+                            &mut err,
+                            &format!("hidden type `{}` captures ", hidden_ty),
+                            r,
+                            ""
+                        );
+
+                        err.emit();
+                    }
+                }
+                self.tcx.types.re_empty
+            },
+        }
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.sty {
+            ty::TyClosure(def_id, substs) => {
+                // I am a horrible monster and I pray for death. When
+                // we encounter a closure here, it is always a closure
+                // from within the function that we are currently
+                // type-checking -- one that is now being encapsulated
+                // in an existential abstract type. Ideally, we would
+                // go through the types/lifetimes that it references
+                // and treat them just like we would any other type,
+                // which means we would error out if we find any
+                // reference to a type/region that is not in the
+                // "reverse map".
+                //
+                // **However,** in the case of closures, there is a
+                // somewhat subtle (read: hacky) consideration. The
+                // problem is that our closure types currently include
+                // all the lifetime parameters declared on the
+                // enclosing function, even if they are unused by the
+                // closure itself. We can't readily filter them out,
+                // so here we replace those values with `'empty`. This
+                // can't really make a difference to the rest of the
+                // compiler; those regions are ignored for the
+                // outlives relation, and hence don't affect trait
+                // selection or auto traits, and they are erased
+                // during trans.
+
+                let generics = self.tcx.generics_of(def_id);
+                let parent_len = generics.parent_count();
+                let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
+                    |(index, &kind)| {
+                        if index < parent_len {
+                            // Accommodate missing regions in the parent kinds...
+                            self.fold_kind_mapping_missing_regions_to_empty(kind)
+                        } else {
+                            // ...but not elsewhere.
+                            self.fold_kind_normally(kind)
+                        }
+                    },
+                ));
+
+                self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs })
+            }
+
+            _ => ty.super_fold_with(self),
+        }
+    }
+}
+
 struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     parent_def_id: DefId,
@@ -565,12 +691,13 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
                             return self.fold_anon_ty(ty, def_id, substs);
                         }
 
-                        debug!("instantiate_anon_types_in_map: \
-                                encountered anon with wrong parent \
-                                def_id={:?} \
-                                anon_parent_def_id={:?}",
-                               def_id,
-                               anon_parent_def_id);
+                        debug!(
+                            "instantiate_anon_types_in_map: \
+                             encountered anon with wrong parent \
+                             def_id={:?} \
+                             anon_parent_def_id={:?}",
+                            def_id, anon_parent_def_id
+                        );
                     }
                 }
 
@@ -590,8 +717,7 @@ fn fold_anon_ty(
 
         debug!(
             "instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})",
-            def_id,
-            substs
+            def_id, substs
         );
 
         // Use the same type variable if the exact same TyAnon appears more
@@ -600,8 +726,10 @@ fn fold_anon_ty(
             return anon_defn.concrete_ty;
         }
         let span = tcx.def_span(def_id);
-        let ty_var = infcx.next_ty_var(ty::UniverseIndex::ROOT,
-                                       TypeVariableOrigin::TypeInference(span));
+        let ty_var = infcx.next_ty_var(
+            ty::UniverseIndex::ROOT,
+            TypeVariableOrigin::TypeInference(span),
+        );
 
         let predicates_of = tcx.predicates_of(def_id);
         let bounds = predicates_of.instantiate(tcx, substs);
index 4e0cf59e8a7fd7dc6db068c5f4d60ac62feaab49..22526c7751d5021dfb4809f3b5a1d061e164aa6f 100644 (file)
@@ -40,6 +40,7 @@
 use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
 use ty::subst::{Kind, UnpackedKind};
 use ty::fold::{TypeFoldable, TypeFolder};
+use util::captures::Captures;
 use util::common::CellUsizeExt;
 
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -382,7 +383,7 @@ fn query_region_constraints_into_obligations<'a>(
         param_env: ty::ParamEnv<'tcx>,
         unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>,
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a {
         let QueryRegionConstraints {
             region_outlives,
             ty_outlives,
index 77259f156e5e24ff37dd636365849030c56162c8..22b07c8cc044f55619255ee7edbfdcff18a4b843 100644 (file)
@@ -157,6 +157,7 @@ pub mod middle {
 pub mod ty;
 
 pub mod util {
+    pub mod captures;
     pub mod common;
     pub mod ppaux;
     pub mod nodemap;
index e0d662657b7de60574a69a9bf59ecbcb60bdde54..e56a8662f3eb4346747c3ae36e083d49422c6a8d 100644 (file)
@@ -19,6 +19,7 @@
 use ty::fast_reject::{self, SimplifiedType};
 use rustc_data_structures::sync::Lrc;
 use syntax::ast::Name;
+use util::captures::Captures;
 use util::nodemap::{DefIdMap, FxHashMap};
 
 /// A per-trait graph of impls in specialization order. At the moment, this
@@ -313,9 +314,10 @@ pub fn is_from_trait(&self) -> bool {
     }
 
     /// Iterate over the items defined directly by the given (impl or trait) node.
-    #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
-    pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                 -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+    pub fn items(
+        &self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
         tcx.associated_items(self.def_id())
     }
 
@@ -367,9 +369,13 @@ impl<'a, 'gcx, 'tcx> Ancestors {
     /// Search the items from the given ancestors, returning each definition
     /// with the given name and the given kind.
     #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
-    pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_item_name: Name,
-                trait_item_kind: ty::AssociatedKind, trait_def_id: DefId)
-                -> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + 'a {
+    pub fn defs(
+        self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        trait_item_name: Name,
+        trait_item_kind: ty::AssociatedKind,
+        trait_def_id: DefId,
+    ) -> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + Captures<'gcx> + Captures<'tcx> + 'a {
         self.flat_map(move |node| {
             node.items(tcx).filter(move |impl_item| {
                 impl_item.kind == trait_item_kind &&
index b6b7361bb2f72b2758851fc126a7b2d5b4466e9f..6c3b4efb932ad891923f0bce0c88fa90ec4a2c7c 100644 (file)
 
     [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
 
+    [] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (),
+    [] fn check_trait_item_well_formed: CheckTraitItemWellFormed(DefId) -> (),
+    [] fn check_impl_item_well_formed: CheckImplItemWellFormed(DefId) -> (),
+
     // The DefIds of all non-generic functions and statics in the given crate
     // that can be reached from outside the crate.
     //
index c514679042527f3cbb225dffa0897b93a2519c91..4170fa7679716034468fdf9e8cb52d32403f1eed 100644 (file)
@@ -871,6 +871,9 @@ macro_rules! force {
         DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
         DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
         DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
+        DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); }
+        DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
+        DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
         DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
         DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
         DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
index 9ffdccefae58569bfcc0c1acb9ee1aa06ba2e848..643155ef7782c31055af1dee72e9bbcaaaaa8220 100644 (file)
@@ -34,6 +34,7 @@
 use ty::subst::{Subst, Substs};
 use ty::util::{IntTypeExt, Discr};
 use ty::walk::TypeWalker;
+use util::captures::Captures;
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
 
 use serialize::{self, Encodable, Encoder};
@@ -1929,8 +1930,10 @@ pub fn eval_explicit_discr(
     }
 
     #[inline]
-    pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                         -> impl Iterator<Item=Discr<'tcx>> + 'a {
+    pub fn discriminants(
+        &'a self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx.global_tcx());
         let mut prev_discr = None::<Discr<'tcx>>;
@@ -2277,7 +2280,9 @@ pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
     /// Returns an iterator of the def-ids for all body-owners in this
     /// crate. If you would prefer to iterate over the bodies
     /// themselves, you can do `self.hir.krate().body_ids.iter()`.
-    pub fn body_owners(self) -> impl Iterator<Item = DefId> + 'a {
+    pub fn body_owners(
+        self,
+    ) -> impl Iterator<Item = DefId> + Captures<'tcx> + Captures<'gcx> + 'a {
         self.hir.krate()
                 .body_ids
                 .iter()
@@ -2381,11 +2386,13 @@ fn associated_item_from_impl_item_ref(self,
         }
     }
 
-    #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
-    pub fn associated_items(self, def_id: DefId)
-                            -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+    pub fn associated_items(
+        self,
+        def_id: DefId,
+    ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
         let def_ids = self.associated_item_def_ids(def_id);
-        (0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
+        Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i])))
+            as Box<dyn Iterator<Item = ty::AssociatedItem> + 'a>
     }
 
     /// Returns true if the impls are the same polarity and are implementing
index bb5c7b5fd2a5e0eddf38a9a041837c7415450109..d7ab6e39ac5f082dbbd4103810abc3266d66a196 100644 (file)
@@ -18,6 +18,7 @@
 use ty::subst::{Substs, Subst, Kind, UnpackedKind};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
+use util::captures::Captures;
 
 use std::iter;
 use std::cmp::Ordering;
@@ -384,9 +385,11 @@ impl<'a, 'gcx, 'tcx> ClosureSubsts<'tcx> {
     /// This returns the types of the MIR locals which had to be stored across suspension points.
     /// It is calculated in rustc_mir::transform::generator::StateTransform.
     /// All the types here must be in the tuple in GeneratorInterior.
-    pub fn state_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
-        impl Iterator<Item=Ty<'tcx>> + 'a
-    {
+    pub fn state_tys(
+        self,
+        def_id: DefId,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    ) -> impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a {
         let state = tcx.generator_layout(def_id).fields.iter();
         state.map(move |d| d.ty.subst(tcx, self.substs))
     }
@@ -403,7 +406,7 @@ impl Iterator<Item=Ty<'tcx>> + 'a
     /// This is the types of all the fields stored in a generator.
     /// It includes the upvars, state types and the state discriminant which is u32.
     pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
-        impl Iterator<Item=Ty<'tcx>> + 'a
+        impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a
     {
         self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx))
     }
diff --git a/src/librustc/util/captures.rs b/src/librustc/util/captures.rs
new file mode 100644 (file)
index 0000000..b68cfd2
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2012-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.
+
+/// "Signaling" trait used in impl trait to tag lifetimes that you may
+/// need to capture but don't really need for other reasons.
+/// Basically a workaround; see [this comment] for details.
+///
+/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
+pub trait Captures<'a> { }
+
+impl<'a, T: ?Sized> Captures<'a> for T { }
index a5b1a7e57ab4668167dc893fb2bbf003396138d2..cbb3ff5171592be599cc292b6e07b477c627a949 100644 (file)
@@ -503,6 +503,13 @@ pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
             (c1, c2)
         }
     }
+
+    pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
+        IndexVec {
+            raw: self.raw,
+            _marker: PhantomData,
+        }
+    }
 }
 
 impl<I: Idx, T: Clone> IndexVec<I, T> {
index ca1e3563089dbdfe226f2621604255d097d8b137..a5bc1106ba0b00fc24264b5378cd5711274e69ea 100644 (file)
@@ -162,7 +162,7 @@ struct Stat {
 
         let mut counts: FxHashMap<_, Stat> = FxHashMap();
 
-        for (i, &(node, _)) in serialized_graph.nodes.iter_enumerated() {
+        for (i, &node) in serialized_graph.nodes.iter_enumerated() {
             let stat = counts.entry(node.kind).or_insert(Stat {
                 kind: node.kind,
                 node_counter: 0,
index e1c17e8260a79576ecab9d307431bda336c958f0..b0c945fbf2a052f3f1f1027c3d62b03dc2b76451 100644 (file)
@@ -29,6 +29,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::codec::TyDecoder;
 use rustc::mir::Mir;
+use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
 
 use std::collections::BTreeMap;
@@ -146,7 +147,10 @@ pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
 }
 
 impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
-    pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item = T> + 'a {
+    pub fn decode<M: Metadata<'a, 'tcx>>(
+        self,
+        meta: M,
+    ) -> impl Iterator<Item = T> + Captures<'tcx> + 'a {
         let mut dcx = meta.decoder(self.position);
         dcx.lazy_state = LazyState::NodeStart(self.position);
         (0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
index ef30b1e452230df786add31df2af97b9344bda0d..7281fb59663881ee222345491332af71b5721070 100644 (file)
@@ -117,10 +117,9 @@ fn ast_block_stmts(&mut self,
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
                         unpack!(block = this.in_opt_scope(
-                            opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
+                            opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
                                 let scope = (init_scope, source_info);
-                                this.in_scope(scope, lint_level, block, move |this| {
-                                    // FIXME #30046                             ^~~~
+                                this.in_scope(scope, lint_level, block, |this| {
                                     this.expr_into_pattern(block, pattern, init)
                                 })
                             }));
index 82eb28287b033c16c87e186421042ade8ff36138..47f6f61072e13acb232e5edc8c74249bf3fa56c0 100644 (file)
@@ -339,6 +339,14 @@ fn init_static<'a>(
         ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         cid: GlobalId<'tcx>,
     ) -> EvalResult<'tcx, AllocId> {
+        let alloc = ecx
+                    .tcx
+                    .interpret_interner
+                    .get_cached(cid.instance.def_id());
+        // Don't evaluate when already cached to prevent cycles
+        if let Some(alloc) = alloc {
+            return Ok(alloc)
+        }
         // ensure the static is computed
         ecx.const_eval(cid)?;
         Ok(ecx
index d27de3ef6bfc4e4c900ffeef81ea4cfed3b49239..456f5fd75db09772ea8949c7c887c71a1ad0cb54 100644 (file)
@@ -197,29 +197,17 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
             },
 
             Static(ref static_) => {
-                let alloc = self
-                    .tcx
-                    .interpret_interner
-                    .get_cached(static_.def_id);
                 let layout = self.layout_of(self.place_ty(mir_place))?;
-                if let Some(alloc) = alloc {
-                    Place::Ptr {
-                        ptr: MemoryPointer::new(alloc, 0).into(),
-                        align: layout.align,
-                        extra: PlaceExtra::None,
-                    }
-                } else {
-                    let instance = ty::Instance::mono(*self.tcx, static_.def_id);
-                    let cid = GlobalId {
-                        instance,
-                        promoted: None
-                    };
-                    let alloc = Machine::init_static(self, cid)?;
-                    Place::Ptr {
-                        ptr: MemoryPointer::new(alloc, 0).into(),
-                        align: layout.align,
-                        extra: PlaceExtra::None,
-                    }
+                let instance = ty::Instance::mono(*self.tcx, static_.def_id);
+                let cid = GlobalId {
+                    instance,
+                    promoted: None
+                };
+                let alloc = Machine::init_static(self, cid)?;
+                Place::Ptr {
+                    ptr: MemoryPointer::new(alloc, 0).into(),
+                    align: layout.align,
+                    extra: PlaceExtra::None,
                 }
             }
 
index e95126c8a1a0f555daf24fe575bf0f6743b14db7..19f33ef5d45a83f6a6b4b964c613f6574bfa924b 100644 (file)
@@ -177,7 +177,7 @@ pub fn elaborate_drop<'a>(&mut self, bb: BasicBlock) {
                 });
             }
             DropStyle::Conditional => {
-                let unwind = self.unwind; // FIXME(#6393)
+                let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 let drop_bb = self.complete_drop(Some(DropFlagMode::Deep), succ, unwind);
                 self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
@@ -268,7 +268,7 @@ fn drop_ladder_bottom(&mut self) -> (BasicBlock, Unwind) {
         // Clear the "master" drop flag at the end. This is needed
         // because the "master" drop protects the ADT's discriminant,
         // which is invalidated after the ADT is dropped.
-        let (succ, unwind) = (self.succ, self.unwind); // FIXME(#6393)
+        let (succ, unwind) = (self.succ, self.unwind); // FIXME(#43234)
         (
             self.drop_flag_reset_block(DropFlagMode::Shallow, succ, unwind),
             unwind.map(|unwind| {
@@ -344,7 +344,7 @@ fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock
         let interior = self.place.clone().deref();
         let interior_path = self.elaborator.deref_subpath(self.path);
 
-        let succ = self.succ; // FIXME(#6393)
+        let succ = self.succ; // FIXME(#43234)
         let unwind = self.unwind;
         let succ = self.box_free_block(ty, succ, unwind);
         let unwind_succ = self.unwind.map(|unwind| {
@@ -717,7 +717,7 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
                            ptr_based)
         });
 
-        let succ = self.succ; // FIXME(#6393)
+        let succ = self.succ; // FIXME(#43234)
         let loop_block = self.drop_loop(
             succ,
             cur,
@@ -798,7 +798,7 @@ fn open_drop<'a>(&mut self) -> BasicBlock {
                 self.open_drop_for_adt(def, substs)
             }
             ty::TyDynamic(..) => {
-                let unwind = self.unwind; // FIXME(#6393)
+                let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
             }
@@ -849,7 +849,7 @@ fn drop_flag_reset_block(&mut self,
 
     fn elaborated_drop_block<'a>(&mut self) -> BasicBlock {
         debug!("elaborated_drop_block({:?})", self);
-        let unwind = self.unwind; // FIXME(#6393)
+        let unwind = self.unwind; // FIXME(#43234)
         let succ = self.succ;
         let blk = self.drop_block(succ, unwind);
         self.elaborate_drop(blk);
@@ -882,7 +882,7 @@ fn unelaborated_free_block<'a>(
             args: vec![Operand::Move(self.place.clone())],
             destination: Some((unit_temp, target)),
             cleanup: None
-        }; // FIXME(#6393)
+        }; // FIXME(#43234)
         let free_block = self.new_block(unwind, call);
 
         let block_start = Location { block: free_block, statement_index: 0 };
index 356ad9ec11bb70c0b6e4883e8d22af3c0eb690c0..76cbc670969880406426610d06338ec1d461dd86 100644 (file)
@@ -373,10 +373,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             }
         }
         hir::ExprMethodCall(..) => {
-            let def_id = v.tables.type_dependent_defs()[e.hir_id].def_id();
-            match v.tcx.associated_item(def_id).container {
-                ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
-                ty::TraitContainer(_) => v.promotable = false
+            if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) {
+                let def_id = def.def_id();
+                match v.tcx.associated_item(def_id).container {
+                    ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
+                    ty::TraitContainer(_) => v.promotable = false
+                }
+            } else {
+                v.tcx.sess.delay_span_bug(e.span, "no type-dependent def for method call");
             }
         }
         hir::ExprStruct(..) => {
index 4cbebdc3c1c39f9458fb732e4e0da80bf471d2f7..644a2ffe3c379bfc9c7864bfe8e7c51502c0132e 100644 (file)
@@ -1025,28 +1025,9 @@ fn import_path_to_string(names: &[SpannedIdent],
         if names.is_empty() {
             import_directive_subclass_to_string(subclass)
         } else {
-            // FIXME: Remove this entire logic after #48116 is fixed.
-            //
-            // Note that this code looks a little wonky, it's currently here to
-            // hopefully help debug #48116, but otherwise isn't intended to
-            // cause any problems.
-            let x = format!(
-                "{}::{}",
-                names_to_string(names),
-                import_directive_subclass_to_string(subclass),
-            );
-            if names.is_empty() || x.starts_with("::") {
-                span_bug!(
-                    span,
-                    "invalid name `{}` at {:?}; global = {}, names = {:?}, subclass = {:?}",
-                    x,
-                    span,
-                    global,
-                    names,
-                    subclass
-                );
-            }
-            return x
+            format!("{}::{}",
+                    names_to_string(names),
+                    import_directive_subclass_to_string(subclass))
         }
     }
 }
index c9666f55d440e4480bfcd2d246235b10660a4d93..1092e826a35f96c643a9c9e25d620d28a08172c1 100644 (file)
@@ -12,6 +12,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::subst::Substs;
 use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
 use syntax::ast;
 use rustc_data_structures::sync::Lrc;
@@ -104,6 +105,7 @@ fn lower(&self) -> Goal<'tcx> {
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = tcx.hir.expect_item(node_id);
     match item.node {
+        hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
         hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
 
         // FIXME: other constructions e.g. traits, associated types...
@@ -111,6 +113,36 @@ fn lower(&self) -> Goal<'tcx> {
     }
 }
 
+fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> Lrc<Vec<Clause<'tcx>>>
+{
+    // Rule Implemented-From-Env (see rustc guide)
+    //
+    // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
+    //
+    // ```
+    // forall<Self, P1..Pn> {
+    //   Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)
+    // }
+    // ```
+
+    // `Self: Trait<P1..Pn>`
+    let trait_pred = ty::TraitPredicate {
+        trait_ref: ty::TraitRef {
+            def_id,
+            substs: Substs::identity_for_item(tcx, def_id)
+        }
+    };
+    // `FromEnv(Self: Trait<P1..Pn>)`
+    let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower()));
+    // `Implemented(Self: Trait<P1..Pn>)`
+    let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
+
+    // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
+    let clause = Clause::Implies(vec![from_env], impl_trait);
+    Lrc::new(vec![clause])
+}
+
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     -> Lrc<Vec<Clause<'tcx>>>
 {
@@ -118,15 +150,24 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
         return Lrc::new(vec![]);
     }
 
-    // Rule Implemented-From-Impl
+    // Rule Implemented-From-Impl (see rustc guide)
+    //
+    // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
     //
-    // (see rustc guide)
+    // ```
+    // forall<P0..Pn> {
+    //   Implemented(A0: Trait<A1..An>) :- WC
+    // }
+    // ```
 
     let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
-    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
+    // `Implemented(A0: Trait<A1..An>)`
+    let trait_pred = ty::TraitPredicate { trait_ref }.lower();
+     // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates.lower();
 
-    let clause = Clause::Implies(where_clauses, trait_ref);
+     // `Implemented(A0: Trait<A1..An>) :- WC`
+    let clause = Clause::Implies(where_clauses, trait_pred);
     Lrc::new(vec![clause])
 }
 
index d5ec8d1b5526256573cf69552de26dc754f878fd..040d9455334bc9ede85ff33901506f72683c1be3 100644 (file)
@@ -148,9 +148,17 @@ fn cstr(s: &'static str) -> &CStr {
 pub fn provide(providers: &mut Providers) {
     providers.target_features_whitelist = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
-            .iter()
-            .map(|c| c.to_string())
-            .collect())
+        if tcx.sess.opts.actually_rustdoc {
+            // rustdoc needs to be able to document functions that use all the features, so
+            // whitelist them all
+            Lrc::new(llvm_util::all_known_features()
+                .map(|c| c.to_string())
+                .collect())
+        } else {
+            Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
+                .iter()
+                .map(|c| c.to_string())
+                .collect())
+        }
     };
 }
index 3f5a9a54ff1eacfab2bd485672b2091e50d4635a..91eabb9998f4a6425d7ae0b1105424bf250688b6 100644 (file)
@@ -1036,7 +1036,7 @@ pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
     pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmin");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true);
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
             }
@@ -1046,7 +1046,7 @@ pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
     pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmax");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true);
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
             }
@@ -1056,7 +1056,7 @@ pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
     pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmin_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false);
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
             }
@@ -1067,7 +1067,7 @@ pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
     pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
         self.count_insn("vector.reduce.fmax_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false);
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
             if instr.is_null() {
                 bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
             }
index dd8b44c96b90c575639ef245f89dad39f8e6e6c3..5113b65a5c4700231f9e573711669abe549426ac 100644 (file)
@@ -107,6 +107,20 @@ unsafe fn configure_llvm(sess: &Session) {
 
 const MIPS_WHITELIST: &'static [&'static str] = &["fp64", "msa"];
 
+/// When rustdoc is running, provide a list of all known features so that all their respective
+/// primtives may be documented.
+///
+/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
+/// iterator!
+pub fn all_known_features() -> impl Iterator<Item=&'static str> {
+    ARM_WHITELIST.iter().cloned()
+        .chain(AARCH64_WHITELIST.iter().cloned())
+        .chain(X86_WHITELIST.iter().cloned())
+        .chain(HEXAGON_WHITELIST.iter().cloned())
+        .chain(POWERPC_WHITELIST.iter().cloned())
+        .chain(MIPS_WHITELIST.iter().cloned())
+}
+
 pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
     let arch = if sess.target.target.arch == "x86_64" {
         "x86"
index 267c8d2bd03c861bcfac1d495c359c6fdfe1b8fd..47bbd67fb5c70840cc5fdf85e8cfca77338df991 100644 (file)
@@ -15,7 +15,6 @@
 //! paths etc in all kinds of annoying scenarios.
 
 use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
@@ -34,8 +33,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     tcx.dep_graph.with_ignore(|| {
         let mut visitor = SymbolNamesTest { tcx: tcx };
-        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
-        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+        tcx.hir.krate().visit_all_item_likes(&mut visitor);
     })
 }
 
@@ -66,23 +64,16 @@ fn process_attrs(&mut self,
     }
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
+impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.process_attrs(item.id);
-        intravisit::walk_item(self, item);
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        self.process_attrs(ti.id);
-        intravisit::walk_trait_item(self, ti)
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.process_attrs(trait_item.id);
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        self.process_attrs(ii.id);
-        intravisit::walk_impl_item(self, ii)
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        self.process_attrs(impl_item.id);
     }
 }
index 4a685cfddb7a42f5e760d8a4427d26b622064335..69879bbe85d6e4e50d22af815d071c08be95a4f2 100644 (file)
@@ -718,6 +718,18 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum
     })?)
 }
 
+fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_item_well_formed(tcx, def_id);
+}
+
+fn check_trait_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_trait_item(tcx, def_id);
+}
+
+fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_impl_item(tcx, def_id);
+}
+
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         typeck_item_bodies,
@@ -725,6 +737,9 @@ pub fn provide(providers: &mut Providers) {
         has_typeck_tables,
         adt_destructor,
         used_trait_imports,
+        check_item_well_formed,
+        check_trait_item_well_formed,
+        check_impl_item_well_formed,
         ..*providers
     };
 }
@@ -2869,7 +2884,7 @@ fn expected_inputs_for_expected_output(&self,
                 let origin = self.misc(call_span);
                 let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
 
-                // FIXME(#15760) can't use try! here, FromError doesn't default
+                // FIXME(#27336) can't use ? here, Try::from_error doesn't default
                 // to identity so the resulting type is not constrained.
                 match ures {
                     Ok(ok) => {
@@ -2877,19 +2892,13 @@ fn expected_inputs_for_expected_output(&self,
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        let result = self.save_and_restore_in_snapshot_flag(|_| {
+                        self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = FulfillmentContext::new();
-                            let ok = ok; // FIXME(#30046)
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
                             fulfill.select_where_possible(self)
-                        });
-
-                        match result {
-                            Ok(()) => { }
-                            Err(_) => return Err(()),
-                        }
+                        }).map_err(|_| ())?;
                     }
                     Err(_) => return Err(()),
                 }
index ab148afafbe0909c300f0cbbcab5a773b3bfeb00..4fc3344dab2a919dd796d84de0e27e70fe9cdf8c 100644 (file)
@@ -217,7 +217,7 @@ fn analyze_closure(
             .upvar_tys(closure_def_id, self.tcx)
             .zip(final_upvar_tys)
         {
-            self.demand_eqtype(span, final_upvar_ty, upvar_ty);
+            self.demand_suptype(span, upvar_ty, final_upvar_ty);
         }
 
         // If we are also inferred the closure kind here,
index b94af0a1e0081d2b8ecbc8b7d1eb569577836165..406ff9463a03c314f4da185ca068dd0ae2c24a37 100644 (file)
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
 
-pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    code: ObligationCauseCode<'tcx>,
-}
-
 /// Helper type of a temporary returned by .for_item(...).
 /// Necessary because we can't write the following bound:
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
 struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
-    code: ObligationCauseCode<'gcx>,
     id: ast::NodeId,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
@@ -45,585 +39,597 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
     fn with_fcx<F>(&'tcx mut self, f: F) where
         F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>,
-                          &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec<Ty<'tcx>>
+                         TyCtxt<'b, 'gcx, 'gcx>) -> Vec<Ty<'tcx>>
     {
-        let code = self.code.clone();
         let id = self.id;
         let span = self.span;
         let param_env = self.param_env;
         self.inherited.enter(|inh| {
             let fcx = FnCtxt::new(&inh, param_env, id);
-            let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
-                tcx: fcx.tcx.global_tcx(),
-                code,
-            });
+            let wf_tys = f(&fcx, fcx.tcx.global_tcx());
             fcx.select_all_obligations_or_error();
             fcx.regionck_item(id, span, &wf_tys);
         });
     }
 }
 
-impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
-               -> CheckTypeWellFormedVisitor<'a, 'gcx> {
-        CheckTypeWellFormedVisitor {
-            tcx,
-            code: ObligationCauseCode::MiscObligation
-        }
-    }
-
-    /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
-    /// well-formed, meaning that they do not require any constraints not declared in the struct
-    /// definition itself. For example, this definition would be illegal:
-    ///
-    ///     struct Ref<'a, T> { x: &'a T }
-    ///
-    /// because the type did not declare that `T:'a`.
-    ///
-    /// We do this check as a pre-pass before checking fn bodies because if these constraints are
-    /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
-    /// the types first.
-    fn check_item_well_formed(&mut self, item: &hir::Item) {
-        let tcx = self.tcx;
-        debug!("check_item_well_formed(it.id={}, it.name={})",
-               item.id,
-               tcx.item_path_str(tcx.hir.local_def_id(item.id)));
-
-        match item.node {
-            // Right now we check that every default trait implementation
-            // has an implementation of itself. Basically, a case like:
-            //
-            // `impl Trait for T {}`
-            //
-            // has a requirement of `T: Trait` which was required for default
-            // method implementations. Although this could be improved now that
-            // there's a better infrastructure in place for this, it's being left
-            // for a follow-up work.
-            //
-            // Since there's such a requirement, we need to check *just* positive
-            // implementations, otherwise things like:
-            //
-            // impl !Send for T {}
-            //
-            // won't be allowed unless there's an *explicit* implementation of `Send`
-            // for `T`
-            hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
-                let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
-                                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
-                if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
-                    tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
-                }
-                if polarity == hir::ImplPolarity::Positive {
-                    self.check_impl(item, self_ty, trait_ref);
-                } else {
-                    // FIXME(#27579) what amount of WF checking do we need for neg impls?
-                    if trait_ref.is_some() && !is_auto {
-                        span_err!(tcx.sess, item.span, E0192,
-                                  "negative impls are only allowed for \
-                                   auto traits (e.g., `Send` and `Sync`)")
-                    }
-                }
-            }
-            hir::ItemFn(..) => {
-                self.check_item_fn(item);
-            }
-            hir::ItemStatic(..) => {
-                self.check_item_type(item);
+/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
+/// well-formed, meaning that they do not require any constraints not declared in the struct
+/// definition itself. For example, this definition would be illegal:
+///
+///     struct Ref<'a, T> { x: &'a T }
+///
+/// because the type did not declare that `T:'a`.
+///
+/// We do this check as a pre-pass before checking fn bodies because if these constraints are
+/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
+/// the types first.
+pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let item = tcx.hir.expect_item(node_id);
+
+    debug!("check_item_well_formed(it.id={}, it.name={})",
+            item.id,
+            tcx.item_path_str(def_id));
+
+    match item.node {
+        // Right now we check that every default trait implementation
+        // has an implementation of itself. Basically, a case like:
+        //
+        // `impl Trait for T {}`
+        //
+        // has a requirement of `T: Trait` which was required for default
+        // method implementations. Although this could be improved now that
+        // there's a better infrastructure in place for this, it's being left
+        // for a follow-up work.
+        //
+        // Since there's such a requirement, we need to check *just* positive
+        // implementations, otherwise things like:
+        //
+        // impl !Send for T {}
+        //
+        // won't be allowed unless there's an *explicit* implementation of `Send`
+        // for `T`
+        hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
+            let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
+                                .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
+            if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
+                tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
             }
-            hir::ItemConst(..) => {
-                self.check_item_type(item);
+            if polarity == hir::ImplPolarity::Positive {
+                check_impl(tcx, item, self_ty, trait_ref);
+            } else {
+                // FIXME(#27579) what amount of WF checking do we need for neg impls?
+                if trait_ref.is_some() && !is_auto {
+                    span_err!(tcx.sess, item.span, E0192,
+                                "negative impls are only allowed for \
+                                auto traits (e.g., `Send` and `Sync`)")
+                }
             }
-            hir::ItemStruct(ref struct_def, ref ast_generics) => {
-                self.check_type_defn(item, false, |fcx| {
-                    vec![fcx.non_enum_variant(struct_def)]
-                });
+        }
+        hir::ItemFn(..) => {
+            check_item_fn(tcx, item);
+        }
+        hir::ItemStatic(..) => {
+            check_item_type(tcx, item);
+        }
+        hir::ItemConst(..) => {
+            check_item_type(tcx, item);
+        }
+        hir::ItemStruct(ref struct_def, ref ast_generics) => {
+            check_type_defn(tcx, item, false, |fcx| {
+                vec![fcx.non_enum_variant(struct_def)]
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemUnion(ref struct_def, ref ast_generics) => {
-                self.check_type_defn(item, true, |fcx| {
-                    vec![fcx.non_enum_variant(struct_def)]
-                });
+            check_variances_for_type_defn(tcx, item, ast_generics);
+        }
+        hir::ItemUnion(ref struct_def, ref ast_generics) => {
+            check_type_defn(tcx, item, true, |fcx| {
+                vec![fcx.non_enum_variant(struct_def)]
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemEnum(ref enum_def, ref ast_generics) => {
-                self.check_type_defn(item, true, |fcx| {
-                    fcx.enum_variants(enum_def)
-                });
+            check_variances_for_type_defn(tcx, item, ast_generics);
+        }
+        hir::ItemEnum(ref enum_def, ref ast_generics) => {
+            check_type_defn(tcx, item, true, |fcx| {
+                fcx.enum_variants(enum_def)
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemTrait(..) => {
-                self.check_trait(item);
-            }
-            _ => {}
+            check_variances_for_type_defn(tcx, item, ast_generics);
         }
+        hir::ItemTrait(..) => {
+            check_trait(tcx, item);
+        }
+        _ => {}
     }
+}
 
-    fn check_associated_item(&mut self,
-                             item_id: ast::NodeId,
-                             span: Span,
-                             sig_if_method: Option<&hir::MethodSig>) {
-        let code = self.code.clone();
-        self.for_id(item_id, span).with_fcx(|fcx, this| {
-            let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
-
-            let (mut implied_bounds, self_ty) = match item.container {
-                ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
-                ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
-                                              fcx.tcx.type_of(def_id))
-            };
+pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let trait_item = tcx.hir.expect_trait_item(node_id);
+
+    let method_sig = match trait_item.node {
+        hir::TraitItemKind::Method(ref sig, _) => Some(sig),
+        _ => None
+    };
+    check_associated_item(tcx, trait_item.id, trait_item.span, method_sig);
+}
+
+pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let impl_item = tcx.hir.expect_impl_item(node_id);
+
+    let method_sig = match impl_item.node {
+        hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+        _ => None
+    };
+    check_associated_item(tcx, impl_item.id, impl_item.span, method_sig);
+}
+
+fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            item_id: ast::NodeId,
+                            span: Span,
+                            sig_if_method: Option<&hir::MethodSig>) {
+    let code = ObligationCauseCode::MiscObligation;
+    for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
+        let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
+
+        let (mut implied_bounds, self_ty) = match item.container {
+            ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
+            ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
+                                            fcx.tcx.type_of(def_id))
+        };
 
-            match item.kind {
-                ty::AssociatedKind::Const => {
+        match item.kind {
+            ty::AssociatedKind::Const => {
+                let ty = fcx.tcx.type_of(item.def_id);
+                let ty = fcx.normalize_associated_types_in(span, &ty);
+                fcx.register_wf_obligation(ty, span, code.clone());
+            }
+            ty::AssociatedKind::Method => {
+                reject_shadowing_type_parameters(fcx.tcx, item.def_id);
+                let sig = fcx.tcx.fn_sig(item.def_id);
+                let sig = fcx.normalize_associated_types_in(span, &sig);
+                check_fn_or_method(tcx, fcx, span, sig,
+                                        item.def_id, &mut implied_bounds);
+                let sig_if_method = sig_if_method.expect("bad signature for method");
+                check_method_receiver(fcx, sig_if_method, &item, self_ty);
+            }
+            ty::AssociatedKind::Type => {
+                if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
                     let ty = fcx.normalize_associated_types_in(span, &ty);
                     fcx.register_wf_obligation(ty, span, code.clone());
                 }
-                ty::AssociatedKind::Method => {
-                    reject_shadowing_type_parameters(fcx.tcx, item.def_id);
-                    let sig = fcx.tcx.fn_sig(item.def_id);
-                    let sig = fcx.normalize_associated_types_in(span, &sig);
-                    this.check_fn_or_method(fcx, span, sig,
-                                            item.def_id, &mut implied_bounds);
-                    let sig_if_method = sig_if_method.expect("bad signature for method");
-                    this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
-                }
-                ty::AssociatedKind::Type => {
-                    if item.defaultness.has_value() {
-                        let ty = fcx.tcx.type_of(item.def_id);
-                        let ty = fcx.normalize_associated_types_in(span, &ty);
-                        fcx.register_wf_obligation(ty, span, code.clone());
-                    }
-                }
             }
+        }
 
-            implied_bounds
-        })
-    }
-
-    fn for_item<'tcx>(&self, item: &hir::Item)
-                      -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-        self.for_id(item.id, item.span)
-    }
+        implied_bounds
+    })
+}
 
-    fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
+fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item)
                     -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-        let def_id = self.tcx.hir.local_def_id(id);
-        CheckWfFcxBuilder {
-            inherited: Inherited::build(self.tcx, def_id),
-            code: self.code.clone(),
-            id,
-            span,
-            param_env: self.tcx.param_env(def_id),
-        }
+    for_id(tcx, item.id, item.span)
+}
+
+fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span)
+                -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
+    let def_id = tcx.hir.local_def_id(id);
+    CheckWfFcxBuilder {
+        inherited: Inherited::build(tcx, def_id),
+        id,
+        span,
+        param_env: tcx.param_env(def_id),
     }
+}
 
-    /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-    fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_fields: F)
-        where F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) -> Vec<AdtVariant<'tcx>>
-    {
-        self.for_item(item).with_fcx(|fcx, this| {
-            let variants = lookup_fields(fcx);
-            let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let packed = fcx.tcx.adt_def(def_id).repr.packed();
-
-            for variant in &variants {
-                // For DST, or when drop needs to copy things around, all
-                // intermediate types must be sized.
-                let needs_drop_copy = || {
-                    packed && {
-                        let ty = variant.fields.last().unwrap().ty;
-                        let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(this.tcx)
-                            .unwrap_or_else(|| {
-                                span_bug!(item.span, "inference variables in {:?}", ty)
-                            });
-                        ty.needs_drop(this.tcx, this.tcx.param_env(def_id))
-                    }
-                };
-                let unsized_len = if
-                    all_sized ||
-                    variant.fields.is_empty() ||
-                    needs_drop_copy()
-                {
-                    0
-                } else {
-                    1
-                };
-                for field in &variant.fields[..variant.fields.len() - unsized_len] {
-                    fcx.register_bound(
-                        field.ty,
-                        fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
-                        traits::ObligationCause::new(field.span,
-                                                     fcx.body_id,
-                                                     traits::FieldSized(match item.node.adt_kind() {
-                                                        Some(i) => i,
-                                                        None => bug!(),
-                                                     })));
+/// In a type definition, we check that to ensure that the types of the fields are well-formed.
+fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                item: &hir::Item, all_sized: bool, mut lookup_fields: F)
+    where F: for<'fcx, 'gcx, 'tcx2> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx2>) -> Vec<AdtVariant<'tcx2>>
+{
+    for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
+        let variants = lookup_fields(fcx);
+        let def_id = fcx.tcx.hir.local_def_id(item.id);
+        let packed = fcx.tcx.adt_def(def_id).repr.packed();
+
+        for variant in &variants {
+            // For DST, or when drop needs to copy things around, all
+            // intermediate types must be sized.
+            let needs_drop_copy = || {
+                packed && {
+                    let ty = variant.fields.last().unwrap().ty;
+                    let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx)
+                        .unwrap_or_else(|| {
+                            span_bug!(item.span, "inference variables in {:?}", ty)
+                        });
+                    ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
                 }
+            };
+            let unsized_len = if
+                all_sized ||
+                variant.fields.is_empty() ||
+                needs_drop_copy()
+            {
+                0
+            } else {
+                1
+            };
+            for field in &variant.fields[..variant.fields.len() - unsized_len] {
+                fcx.register_bound(
+                    field.ty,
+                    fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
+                    traits::ObligationCause::new(field.span,
+                                                    fcx.body_id,
+                                                    traits::FieldSized(match item.node.adt_kind() {
+                                                    Some(i) => i,
+                                                    None => bug!(),
+                                                    })));
+            }
 
-                // All field types must be well-formed.
-                for field in &variant.fields {
-                    fcx.register_wf_obligation(field.ty, field.span, this.code.clone())
-                }
+            // All field types must be well-formed.
+            for field in &variant.fields {
+                fcx.register_wf_obligation(field.ty, field.span,
+                    ObligationCauseCode::MiscObligation)
             }
+        }
 
-            self.check_where_clauses(fcx, item.span, def_id);
+        check_where_clauses(tcx, fcx, item.span, def_id);
 
-            vec![] // no implied bounds in a struct def'n
-        });
-    }
+        vec![] // no implied bounds in a struct def'n
+    });
+}
 
-    fn check_trait(&mut self, item: &hir::Item) {
-        let trait_def_id = self.tcx.hir.local_def_id(item.id);
-        self.for_item(item).with_fcx(|fcx, _| {
-            self.check_where_clauses(fcx, item.span, trait_def_id);
-            vec![]
-        });
-    }
+fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    let trait_def_id = tcx.hir.local_def_id(item.id);
+    for_item(tcx, item).with_fcx(|fcx, _| {
+        check_where_clauses(tcx, fcx, item.span, trait_def_id);
+        vec![]
+    });
+}
 
-    fn check_item_fn(&mut self, item: &hir::Item) {
-        self.for_item(item).with_fcx(|fcx, this| {
-            let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let sig = fcx.tcx.fn_sig(def_id);
-            let sig = fcx.normalize_associated_types_in(item.span, &sig);
-            let mut implied_bounds = vec![];
-            this.check_fn_or_method(fcx, item.span, sig,
-                                    def_id, &mut implied_bounds);
-            implied_bounds
-        })
-    }
+fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    for_item(tcx, item).with_fcx(|fcx, tcx| {
+        let def_id = fcx.tcx.hir.local_def_id(item.id);
+        let sig = fcx.tcx.fn_sig(def_id);
+        let sig = fcx.normalize_associated_types_in(item.span, &sig);
+        let mut implied_bounds = vec![];
+        check_fn_or_method(tcx, fcx, item.span, sig,
+                                def_id, &mut implied_bounds);
+        implied_bounds
+    })
+}
 
-    fn check_item_type(&mut self,
-                       item: &hir::Item)
-    {
-        debug!("check_item_type: {:?}", item);
+fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    item: &hir::Item)
+{
+    debug!("check_item_type: {:?}", item);
 
-        self.for_item(item).with_fcx(|fcx, this| {
-            let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
-            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
+    for_item(tcx, item).with_fcx(|fcx, _this| {
+        let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
+        let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
 
-            fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
+        fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation);
 
-            vec![] // no implied bounds in a const etc
-        });
-    }
+        vec![] // no implied bounds in a const etc
+    });
+}
 
-    fn check_impl(&mut self,
-                  item: &hir::Item,
-                  ast_self_ty: &hir::Ty,
-                  ast_trait_ref: &Option<hir::TraitRef>)
-    {
-        debug!("check_impl: {:?}", item);
-
-        self.for_item(item).with_fcx(|fcx, this| {
-            let item_def_id = fcx.tcx.hir.local_def_id(item.id);
-
-            match *ast_trait_ref {
-                Some(ref ast_trait_ref) => {
-                    let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
-                    let trait_ref =
-                        fcx.normalize_associated_types_in(
-                            ast_trait_ref.path.span, &trait_ref);
-                    let obligations =
-                        ty::wf::trait_obligations(fcx,
-                                                  fcx.param_env,
-                                                  fcx.body_id,
-                                                  &trait_ref,
-                                                  ast_trait_ref.path.span);
-                    for obligation in obligations {
-                        fcx.register_predicate(obligation);
-                    }
-                }
-                None => {
-                    let self_ty = fcx.tcx.type_of(item_def_id);
-                    let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
-                    fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
+fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                item: &hir::Item,
+                ast_self_ty: &hir::Ty,
+                ast_trait_ref: &Option<hir::TraitRef>)
+{
+    debug!("check_impl: {:?}", item);
+
+    for_item(tcx, item).with_fcx(|fcx, tcx| {
+        let item_def_id = fcx.tcx.hir.local_def_id(item.id);
+
+        match *ast_trait_ref {
+            Some(ref ast_trait_ref) => {
+                let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
+                let trait_ref =
+                    fcx.normalize_associated_types_in(
+                        ast_trait_ref.path.span, &trait_ref);
+                let obligations =
+                    ty::wf::trait_obligations(fcx,
+                                                fcx.param_env,
+                                                fcx.body_id,
+                                                &trait_ref,
+                                                ast_trait_ref.path.span);
+                for obligation in obligations {
+                    fcx.register_predicate(obligation);
                 }
             }
+            None => {
+                let self_ty = fcx.tcx.type_of(item_def_id);
+                let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
+                fcx.register_wf_obligation(self_ty, ast_self_ty.span,
+                    ObligationCauseCode::MiscObligation);
+            }
+        }
 
-            this.check_where_clauses(fcx, item.span, item_def_id);
+        check_where_clauses(tcx, fcx, item.span, item_def_id);
 
-            fcx.impl_implied_bounds(item_def_id, item.span)
-        });
-    }
+        fcx.impl_implied_bounds(item_def_id, item.span)
+    });
+}
 
-    /// Checks where clauses and inline bounds that are declared on def_id.
-    fn check_where_clauses<'fcx, 'tcx>(&mut self,
-                                       fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                       span: Span,
-                                       def_id: DefId) {
-        use ty::subst::Subst;
-        use rustc::ty::TypeFoldable;
-
-        let mut predicates = fcx.tcx.predicates_of(def_id);
-        let mut substituted_predicates = Vec::new();
-
-        let generics = self.tcx.generics_of(def_id);
-        let is_our_default = |def: &ty::TypeParameterDef|
-                                def.has_default && def.index >= generics.parent_count() as u32;
-
-        // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
-        // For example this forbids the declaration:
-        // struct Foo<T = Vec<[u32]>> { .. }
-        // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
-        for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
-            let ty = fcx.tcx.type_of(d);
-            // ignore dependent defaults -- that is, where the default of one type
-            // parameter includes another (e.g., <T, U = T>). In those cases, we can't
-            // be sure if it will error or not as user might always specify the other.
-            if !ty.needs_subst() {
-                fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
-            }
+/// Checks where clauses and inline bounds that are declared on def_id.
+fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                                    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                    span: Span,
+                                    def_id: DefId) {
+    use ty::subst::Subst;
+    use rustc::ty::TypeFoldable;
+
+    let mut predicates = fcx.tcx.predicates_of(def_id);
+    let mut substituted_predicates = Vec::new();
+
+    let generics = tcx.generics_of(def_id);
+    let is_our_default = |def: &ty::TypeParameterDef|
+                            def.has_default && def.index >= generics.parent_count() as u32;
+
+    // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
+    // For example this forbids the declaration:
+    // struct Foo<T = Vec<[u32]>> { .. }
+    // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
+    for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
+        let ty = fcx.tcx.type_of(d);
+        // ignore dependent defaults -- that is, where the default of one type
+        // parameter includes another (e.g., <T, U = T>). In those cases, we can't
+        // be sure if it will error or not as user might always specify the other.
+        if !ty.needs_subst() {
+            fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
+                ObligationCauseCode::MiscObligation);
         }
+    }
 
-        // Check that trait predicates are WF when params are substituted by their defaults.
-        // We don't want to overly constrain the predicates that may be written but we want to
-        // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
-        // Therefore we check if a predicate which contains a single type param
-        // with a concrete default is WF with that default substituted.
-        // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
-        //
-        // First we build the defaulted substitution.
-        let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
-                // All regions are identity.
-                fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
-            }, |def, _| {
-                // If the param has a default,
-                if is_our_default(def) {
-                    let default_ty = fcx.tcx.type_of(def.def_id);
-                    // and it's not a dependent default
-                    if !default_ty.needs_subst() {
-                        // then substitute with the default.
-                        return default_ty;
-                    }
+    // Check that trait predicates are WF when params are substituted by their defaults.
+    // We don't want to overly constrain the predicates that may be written but we want to
+    // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
+    // Therefore we check if a predicate which contains a single type param
+    // with a concrete default is WF with that default substituted.
+    // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
+    //
+    // First we build the defaulted substitution.
+    let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
+            // All regions are identity.
+            fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
+        }, |def, _| {
+            // If the param has a default,
+            if is_our_default(def) {
+                let default_ty = fcx.tcx.type_of(def.def_id);
+                // and it's not a dependent default
+                if !default_ty.needs_subst() {
+                    // then substitute with the default.
+                    return default_ty;
                 }
-                // Mark unwanted params as err.
-                fcx.tcx.types.err
-            });
-        // Now we build the substituted predicates.
-        for &pred in predicates.predicates.iter() {
-            struct CountParams { params: FxHashSet<u32> }
-            impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
-                fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-                    match t.sty {
-                        ty::TyParam(p) => {
-                            self.params.insert(p.idx);
-                            t.super_visit_with(self)
-                        }
-                        _ => t.super_visit_with(self)
+            }
+            // Mark unwanted params as err.
+            fcx.tcx.types.err
+        });
+    // Now we build the substituted predicates.
+    for &pred in predicates.predicates.iter() {
+        struct CountParams { params: FxHashSet<u32> }
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                match t.sty {
+                    ty::TyParam(p) => {
+                        self.params.insert(p.idx);
+                        t.super_visit_with(self)
                     }
+                    _ => t.super_visit_with(self)
                 }
             }
-            let mut param_count = CountParams { params: FxHashSet() };
-            pred.visit_with(&mut param_count);
-            let substituted_pred = pred.subst(fcx.tcx, substs);
-            // Don't check non-defaulted params, dependent defaults or preds with multiple params.
-            if substituted_pred.references_error() || param_count.params.len() > 1 {
-                continue;
-            }
-            // Avoid duplication of predicates that contain no parameters, for example.
-            if !predicates.predicates.contains(&substituted_pred) {
-                substituted_predicates.push(substituted_pred);
-            }
         }
-
-        predicates.predicates.extend(substituted_predicates);
-        let predicates = predicates.instantiate_identity(fcx.tcx);
-        let predicates = fcx.normalize_associated_types_in(span, &predicates);
-
-        let obligations =
-            predicates.predicates
-                      .iter()
-                      .flat_map(|p| ty::wf::predicate_obligations(fcx,
-                                                                  fcx.param_env,
-                                                                  fcx.body_id,
-                                                                  p,
-                                                                  span));
-
-        for obligation in obligations {
-            fcx.register_predicate(obligation);
+        let mut param_count = CountParams { params: FxHashSet() };
+        pred.visit_with(&mut param_count);
+        let substituted_pred = pred.subst(fcx.tcx, substs);
+        // Don't check non-defaulted params, dependent defaults or preds with multiple params.
+        if substituted_pred.references_error() || param_count.params.len() > 1 {
+            continue;
+        }
+        // Avoid duplication of predicates that contain no parameters, for example.
+        if !predicates.predicates.contains(&substituted_pred) {
+            substituted_predicates.push(substituted_pred);
         }
     }
 
-    fn check_fn_or_method<'fcx, 'tcx>(&mut self,
-                                      fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                      span: Span,
-                                      sig: ty::PolyFnSig<'tcx>,
-                                      def_id: DefId,
-                                      implied_bounds: &mut Vec<Ty<'tcx>>)
-    {
-        let sig = fcx.normalize_associated_types_in(span, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
-
-        for input_ty in sig.inputs() {
-            fcx.register_wf_obligation(&input_ty, span, self.code.clone());
-        }
-        implied_bounds.extend(sig.inputs());
+    predicates.predicates.extend(substituted_predicates);
+    let predicates = predicates.instantiate_identity(fcx.tcx);
+    let predicates = fcx.normalize_associated_types_in(span, &predicates);
+
+    let obligations =
+        predicates.predicates
+                    .iter()
+                    .flat_map(|p| ty::wf::predicate_obligations(fcx,
+                                                                fcx.param_env,
+                                                                fcx.body_id,
+                                                                p,
+                                                                span));
+
+    for obligation in obligations {
+        fcx.register_predicate(obligation);
+    }
+}
 
-        fcx.register_wf_obligation(sig.output(), span, self.code.clone());
+fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                                    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                    span: Span,
+                                    sig: ty::PolyFnSig<'tcx>,
+                                    def_id: DefId,
+                                    implied_bounds: &mut Vec<Ty<'tcx>>)
+{
+    let sig = fcx.normalize_associated_types_in(span, &sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
+
+    for input_ty in sig.inputs() {
+        fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation);
+    }
+    implied_bounds.extend(sig.inputs());
 
-        // FIXME(#25759) return types should not be implied bounds
-        implied_bounds.push(sig.output());
+    fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation);
 
-        self.check_where_clauses(fcx, span, def_id);
-    }
+    // FIXME(#25759) return types should not be implied bounds
+    implied_bounds.push(sig.output());
 
-    fn check_method_receiver<'fcx, 'tcx>(&mut self,
-                                         fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                         method_sig: &hir::MethodSig,
-                                         method: &ty::AssociatedItem,
-                                         self_ty: Ty<'tcx>)
-    {
-        // check that the method has a valid receiver type, given the type `Self`
-        debug!("check_method_receiver({:?}, self_ty={:?})",
-               method, self_ty);
+    check_where_clauses(tcx, fcx, span, def_id);
+}
 
-        if !method.method_has_self_argument {
-            return;
-        }
+fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                           method_sig: &hir::MethodSig,
+                                           method: &ty::AssociatedItem,
+                                           self_ty: Ty<'tcx>)
+{
+    // check that the method has a valid receiver type, given the type `Self`
+    debug!("check_method_receiver({:?}, self_ty={:?})",
+            method, self_ty);
+
+    if !method.method_has_self_argument {
+        return;
+    }
 
-        let span = method_sig.decl.inputs[0].span;
+    let span = method_sig.decl.inputs[0].span;
 
-        let sig = fcx.tcx.fn_sig(method.def_id);
-        let sig = fcx.normalize_associated_types_in(span, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig);
+    let sig = fcx.tcx.fn_sig(method.def_id);
+    let sig = fcx.normalize_associated_types_in(span, &sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig);
 
-        debug!("check_method_receiver: sig={:?}", sig);
+    debug!("check_method_receiver: sig={:?}", sig);
 
-        let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
-        let self_ty = fcx.tcx.liberate_late_bound_regions(
-            method.def_id,
-            &ty::Binder(self_ty)
-        );
+    let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
+    let self_ty = fcx.tcx.liberate_late_bound_regions(
+        method.def_id,
+        &ty::Binder(self_ty)
+    );
 
-        let self_arg_ty = sig.inputs()[0];
+    let self_arg_ty = sig.inputs()[0];
 
-        let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
-        let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
-        let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
-            method.def_id,
-            &ty::Binder(self_arg_ty)
-        );
+    let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
+    let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
+    let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
+        method.def_id,
+        &ty::Binder(self_arg_ty)
+    );
 
-        let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
+    let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
 
-        loop {
-            if let Some((potential_self_ty, _)) = autoderef.next() {
-                debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
-                    potential_self_ty, self_ty);
+    loop {
+        if let Some((potential_self_ty, _)) = autoderef.next() {
+            debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
+                potential_self_ty, self_ty);
 
-                if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
-                    autoderef.finalize();
-                    if let Some(mut err) = fcx.demand_eqtype_with_origin(
-                        &cause, self_ty, potential_self_ty) {
-                        err.emit();
-                    }
-                    break
+            if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
+                autoderef.finalize();
+                if let Some(mut err) = fcx.demand_eqtype_with_origin(
+                    &cause, self_ty, potential_self_ty) {
+                    err.emit();
                 }
-            } else {
-                fcx.tcx.sess.diagnostic().mut_span_err(
-                    span, &format!("invalid `self` type: {:?}", self_arg_ty))
-                .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
-                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                .code(DiagnosticId::Error("E0307".into()))
-                .emit();
-                return
+                break
             }
+        } else {
+            fcx.tcx.sess.diagnostic().mut_span_err(
+                span, &format!("invalid `self` type: {:?}", self_arg_ty))
+            .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
+            .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+            .code(DiagnosticId::Error("E0307".into()))
+            .emit();
+            return
         }
+    }
 
-        let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
-        let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
-
-        if !fcx.tcx.features().arbitrary_self_types {
-            match self_kind {
-                ExplicitSelf::ByValue |
-                ExplicitSelf::ByReference(_, _) |
-                ExplicitSelf::ByBox => (),
-
-                ExplicitSelf::ByRawPointer(_) => {
-                    feature_gate::feature_err(
-                        &fcx.tcx.sess.parse_sess,
-                        "arbitrary_self_types",
-                        span,
-                        GateIssue::Language,
-                        "raw pointer `self` is unstable")
-                    .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                    .emit();
-                }
+    let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
+    let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
+
+    if !fcx.tcx.features().arbitrary_self_types {
+        match self_kind {
+            ExplicitSelf::ByValue |
+            ExplicitSelf::ByReference(_, _) |
+            ExplicitSelf::ByBox => (),
+
+            ExplicitSelf::ByRawPointer(_) => {
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,
+                    "raw pointer `self` is unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
+            }
 
-                ExplicitSelf::Other => {
-                    feature_gate::feature_err(
-                        &fcx.tcx.sess.parse_sess,
-                        "arbitrary_self_types",
-                        span,
-                        GateIssue::Language,"arbitrary `self` types are unstable")
-                    .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                    .emit();
-                }
+            ExplicitSelf::Other => {
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,"arbitrary `self` types are unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
             }
         }
     }
+}
 
-    fn check_variances_for_type_defn(&self,
-                                     item: &hir::Item,
-                                     ast_generics: &hir::Generics)
-    {
-        let item_def_id = self.tcx.hir.local_def_id(item.id);
-        let ty = self.tcx.type_of(item_def_id);
-        if self.tcx.has_error_field(ty) {
-            return;
-        }
-
-        let ty_predicates = self.tcx.predicates_of(item_def_id);
-        assert_eq!(ty_predicates.parent, None);
-        let variances = self.tcx.variances_of(item_def_id);
+fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                    item: &hir::Item,
+                                    ast_generics: &hir::Generics)
+{
+    let item_def_id = tcx.hir.local_def_id(item.id);
+    let ty = tcx.type_of(item_def_id);
+    if tcx.has_error_field(ty) {
+        return;
+    }
 
-        let mut constrained_parameters: FxHashSet<_> =
-            variances.iter().enumerate()
-                     .filter(|&(_, &variance)| variance != ty::Bivariant)
-                     .map(|(index, _)| Parameter(index as u32))
-                     .collect();
+    let ty_predicates = tcx.predicates_of(item_def_id);
+    assert_eq!(ty_predicates.parent, None);
+    let variances = tcx.variances_of(item_def_id);
 
-        identify_constrained_type_params(self.tcx,
-                                         ty_predicates.predicates.as_slice(),
-                                         None,
-                                         &mut constrained_parameters);
+    let mut constrained_parameters: FxHashSet<_> =
+        variances.iter().enumerate()
+                    .filter(|&(_, &variance)| variance != ty::Bivariant)
+                    .map(|(index, _)| Parameter(index as u32))
+                    .collect();
 
-        for (index, _) in variances.iter().enumerate() {
-            if constrained_parameters.contains(&Parameter(index as u32)) {
-                continue;
-            }
+    identify_constrained_type_params(tcx,
+                                        ty_predicates.predicates.as_slice(),
+                                        None,
+                                        &mut constrained_parameters);
 
-            let (span, name) = match ast_generics.params[index] {
-                hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
-                hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
-            };
-            self.report_bivariance(span, name);
+    for (index, _) in variances.iter().enumerate() {
+        if constrained_parameters.contains(&Parameter(index as u32)) {
+            continue;
         }
+
+        let (span, name) = match ast_generics.params[index] {
+            hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
+            hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
+        };
+        report_bivariance(tcx, span, name);
     }
+}
 
-    fn report_bivariance(&self,
-                         span: Span,
-                         param_name: ast::Name)
-    {
-        let mut err = error_392(self.tcx, span, param_name);
-
-        let suggested_marker_id = self.tcx.lang_items().phantom_data();
-        match suggested_marker_id {
-            Some(def_id) => {
-                err.help(
-                    &format!("consider removing `{}` or using a marker such as `{}`",
-                             param_name,
-                             self.tcx.item_path_str(def_id)));
-            }
-            None => {
-                // no lang items, no help!
-            }
+fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        span: Span,
+                        param_name: ast::Name)
+{
+    let mut err = error_392(tcx, span, param_name);
+
+    let suggested_marker_id = tcx.lang_items().phantom_data();
+    match suggested_marker_id {
+        Some(def_id) => {
+            err.help(
+                &format!("consider removing `{}` or using a marker such as `{}`",
+                            param_name,
+                            tcx.item_path_str(def_id)));
+        }
+        None => {
+            // no lang items, no help!
         }
-        err.emit();
     }
+    err.emit();
 }
 
 fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
@@ -648,6 +654,19 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
     }
 }
 
+pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
+               -> CheckTypeWellFormedVisitor<'a, 'gcx> {
+        CheckTypeWellFormedVisitor {
+            tcx,
+        }
+    }
+}
+
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
         NestedVisitorMap::None
@@ -655,27 +674,22 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
 
     fn visit_item(&mut self, i: &hir::Item) {
         debug!("visit_item: {:?}", i);
-        self.check_item_well_formed(i);
+        let def_id = self.tcx.hir.local_def_id(i.id);
+        ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_item(self, i);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
-        let method_sig = match trait_item.node {
-            hir::TraitItemKind::Method(ref sig, _) => Some(sig),
-            _ => None
-        };
-        self.check_associated_item(trait_item.id, trait_item.span, method_sig);
+        let def_id = self.tcx.hir.local_def_id(trait_item.id);
+        ty::maps::queries::check_trait_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_trait_item(self, trait_item)
     }
 
     fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
-        let method_sig = match impl_item.node {
-            hir::ImplItemKind::Method(ref sig, _) => Some(sig),
-            _ => None
-        };
-        self.check_associated_item(impl_item.id, impl_item.span, method_sig);
+        let def_id = self.tcx.hir.local_def_id(impl_item.id);
+        ty::maps::queries::check_impl_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
index a17b35dec42d7c2f75683b7ec789a3ee6adf0a66..6f24d06844bb4c124ed600787acfe1ec7459e949 100644 (file)
@@ -35,8 +35,9 @@
 use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::IntTypeExt;
-use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::ty::util::Discr;
+use rustc::util::captures::Captures;
+use rustc::util::nodemap::{FxHashSet, FxHashMap};
 
 use syntax::{abi, ast};
 use syntax::ast::MetaItemKind;
@@ -1281,7 +1282,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
 fn early_bound_lifetimes_from_generics<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ast_generics: &'a hir::Generics)
-    -> impl Iterator<Item=&'a hir::LifetimeDef>
+    -> impl Iterator<Item=&'a hir::LifetimeDef> + Captures<'tcx>
 {
     ast_generics
         .lifetimes()
index 5cac2d1bbe7eeb1e0a5e55b1a26a218b1ed8df00..c228f54217d34c7f583dff93ef4744cf867d942d 100644 (file)
@@ -138,7 +138,7 @@ fn is_all(&self) -> bool {
 
     /// Renders the configuration for human display, as a short HTML description.
     pub(crate) fn render_short_html(&self) -> String {
-        let mut msg = Html(self).to_string();
+        let mut msg = ShortHtml(self).to_string();
         if self.should_capitalize_first_letter() {
             if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
                 msg[i .. i+1].make_ascii_uppercase();
@@ -149,7 +149,13 @@ pub(crate) fn render_short_html(&self) -> String {
 
     /// Renders the configuration for long display, as a long HTML description.
     pub(crate) fn render_long_html(&self) -> String {
-        let mut msg = format!("This is supported on <strong>{}</strong>", Html(self));
+        let on = if self.should_use_with_in_description() {
+            "with"
+        } else {
+            "on"
+        };
+
+        let mut msg = format!("This is supported {} <strong>{}</strong>", on, Html(self));
         if self.should_append_only_to_description() {
             msg.push_str(" only");
         }
@@ -180,6 +186,13 @@ fn should_append_only_to_description(&self) -> bool {
             }
         }
     }
+
+    fn should_use_with_in_description(&self) -> bool {
+        match *self {
+            Cfg::Cfg(ref name, _) if name == &"target_feature" => true,
+            _ => false,
+        }
+    }
 }
 
 impl ops::Not for Cfg {
@@ -376,6 +389,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                     },
                     ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
                     ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
+                    ("target_feature", Some(feat)) =>
+                        return write!(fmt, "target feature <code>{}</code>", feat),
                     _ => "",
                 };
                 if !human_readable.is_empty() {
@@ -390,6 +405,19 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+struct ShortHtml<'a>(&'a Cfg);
+
+impl<'a> fmt::Display for ShortHtml<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match *self.0 {
+            Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => {
+                write!(fmt, "<code>{}</code>", vendor)
+            },
+            ref cfg => write!(fmt, "{}", Html(cfg)),
+        }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::Cfg;
@@ -824,6 +852,10 @@ fn test_render_short_html() {
                 ).render_short_html(),
                 "(Debug-assertions enabled or Windows) and Unix"
             );
+            assert_eq!(
+                name_value_cfg("target_feature", "sse2").render_short_html(),
+                "<code>sse2</code>"
+            );
         })
     }
 
@@ -898,6 +930,10 @@ fn test_render_long_html() {
                 "This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
                 </strong> only."
             );
+            assert_eq!(
+                name_value_cfg("target_feature", "sse2").render_long_html(),
+                "This is supported with <strong>target feature <code>sse2</code></strong> only."
+            );
         })
     }
 }
index 904c24815cb7f3d4c36b033a044f087e66c9901e..1a42b02140cd27b04b0a1626343af235522a3547 100644 (file)
@@ -828,6 +828,19 @@ pub fn from_ast(diagnostic: &::errors::Handler,
             })
         }).collect();
 
+        // treat #[target_feature(enable = "feat")] attributes as if they were
+        // #[doc(cfg(target_feature = "feat"))] attributes as well
+        for attr in attrs.lists("target_feature") {
+            if attr.check_name("enable") {
+                if let Some(feat) = attr.value_str() {
+                    let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
+                    if let Ok(feat_cfg) = Cfg::parse(&meta) {
+                        cfg &= feat_cfg;
+                    }
+                }
+            }
+        }
+
         Attributes {
             doc_strings,
             other_attrs,
@@ -929,7 +942,7 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
                       select the {}",
                       disambig1, kind1, disambig2,
                       kind2))
-             .emit();
+      .emit();
 }
 
 /// Given an enum variant's def, return the def of its enum and the associated fragment
@@ -1074,6 +1087,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
     }
 }
 
+#[derive(Debug)]
 enum PathKind {
     /// can be either value or type, not a macro
     Unknown,
@@ -1082,7 +1096,7 @@ enum PathKind {
     /// values, functions, consts, statics, everything in the value namespace
     Value,
     /// types, traits, everything in the type namespace
-    Type
+    Type,
 }
 
 impl Clean<Attributes> for [ast::Attribute] {
@@ -1091,12 +1105,13 @@ fn clean(&self, cx: &DocContext) -> Attributes {
 
         if UnstableFeatures::from_environment().is_nightly_build() {
             let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
-            for link in markdown_links(&dox) {
+            for ori_link in markdown_links(&dox) {
                 // bail early for real links
-                if link.contains('/') {
+                if ori_link.contains('/') {
                     continue;
                 }
-                let (def, fragment)  = {
+                let link = ori_link.replace("`", "");
+                let (def, fragment) = {
                     let mut kind = PathKind::Unknown;
                     let path_str = if let Some(prefix) =
                         ["struct@", "enum@", "type@",
@@ -1132,7 +1147,6 @@ fn clean(&self, cx: &DocContext) -> Attributes {
                         continue;
                     }
 
-
                     match kind {
                         PathKind::Value => {
                             if let Ok(def) = resolve(cx, path_str, true) {
@@ -1206,9 +1220,8 @@ fn clean(&self, cx: &DocContext) -> Attributes {
                     }
                 };
 
-
                 let id = register_def(cx, def);
-                attrs.links.push((link, id, fragment));
+                attrs.links.push((ori_link, id, fragment));
             }
 
             cx.sess().abort_if_errors();
index 5e55353a26e6b49fe9a692a7ea61c23b3dfea59e..c09bd4cc84ae5222714bf7bb514a38d10c4998ec 100644 (file)
@@ -27,6 +27,7 @@
 
 #![allow(non_camel_case_types)]
 
+use rustc::session;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
@@ -232,14 +233,14 @@ fn dont_escape(c: u8) -> bool {
 /// Make headings links with anchor ids and build up TOC.
 struct LinkReplacer<'a, 'b, I: Iterator<Item = Event<'a>>> {
     inner: I,
-    links: &'b [(String, String)]
+    links: &'b [(String, String)],
 }
 
 impl<'a, 'b, I: Iterator<Item = Event<'a>>> LinkReplacer<'a, 'b, I> {
     fn new(iter: I, links: &'b [(String, String)]) -> Self {
         LinkReplacer {
             inner: iter,
-            links
+            links,
         }
     }
 }
@@ -434,7 +435,8 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
+                          sess: Option<&session::Session>) {
     tests.set_position(position);
 
     let mut parser = Parser::new(doc);
@@ -484,6 +486,9 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                                    line, filename, block_info.allow_fail);
                     prev_offset = offset;
                 } else {
+                    if let Some(ref sess) = sess {
+                        sess.span_warn(position, "invalid start of a new code block");
+                    }
                     break;
                 }
             }
index 0f107457d2bf88815927dbc36de0bfc679da5948..3a55b279b5cc701914f4330513a1b53320976c65 100644 (file)
@@ -152,7 +152,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(PathBuf::from(input)),
                                        linker);
-    find_testable_code(&input_str, &mut collector, DUMMY_SP);
+    find_testable_code(&input_str, &mut collector, DUMMY_SP, None);
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests,
                        testing::Options::new().display_output(display_warnings));
index 117b21d47587f830121b43e9c2ff46b375b1dce3..3ce8bd4ebb4c1002f70e891ff7cd78930f6c924a 100644 (file)
@@ -416,6 +416,7 @@ fn partition_source(s: &str) -> (String, String) {
         let trimline = line.trim();
         let header = trimline.is_whitespace() ||
             trimline.starts_with("#![") ||
+            trimline.starts_with("#[macro_use] extern crate") ||
             trimline.starts_with("extern crate");
         if !header || after_header {
             after_header = true;
@@ -645,8 +646,10 @@ fn visit_testable<F: FnOnce(&mut Self)>(&mut self,
         // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us
         if let Some(doc) = attrs.collapsed_doc_value() {
-            markdown::find_testable_code(&doc, self.collector,
-                                         attrs.span.unwrap_or(DUMMY_SP));
+            markdown::find_testable_code(&doc,
+                                         self.collector,
+                                         attrs.span.unwrap_or(DUMMY_SP),
+                                         Some(self.sess));
         }
 
         nested(self);
@@ -825,6 +828,24 @@ fn main() {
         assert_eq!(output, (expected, 2));
     }
 
+    #[test]
+    fn make_test_manual_extern_crate_with_macro_use() {
+        let opts = TestOptions::default();
+        let input =
+"#[macro_use] extern crate asdf;
+use asdf::qwop;
+assert_eq!(2+2, 4);";
+        let expected =
+"#![allow(unused)]
+#[macro_use] extern crate asdf;
+fn main() {
+use asdf::qwop;
+assert_eq!(2+2, 4);
+}".to_string();
+        let output = make_test(input, Some("asdf"), false, &opts);
+        assert_eq!(output, (expected, 2));
+    }
+
     #[test]
     fn make_test_opts_attrs() {
         //if you supplied some doctest attributes with #![doc(test(attr(...)))], it will use those
index 0837ff91c142d658aa5b68c967c3bdb20a9e9dce..6472edb0aa7d3981c8629d98185955c0244f1d89 100644 (file)
@@ -52,6 +52,7 @@
 ///
 /// [combining character]: https://en.wikipedia.org/wiki/Combining_character
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
 pub trait AsciiExt {
     /// Container type for copied ASCII characters.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -84,6 +85,7 @@ pub trait AsciiExt {
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_uppercase(&self) -> Self::Owned;
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -104,6 +106,7 @@ pub trait AsciiExt {
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_lowercase(&self) -> Self::Owned;
 
     /// Checks that two values are an ASCII case-insensitive match.
@@ -162,6 +165,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII uppercase character:
@@ -174,6 +178,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII lowercase character:
@@ -186,6 +191,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII alphanumeric character:
@@ -199,6 +205,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII decimal digit:
@@ -211,6 +218,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII hexadecimal digit:
@@ -224,6 +232,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII punctuation character:
@@ -241,6 +250,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII graphic character:
@@ -253,6 +263,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII whitespace character:
@@ -282,6 +293,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII control character:
@@ -294,6 +306,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
@@ -354,6 +367,7 @@ fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for u8 {
     type Owned = u8;
 
@@ -362,6 +376,7 @@ impl AsciiExt for u8 {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for char {
     type Owned = char;
 
@@ -370,6 +385,7 @@ impl AsciiExt for char {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
 
@@ -427,6 +443,7 @@ fn is_ascii_control(&self) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for str {
     type Owned = String;
 
index f8dbe193fed27133df5c0f4ac76556affa768e55..79bb6af168fa022d4113c432c10c5757ac759159 100644 (file)
@@ -56,7 +56,6 @@
 use borrow::Cow;
 use cell;
 use char;
-use convert;
 use core::array;
 use fmt::{self, Debug, Display};
 use mem::transmute;
@@ -371,14 +370,6 @@ fn description(&self) -> &str {
     }
 }
 
-#[unstable(feature = "try_from", issue = "33417")]
-impl Error for convert::Infallible {
-    fn description(&self) -> &str {
-        match *self {
-        }
-    }
-}
-
 // copied from any.rs
 impl Error + 'static {
     /// Returns true if the boxed type is the same as `T`
index a2c133954a3279695e3249cee369bcfdf3561c96..33d7053852246a9bf4c63d02d94682f989f888ba 100644 (file)
@@ -169,7 +169,6 @@ fn $test_name() {
 
     macro_rules! test_checked_next_power_of_two {
         ($test_name:ident, $T:ident) => (
-            #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119)
             fn $test_name() {
                 #![test]
                 assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
index f1ab9c4760965e38efcf59dbb4b98ebd603dcca9..afa8e3e1369354f370d5cbf5442b09dd2f3ef53b 100644 (file)
@@ -10,7 +10,6 @@
 
 #![unstable(feature = "process_internals", issue = "0")]
 
-use ascii::AsciiExt;
 use collections::BTreeMap;
 use env::split_paths;
 use env;
index 9fff8b91f96f32f155f8f9378e515e785ee56b1e..78b2bb5fe6e2f9213f1886922e8d7e19f0c2edae 100644 (file)
@@ -27,7 +27,6 @@
 
 use core::str::next_code_point;
 
-use ascii::*;
 use borrow::Cow;
 use char;
 use fmt;
@@ -871,24 +870,22 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
-impl AsciiExt for Wtf8 {
-    type Owned = Wtf8Buf;
-
-    fn is_ascii(&self) -> bool {
+impl Wtf8 {
+    pub fn is_ascii(&self) -> bool {
         self.bytes.is_ascii()
     }
-    fn to_ascii_uppercase(&self) -> Wtf8Buf {
+    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
         Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
     }
-    fn to_ascii_lowercase(&self) -> Wtf8Buf {
+    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
         Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
     }
-    fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
+    pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
         self.bytes.eq_ignore_ascii_case(&other.bytes)
     }
 
-    fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
-    fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
+    pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
+    pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
 }
 
 #[cfg(test)]
index f7e5d40b52468821e79a28e324a01cdd866fdb1f..202dc03eaa41d511452cb28880e194460d610dc9 100644 (file)
@@ -298,7 +298,6 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
     debug!("parse_str_lit: given {}", escape_default(lit));
     let mut res = String::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
@@ -503,7 +502,6 @@ pub fn byte_lit(lit: &str) -> (u8, usize) {
 pub fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
     let mut res = Vec::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
index 9edfa767d31958df8c0ff07e7850c49708c072b0..5264b627e96137b0b933adce4c3bdcab30115ae5 100644 (file)
@@ -628,8 +628,15 @@ fn path_node(ids: Vec<Ident>) -> ast::Path {
 }
 
 fn path_name_i(idents: &[Ident]) -> String {
-    // FIXME: Bad copies (#2543 -- same for everything else that says "bad")
-    idents.iter().map(|i| i.to_string()).collect::<Vec<String>>().join("::")
+    let mut path_name = "".to_string();
+    let mut idents_iter = idents.iter().peekable();
+    while let Some(ident) = idents_iter.next() {
+        path_name.push_str(&ident.name.as_str());
+        if let Some(_) = idents_iter.peek() {
+            path_name.push_str("::")
+        }
+    }
+    path_name
 }
 
 fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
@@ -682,7 +689,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // gensym information.
 
     let span = ignored_span(cx, test.span);
-    let path = test.path.clone();
     let ecx = &cx.ext_cx;
     let self_id = ecx.ident_of("self");
     let test_id = ecx.ident_of("test");
@@ -694,10 +700,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // creates $name: $expr
     let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
 
-    debug!("encoding {}", path_name_i(&path[..]));
-
     // path to the #[test] function: "foo::bar::baz"
-    let path_string = path_name_i(&path[..]);
+    let path_string = path_name_i(&test.path[..]);
+
+    debug!("encoding {}", path_string);
+
     let name_expr = ecx.expr_str(span, Symbol::intern(&path_string));
 
     // self::test::StaticTestName($name_expr)
@@ -744,7 +751,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             diag.bug("expected to find top-level re-export name, but found None");
         }
     };
-    visible_path.extend(path);
+    visible_path.extend_from_slice(&test.path[..]);
 
     // Rather than directly give the test function to the test
     // harness, we create a wrapper like one of the following:
index ab9356f2af650815d339d77306f0d09c44d531ad..bcb720e55861c38db47f2ebdf26b7198338cb39d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ab9356f2af650815d339d77306f0d09c44d531ad
+Subproject commit bcb720e55861c38db47f2ebdf26b7198338cb39d
index 707531bf376a7e870e353a757a66ee214db04b06..367d509cadfe3755e38ad0f17a79bbe3dfc80b3f 100644 (file)
@@ -19,6 +19,7 @@
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
+// ignore-powerpc64
 // ignore-s390x
 // ignore-sparc
 // ignore-wasm32
index 9bfe47d0a1f28b67fb5387ddb5e3ac7251a3dcce..d6dd3f356b5fe7b363d4799ab2f6c7eb75f45fb8 100644 (file)
@@ -23,6 +23,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index 94b69a6cab58344ab4e0d944edb7fc05f201f587..6b79e79fa0080df6e56c9c97fc9e60186e6ab24b 100644 (file)
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index c3688077f221bb479a742a3c7434bdbc8feabaa7..3f73a1cabbf19630d0e2a583af34ca75860bafbb 100644 (file)
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index 3b8fe43fa048a98819d817e6994f365281c23362..3e118a50d454e10dc0642dff7ce357e9afa250d9 100644 (file)
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index 655e67cf7eefe543a230a2089b4dabf9c55138ad..2eeed2b788ce2f68154dfa32243aa51bc7a6fc2a 100644 (file)
@@ -14,6 +14,7 @@
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
+// ignore-powerpc64
 // See repr-transparent.rs
 
 #![crate_type="lib"]
index 405864aba94365fb85c895a2665553d58978c092..d621cdb4d58f8c89d5f3791f581963cca37f624d 100644 (file)
@@ -36,7 +36,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //    let _2: &'21_1rs D;
 //    ...
 //    let mut _3: ();
-//    let mut _4: [closure@NodeId(22) r:&'21_1rs D];
+//    let mut _4: [closure@NodeId(22) r:&'19s D];
 //    let mut _5: &'21_1rs D;
 //    bb0: {
 //        StorageLive(_1);
@@ -54,6 +54,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //        resume;
 //    }
 //    bb2: {
+//        EndRegion('19s);
 //        StorageDead(_4);
 //        _0 = ();
 //        EndRegion('21_1rs);
@@ -61,6 +62,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //        drop(_1) -> [return: bb4, unwind: bb1];
 //    }
 //    bb3: {
+//        EndRegion('19s);
 //        EndRegion('21_1rs);
 //        drop(_1) -> bb1;
 //    }
@@ -72,7 +74,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 // END rustc.main.SimplifyCfg-qualify-consts.after.mir
 
 // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'21_1rs D]) -> i32 {
+// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'19s D]) -> i32 {
 //     let mut _0: i32;
 //     let mut _2: i32;
 //
index d9103e1992735eda23ea2bfeeeb7984996f20edd..af1707de6c02f52432cfc241cca0df4f9e06ad70 100644 (file)
@@ -9,7 +9,7 @@ RUSTC_ORIGINAL := $(RUSTC)
 BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)'
 BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)'
 RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS)
-RUSTDOC := $(BARE_RUSTDOC)
+RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR)
 ifdef RUSTC_LINKER
 RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER)
 RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options
index eb2177202a22b526240471c39bec9acfd6e0109c..d3ba477fa573e7ca9937253deb520ac8f0adcc72 100644 (file)
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-use std::ascii::AsciiExt;
-
 static NAME: &'static str = "hello world";
 
 fn main() {
index 3f7d0400c884e953d67835ccd91dc74005cd7457..29a5f6dd24bd0c0f874fc32fb33c9461e33b25b0 100644 (file)
@@ -10,7 +10,6 @@
 
 // Test that a field can have the same name in different variants
 // of an enum
-// FIXME #27889
 
 pub enum Foo {
     X { foo: u32 },
index 8c73830f4d7788bb173162eff80521ecab74e851..e21e487fedd1c81d5618a491e3530b3a75f99907 100644 (file)
@@ -45,7 +45,7 @@ struct Array<T> {
     f32: [T; 32],
 }
 
-// FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone`
+// FIXME(#44580): merge with `Array` once `[T; N]: Clone` where `T: Clone`
 #[derive(Clone, Copy)]
 struct CopyArray<T: Copy> {
     f00: [T; 00],
diff --git a/src/test/rustdoc/check-styled-link.rs b/src/test/rustdoc/check-styled-link.rs
new file mode 100644 (file)
index 0000000..1633711
--- /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.
+
+#![crate_name = "foo"]
+
+pub struct Foo;
+
+// @has foo/struct.Bar.html '//a[@href="../foo/struct.Foo.html"]' 'Foo'
+
+/// Code-styled reference to [`Foo`].
+pub struct Bar;
index 8499e5c741ee043e0225f5025af6ea88578bf114..ea8a13b034beb244eaf4a716864f1317ec70f07d 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(doc_cfg)]
+#![feature(target_feature, cfg_target_feature)]
 
 // @has doc_cfg/struct.Portable.html
 // @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
@@ -45,3 +46,26 @@ impl ArmOnly for super::Portable {
         fn unix_and_arm_only_function() {}
     }
 }
+
+// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
+// item as well
+
+// the portability header is different on the module view versus the full view
+// @has doc_cfg/index.html
+// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+
+// @has doc_cfg/fn.uses_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+//        'This is supported with target feature avx only.'
+#[target_feature(enable = "avx")]
+pub unsafe fn uses_target_feature() {
+    content::should::be::irrelevant();
+}
+
+// @has doc_cfg/fn.uses_cfg_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+//        'This is supported with target feature avx only.'
+#[doc(cfg(target_feature = "avx"))]
+pub fn uses_cfg_target_feature() {
+    uses_target_feature();
+}
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
new file mode 100644 (file)
index 0000000..010cb77
--- /dev/null
@@ -0,0 +1,22 @@
+// 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(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+trait Foo<S, T, U> {
+    fn s(S) -> S;
+    fn t(T) -> T;
+    fn u(U) -> U;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr
new file mode 100644 (file)
index 0000000..6da1e2f
--- /dev/null
@@ -0,0 +1,8 @@
+error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index cd83915fe82d30bba1c2fc4bd320ce0b469a7e86..dd78baf9275098266074f7a73cae1043dfa1ad87 100644 (file)
@@ -1,15 +1,15 @@
-error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
   --> $DIR/auto-trait-regions.rs:40:5
    |
 LL |     assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
-   |     ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
+   |     ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
    |
    = help: the following implementations were found:
              <No as Foo>
    = note: required because it appears within the type `OnlyFooIfStaticRef`
    = note: required because it appears within the type `&OnlyFooIfStaticRef`
    = note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}`
-   = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+   = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
 note: required by `assert_foo`
   --> $DIR/auto-trait-regions.rs:30:1
    |
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs
new file mode 100644 (file)
index 0000000..f554efe
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+fn foo(x: &'x u32) -> impl Fn() -> &'y u32
+where 'x: 'y
+{
+    move || x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs
new file mode 100644 (file)
index 0000000..416bdae
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+trait Trait<'a> { }
+
+impl Trait<'b> for &'a u32 { }
+
+fn foo(x: &'x u32) -> impl Trait<'y>
+where 'x: 'y
+{
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs
new file mode 100644 (file)
index 0000000..38c18ce
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do not allow the region `'x` to escape in the impl
+// trait **even though** `'y` escapes, which outlives `'x`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl Trait<'b> for Cell<&'a u32> { }
+
+fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909]
+where 'x: 'y
+{
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr
new file mode 100644 (file)
index 0000000..5659fee
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0909]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/region-escape-via-bound.rs:27:29
+   |
+LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+   |                             ^^^^^^^^^^^^^^
+   |
+note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 27:1
+  --> $DIR/region-escape-via-bound.rs:27:1
+   |
+LL | / fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+LL | |     //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909]
+LL | | where 'x: 'y
+LL | | {
+LL | |     x
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0909`.
diff --git a/src/test/ui/type-dependent-def-issue-49241.rs b/src/test/ui/type-dependent-def-issue-49241.rs
new file mode 100644 (file)
index 0000000..6426499
--- /dev/null
@@ -0,0 +1,15 @@
+// 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() {
+    let v = vec![0];
+    const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
+    let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
+}
diff --git a/src/test/ui/type-dependent-def-issue-49241.stderr b/src/test/ui/type-dependent-def-issue-49241.stderr
new file mode 100644 (file)
index 0000000..f00edcc
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/type-dependent-def-issue-49241.rs:13:22
+   |
+LL |     const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
+   |                      ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0080]: constant evaluation error
+  --> $DIR/type-dependent-def-issue-49241.rs:14:18
+   |
+LL |     let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
+   |                  ^ encountered constants with type errors, stopping evaluation
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0080, E0434.
+For more information about an error, try `rustc --explain E0080`.
index 953a13a3f582035a45ced2040dd2d03292635043..43220af4893bbcd97efb776f6af9961e68c4f9a0 100644 (file)
@@ -1324,6 +1324,8 @@ fn document(&self, out_dir: &Path) -> ProcRes {
         let mut rustdoc = Command::new(rustdoc_path);
 
         rustdoc
+            .arg("-L")
+            .arg(self.config.run_lib_path.to_str().unwrap())
             .arg("-L")
             .arg(aux_dir)
             .arg("-o")
@@ -2358,11 +2360,6 @@ fn incremental_dir(&self) -> PathBuf {
     }
 
     fn run_rmake_test(&self) {
-        // FIXME(#11094): we should fix these tests
-        if self.config.host != self.config.target {
-            return;
-        }
-
         let cwd = env::current_dir().unwrap();
         let src_root = self.config
             .src_base
index 0e3fa25b13ce9368233e815835902df375795318..c612f0117aaf7f311365369302807cea21eef268 100644 (file)
 /// Conversion table from triple OS name to Rust SYSNAME
 const OS_TABLE: &'static [(&'static str, &'static str)] = &[
     ("android", "android"),
+    ("androideabi", "android"),
     ("bitrig", "bitrig"),
     ("cloudabi", "cloudabi"),
     ("darwin", "macos"),
     ("dragonfly", "dragonfly"),
+    ("emscripten", "emscripten"),
     ("freebsd", "freebsd"),
+    ("fuchsia", "fuchsia"),
     ("haiku", "haiku"),
     ("ios", "ios"),
+    ("l4re", "l4re"),
     ("linux", "linux"),
     ("mingw32", "windows"),
     ("netbsd", "netbsd"),
     ("openbsd", "openbsd"),
+    ("redox", "redox"),
+    ("solaris", "solaris"),
     ("win32", "windows"),
     ("windows", "windows"),
-    ("solaris", "solaris"),
-    ("emscripten", "emscripten"),
 ];
 
 const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
     ("amd64", "x86_64"),
     ("arm", "arm"),
     ("arm64", "aarch64"),
+    ("armv4t", "arm"),
+    ("armv5te", "arm"),
+    ("armv7", "arm"),
+    ("armv7s", "arm"),
+    ("asmjs", "asmjs"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),
     ("i686", "x86"),
-    ("mips64", "mips64"),
     ("mips", "mips"),
+    ("mips64", "mips64"),
+    ("mips64el", "mips64"),
+    ("mipsel", "mips"),
     ("msp430", "msp430"),
     ("powerpc", "powerpc"),
+    ("powerpc64", "powerpc64"),
+    ("powerpc64le", "powerpc64"),
     ("s390x", "s390x"),
     ("sparc", "sparc"),
+    ("sparc64", "sparc64"),
+    ("sparcv9", "sparc64"),
+    ("thumbv6m", "thumb"),
+    ("thumbv7em", "thumb"),
+    ("thumbv7m", "thumb"),
+    ("wasm32", "wasm32"),
     ("x86_64", "x86_64"),
     ("xcore", "xcore"),
-    ("asmjs", "asmjs"),
-    ("wasm32", "wasm32"),
 ];
 
 pub fn matches_os(triple: &str, name: &str) -> bool {
@@ -58,16 +75,18 @@ pub fn matches_os(triple: &str, name: &str) -> bool {
     if triple == "wasm32-unknown-unknown" {
         return name == "emscripten" || name == "wasm32-bare"
     }
+    let triple: Vec<_> = triple.split('-').collect();
     for &(triple_os, os) in OS_TABLE {
-        if triple.contains(triple_os) {
+        if triple.contains(&triple_os) {
             return os == name;
         }
     }
     panic!("Cannot determine OS from triple");
 }
 pub fn get_arch(triple: &str) -> &'static str {
+    let triple: Vec<_> = triple.split('-').collect();
     for &(triple_arch, arch) in ARCH_TABLE {
-        if triple.contains(triple_arch) {
+        if triple.contains(&triple_arch) {
             return arch;
         }
     }