]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #45359 - arielb1:escaping-borrow, r=eddyb
authorbors <bors@rust-lang.org>
Fri, 20 Oct 2017 14:33:43 +0000 (14:33 +0000)
committerbors <bors@rust-lang.org>
Fri, 20 Oct 2017 14:33:43 +0000 (14:33 +0000)
Fix a few bugs in drop generation

This fixes a few bugs in drop generation, one of which causes spurious MIR borrowck errors.

Fixes #44832.

r? @eddyb

175 files changed:
.travis.yml
CONTRIBUTING.md
README.md
config.toml.example
src/bootstrap/README.md
src/bootstrap/bootstrap.py
src/bootstrap/bootstrap_test.py
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/native.rs
src/bootstrap/toolstate.rs
src/ci/docker/asmjs/Dockerfile
src/ci/docker/cross2/build-solaris-toolchain.sh
src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile [deleted file]
src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile [new file with mode: 0644]
src/doc/rustdoc/src/command-line-arguments.md
src/doc/unstable-book/src/language-features/lang-items.md
src/doc/unstable-book/src/library-features/alloc-jemalloc.md
src/doc/unstable-book/src/library-features/alloc-system.md
src/etc/installer/exe/rust.iss
src/etc/installer/msi/rust.wxs
src/etc/installer/pkg/Distribution.xml
src/liballoc/str.rs
src/liballoc_system/lib.rs
src/libcore/hash/sip.rs
src/libcore/result.rs
src/libcore/tests/num/flt2dec/estimator.rs
src/librustc/README.md
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/lowering.rs
src/librustc/ich/fingerprint.rs
src/librustc/ich/impls_ty.rs
src/librustc/lib.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/session/filesearch.rs
src/librustc/traits/coherence.rs
src/librustc/traits/select.rs
src/librustc/ty/README.md
src/librustc/ty/context.rs
src/librustc/ty/erase_regions.rs [new file with mode: 0644]
src/librustc/ty/fold.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/sty.rs
src/librustc_borrowck/borrowck/README.md
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_const_eval/_match.rs
src/librustc_const_eval/check_match.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/sip128.rs [new file with mode: 0644]
src/librustc_data_structures/stable_hasher.rs
src/librustc_driver/driver.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/astencode.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/diagnostics.rs
src/librustc_passes/consts.rs
src/librustc_passes/lib.rs
src/librustc_trans/abi.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/llvm_util.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/outlives/mod.rs [new file with mode: 0644]
src/librustc_typeck/outlives/test.rs [new file with mode: 0644]
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/lib.rs
src/libstd/primitive_docs.rs
src/libstd/process.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/thread/local.rs
src/libsyntax/codemap.rs
src/libsyntax/parse/parser.rs
src/rustllvm/PassWrapper.cpp
src/test/codegen-units/partitioning/local-inlining-but-not-all.rs
src/test/codegen/abi-x86-interrupt.rs
src/test/codegen/mainsubprogram.rs
src/test/codegen/mainsubprogramstart.rs
src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
src/test/compile-fail/lint-unexported-no-mangle.rs
src/test/compile-fail/macro-expanded-include/test.rs
src/test/compile-fail/outlives-associated-types.rs [new file with mode: 0644]
src/test/mir-opt/validate_1.rs
src/test/mir-opt/validate_4.rs
src/test/mir-opt/validate_5.rs
src/test/run-make/inline-always-many-cgu/Makefile [new file with mode: 0644]
src/test/run-make/inline-always-many-cgu/foo.rs [new file with mode: 0644]
src/test/run-pass/asm-concat-src.rs
src/test/run-pass/command-before-exec.rs
src/test/run-pass/command-exec.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/env-args-reverse-iterator.rs
src/test/run-pass/env-funky-keys.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/extern-pass-empty.rs
src/test/run-pass/fds-are-cloexec.rs
src/test/run-pass/format-no-std.rs
src/test/run-pass/generator/smoke.rs
src/test/run-pass/i128.rs
src/test/run-pass/issue-10626.rs
src/test/run-pass/issue-13304.rs
src/test/run-pass/issue-14456.rs
src/test/run-pass/issue-14940.rs
src/test/run-pass/issue-16272.rs
src/test/run-pass/issue-20091.rs
src/test/run-pass/issue-2190-1.rs
src/test/run-pass/issue-24313.rs
src/test/run-pass/issue-28950.rs
src/test/run-pass/issue-29485.rs
src/test/run-pass/issue-29663.rs
src/test/run-pass/issue-30490.rs
src/test/run-pass/issue-33770.rs
src/test/run-pass/issue-36023.rs
src/test/run-pass/issue-40003.rs [new file with mode: 0644]
src/test/run-pass/issue-44402.rs [new file with mode: 0644]
src/test/run-pass/issue-45124.rs [new file with mode: 0644]
src/test/run-pass/linkage1.rs
src/test/run-pass/multi-panic.rs
src/test/run-pass/no-stdio.rs
src/test/run-pass/out-of-stack.rs
src/test/run-pass/packed-struct-layout.rs
src/test/run-pass/packed-tuple-struct-layout.rs
src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs
src/test/run-pass/panic-runtime/abort.rs
src/test/run-pass/panic-runtime/lto-abort.rs
src/test/run-pass/panic-runtime/lto-unwind.rs
src/test/run-pass/process-envs.rs
src/test/run-pass/process-exit.rs
src/test/run-pass/process-remove-from-env.rs
src/test/run-pass/process-spawn-with-unicode-params.rs
src/test/run-pass/process-status-inherits-stdin.rs
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/signal-exit-status.rs
src/test/run-pass/sigpipe-should-be-ignored.rs
src/test/run-pass/simd-intrinsic-generic-cast.rs
src/test/run-pass/stack-probes-lto.rs
src/test/run-pass/stack-probes.rs
src/test/run-pass/stdio-is-blocking.rs
src/test/run-pass/thinlto/thin-lto-inlines.rs
src/test/run-pass/thinlto/thin-lto-inlines2.rs
src/test/run-pass/try-wait.rs
src/test/run-pass/u128.rs
src/test/run-pass/vec-macro-no-std.rs
src/test/run-pass/wait-forked-but-failed-child.rs
src/test/rustdoc/empty-mod-private.rs
src/test/rustdoc/issue-15347.rs
src/test/rustdoc/pub-method.rs
src/test/ui/issue-45296.rs [new file with mode: 0644]
src/test/ui/issue-45296.stderr [new file with mode: 0644]
src/test/ui/lint/suggestions.rs
src/test/ui/lint/suggestions.stderr
src/test/ui/lint/unused_parens_json_suggestion.rs
src/test/ui/lint/unused_parens_json_suggestion.stderr
src/tools/compiletest/src/runtest.rs
src/tools/toolstate.toml

index 139f06ec5704bcfc09f5ea7c40570e6b6406590d..c76e17a27d188c264686e3225d8260398f318a51 100644 (file)
@@ -12,7 +12,7 @@ matrix:
   fast_finish: true
   include:
     # Images used in testing PR and try-build should be run first.
-    - env: IMAGE=x86_64-gnu-llvm-3.7 RUST_BACKTRACE=1
+    - env: IMAGE=x86_64-gnu-llvm-3.9 RUST_BACKTRACE=1
       if: type = pull_request OR branch = auto
 
     - env: IMAGE=dist-x86_64-linux DEPLOY=1
@@ -36,7 +36,7 @@ matrix:
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
       os: osx
-      osx_image: xcode7
+      osx_image: xcode7.3
       if: branch = auto
 
     # macOS builders. These are placed near the beginning because they are very
@@ -57,7 +57,7 @@ matrix:
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
       os: osx
-      osx_image: xcode8.2
+      osx_image: xcode8.3
       if: branch = auto
 
     - env: >
@@ -71,7 +71,7 @@ matrix:
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
       os: osx
-      osx_image: xcode8.2
+      osx_image: xcode8.3
       if: branch = auto
 
     # OSX builders producing releases. These do not run the full test suite and
@@ -91,7 +91,7 @@ matrix:
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
       os: osx
-      osx_image: xcode7
+      osx_image: xcode7.3
       if: branch = auto
 
     - env: >
@@ -105,7 +105,7 @@ matrix:
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
       os: osx
-      osx_image: xcode7
+      osx_image: xcode7.3
       if: branch = auto
 
     # Linux builders, remaining docker images
index a86742d7bd4ff56818e673a615a49d22c99b5a92..4c296a28e90b4a2f8e19b8e6bfefe5a61040feef 100644 (file)
@@ -360,8 +360,120 @@ git add path/to/submodule
 
 outside the submodule.
 
-It can also be more convenient during development to set `submodules = false`
-in the `config.toml` to prevent `x.py` from resetting to the original branch.
+In order to prepare your PR, you can run the build locally by doing
+`./x.py build src/tools/TOOL`. If you will be editing the sources
+there, you may wish to set `submodules = false` in the `config.toml`
+to prevent `x.py` from resetting to the original branch.
+
+#### Breaking Tools Built With The Compiler
+[breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler
+
+Rust's build system builds a number of tools that make use of the
+internals of the compiler. This includes clippy,
+[RLS](https://github.com/rust-lang-nursery/rls) and
+[rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools
+break because of your changes, you may run into a sort of "chicken and egg"
+problem. These tools rely on the latest compiler to be built so you can't update
+them to reflect your changes to the compiler until those changes are merged into
+the compiler. At the same time, you can't get your changes merged into the compiler
+because the rust-lang/rust build won't pass until those tools build and pass their
+tests.
+
+That means that, in the default state, you can't update the compiler without first
+fixing rustfmt, rls and the other tools that the compiler builds.
+
+Luckily, a feature was [added to Rust's build](https://github.com/rust-lang/rust/pull/45243)
+to make all of this easy to handle. The idea is that you mark the tools as "broken",
+so that the rust-lang/rust build passes without trying to build them, then land the change
+in the compiler, wait for a nightly, and go update the tools that you broke. Once you're done
+and the tools are working again, you go back in the compiler and change the tools back
+from "broken".
+
+This should avoid a bunch of synchronization dances and is also much easier on contributors as
+there's no need to block on rls/rustfmt/other tools changes going upstream.
+
+Here are those same steps in detail:
+
+1. (optional) First, if it doesn't exist already, create a `config.toml` by copying
+   `config.toml.example` in the root directory of the Rust repository.
+   Set `submodules = false` in the `[build]` section. This will prevent `x.py`
+   from resetting to the original branch after you make your changes. If you
+   need to [update any submodules to their latest versions][updating-submodules],
+   see the section of this file about that for more information.
+2. (optional) Run `./x.py test src/tools/rustfmt` (substituting the submodule
+   that broke for `rustfmt`). Fix any errors in the submodule (and possibly others).
+3. (optional) Make commits for your changes and send them to upstream repositories as a PR.
+4. (optional) Maintainers of these submodules will **not** merge the PR. The PR can't be
+   merged because CI will be broken. You'll want to write a message on the PR referencing
+   your change, and how the PR should be merged once your change makes it into a nightly.
+5. Update `src/tools/toolstate.toml` to indicate that the tool in question is "broken",
+   that will disable building it on CI. See the documentation in that file for the exact
+   configuration values you can use.
+6. Commit the changes to `src/tools/toolstate.toml`, **do not update submodules in your commit**,
+   and then update the PR you have for rust-lang/rust.
+7. Wait for your PR to merge.
+8. Wait for a nightly
+9. (optional) Help land your PR on the upstream repository now that your changes are in nightly.
+10. (optional) Send a PR to rust-lang/rust updating the submodule, reverting `src/tools/toolstate.toml` back to a "building" or "testing" state.
+
+#### Updating submodules
+[updating-submodules]: #updating-submodules
+
+These instructions are specific to updating `rustfmt`, however they may apply
+to the other submodules as well. Please help by improving these instructions
+if you find any discrepencies or special cases that need to be addressed.
+
+To update the `rustfmt` submodule, start by running the appropriate
+[`git submodule` command](https://git-scm.com/book/en/v2/Git-Tools-Submodules).
+For example, to update to the latest commit on the remote master branch,
+you may want to run:
+```
+git submodule update --remote src/tools/rustfmt
+```
+If you run `./x.py build` now, and you are lucky, it may just work. If you see
+an error message about patches that did not resolve to any crates, you will need
+to complete a few more steps which are outlined with their rationale below.
+
+*(This error may change in the future to include more information.)*
+```
+error: failed to resolve patches for `https://github.com/rust-lang-nursery/rustfmt`
+
+Caused by:
+  patch for `rustfmt-nightly` in `https://github.com/rust-lang-nursery/rustfmt` did not resolve to any crates
+failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml
+```
+
+If you haven't used the `[patch]`
+section of `Cargo.toml` before, there is [some relevant documentation about it
+in the cargo docs](http://doc.crates.io/manifest.html#the-patch-section). In
+addition to that, you should read the 
+[Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#overriding-dependencies)
+section of the documentation as well.
+
+Specifically, the following [section in Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#testing-a-bugfix) reveals what the problem is:
+
+> Next up we need to ensure that our lock file is updated to use this new version of uuid so our project uses the locally checked out copy instead of one from crates.io. The way [patch] works is that it'll load the dependency at ../path/to/uuid and then whenever crates.io is queried for versions of uuid it'll also return the local version.
+> 
+> This means that the version number of the local checkout is significant and will affect whether the patch is used. Our manifest declared uuid = "1.0" which means we'll only resolve to >= 1.0.0, < 2.0.0, and Cargo's greedy resolution algorithm also means that we'll resolve to the maximum version within that range. Typically this doesn't matter as the version of the git repository will already be greater or match the maximum version published on crates.io, but it's important to keep this in mind!
+
+This says that when we updated the submodule, the version number in our
+`src/tools/rustfmt/Cargo.toml` changed. The new version is different from
+the version in `Cargo.lock`, so the build can no longer continue.
+
+To resolve this, we need to update `Cargo.lock`. Luckily, cargo provides a
+command to do this easily.
+
+First, go into the `src/` directory since that is where `Cargo.toml` is in
+the rust repository. Then run, `cargo update -p rustfmt-nightly` to solve
+the problem.
+
+```
+$ cd src
+$ cargo update -p rustfmt-nightly
+```
+
+This should change the version listed in `src/Cargo.lock` to the new version you updated
+the submodule to. Running `./x.py build` should work now.
 
 ## Writing Documentation
 [writing-documentation]: #writing-documentation
index 779acb9fab44451354c7ae67533c9db4978269f1..4fc003036e9b3601a79f18815dd48385d3e97f04 100644 (file)
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ Read ["Installation"] from [The Book].
 ## Building from Source
 [building-from-source]: #building-from-source
 
+### Building on *nix
 1. Make sure you have installed the dependencies:
 
    * `g++` 4.7 or later or `clang++` 3.x or later
index f50543e18a764845d76fab7ef6eb990d850f1fb1..261fe2053879f004fd2ffeecc23d49c43ceb8467 100644 (file)
@@ -35,7 +35,7 @@
 # If an external LLVM root is specified, we automatically check the version by
 # default to make sure it's within the range that we're expecting, but setting
 # this flag will indicate that this version check should not be done.
-#version-check = false
+#version-check = true
 
 # Link libstdc++ statically into the librustc_llvm instead of relying on a
 # dynamic version to be available.
index 6eb074605fc1493e70919edf5e94a728c3be3aef..9ff681ac680874b09b35122160f7807025d4b1cc 100644 (file)
@@ -129,14 +129,14 @@ configure your directory to use this build, like so:
 # configure to use local rust instead of downloading a beta.
 # `--local-rust-root` is optional here. If elided, we will
 # use whatever rustc we find on your PATH.
-> configure --enable-rustbuild --local-rust-root=~/.cargo/ --enable-local-rebuild
+> ./configure --local-rust-root=~/.cargo/ --enable-local-rebuild
 ```
 
 After that, you can use the `--incremental` flag to actually do
 incremental builds:
 
 ```
-> ../x.py build --incremental
+> ./x.py build --incremental
 ```
 
 The `--incremental` flag will store incremental compilation artifacts
index 64f76aa2ef43f645b29d7d402fae63fb06b9507e..0ab4c79e3b236df03426d27690c6f0edfa43c93a 100644 (file)
@@ -8,7 +8,7 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
 import argparse
 import contextlib
 import datetime
@@ -532,7 +532,7 @@ class RustBuild(object):
         """
         config = self.get_toml(program)
         if config:
-            return config
+            return os.path.expanduser(config)
         return os.path.join(self.bin_root(), "bin", "{}{}".format(
             program, self.exe_suffix()))
 
@@ -648,7 +648,8 @@ class RustBuild(object):
                       if not ((module.endswith("llvm") and
                                self.get_toml('llvm-config')) or
                               (module.endswith("jemalloc") and
-                               self.get_toml('jemalloc')))]
+                               (self.get_toml('use-jemalloc') == "false" or
+                                self.get_toml('jemalloc'))))]
         run(["git", "submodule", "update",
              "--init", "--recursive"] + submodules,
             cwd=self.rust_root, verbose=self.verbose)
index 32ea4b4abe638b51cfc95d898e800922962ce792..4db7e2ec016f0c5ef145ba850a3f0bc86cd9c8e9 100644 (file)
@@ -10,6 +10,7 @@
 
 """Bootstrap tests"""
 
+from __future__ import absolute_import, division, print_function
 import os
 import doctest
 import unittest
index 69e0f58f1cd068f8639cb4737bdf6ae73461cd79..d6c83e3acfc8ab3d844535644e4310aab3bb950b 100644 (file)
@@ -299,6 +299,7 @@ pub fn parse(args: &[String]) -> Config {
         let mut config = Config::default();
         config.llvm_enabled = true;
         config.llvm_optimize = true;
+        config.llvm_version_check = true;
         config.use_jemalloc = true;
         config.backtrace = true;
         config.rust_optimize = true;
index 7b43de6a3221392f531b1a110c943f387daca0b6..42425a164a20ef3f2335aa304f9fef6aee6d1eef 100755 (executable)
@@ -11,6 +11,7 @@
 
 # ignore-tidy-linelength
 
+from __future__ import absolute_import, division, print_function
 import sys
 import os
 rust_dir = os.path.dirname(os.path.abspath(__file__))
@@ -20,7 +21,7 @@ sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
 import bootstrap
 
 
-class Option:
+class Option(object):
     def __init__(self, name, rustbuild, desc, value):
         self.name = name
         self.rustbuild = rustbuild
index b57661715cc7028eb0ece07e1ec8e4ef8d3013e9..38dca108012076683fd4760d441e6925965c645e 100644 (file)
@@ -630,7 +630,7 @@ fn run(self, builder: &Builder) -> PathBuf {
         let image = tmpdir(build).join(format!("{}-{}-image", name, target));
 
         let src = build.stage_out(compiler, Mode::Libstd)
-            .join(target).join("release").join("deps");
+            .join(target).join(build.cargo_dir()).join("deps");
 
         let image_src = src.join("save-analysis");
         let dst = image.join("lib/rustlib").join(target).join("analysis");
@@ -1035,7 +1035,7 @@ pub struct Rls {
 }
 
 impl Step for Rls {
-    type Output = PathBuf;
+    type Output = Option<PathBuf>;
     const ONLY_BUILD_TARGETS: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -1050,12 +1050,17 @@ fn make_run(run: RunConfig) {
         });
     }
 
-    fn run(self, builder: &Builder) -> PathBuf {
+    fn run(self, builder: &Builder) -> Option<PathBuf> {
         let build = builder.build;
         let stage = self.stage;
         let target = self.target;
         assert!(build.config.extended);
 
+        if !builder.config.toolstate.rls.testing() {
+            println!("skipping Dist RLS stage{} ({})", stage, target);
+            return None
+        }
+
         println!("Dist RLS stage{} ({})", stage, target);
         let src = build.src.join("src/tools/rls");
         let release_num = build.release_num("rls");
@@ -1102,7 +1107,7 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--component-name=rls-preview");
 
         build.run(&mut cmd);
-        distdir(build).join(format!("{}-{}.tar.gz", name, target))
+        Some(distdir(build).join(format!("{}-{}.tar.gz", name, target)))
     }
 }
 
@@ -1202,8 +1207,12 @@ fn run(self, builder: &Builder) {
         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
         // the std files during uninstall. To do this ensure that rustc comes
         // before rust-std in the list below.
-        let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer,
-                                analysis_installer, std_installer];
+        let mut tarballs = Vec::new();
+        tarballs.push(rustc_installer);
+        tarballs.push(cargo_installer);
+        tarballs.extend(rls_installer.clone());
+        tarballs.push(analysis_installer);
+        tarballs.push(std_installer);
         if build.config.docs {
             tarballs.push(docs_installer);
         }
@@ -1245,35 +1254,38 @@ fn run(self, builder: &Builder) {
         }
         rtf.push_str("}");
 
+        fn filter(contents: &str, marker: &str) -> String {
+            let start = format!("tool-{}-start", marker);
+            let end = format!("tool-{}-end", marker);
+            let mut lines = Vec::new();
+            let mut omitted = false;
+            for line in contents.lines() {
+                if line.contains(&start) {
+                    omitted = true;
+                } else if line.contains(&end) {
+                    omitted = false;
+                } else if !omitted {
+                    lines.push(line);
+                }
+            }
+
+            lines.join("\n")
+        }
+
+        let xform = |p: &Path| {
+            let mut contents = String::new();
+            t!(t!(File::open(p)).read_to_string(&mut contents));
+            if rls_installer.is_none() {
+                contents = filter(&contents, "rls");
+            }
+            let ret = tmp.join(p.file_name().unwrap());
+            t!(t!(File::create(&ret)).write_all(contents.as_bytes()));
+            return ret
+        };
+
         if target.contains("apple-darwin") {
             let pkg = tmp.join("pkg");
             let _ = fs::remove_dir_all(&pkg);
-            t!(fs::create_dir_all(pkg.join("rustc")));
-            t!(fs::create_dir_all(pkg.join("cargo")));
-            t!(fs::create_dir_all(pkg.join("rust-docs")));
-            t!(fs::create_dir_all(pkg.join("rust-std")));
-            t!(fs::create_dir_all(pkg.join("rls")));
-            t!(fs::create_dir_all(pkg.join("rust-analysis")));
-
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)),
-                    &pkg.join("rustc"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)),
-                    &pkg.join("cargo"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)),
-                    &pkg.join("rust-docs"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)),
-                    &pkg.join("rust-std"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)),
-                    &pkg.join("rls"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)),
-                    &pkg.join("rust-analysis"));
-
-            install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755);
-            install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755);
-            install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755);
-            install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755);
-            install(&etc.join("pkg/postinstall"), &pkg.join("rls"), 0o755);
-            install(&etc.join("pkg/postinstall"), &pkg.join("rust-analysis"), 0o755);
 
             let pkgbuild = |component: &str| {
                 let mut cmd = Command::new("pkgbuild");
@@ -1283,12 +1295,23 @@ fn run(self, builder: &Builder) {
                     .arg(pkg.join(component).with_extension("pkg"));
                 build.run(&mut cmd);
             };
-            pkgbuild("rustc");
-            pkgbuild("cargo");
-            pkgbuild("rust-docs");
-            pkgbuild("rust-std");
-            pkgbuild("rls");
-            pkgbuild("rust-analysis");
+
+            let prepare = |name: &str| {
+                t!(fs::create_dir_all(pkg.join(name)));
+                cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)),
+                        &pkg.join(name));
+                install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
+                pkgbuild(name);
+            };
+            prepare("rustc");
+            prepare("cargo");
+            prepare("rust-docs");
+            prepare("rust-std");
+            prepare("rust-analysis");
+
+            if rls_installer.is_some() {
+                prepare("rls");
+            }
 
             // create an 'uninstall' package
             install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
@@ -1298,7 +1321,7 @@ fn run(self, builder: &Builder) {
             t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes()));
             install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
             let mut cmd = Command::new("productbuild");
-            cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml"))
+            cmd.arg("--distribution").arg(xform(&etc.join("pkg/Distribution.xml")))
                 .arg("--resources").arg(pkg.join("res"))
                 .arg(distdir(build).join(format!("{}-{}.pkg",
                                                     pkgname(build, "rust"),
@@ -1310,46 +1333,34 @@ fn run(self, builder: &Builder) {
         if target.contains("windows") {
             let exe = tmp.join("exe");
             let _ = fs::remove_dir_all(&exe);
-            t!(fs::create_dir_all(exe.join("rustc")));
-            t!(fs::create_dir_all(exe.join("cargo")));
-            t!(fs::create_dir_all(exe.join("rls")));
-            t!(fs::create_dir_all(exe.join("rust-analysis")));
-            t!(fs::create_dir_all(exe.join("rust-docs")));
-            t!(fs::create_dir_all(exe.join("rust-std")));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target))
-                        .join("rustc"),
-                    &exe.join("rustc"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target))
-                        .join("cargo"),
-                    &exe.join("cargo"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target))
-                        .join("rust-docs"),
-                    &exe.join("rust-docs"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target))
-                        .join(format!("rust-std-{}", target)),
-                    &exe.join("rust-std"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview"),
-                 &exe.join("rls"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target))
-                        .join(format!("rust-analysis-{}", target)),
-                    &exe.join("rust-analysis"));
-
-            t!(fs::remove_file(exe.join("rustc/manifest.in")));
-            t!(fs::remove_file(exe.join("cargo/manifest.in")));
-            t!(fs::remove_file(exe.join("rust-docs/manifest.in")));
-            t!(fs::remove_file(exe.join("rust-std/manifest.in")));
-            t!(fs::remove_file(exe.join("rls/manifest.in")));
-            t!(fs::remove_file(exe.join("rust-analysis/manifest.in")));
 
+            let prepare = |name: &str| {
+                t!(fs::create_dir_all(exe.join(name)));
+                let dir = if name == "rust-std" || name == "rust-analysis" {
+                    format!("{}-{}", name, target)
+                } else if name == "rls" {
+                    "rls-preview".to_string()
+                } else {
+                    name.to_string()
+                };
+                cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target))
+                            .join(dir),
+                        &exe.join(name));
+                t!(fs::remove_file(exe.join(name).join("manifest.in")));
+            };
+            prepare("rustc");
+            prepare("cargo");
+            prepare("rust-analysis");
+            prepare("rust-docs");
+            prepare("rust-std");
+            if rls_installer.is_some() {
+                prepare("rls");
+            }
             if target.contains("windows-gnu") {
-                t!(fs::create_dir_all(exe.join("rust-mingw")));
-                cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target))
-                            .join("rust-mingw"),
-                        &exe.join("rust-mingw"));
-                t!(fs::remove_file(exe.join("rust-mingw/manifest.in")));
+                prepare("rust-mingw");
             }
 
-            install(&etc.join("exe/rust.iss"), &exe, 0o644);
+            install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644);
             install(&etc.join("exe/modpath.iss"), &exe, 0o644);
             install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
             install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
@@ -1413,16 +1424,18 @@ fn run(self, builder: &Builder) {
                             .arg("-dr").arg("Std")
                             .arg("-var").arg("var.StdDir")
                             .arg("-out").arg(exe.join("StdGroup.wxs")));
-            build.run(Command::new(&heat)
-                            .current_dir(&exe)
-                            .arg("dir")
-                            .arg("rls")
-                            .args(&heat_flags)
-                            .arg("-cg").arg("RlsGroup")
-                            .arg("-dr").arg("Rls")
-                            .arg("-var").arg("var.RlsDir")
-                            .arg("-out").arg(exe.join("RlsGroup.wxs"))
-                            .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
+            if rls_installer.is_some() {
+                build.run(Command::new(&heat)
+                                .current_dir(&exe)
+                                .arg("dir")
+                                .arg("rls")
+                                .args(&heat_flags)
+                                .arg("-cg").arg("RlsGroup")
+                                .arg("-dr").arg("Rls")
+                                .arg("-var").arg("var.RlsDir")
+                                .arg("-out").arg(exe.join("RlsGroup.wxs"))
+                                .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
+            }
             build.run(Command::new(&heat)
                             .current_dir(&exe)
                             .arg("dir")
@@ -1456,26 +1469,30 @@ fn run(self, builder: &Builder) {
                     .arg("-dDocsDir=rust-docs")
                     .arg("-dCargoDir=cargo")
                     .arg("-dStdDir=rust-std")
-                    .arg("-dRlsDir=rls")
                     .arg("-dAnalysisDir=rust-analysis")
                     .arg("-arch").arg(&arch)
                     .arg("-out").arg(&output)
                     .arg(&input);
                 add_env(build, &mut cmd, target);
 
+                if rls_installer.is_some() {
+                    cmd.arg("-dRlsDir=rls");
+                }
                 if target.contains("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
                 build.run(&mut cmd);
             };
-            candle(&etc.join("msi/rust.wxs"));
+            candle(&xform(&etc.join("msi/rust.wxs")));
             candle(&etc.join("msi/ui.wxs"));
             candle(&etc.join("msi/rustwelcomedlg.wxs"));
             candle("RustcGroup.wxs".as_ref());
             candle("DocsGroup.wxs".as_ref());
             candle("CargoGroup.wxs".as_ref());
             candle("StdGroup.wxs".as_ref());
-            candle("RlsGroup.wxs".as_ref());
+            if rls_installer.is_some() {
+                candle("RlsGroup.wxs".as_ref());
+            }
             candle("AnalysisGroup.wxs".as_ref());
 
             if target.contains("windows-gnu") {
@@ -1499,10 +1516,13 @@ fn run(self, builder: &Builder) {
                 .arg("DocsGroup.wixobj")
                 .arg("CargoGroup.wixobj")
                 .arg("StdGroup.wixobj")
-                .arg("RlsGroup.wixobj")
                 .arg("AnalysisGroup.wixobj")
                 .current_dir(&exe);
 
+            if rls_installer.is_some() {
+                cmd.arg("RlsGroup.wixobj");
+            }
+
             if target.contains("windows-gnu") {
                 cmd.arg("GccGroup.wixobj");
             }
index 941ea96bbec23c8b327acf9a6a3471a11c6c21fe..c37b1dad4c687cd9698543861ec74433206c3ab0 100644 (file)
@@ -259,11 +259,14 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
 
     let mut cmd = Command::new(llvm_config);
     let version = output(cmd.arg("--version"));
-    if version.starts_with("3.5") || version.starts_with("3.6") ||
-       version.starts_with("3.7") {
-        return
+    let mut parts = version.split('.').take(2)
+        .filter_map(|s| s.parse::<u32>().ok());
+    if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
+        if major > 3 || (major == 3 && minor >= 9) {
+            return
+        }
     }
-    panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
+    panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
index 8a113f6b4d2dffe9f3a457ac6c978719be829d4e..328cbf0e5d7102e35fdd143131994719935bbe4f 100644 (file)
@@ -31,6 +31,13 @@ pub fn passes(self, other: ToolState) -> BuildExpectation {
             BuildExpectation::Failing
         }
     }
+
+    pub fn testing(&self) -> bool {
+        match *self {
+            ToolState::Testing => true,
+            _ => false,
+        }
+    }
 }
 
 impl Default for ToolState {
index 28caf1fb57a487acef872c34f999765814f31a7a..c0bf689e39db967ece1aa2aef81d95f6a177064a 100644 (file)
@@ -16,6 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/emscripten.sh /scripts/
 RUN bash /scripts/emscripten.sh
 
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
 ENV PATH=$PATH:/emsdk-portable
 ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/
 ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/
@@ -28,7 +31,4 @@ ENV TARGETS=asmjs-unknown-emscripten
 
 ENV RUST_CONFIGURE_ARGS --target=$TARGETS
 
-ENV SCRIPT python2.7 ../x.py test --target $TARGETS
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
+ENV SCRIPT python2.7 ../x.py test --target $TARGETS src/test/run-pass
index 935cbe5d61b58eff77992c5df1cee66d300425c8..71ab998aab20dd1f7f8fc1552525c10bbb6d9b77 100755 (executable)
@@ -38,37 +38,38 @@ cd solaris
 
 dpkg --add-architecture $APT_ARCH
 apt-get update
-apt-get download           \
-  libc:$APT_ARCH           \
+apt-get download $(apt-cache depends --recurse --no-replaces \
   libc-dev:$APT_ARCH       \
-  libm:$APT_ARCH           \
   libm-dev:$APT_ARCH       \
-  libpthread:$APT_ARCH     \
   libpthread-dev:$APT_ARCH \
-  libresolv:$APT_ARCH      \
   libresolv-dev:$APT_ARCH  \
-  librt:$APT_ARCH          \
   librt-dev:$APT_ARCH      \
-  libsocket:$APT_ARCH      \
   libsocket-dev:$APT_ARCH  \
   system-crt:$APT_ARCH     \
-  system-header:$APT_ARCH
+  system-header:$APT_ARCH  \
+  | grep "^\w")
 
 for deb in *$APT_ARCH.deb; do
   dpkg -x $deb .
 done
 
-# Strip Solaris 11 functions that are optionally used by libbacktrace.
+# Remove Solaris 11 functions that are optionally used by libbacktrace.
 # This is for Solaris 10 compatibility.
-$ARCH-sun-solaris2.10-strip -N dl_iterate_phdr -N strnlen lib/$LIB_ARCH/libc.so
+rm usr/include/link.h
+patch -p0  << 'EOF'
+--- usr/include/string.h
++++ usr/include/string10.h
+@@ -93 +92,0 @@
+-extern size_t strnlen(const char *, size_t);
+EOF
 
 mkdir                  /usr/local/$ARCH-sun-solaris2.10/usr
 mv usr/include         /usr/local/$ARCH-sun-solaris2.10/usr/include
 mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib
 mv     lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib
 
-ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/sys-include
-ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/include
+ln -s usr/include /usr/local/$ARCH-sun-solaris2.10/sys-include
+ln -s usr/include /usr/local/$ARCH-sun-solaris2.10/include
 
 cd ..
 rm -rf solaris
@@ -97,8 +98,7 @@ hide_output ../gcc-$GCC/configure \
   --disable-libada                \
   --disable-libsanitizer          \
   --disable-libquadmath-support   \
-  --disable-lto                   \
-  --with-sysroot=/usr/local/$ARCH-sun-solaris2.10
+  --disable-lto
 
 hide_output make -j10
 hide_output make install
diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
deleted file mode 100644 (file)
index e832a24..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python2.7 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  llvm-3.7-tools \
-  libedit-dev \
-  zlib1g-dev \
-  xz-utils
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-3.7
-ENV RUST_CHECK_TARGET check
diff --git a/src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile
new file mode 100644 (file)
index 0000000..6b81860
--- /dev/null
@@ -0,0 +1,27 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  llvm-3.9-tools \
+  libedit-dev \
+  zlib1g-dev \
+  xz-utils
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+      --build=x86_64-unknown-linux-gnu \
+      --llvm-root=/usr/lib/llvm-3.9 \
+      --enable-llvm-link-shared
+ENV RUST_CHECK_TARGET check
index 0f0bda65ce3797d6555c7499d081ac69f26b79c9..8e8e2a7ff1dd5c00b33eb1682eced73fb91dce29 100644 (file)
@@ -96,11 +96,11 @@ Using this flag looks like this:
 $ rustdoc src/lib.rs --crate-name mycrate
 ```
 
-By default, `rustodc` assumes that the name of your crate is the same name
+By default, `rustdoc` assumes that the name of your crate is the same name
 as the `.rs` file. `--crate-name` lets you override this assumption with
 whatever name you choose.
 
-## `-L`/`--library-path`: 
+## `-L`/`--library-path`: where to look for dependencies
 
 Using this flag looks like this:
 
@@ -186,7 +186,7 @@ on documentation tests](documentation-tests.html).
 
 See also `--test-args`.
 
-## `--test-args`: 
+## `--test-args`: pass options to test runner
 
 Using this flag looks like this:
 
@@ -199,7 +199,7 @@ For more, see [the chapter on documentation tests](documentation-tests.html).
 
 See also `--test`.
 
-## `--target`: 
+## `--target`: generate documentation for the specified target triple
 
 Using this flag looks like this:
 
@@ -253,7 +253,7 @@ $ rustdoc README.md --html-before-content extra.html
 ```
 
 This flag takes a list of files, and inserts them inside the `<body>` tag but
-before the other content `rustodc` would normally produce in the rendered
+before the other content `rustdoc` would normally produce in the rendered
 documentation.
 
 ## `--html-after-content`: include more HTML after the content
@@ -266,7 +266,7 @@ $ rustdoc README.md --html-after-content extra.html
 ```
 
 This flag takes a list of files, and inserts them before the `</body>` tag but
-after the other content `rustodc` would normally produce in the rendered
+after the other content `rustdoc` would normally produce in the rendered
 documentation.
 
 
index ecbc860e25c03200be283cc7ab66a40f71a3e1d9..0137a052a62d868f02fcfded212f49fc0e634ba9 100644 (file)
@@ -227,3 +227,95 @@ A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_
 flag is set in the options of the compilation target. It allows customizing the
 process of resuming unwind at the end of the landing pads. The language item's name
 is `eh_unwind_resume`.
+
+## List of all language items
+
+This is a list of all language items in Rust along with where they are located in
+the source code.
+
+- Primitives
+  - `i8`: `libcore/num/mod.rs`
+  - `i16`: `libcore/num/mod.rs`
+  - `i32`: `libcore/num/mod.rs`
+  - `i64`: `libcore/num/mod.rs`
+  - `i128`: `libcore/num/mod.rs`
+  - `isize`: `libcore/num/mod.rs`
+  - `u8`: `libcore/num/mod.rs`
+  - `u16`: `libcore/num/mod.rs`
+  - `u32`: `libcore/num/mod.rs`
+  - `u64`: `libcore/num/mod.rs`
+  - `u128`: `libcore/num/mod.rs`
+  - `usize`: `libcore/num/mod.rs`
+  - `f32`: `libstd/f32.rs`
+  - `f64`: `libstd/f64.rs`
+  - `char`: `libstd_unicode/char.rs`
+  - `slice`: `liballoc/slice.rs`
+  - `str`: `liballoc/str.rs`
+  - `const_ptr`: `libcore/ptr.rs`
+  - `mut_ptr`: `libcore/ptr.rs`
+  - `unsafe_cell`: `libcore/cell.rs`
+- Runtime
+  - `start`: `libstd/rt.rs`
+  - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
+  - `eh_personality`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU)
+  - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
+  - `eh_unwind_resume`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU)
+  - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC)
+  - `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH)
+  - `panic`: `libcore/panicking.rs`
+  - `panic_bounds_check`: `libcore/panicking.rs`
+  - `panic_fmt`: `libcore/panicking.rs`
+  - `panic_fmt`: `libstd/panicking.rs`
+- Allocations
+  - `owned_box`: `liballoc/boxed.rs`
+  - `exchange_malloc`: `liballoc/heap.rs`
+  - `box_free`: `liballoc/heap.rs`
+- Operands
+  - `not`: `libcore/ops/bit.rs`
+  - `bitand`: `libcore/ops/bit.rs`
+  - `bitor`: `libcore/ops/bit.rs`
+  - `bitxor`: `libcore/ops/bit.rs`
+  - `shl`: `libcore/ops/bit.rs`
+  - `shr`: `libcore/ops/bit.rs`
+  - `bitand_assign`: `libcore/ops/bit.rs`
+  - `bitor_assign`: `libcore/ops/bit.rs`
+  - `bitxor_assign`: `libcore/ops/bit.rs`
+  - `shl_assign`: `libcore/ops/bit.rs`
+  - `shr_assign`: `libcore/ops/bit.rs`
+  - `deref`: `libcore/ops/deref.rs`
+  - `deref_mut`: `libcore/ops/deref.rs`
+  - `index`: `libcore/ops/index.rs`
+  - `index_mut`: `libcore/ops/index.rs`
+  - `add`: `libcore/ops/arith.rs`
+  - `sub`: `libcore/ops/arith.rs`
+  - `mul`: `libcore/ops/arith.rs`
+  - `div`: `libcore/ops/arith.rs`
+  - `rem`: `libcore/ops/arith.rs`
+  - `neg`: `libcore/ops/arith.rs`
+  - `add_assign`: `libcore/ops/arith.rs`
+  - `sub_assign`: `libcore/ops/arith.rs`
+  - `mul_assign`: `libcore/ops/arith.rs`
+  - `div_assign`: `libcore/ops/arith.rs`
+  - `rem_assign`: `libcore/ops/arith.rs`
+  - `eq`: `libcore/cmp.rs`
+  - `ord`: `libcore/cmp.rs`
+- Functions
+  - `fn`: `libcore/ops/function.rs`
+  - `fn_mut`: `libcore/ops/function.rs`
+  - `fn_once`: `libcore/ops/function.rs`
+  - `generator_state`: `libcore/ops/generator.rs`
+  - `generator`: `libcore/ops/generator.rs`
+- Other
+  - `coerce_unsized`: `libcore/ops/unsize.rs`
+  - `drop`: `libcore/ops/drop.rs`
+  - `drop_in_place`: `libcore/ptr.rs`
+  - `clone`: `libcore/clone.rs`
+  - `copy`: `libcore/marker.rs`
+  - `send`: `libcore/marker.rs`
+  - `sized`: `libcore/marker.rs`
+  - `unsize`: `libcore/marker.rs`
+  - `sync`: `libcore/marker.rs`
+  - `phantom_data`: `libcore/marker.rs`
+  - `freeze`: `libcore/marker.rs`
+  - `debug_trait`: `libcore/fmt/mod.rs`
+  - `non_zero`: `libcore/nonzero.rs`
\ No newline at end of file
index 18ff838dd32b961743f14b03a95d13d0d14790f9..425d4cb79b2df7e359fbd0c05edd3c8155d3156c 100644 (file)
@@ -8,55 +8,6 @@ See also [`alloc_system`](library-features/alloc-system.html).
 
 ------------------------
 
-The compiler currently ships two default allocators: `alloc_system` and
-`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
-are normal Rust crates and contain an implementation of the routines to
-allocate and deallocate memory. The standard library is not compiled assuming
-either one, and the compiler will decide which allocator is in use at
-compile-time depending on the type of output artifact being produced.
-
-Binaries generated by the compiler will use `alloc_jemalloc` by default (where
-available). In this situation the compiler "controls the world" in the sense of
-it has power over the final link. Primarily this means that the allocator
-decision can be left up the compiler.
-
-Dynamic and static libraries, however, will use `alloc_system` by default. Here
-Rust is typically a 'guest' in another application or another world where it
-cannot authoritatively decide what allocator is in use. As a result it resorts
-back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
-memory.
-
-# Switching Allocators
-
-Although the compiler's default choices may work most of the time, it's often
-necessary to tweak certain aspects. Overriding the compiler's decision about
-which allocator is in use is done simply by linking to the desired allocator:
-
-```rust,no_run
-#![feature(alloc_system)]
-
-extern crate alloc_system;
-
-fn main() {
-    let a = Box::new(4); // Allocates from the system allocator.
-    println!("{}", a);
-}
-```
-
-In this example the binary generated will not link to jemalloc by default but
-instead use the system allocator. Conversely to generate a dynamic library which
-uses jemalloc by default one would write:
-
-```rust,ignore
-#![feature(alloc_jemalloc)]
-#![crate_type = "dylib"]
-
-extern crate alloc_jemalloc;
-
-pub fn foo() {
-    let a = Box::new(4); // Allocates from jemalloc.
-    println!("{}", a);
-}
-# fn main() {}
-```
+This feature has been replaced by [the `jemallocator` crate on crates.io.][jemallocator].
 
+[jemallocator]: https://crates.io/crates/jemallocator
index 1d261db6ba1b3f810a08aa3892837c99cdeaf280..9effab202cabd909b8c270110f2ff1df5f7fa568 100644 (file)
@@ -1,10 +1,10 @@
 # `alloc_system`
 
-The tracking issue for this feature is: [#33082]
+The tracking issue for this feature is: [#32838]
 
-[#33082]: https://github.com/rust-lang/rust/issues/33082
+[#32838]: https://github.com/rust-lang/rust/issues/32838
 
-See also [`alloc_jemalloc`](library-features/alloc-jemalloc.html).
+See also [`global_allocator`](language-features/global-allocator.html).
 
 ------------------------
 
@@ -30,13 +30,18 @@ memory.
 
 Although the compiler's default choices may work most of the time, it's often
 necessary to tweak certain aspects. Overriding the compiler's decision about
-which allocator is in use is done simply by linking to the desired allocator:
+which allocator is in use is done through the `#[global_allocator]` attribute:
 
 ```rust,no_run
-#![feature(alloc_system)]
+#![feature(alloc_system, global_allocator, allocator_api)]
 
 extern crate alloc_system;
 
+use alloc_system::System;
+
+#[global_allocator]
+static A: System = System;
+
 fn main() {
     let a = Box::new(4); // Allocates from the system allocator.
     println!("{}", a);
@@ -47,11 +52,22 @@ In this example the binary generated will not link to jemalloc by default but
 instead use the system allocator. Conversely to generate a dynamic library which
 uses jemalloc by default one would write:
 
+(The `alloc_jemalloc` crate cannot be used to control the global allocator,
+crate.io’s `jemallocator` crate provides equivalent functionality.)
+
+```toml
+# Cargo.toml
+[dependencies]
+jemallocator = "0.1"
+```
 ```rust,ignore
-#![feature(alloc_jemalloc)]
+#![feature(global_allocator)]
 #![crate_type = "dylib"]
 
-extern crate alloc_jemalloc;
+extern crate jemallocator;
+
+#[global_allocator]
+static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
 
 pub fn foo() {
     let a = Box::new(4); // Allocates from jemalloc.
@@ -59,4 +75,3 @@ pub fn foo() {
 }
 # fn main() {}
 ```
-
index e7d4ec61946869369ef89227b34034d12bce616c..c22d60b6c5df1031313c4ed4e30c3c6e9e6d69de 100644 (file)
@@ -46,7 +46,9 @@ Name: gcc; Description: "Linker and platform libraries"; Types: full
 Name: docs; Description: "HTML documentation"; Types: full
 Name: cargo; Description: "Cargo, the Rust package manager"; Types: full
 Name: std; Description: "The Rust Standard Library"; Types: full
+// tool-rls-start
 Name: rls; Description: "RLS, the Rust Language Server"
+// tool-rls-end
 
 [Files]
 Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust
@@ -56,8 +58,10 @@ Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs;
 Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs
 Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo
 Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std
+// tool-rls-start
 Source: "rls/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls
 Source: "rust-analysis/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls
+// tool-rls-end
 
 [Code]
 const
index 258291cbb72e1e2d9ab4b8dabf78ee8e8d5698df..d95b096d732f41ede7743ff8d08341b2d54392fc 100644 (file)
                     <Directory Id="Docs" Name="." />
                     <Directory Id="Cargo" Name="." />
                     <Directory Id="Std" Name="." />
+                    <!-- tool-rls-start -->
                     <Directory Id="Rls" Name="." />
                     <Directory Id="Analysis" Name="." />
+                    <!-- tool-rls-end -->
                 </Directory>
             </Directory>
 
                  <ComponentRef Id="PathEnvPerMachine" />
                  <ComponentRef Id="PathEnvPerUser" />
         </Feature>
+        <!-- tool-rls-start -->
         <Feature Id="RLS"
                  Title="RLS, the Rust Language Server"
                  Display="7"
                  <ComponentGroupRef Id="RlsGroup" />
                  <ComponentGroupRef Id="AnalysisGroup" />
         </Feature>
+        <!-- tool-rls-end -->
 
         <UIRef Id="RustUI" />
     </Product>
index f138a1a315489e905d8e14ee7b19f768703ee40f..077ee17511655b9018ee0fe5e2270d911edb805a 100644 (file)
@@ -16,7 +16,9 @@
       <line choice="rust-std"/>
       <line choice="cargo"/>
       <line choice="rust-docs"/>
+      <!-- tool-rls-start -->
       <line choice="rls"/>
+      <!-- tool-rls-end -->
       </line>
       <line choice="uninstall" />
     </choices-outline>
@@ -62,6 +64,7 @@
         >
         <pkg-ref id="org.rust-lang.rust-docs"/>
     </choice>
+    <!-- tool-rls-start -->
     <choice id="rls" visible="true"
         title="RLS" description="RLS, the Rust Language Server"
         selected="(!choices.uninstall.selected &amp;&amp; choices['rls'].selected) || (choices.uninstall.selected &amp;&amp; choices.install.selected)"
         <pkg-ref id="org.rust-lang.rls"/>
         <pkg-ref id="org.rust-lang.rust-analysis"/>
     </choice>
+    <!-- tool-rls-end -->
     <pkg-ref id="org.rust-lang.rustc" version="0" onConclusion="none">rustc.pkg</pkg-ref>
     <pkg-ref id="org.rust-lang.cargo" version="0" onConclusion="none">cargo.pkg</pkg-ref>
     <pkg-ref id="org.rust-lang.rust-docs" version="0" onConclusion="none">rust-docs.pkg</pkg-ref>
     <pkg-ref id="org.rust-lang.rust-std" version="0" onConclusion="none">rust-std.pkg</pkg-ref>
+    <!-- tool-rls-start -->
     <pkg-ref id="org.rust-lang.rls" version="0" onConclusion="none">rls.pkg</pkg-ref>
+    <!-- tool-rls-end -->
     <pkg-ref id="org.rust-lang.rust-analysis" version="0" onConclusion="none">rust-analysis.pkg</pkg-ref>
     <pkg-ref id="org.rust-lang.uninstall" version="0" onConclusion="none">uninstall.pkg</pkg-ref>
     <background file="rust-logo.png" mime-type="image/png"
index 830128f2b9fcbdc2b701807389db01040139652b..895607ff8d4f0cdd2f85d4f009f419da48ef4dbc 100644 (file)
@@ -959,13 +959,15 @@ pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
     /// assert_eq!(s.find("Léopard"), Some(13));
     /// ```
     ///
-    /// More complex patterns with closures:
+    /// More complex patterns using point-free style and closures:
     ///
     /// ```
     /// let s = "Löwe 老虎 Léopard";
     ///
     /// assert_eq!(s.find(char::is_whitespace), Some(5));
     /// assert_eq!(s.find(char::is_lowercase), Some(1));
+    /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1));
+    /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4));
     /// ```
     ///
     /// Not finding the pattern:
index 2eb659699eb9b4839c3615c41c99d47686c6cb22..7aa5f8a9186b0a229412e370e1faa93b08a61e80 100644 (file)
@@ -14,7 +14,7 @@
 #![unstable(feature = "alloc_system",
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
-            issue = "27783")]
+            issue = "32838")]
 #![feature(global_allocator)]
 #![feature(allocator_api)]
 #![feature(alloc)]
index 91fd01b36d495901c8279f6bf90ca511599fbc2e..d82de082da6d0d84cc4cd76b32bf08658bbe8a49 100644 (file)
@@ -72,6 +72,7 @@ struct Hasher<S: Sip> {
 }
 
 #[derive(Debug, Clone, Copy)]
+#[repr(C)]
 struct State {
     // v0, v2 and v1, v3 show up in pairs in the algorithm,
     // and simd implementations of SipHash will use vectors
index ea064ca5c39fe0539804ab0536e519e538000cc3..db5bffced10cce609149f61088e049930e1dd615 100644 (file)
@@ -1060,7 +1060,7 @@ unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {}
 /// [`Result`]: enum.Result.html
 /// [`into_iter`]: ../iter/trait.IntoIterator.html#tymethod.into_iter
 /// [`IntoIterator`]: ../iter/trait.IntoIterator.html
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> { inner: Option<T> }
 
index 0bca616ea9abcc99e5fc604ee4d91f2472b2985d..857aae72c8a5bd5d92a0088a36bbe3c37fc58b37 100644 (file)
@@ -8,11 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// FIXME https://github.com/kripken/emscripten/issues/4563
-// NB we have to actually not compile this test to avoid
-// an undefined symbol error
-#![cfg(not(target_os = "emscripten"))]
-
 use core::num::flt2dec::estimator::*;
 
 #[test]
index 3ac2949b83e46fa74be882a84639efd3342b84f5..ddf71a06d607c7f7016546b0cc6fdb7da8ee3bef 100644 (file)
@@ -98,7 +98,7 @@ entire program, and each did a particular check of transformation.
 We are gradually replacing this pass-based code with an alternative
 setup based on on-demand **queries**. In the query-model, we work
 backwards, executing a *query* that expresses our ultimate goal (e.g.,
-"compiler this crate"). This query in turn may make other queries
+"compile this crate"). This query in turn may make other queries
 (e.g., "get me a list of all modules in the crate"). Those queries
 make other queries that ultimately bottom out in the base operations,
 like parsing the input, running the type-checker, and so forth. This
@@ -162,7 +162,7 @@ The compiler uses a number of...idiosyncratic abbreviations and
 things. This glossary attempts to list them and give you a few
 pointers for understanding them better.
 
-- AST -- the **abstract syntax tree** produced the `syntax` crate; reflects user syntax
+- AST -- the **abstract syntax tree** produced by the `syntax` crate; reflects user syntax
   very closely. 
 - codegen unit -- when we produce LLVM IR, we group the Rust code into a number of codegen
   units. Each of these units is processed by LLVM independently from one another,
index 4600cdbc692e7f37e51bf1d0a510bc346cb6c979..f9e902b910504245c5d4635c264de985eea904a6 100644 (file)
@@ -476,6 +476,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] TypeOfItem(DefId),
     [] GenericsOfItem(DefId),
     [] PredicatesOfItem(DefId),
+    [] InferredOutlivesOf(DefId),
     [] SuperPredicatesOfItem(DefId),
     [] TraitDefOfItem(DefId),
     [] AdtDefOfItem(DefId),
@@ -553,6 +554,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] LookupDeprecationEntry(DefId),
     [] ItemBodyNestedBodies(DefId),
     [] ConstIsRvaluePromotableToStatic(DefId),
+    [] RvaluePromotableMap(DefId),
     [] ImplParent(DefId),
     [] TraitOfItem(DefId),
     [] IsExportedSymbol(DefId),
@@ -608,6 +610,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] PostorderCnums,
     [] HasCloneClosures(CrateNum),
     [] HasCopyClosures(CrateNum),
+    [] EraseRegionsTy { ty: Ty<'tcx> },
 
     [] Freevars(DefId),
     [] MaybeUnusedTraitImport(DefId),
index 54aecb4b00f826580f8d0e683ec2d1e80c7d4650..848da9637a299796a0f2ab526c1a646f6d0141e0 100644 (file)
@@ -2547,7 +2547,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 };
 
                 // Err(err) => #[allow(unreachable_code)]
-                //             return Carrier::from_error(From::from(err)),
+                //             return Try::from_error(From::from(err)),
                 let err_arm = {
                     let err_ident = self.str_to_ident("err");
                     let err_local = self.pat_ident(e.span, err_ident);
index 2391b61253aa98883a2e9778bfe3c3971e17f8f1..f3bb3b385667ed041d768cf584e49eb0007dc620 100644 (file)
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 use rustc_data_structures::stable_hasher;
-use std::mem;
-use std::slice;
 
 #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
 pub struct Fingerprint(u64, u64);
@@ -54,16 +52,9 @@ fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::E
 }
 
 impl stable_hasher::StableHasherResult for Fingerprint {
-    fn finish(mut hasher: stable_hasher::StableHasher<Self>) -> Self {
-        let hash_bytes: &[u8] = hasher.finalize();
-
-        assert!(hash_bytes.len() >= mem::size_of::<u64>() * 2);
-        let hash_bytes: &[u64] = unsafe {
-            slice::from_raw_parts(hash_bytes.as_ptr() as *const u64, 2)
-        };
-
-        // The bytes returned bytes the Blake2B hasher are always little-endian.
-        Fingerprint(u64::from_le(hash_bytes[0]), u64::from_le(hash_bytes[1]))
+    fn finish(hasher: stable_hasher::StableHasher<Self>) -> Self {
+        let (_0, _1) = hasher.finalize();
+        Fingerprint(_0, _1)
     }
 }
 
index f719ce150924f0652d28bdb55657a72923dbaeb5..50f7e4ba176e5ddf6d3236bb5576485d21962b29 100644 (file)
@@ -518,7 +518,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     FnPtrAddrCast
 });
 
-impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { idx });
+impl_stable_hash_for!(tuple_struct ::middle::region::FirstStatementIndex { idx });
 impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
 
 impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope {
index ed440849b4826c7c2111b296ec84367f257aa74e..64fe4626d6ee69e4a31ba10043fb396348949624 100644 (file)
@@ -60,7 +60,7 @@
 #![cfg_attr(stage0, feature(const_fn))]
 #![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
 
-#![recursion_limit="256"]
+#![recursion_limit="512"]
 
 extern crate arena;
 #[macro_use] extern crate bitflags;
index e88678dea1d747d485c0c72af523c2ee58be2f3e..5c86554f9079011e12b1244f40dce588c6f84309 100644 (file)
@@ -171,7 +171,7 @@ fn build_local_id_to_index(body: Option<&hir::Body>,
                            -> FxHashMap<hir::ItemLocalId, Vec<CFGIndex>> {
     let mut index = FxHashMap();
 
-    // FIXME (#6298): Would it be better to fold formals from decl
+    // FIXME(#15020) Would it be better to fold formals from decl
     // into cfg itself?  i.e. introduce a fn-based flow-graph in
     // addition to the current block-based flow-graph, rather than
     // have to put traversals like this here?
index b036b145a96e4639f1a488a658e160305a463b51..e62cc2a658a474cf6f1d75da9956ebc627afa813 100644 (file)
 use ty::{self, TyCtxt, adjustment};
 
 use hir::{self, PatKind};
-
+use std::rc::Rc;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax_pos::Span;
+use util::nodemap::ItemLocalMap;
 
 ///////////////////////////////////////////////////////////////////////////
 // The Delegate trait
@@ -262,15 +263,30 @@ macro_rules! return_if_err {
 }
 
 impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
+    /// Creates the ExprUseVisitor, configuring it with the various options provided:
+    ///
+    /// - `delegate` -- who receives the callbacks
+    /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`)
+    /// - `region_scope_tree` --- region scope tree for the code being analyzed
+    /// - `tables` --- typeck results for the code being analyzed
+    /// - `rvalue_promotable_map` --- if you care about rvalue promotion, then provide
+    ///   the map here (it can be computed with `tcx.rvalue_promotable_map(def_id)`).
+    ///   `None` means that rvalues will be given more conservative lifetimes.
+    ///
+    /// See also `with_infer`, which is used *during* typeck.
     pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
                tcx: TyCtxt<'a, 'tcx, 'tcx>,
                param_env: ty::ParamEnv<'tcx>,
                region_scope_tree: &'a region::ScopeTree,
-               tables: &'a ty::TypeckTables<'tcx>)
+               tables: &'a ty::TypeckTables<'tcx>,
+               rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
                -> Self
     {
         ExprUseVisitor {
-            mc: mc::MemCategorizationContext::new(tcx, region_scope_tree, tables),
+            mc: mc::MemCategorizationContext::new(tcx,
+                                                  region_scope_tree,
+                                                  tables,
+                                                  rvalue_promotable_map),
             delegate,
             param_env,
         }
index c973881c980eef5dd2669fa27a29e91b43a51b85..e0e30f8831676aa28cb69b3a062a156b2a819ea8 100644 (file)
@@ -86,6 +86,7 @@
 
 use std::fmt;
 use std::rc::Rc;
+use util::nodemap::ItemLocalMap;
 
 #[derive(Clone, PartialEq)]
 pub enum Categorization<'tcx> {
@@ -285,6 +286,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
     pub region_scope_tree: &'a region::ScopeTree,
     pub tables: &'a ty::TypeckTables<'tcx>,
+    rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>,
     infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>,
 }
 
@@ -392,21 +394,46 @@ pub fn to_user_str(&self) -> &'static str {
 impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                region_scope_tree: &'a region::ScopeTree,
-               tables: &'a ty::TypeckTables<'tcx>)
+               tables: &'a ty::TypeckTables<'tcx>,
+               rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
                -> MemCategorizationContext<'a, 'tcx, 'tcx> {
-        MemCategorizationContext { tcx, region_scope_tree, tables, infcx: None }
+        MemCategorizationContext {
+            tcx,
+            region_scope_tree,
+            tables,
+            rvalue_promotable_map,
+            infcx: None
+        }
     }
 }
 
 impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
+    /// Creates a `MemCategorizationContext` during type inference.
+    /// This is used during upvar analysis and a few other places.
+    /// Because the typeck tables are not yet complete, the results
+    /// from the analysis must be used with caution:
+    ///
+    /// - rvalue promotions are not known, so the lifetimes of
+    ///   temporaries may be overly conservative;
+    /// - similarly, as the results of upvar analysis are not yet
+    ///   known, the results around upvar accesses may be incorrect.
     pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
                       region_scope_tree: &'a region::ScopeTree,
                       tables: &'a ty::TypeckTables<'tcx>)
                       -> MemCategorizationContext<'a, 'gcx, 'tcx> {
+        let tcx = infcx.tcx;
+
+        // Subtle: we can't do rvalue promotion analysis until the
+        // typeck phase is complete, which means that you can't trust
+        // the rvalue lifetimes that result, but that's ok, since we
+        // don't need to know those during type inference.
+        let rvalue_promotable_map = None;
+
         MemCategorizationContext {
-            tcx: infcx.tcx,
+            tcx,
             region_scope_tree,
             tables,
+            rvalue_promotable_map,
             infcx: Some(infcx),
         }
     }
@@ -477,10 +504,8 @@ pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
 
     fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
         let base_ty = self.node_ty(pat.hir_id)?;
-        // FIXME (Issue #18207): This code detects whether we are
-        // looking at a `ref x`, and if so, figures out what the type
-        // *being borrowed* is.  But ideally we would put in a more
-        // fundamental fix to this conflated use of the node id.
+        // This code detects whether we are looking at a `ref x`,
+        // and if so, figures out what the type *being borrowed* is.
         let ret_ty = match pat.node {
             PatKind::Binding(..) => {
                 let bm = *self.tables
@@ -871,8 +896,9 @@ pub fn cat_rvalue_node(&self,
                            span: Span,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
-        let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned()
-                                   .unwrap_or(false);
+        let hir_id = self.tcx.hir.node_to_hir_id(id);
+        let promotable = self.rvalue_promotable_map.as_ref().map(|m| m[&hir_id.local_id])
+                                                            .unwrap_or(false);
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
@@ -887,7 +913,7 @@ pub fn cat_rvalue_node(&self,
         let re = if promotable {
             self.tcx.types.re_static
         } else {
-            self.temporary_scope(self.tcx.hir.node_to_hir_id(id).local_id)
+            self.temporary_scope(hir_id.local_id)
         };
         let ret = self.cat_rvalue(id, span, re, expr_ty);
         debug!("cat_rvalue_node ret {:?}", ret);
index b909ee9f93bcd2f0103593a4c0404f6fada11198..fa4ee7c00929152db196d7ec8b431e42cbf5d27d 100644 (file)
@@ -156,26 +156,11 @@ pub struct BlockRemainder {
     pub first_statement_index: FirstStatementIndex,
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
-         RustcDecodable, Copy)]
-pub struct FirstStatementIndex { pub idx: u32 }
-
-impl Idx for FirstStatementIndex {
-    fn new(idx: usize) -> Self {
-        assert!(idx <= SCOPE_DATA_REMAINDER_MAX as usize);
-        FirstStatementIndex { idx: idx as u32 }
-    }
-
-    fn index(self) -> usize {
-        self.idx as usize
-    }
-}
-
-impl fmt::Debug for FirstStatementIndex {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.index(), formatter)
-    }
-}
+newtype_index!(FirstStatementIndex
+    {
+        DEBUG_NAME = "",
+        MAX = SCOPE_DATA_REMAINDER_MAX,
+    });
 
 impl From<ScopeData> for Scope {
     #[inline]
@@ -208,7 +193,7 @@ pub fn data(self) -> ScopeData {
             SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id),
             idx => ScopeData::Remainder(BlockRemainder {
                 block: self.id,
-                first_statement_index: FirstStatementIndex { idx }
+                first_statement_index: FirstStatementIndex::new(idx as usize)
             })
         }
     }
@@ -960,7 +945,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
 
             hir::ExprAssignOp(..) | hir::ExprIndex(..) |
             hir::ExprUnary(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) => {
-                // FIXME(#6268) Nested method calls
+                // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls
                 //
                 // The lifetimes for a call or method call look as follows:
                 //
@@ -1081,8 +1066,6 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
     // Here, the expression `[...]` has an extended lifetime due to rule
     // A, but the inner rvalues `a()` and `b()` have an extended lifetime
     // due to rule C.
-    //
-    // FIXME(#6308) -- Note that `[]` patterns work more smoothly post-DST.
 
     if let Some(expr) = init {
         record_rvalue_scope_if_borrow_expr(visitor, &expr, blk_scope);
index 1004b2826022aad753f30013ffa1ea63759e5ef0..b636fc6c9950a7241b9f2071b7ac57a99bf57df2 100644 (file)
@@ -28,8 +28,6 @@ pub enum FileMatch {
 }
 
 // A module for searching for libraries
-// FIXME (#2658): I'm not happy how this module turned out. Should
-// probably just be folded into cstore.
 
 pub struct FileSearch<'a> {
     pub sysroot: &'a Path,
index f3682f8d35d84d901f32e49132977c1a00075973..dc5ce7353246ab8e7972f309508073f4549f1286 100644 (file)
@@ -252,7 +252,6 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
 
 fn is_type_parameter(ty: Ty) -> bool {
     match ty.sty {
-        // FIXME(#20590) straighten story about projection types
         ty::TyProjection(..) | ty::TyParam(..) => true,
         _ => false,
     }
index 00f0672822fc119a5feea7945fff7bb6d908044b..cec79faff315d6fb4034f9f6e3d089d17d7f675d 100644 (file)
@@ -1309,13 +1309,13 @@ fn assemble_candidates<'o>(&mut self,
         };
 
         if obligation.predicate.skip_binder().self_ty().is_ty_var() {
-            // FIXME(#20297): Self is a type variable (e.g. `_: AsRef<str>`).
+            // Self is a type variable (e.g. `_: AsRef<str>`).
             //
             // This is somewhat problematic, as the current scheme can't really
             // handle it turning to be a projection. This does end up as truly
             // ambiguous in most cases anyway.
             //
-            // Until this is fixed, take the fast path out - this also improves
+            // Take the fast path out - this also improves
             // performance by preventing assemble_candidates_from_impls from
             // matching every impl for this trait.
             return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
@@ -1383,8 +1383,6 @@ fn assemble_candidates_from_projected_tys(&mut self,
     {
         debug!("assemble_candidates_for_projected_tys({:?})", obligation);
 
-        // FIXME(#20297) -- just examining the self-type is very simplistic
-
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.0.trait_ref.self_ty().sty {
@@ -2174,14 +2172,6 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             }
 
             ty::TyClosure(def_id, ref substs) => {
-                // FIXME(#27086). We are invariant w/r/t our
-                // func_substs, but we don't see them as
-                // constituent types; this seems RIGHT but also like
-                // something that a normal type couldn't simulate. Is
-                // this just a gap with the way that PhantomData and
-                // OIBIT interact? That is, there is no way to say
-                // "make me invariant with respect to this TYPE, but
-                // do not act as though I can reach it"
                 substs.upvar_tys(def_id, self.tcx()).collect()
             }
 
index 4f63912a1e0d1a8f8269a5a6d491d4e6827bd322..3fd956ecfb87dea7f60567b9cf192103b7b5c8e2 100644 (file)
@@ -42,7 +42,7 @@ wasteful.
 Often, we wish to write code that explicitly asserts that it is not
 taking place during inference. In that case, there is no "local"
 arena, and all the types that you can access are allocated in the
-global arena.  To express this, the idea is to us the same lifetime
+global arena.  To express this, the idea is to use the same lifetime
 for the `'gcx` and `'tcx` parameters of `TyCtxt`. Just to be a touch
 confusing, we tend to use the name `'tcx` in such contexts. Here is an
 example:
@@ -100,10 +100,10 @@ fn test_type<'tcx>(ty: Ty<'tcx>) {
 
 The `sty` field (the origin of this name is unclear to me; perhaps
 structural type?) is of type `TypeVariants<'tcx>`, which is an enum
-definined all of the different kinds of types in the compiler.
+defining all of the different kinds of types in the compiler.
 
 > NB: inspecting the `sty` field on types during type inference can be
-> risky, as there are may be inference variables and other things to
+> risky, as there may be inference variables and other things to
 > consider, or sometimes types are not yet known that will become
 > known later.).
 
@@ -132,7 +132,7 @@ a safe approximation, so that is what you get back.
 > you are going to be testing for type equality, you probably need to
 > start looking into the inference code to do it right.
 
-You can also find various common types in the tcx itself by accessing
+You can also find various common types in the `tcx` itself by accessing
 `tcx.types.bool`, `tcx.types.char`, etc (see `CommonTypes` for more).
 
 ### Beyond types: Other kinds of arena-allocated data structures
@@ -143,7 +143,7 @@ module. Here are a few examples:
 
 - `Substs`, allocated with `mk_substs` -- this will intern a slice of types, often used to
   specify the values to be substituted for generics (e.g., `HashMap<i32, u32>`
-  would be represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`.
+  would be represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
 - `TraitRef`, typically passed by value -- a **trait reference**
   consists of a reference to a trait along with its various type
   parameters (including `Self`), like `i32: Display` (here, the def-id
index 24ba38cf147796449be3a2883fba992892a54fff..3d5e8ea583ccc71b3c78d0dd0160c58838183340 100644 (file)
@@ -43,7 +43,6 @@
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
 use ty::TypeVariants::*;
 use ty::layout::{Layout, TargetDataLayout};
-use ty::inhabitedness::DefIdForest;
 use ty::maps;
 use ty::steal::Steal;
 use ty::BindingMode;
@@ -893,11 +892,6 @@ pub struct GlobalCtxt<'tcx> {
     // Internal cache for metadata decoding. No need to track deps on this.
     pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
 
-    // FIXME dep tracking -- should be harmless enough
-    pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
-
-    pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>,
-
     /// Caches the results of trait selection. This cache is used
     /// for things that do not have to do with the parameters in scope.
     pub selection_cache: traits::SelectionCache<'tcx>,
@@ -907,9 +901,6 @@ pub struct GlobalCtxt<'tcx> {
     /// Merge this with `selection_cache`?
     pub evaluation_cache: traits::EvaluationCache<'tcx>,
 
-    /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
-    pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
-
     /// The definite name of the current crate after taking into account
     /// attributes, commandline parameters, etc.
     pub crate_name: Symbol,
@@ -1178,11 +1169,8 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             maps: maps::Maps::new(providers),
             mir_passes,
             rcache: RefCell::new(FxHashMap()),
-            normalized_cache: RefCell::new(FxHashMap()),
-            inhabitedness_cache: RefCell::new(FxHashMap()),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
-            rvalue_promotable_to_static: RefCell::new(NodeMap()),
             crate_name: Symbol::intern(crate_name),
             data_layout,
             layout_interner: RefCell::new(FxHashSet()),
diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs
new file mode 100644 (file)
index 0000000..4f8fca6
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ty::{self, Ty, TyCtxt};
+use ty::fold::{TypeFolder, TypeFoldable};
+
+pub(super) fn provide(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        erase_regions_ty,
+        ..*providers
+    };
+}
+
+fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+    // NB: use `super_fold_with` here. If we used `fold_with`, it
+    // could invoke the `erase_regions_ty` query recursively.
+    ty.super_fold_with(&mut RegionEraserVisitor { tcx })
+}
+
+impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+    /// Returns an equivalent value with all free regions removed (note
+    /// that late-bound regions remain, because they are important for
+    /// subtyping, but they are anonymized and normalized as well)..
+    pub fn erase_regions<T>(self, value: &T) -> T
+        where T : TypeFoldable<'tcx>
+    {
+        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
+        debug!("erase_regions({:?}) = {:?}", value, value1);
+        value1
+    }
+}
+
+struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+}
+
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
+            self.tcx.erase_regions_ty(ty_lifted)
+        } else {
+            ty.super_fold_with(self)
+        }
+    }
+
+    fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+        where T : TypeFoldable<'tcx>
+    {
+        let u = self.tcx.anonymize_late_bound_regions(t);
+        u.super_fold_with(self)
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        // because late-bound regions affect subtyping, we can't
+        // erase the bound/free distinction, but we can replace
+        // all free regions with 'erased.
+        //
+        // Note that we *CAN* replace early-bound regions -- the
+        // type system never "sees" those, they get substituted
+        // away. In trans, they will always be erased to 'erased
+        // whenever a substitution occurs.
+        match *r {
+            ty::ReLateBound(..) => r,
+            _ => self.tcx.types.re_erased
+        }
+    }
+}
+
index 543e8f3e2f04d9511cbce9a1e1c68eefa9bb306f..edd4329fa419c39f03cbd4e1dd443d8271e705d7 100644 (file)
@@ -444,67 +444,6 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// Region eraser
-
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    /// Returns an equivalent value with all free regions removed (note
-    /// that late-bound regions remain, because they are important for
-    /// subtyping, but they are anonymized and normalized as well)..
-    pub fn erase_regions<T>(self, value: &T) -> T
-        where T : TypeFoldable<'tcx>
-    {
-        let value1 = value.fold_with(&mut RegionEraser(self));
-        debug!("erase_regions({:?}) = {:?}",
-               value, value1);
-        return value1;
-
-        struct RegionEraser<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>);
-
-        impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraser<'a, 'gcx, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.0 }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let Some(u) = self.tcx().normalized_cache.borrow().get(&ty).cloned() {
-                    return u;
-                }
-
-                // FIXME(eddyb) should local contexts have a cache too?
-                if let Some(ty_lifted) = self.tcx().lift_to_global(&ty) {
-                    let tcx = self.tcx().global_tcx();
-                    let t_norm = ty_lifted.super_fold_with(&mut RegionEraser(tcx));
-                    tcx.normalized_cache.borrow_mut().insert(ty_lifted, t_norm);
-                    t_norm
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-
-            fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
-                where T : TypeFoldable<'tcx>
-            {
-                let u = self.tcx().anonymize_late_bound_regions(t);
-                u.super_fold_with(self)
-            }
-
-            fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-                // because late-bound regions affect subtyping, we can't
-                // erase the bound/free distinction, but we can replace
-                // all free regions with 'erased.
-                //
-                // Note that we *CAN* replace early-bound regions -- the
-                // type system never "sees" those, they get substituted
-                // away. In trans, they will always be erased to 'erased
-                // whenever a substitution occurs.
-                match *r {
-                    ty::ReLateBound(..) => r,
-                    _ => self.tcx().types.re_erased
-                }
-            }
-        }
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Region shifter
 //
index a829814e0905ba2b9d1c51baf4df34149ec20359..0072512464a0e95406d9d7ab3a9dde4b29efcb4a 100644 (file)
@@ -10,7 +10,7 @@
 
 use util::nodemap::{FxHashMap, FxHashSet};
 use ty::context::TyCtxt;
-use ty::{AdtDef, VariantDef, FieldDef, TyS};
+use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
 use ty::{DefId, Substs};
 use ty::{AdtKind, Visibility};
 use ty::TypeVariants::*;
 // This code should only compile in modules where the uninhabitedness of Foo is
 // visible.
 
+impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+    /// Checks whether a type is visibly uninhabited from a particular module.
+    /// # Example
+    /// ```rust
+    /// enum Void {}
+    /// mod a {
+    ///     pub mod b {
+    ///         pub struct SecretlyUninhabited {
+    ///             _priv: !,
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// mod c {
+    ///     pub struct AlsoSecretlyUninhabited {
+    ///         _priv: Void,
+    ///     }
+    ///     mod d {
+    ///     }
+    /// }
+    ///
+    /// struct Foo {
+    ///     x: a::b::SecretlyUninhabited,
+    ///     y: c::AlsoSecretlyUninhabited,
+    /// }
+    /// ```
+    /// In this code, the type `Foo` will only be visibly uninhabited inside the
+    /// modules b, c and d. This effects pattern-matching on `Foo` or types that
+    /// contain `Foo`.
+    ///
+    /// # Example
+    /// ```rust
+    /// let foo_result: Result<T, Foo> = ... ;
+    /// let Ok(t) = foo_result;
+    /// ```
+    /// This code should only compile in modules where the uninhabitedness of Foo is
+    /// visible.
+    pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
+        // To check whether this type is uninhabited at all (not just from the
+        // given node) you could check whether the forest is empty.
+        // ```
+        // forest.is_empty()
+        // ```
+        self.ty_inhabitedness_forest(ty).contains(self, module)
+    }
+
+    pub fn is_ty_uninhabited_from_all_modules(self, ty: Ty<'tcx>) -> bool {
+        !self.ty_inhabitedness_forest(ty).is_empty()
+    }
+
+    fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
+        ty.uninhabited_from(&mut FxHashMap(), self)
+    }
+
+    pub fn is_enum_variant_uninhabited_from(self,
+                                            module: DefId,
+                                            variant: &'tcx VariantDef,
+                                            substs: &'tcx Substs<'tcx>)
+                                            -> bool
+    {
+        self.variant_inhabitedness_forest(variant, substs).contains(self, module)
+    }
+
+    pub fn is_variant_uninhabited_from_all_modules(self,
+                                                   variant: &'tcx VariantDef,
+                                                   substs: &'tcx Substs<'tcx>)
+                                                   -> bool
+    {
+        !self.variant_inhabitedness_forest(variant, substs).is_empty()
+    }
+
+    fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: &'tcx Substs<'tcx>)
+                                    -> DefIdForest {
+        // Determine the ADT kind:
+        let adt_def_id = self.adt_def_id_of_variant(variant);
+        let adt_kind = self.adt_def(adt_def_id).adt_kind();
+
+        // Compute inhabitedness forest:
+        variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind)
+    }
+}
+
 impl<'a, 'gcx, 'tcx> AdtDef {
     /// Calculate the forest of DefIds from which this adt is visibly uninhabited.
-    pub fn uninhabited_from(
-                &self,
-                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
-                tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                substs: &'tcx Substs<'tcx>) -> DefIdForest
+    fn uninhabited_from(
+        &self,
+        visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        substs: &'tcx Substs<'tcx>) -> DefIdForest
     {
         DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
             v.uninhabited_from(visited, tcx, substs, self.adt_kind())
@@ -78,12 +160,12 @@ pub fn uninhabited_from(
 
 impl<'a, 'gcx, 'tcx> VariantDef {
     /// Calculate the forest of DefIds from which this variant is visibly uninhabited.
-    pub fn uninhabited_from(
-                &self,
-                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
-                tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                substs: &'tcx Substs<'tcx>,
-                adt_kind: AdtKind) -> DefIdForest
+    fn uninhabited_from(
+        &self,
+        visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        substs: &'tcx Substs<'tcx>,
+        adt_kind: AdtKind) -> DefIdForest
     {
         match adt_kind {
             AdtKind::Union => {
@@ -107,12 +189,12 @@ pub fn uninhabited_from(
 
 impl<'a, 'gcx, 'tcx> FieldDef {
     /// Calculate the forest of DefIds from which this field is visibly uninhabited.
-    pub fn uninhabited_from(
-                &self,
-                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
-                tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                substs: &'tcx Substs<'tcx>,
-                is_enum: bool) -> DefIdForest
+    fn uninhabited_from(
+        &self,
+        visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        substs: &'tcx Substs<'tcx>,
+        is_enum: bool) -> DefIdForest
     {
         let mut data_uninhabitedness = move || {
             self.ty(tcx, substs).uninhabited_from(visited, tcx)
@@ -138,35 +220,10 @@ pub fn uninhabited_from(
 
 impl<'a, 'gcx, 'tcx> TyS<'tcx> {
     /// Calculate the forest of DefIds from which this type is visibly uninhabited.
-    pub fn uninhabited_from(
-                &self,
-                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
-                tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
-    {
-        match tcx.lift_to_global(&self) {
-            Some(global_ty) => {
-                {
-                    let cache = tcx.inhabitedness_cache.borrow();
-                    if let Some(forest) = cache.get(&global_ty) {
-                        return forest.clone();
-                    }
-                }
-                let forest = global_ty.uninhabited_from_inner(visited, tcx);
-                let mut cache = tcx.inhabitedness_cache.borrow_mut();
-                cache.insert(global_ty, forest.clone());
-                forest
-            },
-            None => {
-                let forest = self.uninhabited_from_inner(visited, tcx);
-                forest
-            },
-        }
-    }
-
-    fn uninhabited_from_inner(
-                &self,
-                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
-                tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
+    fn uninhabited_from(
+        &self,
+        visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
     {
         match self.sty {
             TyAdt(def, substs) => {
index 137039598a55b5601ca6b7d887d6f740d0fd760f..8f8cda0e0f1d1dff3c4be091232d5595ce0635bc 100644 (file)
@@ -29,7 +29,12 @@ pub(super) trait QueryDescription: QueryConfig {
 
 impl<M: QueryConfig<Key=DefId>> QueryDescription for M {
     default fn describe(tcx: TyCtxt, def_id: DefId) -> String {
-        format!("processing `{}`", tcx.item_path_str(def_id))
+        if !tcx.sess.verbose() {
+            format!("processing `{}`", tcx.item_path_str(def_id))
+        } else {
+            let name = unsafe { ::std::intrinsics::type_name::<M>() };
+            format!("processing `{}` applied to `{:?}`", name, def_id)
+        }
     }
 }
 
@@ -70,6 +75,12 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::erase_regions_ty<'tcx> {
+    fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
+        format!("erasing regions from `{:?}`", ty)
+    }
+}
+
 impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> {
     fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String {
         let id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -214,6 +225,13 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::rvalue_promotable_map<'tcx> {
+    fn describe(tcx: TyCtxt, def_id: DefId) -> String {
+        format!("checking which parts of `{}` are promotable to static",
+                tcx.item_path_str(def_id))
+    }
+}
+
 impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("checking if item is mir available: `{}`",
index 58405c261ad7239f73e4bef519aabbc78face5ba..839042bf229aaffc87c99e44f9d4536931f36938 100644 (file)
@@ -37,7 +37,7 @@
 use ty::layout::{Layout, LayoutError};
 use ty::steal::Steal;
 use ty::subst::Substs;
-use util::nodemap::{DefIdSet, DefIdMap};
+use util::nodemap::{DefIdSet, DefIdMap, ItemLocalMap};
 use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
     /// (inferred) variance.
     [] fn variances_of: ItemVariances(DefId) -> Rc<Vec<ty::Variance>>,
 
+    /// Maps from def-id of a type to its (inferred) outlives.
+    [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Vec<ty::Predicate<'tcx>>,
+
     /// Maps from an impl/trait def-id to a list of the def-ids of its items
     [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>>,
 
     [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
     [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
     [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
+    [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Rc<ItemLocalMap<bool>>,
     [] fn is_mir_available: IsMirAvailable(DefId) -> bool,
     [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
                           -> Rc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>,
 
     [] fn has_copy_closures: HasCopyClosures(CrateNum) -> bool,
     [] fn has_clone_closures: HasCloneClosures(CrateNum) -> bool,
+
+    // Erases regions from `ty` to yield a new type.
+    // Normally you would just use `tcx.erase_regions(&value)`,
+    // however, which uses this query as a kind of cache.
+    [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>,
 }
 
 //////////////////////////////////////////////////////////////////////
 // These functions are little shims used to find the dep-node for a
 // given query when there is not a *direct* mapping:
 
+fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
+    DepConstructor::EraseRegionsTy { ty }
+}
+
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::TypeParamPredicates {
         item_id,
index d6eaf6d1bc48fef0eee6daabc1b93134e8ca146d..5f93c3de336cc47b7b1626b4e333d82079b622e9 100644 (file)
@@ -12,7 +12,7 @@
 //! that generate the actual methods on tcx which find and execute the
 //! provider, manage the caches, and so forth.
 
-use dep_graph::{DepNodeIndex, DepNode, DepKind};
+use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
 use errors::{Diagnostic, DiagnosticBuilder};
 use ty::{TyCtxt};
 use ty::maps::Query; // NB: actually generated by the macros in this file
@@ -133,6 +133,40 @@ pub(super) fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F
 
         Ok(result)
     }
+
+    /// Try to read a node index for the node dep_node.
+    /// A node will have an index, when it's already been marked green, or when we can mark it
+    /// green. This function will mark the current task as a reader of the specified node, when
+    /// the a node index can be found for that node.
+    pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option<DepNodeIndex> {
+        match self.dep_graph.node_color(dep_node) {
+            Some(DepNodeColor::Green(dep_node_index)) => {
+                self.dep_graph.read_index(dep_node_index);
+                Some(dep_node_index)
+            }
+            Some(DepNodeColor::Red) => {
+                None
+            }
+            None => {
+                // try_mark_green (called below) will panic when full incremental
+                // compilation is disabled. If that's the case, we can't try to mark nodes
+                // as green anyway, so we can safely return None here.
+                if !self.dep_graph.is_fully_enabled() {
+                    return None;
+                }
+                match self.dep_graph.try_mark_green(self, &dep_node) {
+                    Some(dep_node_index) => {
+                        debug_assert!(self.dep_graph.is_green(dep_node_index));
+                        self.dep_graph.read_index(dep_node_index);
+                        Some(dep_node_index)
+                    }
+                    None => {
+                        None
+                    }
+                }
+            }
+        }
+    }
 }
 
 // If enabled, send a message to the profile-queries thread
@@ -309,25 +343,8 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                 }
 
                 if !dep_node.kind.is_input() {
-                    use dep_graph::DepNodeColor;
-                    if let Some(DepNodeColor::Green(dep_node_index)) = tcx.dep_graph
-                                                                          .node_color(&dep_node) {
+                    if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) {
                         profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                        tcx.dep_graph.read_index(dep_node_index);
-                        return Self::load_from_disk_and_cache_in_memory(tcx,
-                                                                        key,
-                                                                        span,
-                                                                        dep_node_index)
-                    }
-
-                    debug!("ty::queries::{}::try_get_with(key={:?}) - running try_mark_green",
-                           stringify!($name),
-                           key);
-
-                    if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, &dep_node) {
-                        debug_assert!(tcx.dep_graph.is_green(dep_node_index));
-                        profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                        tcx.dep_graph.read_index(dep_node_index);
                         return Self::load_from_disk_and_cache_in_memory(tcx,
                                                                         key,
                                                                         span,
@@ -357,36 +374,14 @@ pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () {
                 // Ensuring an "input" or anonymous query makes no sense
                 assert!(!dep_node.kind.is_anon());
                 assert!(!dep_node.kind.is_input());
-                use dep_graph::DepNodeColor;
-                match tcx.dep_graph.node_color(&dep_node) {
-                    Some(DepNodeColor::Green(dep_node_index)) => {
-                        tcx.dep_graph.read_index(dep_node_index);
-                    }
-                    Some(DepNodeColor::Red) => {
-                        // A DepNodeColor::Red DepNode means that this query was executed
-                        // before. We can not call `dep_graph.read()` here as we don't have
-                        // the DepNodeIndex. Instead, We call the query again to issue the
-                        // appropriate `dep_graph.read()` call. The performance cost this
-                        // introduces should be negligible as we'll immediately hit the
-                        // in-memory cache.
-                        let _ = tcx.$name(key);
-                    }
-                    None => {
-                        // Huh
-                        if !tcx.dep_graph.is_fully_enabled() {
-                            let _ = tcx.$name(key);
-                            return;
-                        }
-                        match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
-                            Some(dep_node_index) => {
-                                debug_assert!(tcx.dep_graph.is_green(dep_node_index));
-                                tcx.dep_graph.read_index(dep_node_index);
-                            }
-                            None => {
-                                let _ = tcx.$name(key);
-                            }
-                        }
-                    }
+                if tcx.try_mark_green_and_read(&dep_node).is_none() {
+                    // A None return from `try_mark_green_and_read` means that this is either
+                    // a new dep node or that the dep node has already been marked red.
+                    // Either way, we can't call `dep_graph.read()` as we don't have the
+                    // DepNodeIndex. We must invoke the query itself. The performance cost
+                    // this introduces should be negligible as we'll immediately hit the
+                    // in-memory cache, or another query down the line will.
+                    let _ = tcx.$name(key);
                 }
             }
 
@@ -701,6 +696,7 @@ macro_rules! force {
         DepKind::CompileCodegenUnit |
         DepKind::FulfillObligation |
         DepKind::VtableMethods |
+        DepKind::EraseRegionsTy |
 
         // These are just odd
         DepKind::Null |
@@ -736,6 +732,7 @@ macro_rules! force {
         DepKind::TypeOfItem => { force!(type_of, def_id!()); }
         DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
         DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
+        DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
         DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
         DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
         DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
@@ -773,6 +770,7 @@ macro_rules! force {
         DepKind::ConstIsRvaluePromotableToStatic => {
             force!(const_is_rvalue_promotable_to_static, def_id!());
         }
+        DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
         DepKind::ImplParent => { force!(impl_parent, def_id!()); }
         DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
         DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); }
index c4f526d80146b8868b48798ff991a5e3e004b0fc..129c81c5cd61f75cc0c96b628c324c5b44085973 100644 (file)
@@ -18,6 +18,7 @@
 use hir::{map as hir_map, FreevarMap, TraitMap};
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use hir::map::DefPathData;
 use ich::StableHashingContext;
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
@@ -89,6 +90,7 @@
 pub mod binding;
 pub mod cast;
 pub mod error;
+mod erase_regions;
 pub mod fast_reject;
 pub mod fold;
 pub mod inhabitedness;
@@ -2232,6 +2234,20 @@ pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
         }
     }
 
+    /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part.
+    pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId {
+        let def_key = self.def_key(variant_def.did);
+        match def_key.disambiguated_data.data {
+            // for enum variants and tuple structs, the def-id of the ADT itself
+            // is the *parent* of the variant
+            DefPathData::EnumVariant(..) | DefPathData::StructCtor =>
+                DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() },
+
+            // otherwise, for structs and unions, they share a def-id
+            _ => variant_def.did,
+        }
+    }
+
     pub fn item_name(self, id: DefId) -> InternedString {
         if let Some(id) = self.hir.as_local_node_id(id) {
             self.hir.name(id).as_str()
@@ -2560,6 +2576,7 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn provide(providers: &mut ty::maps::Providers) {
     util::provide(providers);
     context::provide(providers);
+    erase_regions::provide(providers);
     *providers = ty::maps::Providers {
         associated_item,
         associated_item_def_ids,
index 657ed4077911c8cd0dd1ea353cce5b366c230fe6..5e1dc485d420f7ba8505511982b925cf00d57e61 100644 (file)
@@ -73,42 +73,6 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
         // projection).
         match ty.sty {
             ty::TyClosure(def_id, ref substs) => {
-                // FIXME(#27086). We do not accumulate from substs, since they
-                // don't represent reachable data. This means that, in
-                // practice, some of the lifetime parameters might not
-                // be in scope when the body runs, so long as there is
-                // no reachable data with that lifetime. For better or
-                // worse, this is consistent with fn types, however,
-                // which can also encapsulate data in this fashion
-                // (though it's somewhat harder, and typically
-                // requires virtual dispatch).
-                //
-                // Note that changing this (in a naive way, at least)
-                // causes regressions for what appears to be perfectly
-                // reasonable code like this:
-                //
-                // ```
-                // fn foo<'a>(p: &Data<'a>) {
-                //    bar(|q: &mut Parser| q.read_addr())
-                // }
-                // fn bar(p: Box<FnMut(&mut Parser)+'static>) {
-                // }
-                // ```
-                //
-                // Note that `p` (and `'a`) are not used in the
-                // closure at all, but to meet the requirement that
-                // the closure type `C: 'static` (so it can be coerced
-                // to the object type), we get the requirement that
-                // `'a: 'static` since `'a` appears in the closure
-                // type `C`.
-                //
-                // A smarter fix might "prune" unused `func_substs` --
-                // this would avoid breaking simple examples like
-                // this, but would still break others (which might
-                // indeed be invalid, depending on your POV). Pruning
-                // would be a subtle process, since we have to see
-                // what func/type parameters are used and unused,
-                // taking into consideration UFCS and so forth.
 
                 for upvar_ty in substs.upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
index 10e1286465dbfa3de1cef6fbb25eca4e587a6404..064627c21bfe64f98cd2e0323e990b2bf5655994 100644 (file)
@@ -24,7 +24,6 @@
 use syntax::abi;
 use syntax::ast::{self, Name};
 use syntax::symbol::keywords;
-use util::nodemap::FxHashMap;
 
 use serialize;
 
@@ -1070,54 +1069,6 @@ pub fn is_defaulted_unit(&self) -> bool {
         }
     }
 
-    /// Checks whether a type is visibly uninhabited from a particular module.
-    /// # Example
-    /// ```rust
-    /// enum Void {}
-    /// mod a {
-    ///     pub mod b {
-    ///         pub struct SecretlyUninhabited {
-    ///             _priv: !,
-    ///         }
-    ///     }
-    /// }
-    ///
-    /// mod c {
-    ///     pub struct AlsoSecretlyUninhabited {
-    ///         _priv: Void,
-    ///     }
-    ///     mod d {
-    ///     }
-    /// }
-    ///
-    /// struct Foo {
-    ///     x: a::b::SecretlyUninhabited,
-    ///     y: c::AlsoSecretlyUninhabited,
-    /// }
-    /// ```
-    /// In this code, the type `Foo` will only be visibly uninhabited inside the
-    /// modules b, c and d. This effects pattern-matching on `Foo` or types that
-    /// contain `Foo`.
-    ///
-    /// # Example
-    /// ```rust
-    /// let foo_result: Result<T, Foo> = ... ;
-    /// let Ok(t) = foo_result;
-    /// ```
-    /// This code should only compile in modules where the uninhabitedness of Foo is
-    /// visible.
-    pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
-        let mut visited = FxHashMap::default();
-        let forest = self.uninhabited_from(&mut visited, tcx);
-
-        // To check whether this type is uninhabited at all (not just from the
-        // given node) you could check whether the forest is empty.
-        // ```
-        // forest.is_empty()
-        // ```
-        forest.contains(tcx, module)
-    }
-
     pub fn is_primitive(&self) -> bool {
         match self.sty {
             TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,
index 034b7cbadd9c64a20cde15f215d00d01ac4be3cb..b877c5a9cbcbcccbb7ec2d8d2b728f41c0a709da 100644 (file)
@@ -781,8 +781,9 @@ the base path, it will still be considered freezable.
 
 
 
-**FIXME #10520: Restrictions against mutating the base pointer.** When
-an `&mut` pointer is frozen or claimed, we currently pass along the
+**FIXME [RFC 1751](https://github.com/rust-lang/rfcs/issues/1751)
+Restrictions against mutating the base pointer.**
+When an `&mut` pointer is frozen or claimed, we currently pass along the
 restriction against MUTATE to the base pointer. I do not believe this
 restriction is needed. It dates from the days when we had a way to
 mutate that preserved the value being mutated (i.e., swap). Nowadays
index 6ce5afd4bf15f97c81d3a60b41c15e8ba47483ef..6fd9ff4012efa6b23732c3161115447fc8c72615 100644 (file)
@@ -206,7 +206,13 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         all_loans,
         param_env,
     };
-    euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_scope_tree, bccx.tables)
+    let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
+    euv::ExprUseVisitor::new(&mut clcx,
+                             bccx.tcx,
+                             param_env,
+                             &bccx.region_scope_tree,
+                             bccx.tables,
+                             Some(rvalue_promotable_map))
         .consume_body(body);
 }
 
@@ -659,7 +665,7 @@ fn check_if_path_is_moved(&self,
         debug!("check_if_path_is_moved(id={:?}, use_kind={:?}, lp={:?})",
                id, use_kind, lp);
 
-        // FIXME (22079): if you find yourself tempted to cut and paste
+        // FIXME: if you find yourself tempted to cut and paste
         // the body below and then specializing the error reporting,
         // consider refactoring this instead!
 
@@ -720,7 +726,7 @@ fn check_if_assigned_path_is_moved(&self,
                         // the path must be initialized to prevent a case of
                         // partial reinitialization
                         //
-                        // FIXME (22079): could refactor via hypothetical
+                        // FIXME: could refactor via hypothetical
                         // generalized check_if_path_is_moved
                         let loan_path = owned_ptr_base_path_rc(lp_base);
                         self.move_data.each_move_of(id, &loan_path, |_, _| {
index 1827ddabe4e2a9d6c7f46e695a96f99166ddbafe..8654f2a50e46bf1c693c328d359feee85dfbba3a 100644 (file)
@@ -48,7 +48,13 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
 
-    euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, param_env, &bccx.region_scope_tree, bccx.tables)
+    let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
+    euv::ExprUseVisitor::new(&mut glcx,
+                             bccx.tcx,
+                             param_env,
+                             &bccx.region_scope_tree,
+                             bccx.tables,
+                             Some(rvalue_promotable_map))
         .consume_body(bccx.body);
 
     glcx.report_potential_errors();
@@ -406,7 +412,7 @@ fn guarantee_valid(&mut self,
         self.all_loans.push(loan);
 
         // if loan_gen_scope != borrow_id {
-            // FIXME(#6268) Nested method calls
+            // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls
             //
             // Typically, the scope of the loan includes the point at
             // which the loan is originated. This
@@ -417,9 +423,8 @@ fn guarantee_valid(&mut self,
             //let restr = restrictions::compute_restrictions(
             //    self.bccx, borrow_span, cmt, RESTR_EMPTY);
             //let loan = {
-            //    let all_loans = &mut *self.all_loans; // FIXME(#5074)
             //    Loan {
-            //        index: all_loans.len(),
+            //        index: self.all_loans.len(),
             //        loan_path,
             //        cmt,
             //        mutbl: ConstMutability,
index b836b71e74bf65227e8ef9c3d2b2b8e45262299d..08f3b0a4c5fd1cfd0e1104fa852a58d7f1c14723 100644 (file)
@@ -25,7 +25,7 @@
 
 use rustc::hir::def_id::DefId;
 use rustc::hir::RangeEnd;
-use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 
 use rustc::mir::Field;
 use rustc::util::common::ErrorReported;
@@ -202,7 +202,7 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         if self.tcx.sess.features.borrow().never_type {
-            ty.is_uninhabited_from(self.module, self.tcx)
+            self.tcx.is_ty_uninhabited_from(self.module, ty)
         } else {
             false
         }
@@ -210,13 +210,11 @@ fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
 
     fn is_variant_uninhabited(&self,
                               variant: &'tcx ty::VariantDef,
-                              substs: &'tcx ty::subst::Substs<'tcx>) -> bool
+                              substs: &'tcx ty::subst::Substs<'tcx>)
+                              -> bool
     {
         if self.tcx.sess.features.borrow().never_type {
-            let forest = variant.uninhabited_from(
-                &mut FxHashMap::default(), self.tcx, substs, AdtKind::Enum
-            );
-            forest.contains(self.tcx, self.module)
+            self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
         } else {
             false
         }
index 0339969f2b45adf21fc79436d94b08806e618f6c..e6a04c9c57a6c05eba0cf2b049b28beb37546a67 100644 (file)
@@ -192,7 +192,7 @@ fn check_match(
             let module = self.tcx.hir.get_module_parent(scrut.id);
             if inlined_arms.is_empty() {
                 let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
-                    pat_ty.is_uninhabited_from(module, self.tcx)
+                    self.tcx.is_ty_uninhabited_from(module, pat_ty)
                 } else {
                     self.conservative_is_uninhabited(pat_ty)
                 };
@@ -526,7 +526,7 @@ fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
     let mut checker = MutationChecker {
         cx,
     };
-    ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables)
+    ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None)
         .walk_expr(guard);
 }
 
index 6c5a37aa1e5750ffb9b39daf67d86d578c585bdf..1d1b367de200eead52088b3b4440ebb678b5b377 100644 (file)
@@ -65,7 +65,7 @@ macro_rules! newtype_index {
     (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]) => (
         #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
             RustcEncodable, RustcDecodable)]
-        pub struct $type(u32);
+        pub struct $type(pub u32);
 
         impl Idx for $type {
             fn new(value: usize) -> Self {
@@ -99,7 +99,7 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
     // Replace existing default for max
     (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr]
             MAX = $max:expr, $($tokens:tt)*) => (
-        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $(tokens)*);
+        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
     );
 
     // Replace existing default for debug_name
index 47061883425e285d4aad04da74be96033fc0418f..3a20343033c233af91d976973b83e54e0b8ca37c 100644 (file)
@@ -28,6 +28,7 @@
 #![feature(fn_traits)]
 #![feature(unsize)]
 #![feature(i128_type)]
+#![feature(i128)]
 #![feature(conservative_impl_trait)]
 #![feature(specialization)]
 
@@ -54,6 +55,7 @@
 pub mod indexed_set;
 pub mod indexed_vec;
 pub mod obligation_forest;
+pub mod sip128;
 pub mod snapshot_map;
 pub mod snapshot_vec;
 pub mod stable_hasher;
diff --git a/src/librustc_data_structures/sip128.rs b/src/librustc_data_structures/sip128.rs
new file mode 100644 (file)
index 0000000..1f0b0d9
--- /dev/null
@@ -0,0 +1,533 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This is a copy of `core::hash::sip` adapted to providing 128 bit hashes.
+
+use std::cmp;
+use std::hash::Hasher;
+use std::slice;
+use std::ptr;
+use std::mem;
+
+#[derive(Debug, Clone)]
+pub struct SipHasher128 {
+    k0: u64,
+    k1: u64,
+    length: usize, // how many bytes we've processed
+    state: State, // hash State
+    tail: u64, // unprocessed bytes le
+    ntail: usize, // how many bytes in tail are valid
+}
+
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+struct State {
+    // v0, v2 and v1, v3 show up in pairs in the algorithm,
+    // and simd implementations of SipHash will use vectors
+    // of v02 and v13. By placing them in this order in the struct,
+    // the compiler can pick up on just a few simd optimizations by itself.
+    v0: u64,
+    v2: u64,
+    v1: u64,
+    v3: u64,
+}
+
+macro_rules! compress {
+    ($state:expr) => ({
+        compress!($state.v0, $state.v1, $state.v2, $state.v3)
+    });
+    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
+    ({
+        $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0;
+        $v0 = $v0.rotate_left(32);
+        $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2;
+        $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0;
+        $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2;
+        $v2 = $v2.rotate_left(32);
+    });
+}
+
+/// Load an integer of the desired type from a byte stream, in LE order. Uses
+/// `copy_nonoverlapping` to let the compiler generate the most efficient way
+/// to load it from a possibly unaligned address.
+///
+/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
+macro_rules! load_int_le {
+    ($buf:expr, $i:expr, $int_ty:ident) =>
+    ({
+       debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
+       let mut data = 0 as $int_ty;
+       ptr::copy_nonoverlapping($buf.get_unchecked($i),
+                                &mut data as *mut _ as *mut u8,
+                                mem::size_of::<$int_ty>());
+       data.to_le()
+    });
+}
+
+/// Load an u64 using up to 7 bytes of a byte slice.
+///
+/// Unsafe because: unchecked indexing at start..start+len
+#[inline]
+unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
+    debug_assert!(len < 8);
+    let mut i = 0; // current byte index (from LSB) in the output u64
+    let mut out = 0;
+    if i + 3 < len {
+        out = load_int_le!(buf, start + i, u32) as u64;
+        i += 4;
+    }
+    if i + 1 < len {
+        out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8);
+        i += 2
+    }
+    if i < len {
+        out |= (*buf.get_unchecked(start + i) as u64) << (i * 8);
+        i += 1;
+    }
+    debug_assert_eq!(i, len);
+    out
+}
+
+
+impl SipHasher128 {
+    #[inline]
+    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher128 {
+        let mut state = SipHasher128 {
+            k0: key0,
+            k1: key1,
+            length: 0,
+            state: State {
+                v0: 0,
+                v1: 0,
+                v2: 0,
+                v3: 0,
+            },
+            tail: 0,
+            ntail: 0,
+        };
+        state.reset();
+        state
+    }
+
+    #[inline]
+    fn reset(&mut self) {
+        self.length = 0;
+        self.state.v0 = self.k0 ^ 0x736f6d6570736575;
+        self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
+        self.state.v2 = self.k0 ^ 0x6c7967656e657261;
+        self.state.v3 = self.k1 ^ 0x7465646279746573;
+        self.ntail = 0;
+
+        // This is only done in the 128 bit version:
+        self.state.v1 ^= 0xee;
+    }
+
+    // Specialized write function that is only valid for buffers with len <= 8.
+    // It's used to force inlining of write_u8 and write_usize, those would normally be inlined
+    // except for composite types (that includes slices and str hashing because of delimiter).
+    // Without this extra push the compiler is very reluctant to inline delimiter writes,
+    // degrading performance substantially for the most common use cases.
+    #[inline]
+    fn short_write(&mut self, msg: &[u8]) {
+        debug_assert!(msg.len() <= 8);
+        let length = msg.len();
+        self.length += length;
+
+        let needed = 8 - self.ntail;
+        let fill = cmp::min(length, needed);
+        if fill == 8 {
+            self.tail = unsafe { load_int_le!(msg, 0, u64) };
+        } else {
+            self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail);
+            if length < needed {
+                self.ntail += length;
+                return;
+            }
+        }
+        self.state.v3 ^= self.tail;
+        Sip24Rounds::c_rounds(&mut self.state);
+        self.state.v0 ^= self.tail;
+
+        // Buffered tail is now flushed, process new input.
+        self.ntail = length - needed;
+        self.tail = unsafe { u8to64_le(msg, needed, self.ntail) };
+    }
+
+    #[inline(always)]
+    fn short_write_gen<T>(&mut self, x: T) {
+        let bytes = unsafe {
+            slice::from_raw_parts(&x as *const T as *const u8, mem::size_of::<T>())
+        };
+        self.short_write(bytes);
+    }
+
+    #[inline]
+    pub fn finish128(mut self) -> (u64, u64) {
+        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
+
+        self.state.v3 ^= b;
+        Sip24Rounds::c_rounds(&mut self.state);
+        self.state.v0 ^= b;
+
+        self.state.v2 ^= 0xee;
+        Sip24Rounds::d_rounds(&mut self.state);
+        let _0 = self.state.v0 ^ self.state.v1 ^ self.state.v2 ^ self.state.v3;
+
+        self.state.v1 ^= 0xdd;
+        Sip24Rounds::d_rounds(&mut self.state);
+        let _1 = self.state.v0 ^ self.state.v1 ^ self.state.v2 ^ self.state.v3;
+        (_0, _1)
+    }
+}
+
+impl Hasher for SipHasher128 {
+    #[inline]
+    fn write_u8(&mut self, i: u8) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_u16(&mut self, i: u16) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_u32(&mut self, i: u32) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_u64(&mut self, i: u64) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_usize(&mut self, i: usize) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_i8(&mut self, i: i8) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_i16(&mut self, i: i16) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_i32(&mut self, i: i32) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_i64(&mut self, i: i64) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write_isize(&mut self, i: isize) {
+        self.short_write_gen(i);
+    }
+
+    #[inline]
+    fn write(&mut self, msg: &[u8]) {
+        let length = msg.len();
+        self.length += length;
+
+        let mut needed = 0;
+
+        if self.ntail != 0 {
+            needed = 8 - self.ntail;
+            self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail;
+            if length < needed {
+                self.ntail += length;
+                return
+            } else {
+                self.state.v3 ^= self.tail;
+                Sip24Rounds::c_rounds(&mut self.state);
+                self.state.v0 ^= self.tail;
+                self.ntail = 0;
+            }
+        }
+
+        // Buffered tail is now flushed, process new input.
+        let len = length - needed;
+        let left = len & 0x7;
+
+        let mut i = needed;
+        while i < len - left {
+            let mi = unsafe { load_int_le!(msg, i, u64) };
+
+            self.state.v3 ^= mi;
+            Sip24Rounds::c_rounds(&mut self.state);
+            self.state.v0 ^= mi;
+
+            i += 8;
+        }
+
+        self.tail = unsafe { u8to64_le(msg, i, left) };
+        self.ntail = left;
+    }
+
+    fn finish(&self) -> u64 {
+        panic!("SipHasher128 cannot provide valid 64 bit hashes")
+    }
+}
+
+#[derive(Debug, Clone, Default)]
+struct Sip24Rounds;
+
+impl Sip24Rounds {
+    #[inline]
+    fn c_rounds(state: &mut State) {
+        compress!(state);
+        compress!(state);
+    }
+
+    #[inline]
+    fn d_rounds(state: &mut State) {
+        compress!(state);
+        compress!(state);
+        compress!(state);
+        compress!(state);
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::hash::{Hash, Hasher};
+    use std::{slice, mem};
+    use super::SipHasher128;
+
+    // Hash just the bytes of the slice, without length prefix
+    struct Bytes<'a>(&'a [u8]);
+
+    impl<'a> Hash for Bytes<'a> {
+        #[allow(unused_must_use)]
+        fn hash<H: Hasher>(&self, state: &mut H) {
+            for byte in self.0 {
+                state.write_u8(*byte);
+            }
+        }
+    }
+
+    fn hash_with<T: Hash>(mut st: SipHasher128, x: &T) -> (u64, u64) {
+        x.hash(&mut st);
+        st.finish128()
+    }
+
+    fn hash<T: Hash>(x: &T) -> (u64, u64) {
+        hash_with(SipHasher128::new_with_keys(0, 0), x)
+    }
+
+    const TEST_VECTOR : [[u8; 16]; 64] = [
+        [0xa3,0x81,0x7f,0x04,0xba,0x25,0xa8,0xe6,0x6d,0xf6,0x72,0x14,0xc7,0x55,0x02,0x93],
+        [0xda,0x87,0xc1,0xd8,0x6b,0x99,0xaf,0x44,0x34,0x76,0x59,0x11,0x9b,0x22,0xfc,0x45],
+        [0x81,0x77,0x22,0x8d,0xa4,0xa4,0x5d,0xc7,0xfc,0xa3,0x8b,0xde,0xf6,0x0a,0xff,0xe4],
+        [0x9c,0x70,0xb6,0x0c,0x52,0x67,0xa9,0x4e,0x5f,0x33,0xb6,0xb0,0x29,0x85,0xed,0x51],
+        [0xf8,0x81,0x64,0xc1,0x2d,0x9c,0x8f,0xaf,0x7d,0x0f,0x6e,0x7c,0x7b,0xcd,0x55,0x79],
+        [0x13,0x68,0x87,0x59,0x80,0x77,0x6f,0x88,0x54,0x52,0x7a,0x07,0x69,0x0e,0x96,0x27],
+        [0x14,0xee,0xca,0x33,0x8b,0x20,0x86,0x13,0x48,0x5e,0xa0,0x30,0x8f,0xd7,0xa1,0x5e],
+        [0xa1,0xf1,0xeb,0xbe,0xd8,0xdb,0xc1,0x53,0xc0,0xb8,0x4a,0xa6,0x1f,0xf0,0x82,0x39],
+        [0x3b,0x62,0xa9,0xba,0x62,0x58,0xf5,0x61,0x0f,0x83,0xe2,0x64,0xf3,0x14,0x97,0xb4],
+        [0x26,0x44,0x99,0x06,0x0a,0xd9,0xba,0xab,0xc4,0x7f,0x8b,0x02,0xbb,0x6d,0x71,0xed],
+        [0x00,0x11,0x0d,0xc3,0x78,0x14,0x69,0x56,0xc9,0x54,0x47,0xd3,0xf3,0xd0,0xfb,0xba],
+        [0x01,0x51,0xc5,0x68,0x38,0x6b,0x66,0x77,0xa2,0xb4,0xdc,0x6f,0x81,0xe5,0xdc,0x18],
+        [0xd6,0x26,0xb2,0x66,0x90,0x5e,0xf3,0x58,0x82,0x63,0x4d,0xf6,0x85,0x32,0xc1,0x25],
+        [0x98,0x69,0xe2,0x47,0xe9,0xc0,0x8b,0x10,0xd0,0x29,0x93,0x4f,0xc4,0xb9,0x52,0xf7],
+        [0x31,0xfc,0xef,0xac,0x66,0xd7,0xde,0x9c,0x7e,0xc7,0x48,0x5f,0xe4,0x49,0x49,0x02],
+        [0x54,0x93,0xe9,0x99,0x33,0xb0,0xa8,0x11,0x7e,0x08,0xec,0x0f,0x97,0xcf,0xc3,0xd9],
+        [0x6e,0xe2,0xa4,0xca,0x67,0xb0,0x54,0xbb,0xfd,0x33,0x15,0xbf,0x85,0x23,0x05,0x77],
+        [0x47,0x3d,0x06,0xe8,0x73,0x8d,0xb8,0x98,0x54,0xc0,0x66,0xc4,0x7a,0xe4,0x77,0x40],
+        [0xa4,0x26,0xe5,0xe4,0x23,0xbf,0x48,0x85,0x29,0x4d,0xa4,0x81,0xfe,0xae,0xf7,0x23],
+        [0x78,0x01,0x77,0x31,0xcf,0x65,0xfa,0xb0,0x74,0xd5,0x20,0x89,0x52,0x51,0x2e,0xb1],
+        [0x9e,0x25,0xfc,0x83,0x3f,0x22,0x90,0x73,0x3e,0x93,0x44,0xa5,0xe8,0x38,0x39,0xeb],
+        [0x56,0x8e,0x49,0x5a,0xbe,0x52,0x5a,0x21,0x8a,0x22,0x14,0xcd,0x3e,0x07,0x1d,0x12],
+        [0x4a,0x29,0xb5,0x45,0x52,0xd1,0x6b,0x9a,0x46,0x9c,0x10,0x52,0x8e,0xff,0x0a,0xae],
+        [0xc9,0xd1,0x84,0xdd,0xd5,0xa9,0xf5,0xe0,0xcf,0x8c,0xe2,0x9a,0x9a,0xbf,0x69,0x1c],
+        [0x2d,0xb4,0x79,0xae,0x78,0xbd,0x50,0xd8,0x88,0x2a,0x8a,0x17,0x8a,0x61,0x32,0xad],
+        [0x8e,0xce,0x5f,0x04,0x2d,0x5e,0x44,0x7b,0x50,0x51,0xb9,0xea,0xcb,0x8d,0x8f,0x6f],
+        [0x9c,0x0b,0x53,0xb4,0xb3,0xc3,0x07,0xe8,0x7e,0xae,0xe0,0x86,0x78,0x14,0x1f,0x66],
+        [0xab,0xf2,0x48,0xaf,0x69,0xa6,0xea,0xe4,0xbf,0xd3,0xeb,0x2f,0x12,0x9e,0xeb,0x94],
+        [0x06,0x64,0xda,0x16,0x68,0x57,0x4b,0x88,0xb9,0x35,0xf3,0x02,0x73,0x58,0xae,0xf4],
+        [0xaa,0x4b,0x9d,0xc4,0xbf,0x33,0x7d,0xe9,0x0c,0xd4,0xfd,0x3c,0x46,0x7c,0x6a,0xb7],
+        [0xea,0x5c,0x7f,0x47,0x1f,0xaf,0x6b,0xde,0x2b,0x1a,0xd7,0xd4,0x68,0x6d,0x22,0x87],
+        [0x29,0x39,0xb0,0x18,0x32,0x23,0xfa,0xfc,0x17,0x23,0xde,0x4f,0x52,0xc4,0x3d,0x35],
+        [0x7c,0x39,0x56,0xca,0x5e,0xea,0xfc,0x3e,0x36,0x3e,0x9d,0x55,0x65,0x46,0xeb,0x68],
+        [0x77,0xc6,0x07,0x71,0x46,0xf0,0x1c,0x32,0xb6,0xb6,0x9d,0x5f,0x4e,0xa9,0xff,0xcf],
+        [0x37,0xa6,0x98,0x6c,0xb8,0x84,0x7e,0xdf,0x09,0x25,0xf0,0xf1,0x30,0x9b,0x54,0xde],
+        [0xa7,0x05,0xf0,0xe6,0x9d,0xa9,0xa8,0xf9,0x07,0x24,0x1a,0x2e,0x92,0x3c,0x8c,0xc8],
+        [0x3d,0xc4,0x7d,0x1f,0x29,0xc4,0x48,0x46,0x1e,0x9e,0x76,0xed,0x90,0x4f,0x67,0x11],
+        [0x0d,0x62,0xbf,0x01,0xe6,0xfc,0x0e,0x1a,0x0d,0x3c,0x47,0x51,0xc5,0xd3,0x69,0x2b],
+        [0x8c,0x03,0x46,0x8b,0xca,0x7c,0x66,0x9e,0xe4,0xfd,0x5e,0x08,0x4b,0xbe,0xe7,0xb5],
+        [0x52,0x8a,0x5b,0xb9,0x3b,0xaf,0x2c,0x9c,0x44,0x73,0xcc,0xe5,0xd0,0xd2,0x2b,0xd9],
+        [0xdf,0x6a,0x30,0x1e,0x95,0xc9,0x5d,0xad,0x97,0xae,0x0c,0xc8,0xc6,0x91,0x3b,0xd8],
+        [0x80,0x11,0x89,0x90,0x2c,0x85,0x7f,0x39,0xe7,0x35,0x91,0x28,0x5e,0x70,0xb6,0xdb],
+        [0xe6,0x17,0x34,0x6a,0xc9,0xc2,0x31,0xbb,0x36,0x50,0xae,0x34,0xcc,0xca,0x0c,0x5b],
+        [0x27,0xd9,0x34,0x37,0xef,0xb7,0x21,0xaa,0x40,0x18,0x21,0xdc,0xec,0x5a,0xdf,0x89],
+        [0x89,0x23,0x7d,0x9d,0xed,0x9c,0x5e,0x78,0xd8,0xb1,0xc9,0xb1,0x66,0xcc,0x73,0x42],
+        [0x4a,0x6d,0x80,0x91,0xbf,0x5e,0x7d,0x65,0x11,0x89,0xfa,0x94,0xa2,0x50,0xb1,0x4c],
+        [0x0e,0x33,0xf9,0x60,0x55,0xe7,0xae,0x89,0x3f,0xfc,0x0e,0x3d,0xcf,0x49,0x29,0x02],
+        [0xe6,0x1c,0x43,0x2b,0x72,0x0b,0x19,0xd1,0x8e,0xc8,0xd8,0x4b,0xdc,0x63,0x15,0x1b],
+        [0xf7,0xe5,0xae,0xf5,0x49,0xf7,0x82,0xcf,0x37,0x90,0x55,0xa6,0x08,0x26,0x9b,0x16],
+        [0x43,0x8d,0x03,0x0f,0xd0,0xb7,0xa5,0x4f,0xa8,0x37,0xf2,0xad,0x20,0x1a,0x64,0x03],
+        [0xa5,0x90,0xd3,0xee,0x4f,0xbf,0x04,0xe3,0x24,0x7e,0x0d,0x27,0xf2,0x86,0x42,0x3f],
+        [0x5f,0xe2,0xc1,0xa1,0x72,0xfe,0x93,0xc4,0xb1,0x5c,0xd3,0x7c,0xae,0xf9,0xf5,0x38],
+        [0x2c,0x97,0x32,0x5c,0xbd,0x06,0xb3,0x6e,0xb2,0x13,0x3d,0xd0,0x8b,0x3a,0x01,0x7c],
+        [0x92,0xc8,0x14,0x22,0x7a,0x6b,0xca,0x94,0x9f,0xf0,0x65,0x9f,0x00,0x2a,0xd3,0x9e],
+        [0xdc,0xe8,0x50,0x11,0x0b,0xd8,0x32,0x8c,0xfb,0xd5,0x08,0x41,0xd6,0x91,0x1d,0x87],
+        [0x67,0xf1,0x49,0x84,0xc7,0xda,0x79,0x12,0x48,0xe3,0x2b,0xb5,0x92,0x25,0x83,0xda],
+        [0x19,0x38,0xf2,0xcf,0x72,0xd5,0x4e,0xe9,0x7e,0x94,0x16,0x6f,0xa9,0x1d,0x2a,0x36],
+        [0x74,0x48,0x1e,0x96,0x46,0xed,0x49,0xfe,0x0f,0x62,0x24,0x30,0x16,0x04,0x69,0x8e],
+        [0x57,0xfc,0xa5,0xde,0x98,0xa9,0xd6,0xd8,0x00,0x64,0x38,0xd0,0x58,0x3d,0x8a,0x1d],
+        [0x9f,0xec,0xde,0x1c,0xef,0xdc,0x1c,0xbe,0xd4,0x76,0x36,0x74,0xd9,0x57,0x53,0x59],
+        [0xe3,0x04,0x0c,0x00,0xeb,0x28,0xf1,0x53,0x66,0xca,0x73,0xcb,0xd8,0x72,0xe7,0x40],
+        [0x76,0x97,0x00,0x9a,0x6a,0x83,0x1d,0xfe,0xcc,0xa9,0x1c,0x59,0x93,0x67,0x0f,0x7a],
+        [0x58,0x53,0x54,0x23,0x21,0xf5,0x67,0xa0,0x05,0xd5,0x47,0xa4,0xf0,0x47,0x59,0xbd],
+        [0x51,0x50,0xd1,0x77,0x2f,0x50,0x83,0x4a,0x50,0x3e,0x06,0x9a,0x97,0x3f,0xbd,0x7c],
+    ];
+
+    // Test vector from reference implementation
+    #[test]
+    fn test_siphash_2_4_test_vector() {
+        let k0 = 0x_07_06_05_04_03_02_01_00;
+        let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+
+        let mut input: Vec<u8> = Vec::new();
+
+        for i in 0 .. 64 {
+            let out = hash_with(SipHasher128::new_with_keys(k0, k1),
+                                &Bytes(&input[..]));
+            let expected = (
+                ((TEST_VECTOR[i][0] as u64) <<  0) |
+                ((TEST_VECTOR[i][1] as u64) <<  8) |
+                ((TEST_VECTOR[i][2] as u64) << 16) |
+                ((TEST_VECTOR[i][3] as u64) << 24) |
+                ((TEST_VECTOR[i][4] as u64) << 32) |
+                ((TEST_VECTOR[i][5] as u64) << 40) |
+                ((TEST_VECTOR[i][6] as u64) << 48) |
+                ((TEST_VECTOR[i][7] as u64) << 56),
+
+                ((TEST_VECTOR[i][8] as u64) <<  0) |
+                ((TEST_VECTOR[i][9] as u64) <<  8) |
+                ((TEST_VECTOR[i][10] as u64) << 16) |
+                ((TEST_VECTOR[i][11] as u64) << 24) |
+                ((TEST_VECTOR[i][12] as u64) << 32) |
+                ((TEST_VECTOR[i][13] as u64) << 40) |
+                ((TEST_VECTOR[i][14] as u64) << 48) |
+                ((TEST_VECTOR[i][15] as u64) << 56),
+            );
+
+            assert_eq!(out, expected);
+            input.push(i as u8);
+        }
+    }
+
+    #[test] #[cfg(target_arch = "arm")]
+    fn test_hash_usize() {
+        let val = 0xdeadbeef_deadbeef_u64;
+        assert!(hash(&(val as u64)) != hash(&(val as usize)));
+        assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+    }
+    #[test] #[cfg(target_arch = "x86_64")]
+    fn test_hash_usize() {
+        let val = 0xdeadbeef_deadbeef_u64;
+        assert_eq!(hash(&(val as u64)), hash(&(val as usize)));
+        assert!(hash(&(val as u32)) != hash(&(val as usize)));
+    }
+    #[test] #[cfg(target_arch = "x86")]
+    fn test_hash_usize() {
+        let val = 0xdeadbeef_deadbeef_u64;
+        assert!(hash(&(val as u64)) != hash(&(val as usize)));
+        assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+    }
+
+    #[test]
+    fn test_hash_idempotent() {
+        let val64 = 0xdeadbeef_deadbeef_u64;
+        assert_eq!(hash(&val64), hash(&val64));
+        let val32 = 0xdeadbeef_u32;
+        assert_eq!(hash(&val32), hash(&val32));
+    }
+
+    #[test]
+    fn test_hash_no_bytes_dropped_64() {
+        let val = 0xdeadbeef_deadbeef_u64;
+
+        assert!(hash(&val) != hash(&zero_byte(val, 0)));
+        assert!(hash(&val) != hash(&zero_byte(val, 1)));
+        assert!(hash(&val) != hash(&zero_byte(val, 2)));
+        assert!(hash(&val) != hash(&zero_byte(val, 3)));
+        assert!(hash(&val) != hash(&zero_byte(val, 4)));
+        assert!(hash(&val) != hash(&zero_byte(val, 5)));
+        assert!(hash(&val) != hash(&zero_byte(val, 6)));
+        assert!(hash(&val) != hash(&zero_byte(val, 7)));
+
+        fn zero_byte(val: u64, byte: usize) -> u64 {
+            assert!(byte < 8);
+            val & !(0xff << (byte * 8))
+        }
+    }
+
+    #[test]
+    fn test_hash_no_bytes_dropped_32() {
+        let val = 0xdeadbeef_u32;
+
+        assert!(hash(&val) != hash(&zero_byte(val, 0)));
+        assert!(hash(&val) != hash(&zero_byte(val, 1)));
+        assert!(hash(&val) != hash(&zero_byte(val, 2)));
+        assert!(hash(&val) != hash(&zero_byte(val, 3)));
+
+        fn zero_byte(val: u32, byte: usize) -> u32 {
+            assert!(byte < 4);
+            val & !(0xff << (byte * 8))
+        }
+    }
+
+    #[test]
+    fn test_hash_no_concat_alias() {
+        let s = ("aa", "bb");
+        let t = ("aabb", "");
+        let u = ("a", "abb");
+
+        assert!(s != t && t != u);
+        assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
+
+        let u = [1, 0, 0, 0];
+        let v = (&u[..1], &u[1..3], &u[3..]);
+        let w = (&u[..], &u[4..4], &u[4..4]);
+
+        assert!(v != w);
+        assert!(hash(&v) != hash(&w));
+    }
+
+    #[test]
+    fn test_write_short_works() {
+        let test_usize = 0xd0c0b0a0usize;
+        let mut h1 = SipHasher128::new_with_keys(0, 0);
+        h1.write_usize(test_usize);
+        h1.write(b"bytes");
+        h1.write(b"string");
+        h1.write_u8(0xFFu8);
+        h1.write_u8(0x01u8);
+        let mut h2 = SipHasher128::new_with_keys(0, 0);
+        h2.write(unsafe {
+            slice::from_raw_parts(&test_usize as *const _ as *const u8,
+                                  mem::size_of::<usize>())
+        });
+        h2.write(b"bytes");
+        h2.write(b"string");
+        h2.write(&[0xFFu8, 0x01u8]);
+        assert_eq!(h1.finish128(), h2.finish128());
+    }
+
+}
index 9aba48c5bef07b60b5f065f15125977056415f9b..831e113016fd903728c5fe3a8c54301dea745f43 100644 (file)
 use std::hash::{Hash, Hasher, BuildHasher};
 use std::marker::PhantomData;
 use std::mem;
-use blake2b::Blake2bHasher;
-use rustc_serialize::leb128;
-
-fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize {
-    leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v)
-}
-
-fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
-    leb128::write_signed_leb128_to(value as i128, |i, v| buf[i] = v)
-}
+use sip128::SipHasher128;
 
 /// When hashing something that ends up affecting properties like symbol names. We
 /// want these symbol names to be calculated independent of other factors like
@@ -41,7 +32,7 @@
 /// and allows for variable output lengths through its type
 /// parameter.
 pub struct StableHasher<W> {
-    state: Blake2bHasher,
+    state: SipHasher128,
     bytes_hashed: u64,
     width: PhantomData<W>,
 }
@@ -59,7 +50,7 @@ pub trait StableHasherResult: Sized {
 impl<W: StableHasherResult> StableHasher<W> {
     pub fn new() -> Self {
         StableHasher {
-            state: Blake2bHasher::new(mem::size_of::<W>(), &[]),
+            state: SipHasher128::new_with_keys(0, 0),
             bytes_hashed: 0,
             width: PhantomData,
         }
@@ -70,58 +61,29 @@ pub fn finish(self) -> W {
     }
 }
 
-impl StableHasherResult for [u8; 20] {
-    fn finish(mut hasher: StableHasher<Self>) -> Self {
-        let mut result: [u8; 20] = [0; 20];
-        result.copy_from_slice(hasher.state.finalize());
-        result
-    }
-}
-
 impl StableHasherResult for u128 {
-    fn finish(mut hasher: StableHasher<Self>) -> Self {
-        let hash_bytes: &[u8] = hasher.finalize();
-        assert!(hash_bytes.len() >= mem::size_of::<u128>());
-
-        unsafe {
-            ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128)
-        }
+    fn finish(hasher: StableHasher<Self>) -> Self {
+        let (_0, _1) = hasher.finalize();
+        (_0 as u128) | ((_1 as u128) << 64)
     }
 }
 
 impl StableHasherResult for u64 {
-    fn finish(mut hasher: StableHasher<Self>) -> Self {
-        hasher.state.finalize();
-        hasher.state.finish()
+    fn finish(hasher: StableHasher<Self>) -> Self {
+        hasher.finalize().0
     }
 }
 
 impl<W> StableHasher<W> {
     #[inline]
-    pub fn finalize(&mut self) -> &[u8] {
-        self.state.finalize()
+    pub fn finalize(self) -> (u64, u64) {
+        self.state.finish128()
     }
 
     #[inline]
     pub fn bytes_hashed(&self) -> u64 {
         self.bytes_hashed
     }
-
-    #[inline]
-    fn write_uleb128(&mut self, value: u64) {
-        let mut buf = [0; 16];
-        let len = write_unsigned_leb128_to_buf(&mut buf, value);
-        self.state.write(&buf[..len]);
-        self.bytes_hashed += len as u64;
-    }
-
-    #[inline]
-    fn write_ileb128(&mut self, value: i64) {
-        let mut buf = [0; 16];
-        let len = write_signed_leb128_to_buf(&mut buf, value);
-        self.state.write(&buf[..len]);
-        self.bytes_hashed += len as u64;
-    }
 }
 
 // For the non-u8 integer cases we leb128 encode them first. Because small
@@ -129,7 +91,7 @@ fn write_ileb128(&mut self, value: i64) {
 // bytes hashed, which is good because blake2b is expensive.
 impl<W> Hasher for StableHasher<W> {
     fn finish(&self) -> u64 {
-        panic!("use StableHasher::finish instead");
+        panic!("use StableHasher::finalize instead");
     }
 
     #[inline]
@@ -146,22 +108,32 @@ fn write_u8(&mut self, i: u8) {
 
     #[inline]
     fn write_u16(&mut self, i: u16) {
-        self.write_uleb128(i as u64);
+        self.state.write_u16(i.to_le());
+        self.bytes_hashed += 2;
     }
 
     #[inline]
     fn write_u32(&mut self, i: u32) {
-        self.write_uleb128(i as u64);
+        self.state.write_u32(i.to_le());
+        self.bytes_hashed += 4;
     }
 
     #[inline]
     fn write_u64(&mut self, i: u64) {
-        self.write_uleb128(i);
+        self.state.write_u64(i.to_le());
+        self.bytes_hashed += 8;
+    }
+
+    #[inline]
+    fn write_u128(&mut self, i: u128) {
+        self.state.write_u128(i.to_le());
+        self.bytes_hashed += 16;
     }
 
     #[inline]
     fn write_usize(&mut self, i: usize) {
-        self.write_uleb128(i as u64);
+        self.state.write_usize(i.to_le());
+        self.bytes_hashed += ::std::mem::size_of::<usize>() as u64;
     }
 
     #[inline]
@@ -172,22 +144,32 @@ fn write_i8(&mut self, i: i8) {
 
     #[inline]
     fn write_i16(&mut self, i: i16) {
-        self.write_ileb128(i as i64);
+        self.state.write_i16(i.to_le());
+        self.bytes_hashed += 2;
     }
 
     #[inline]
     fn write_i32(&mut self, i: i32) {
-        self.write_ileb128(i as i64);
+        self.state.write_i32(i.to_le());
+        self.bytes_hashed += 4;
     }
 
     #[inline]
     fn write_i64(&mut self, i: i64) {
-        self.write_ileb128(i);
+        self.state.write_i64(i.to_le());
+        self.bytes_hashed += 8;
+    }
+
+    #[inline]
+    fn write_i128(&mut self, i: i128) {
+        self.state.write_i128(i.to_le());
+        self.bytes_hashed += 16;
     }
 
     #[inline]
     fn write_isize(&mut self, i: isize) {
-        self.write_ileb128(i as i64);
+        self.state.write_isize(i.to_le());
+        self.bytes_hashed += ::std::mem::size_of::<isize>() as u64;
     }
 }
 
index ad6f7fbf1119bf97ca375583813afd9ba84d14e9..7dbf93da38598d15476770230b867dd46fe1c1d8 100644 (file)
@@ -38,7 +38,7 @@
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
-use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
+use rustc_passes::{self, ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
 use rustc_const_eval::{self, check_match};
 use super::Compilation;
 use ::DefaultTransCrate;
@@ -973,6 +973,7 @@ macro_rules! try_with_f {
     traits::provide(&mut local_providers);
     reachable::provide(&mut local_providers);
     rustc_const_eval::provide(&mut local_providers);
+    rustc_passes::provide(&mut local_providers);
     middle::region::provide(&mut local_providers);
     cstore::provide_local(&mut local_providers);
     lint::provide(&mut local_providers);
index 7f331418d4242193bf597e6063fe5ef2551df518..bc2a1f08441d1a57582e645ce8e96ac2613e171c 100644 (file)
@@ -44,7 +44,7 @@
 use syntax::ast;
 use syntax::attr;
 use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
-use syntax_pos::{Span, SyntaxContext};
+use syntax_pos::{BytePos, Span, SyntaxContext};
 use syntax::symbol::keywords;
 
 use rustc::hir::{self, PatKind};
@@ -153,7 +153,7 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
 declare_lint! {
     NON_SHORTHAND_FIELD_PATTERNS,
     Warn,
-    "using `Struct { x: x }` instead of `Struct { x }`"
+    "using `Struct { x: x }` instead of `Struct { x }` in a pattern"
 }
 
 #[derive(Copy, Clone)]
@@ -174,11 +174,15 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                 }
                 if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
                     if ident.node == fieldpat.node.name {
-                        cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS,
+                        let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
                                      fieldpat.span,
-                                     &format!("the `{}:` in this pattern is redundant and can \
-                                              be removed",
-                                              ident.node))
+                                     &format!("the `{}:` in this pattern is redundant",
+                                              ident.node));
+                        let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':');
+                        err.span_suggestion_short(subspan,
+                                                  "remove this",
+                                                  format!("{}", ident.node));
+                        err.emit();
                     }
                 }
             }
@@ -894,7 +898,6 @@ fn check_fn(&mut self,
             let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION,
                                              sp,
                                              "function cannot return without recurring");
-            // FIXME #19668: these could be span_lint_note's instead of this manual guard.
             // offer some help to the programmer.
             for call in &self_call_spans {
                 db.span_note(*call, "recursive call site");
@@ -1130,35 +1133,55 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
             hir::ItemFn(.., ref generics, _) => {
-                if attr::contains_name(&it.attrs, "no_mangle") &&
-                   !attr::contains_name(&it.attrs, "linkage") {
+                if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
+                    if attr::contains_name(&it.attrs, "linkage") {
+                        return;
+                    }
                     if !cx.access_levels.is_reachable(it.id) {
-                        let msg = format!("function {} is marked #[no_mangle], but not exported",
-                                          it.name);
-                        cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
+                        let msg = "function is marked #[no_mangle], but not exported";
+                        let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
+                        let insertion_span = it.span.with_hi(it.span.lo());
+                        err.span_suggestion(insertion_span,
+                                            "try making it public",
+                                            "pub ".to_owned());
+                        err.emit();
                     }
                     if generics.is_type_parameterized() {
-                        cx.span_lint(NO_MANGLE_GENERIC_ITEMS,
-                                     it.span,
-                                     "functions generic over types must be mangled");
+                        let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
+                                                          it.span,
+                                                          "functions generic over \
+                                                           types must be mangled");
+                        err.span_suggestion_short(no_mangle_attr.span,
+                                                  "remove this attribute",
+                                                  "".to_owned());
+                        err.emit();
                     }
                 }
             }
             hir::ItemStatic(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") &&
                    !cx.access_levels.is_reachable(it.id) {
-                    let msg = format!("static {} is marked #[no_mangle], but not exported",
-                                      it.name);
-                    cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
+                       let msg = "static is marked #[no_mangle], but not exported";
+                       let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
+                       let insertion_span = it.span.with_hi(it.span.lo());
+                       err.span_suggestion(insertion_span,
+                                           "try making it public",
+                                           "pub ".to_owned());
+                       err.emit();
                 }
             }
             hir::ItemConst(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") {
                     // Const items do not refer to a particular location in memory, and therefore
                     // don't have anything to attach a symbol to
-                    let msg = "const items should never be #[no_mangle], consider instead using \
-                               `pub static`";
-                    cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
+                    let msg = "const items should never be #[no_mangle]";
+                    let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
+                    // `const` is 5 chars
+                    let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5));
+                    err.span_suggestion(const_span,
+                                        "try a static value",
+                                        "pub static".to_owned());
+                    err.emit();
                 }
             }
             _ => {}
index d9ab2562efff26b87d70643bea77b9504c2d3ca2..722d0cad238f4f3f3eead66a3eb54e39626ce9c9 100644 (file)
@@ -56,7 +56,8 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         };
 
         let lazy_body = self.lazy(body);
-        let tables = self.tcx.body_tables(body_id);
+        let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
+        let tables = self.tcx.typeck_tables_of(body_owner_def_id);
         let lazy_tables = self.lazy(tables);
 
         let mut visitor = NestedBodyCollector {
@@ -67,7 +68,7 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
 
         let rvalue_promotable_to_static =
-            self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
+            self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
 
         self.lazy(&Ast {
             body: lazy_body,
index 6e3eef5735233aaf8a0ecf589f28f64f3a10a75a..9b3f16f1ab4326b06369a1301008912449f1bb50 100644 (file)
@@ -26,7 +26,6 @@
 use build::matches::{Binding, MatchPair, Candidate};
 use hair::*;
 use rustc::mir::*;
-use rustc_data_structures::fx::FxHashMap;
 
 use std::mem;
 
@@ -102,12 +101,7 @@ fn simplify_match_pair<'pat>(&mut self,
                 if self.hir.tcx().sess.features.borrow().never_type {
                     let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
                         i == variant_index || {
-                            let mut visited = FxHashMap::default();
-                            let node_set = v.uninhabited_from(&mut visited,
-                                                              self.hir.tcx(),
-                                                              substs,
-                                                              adt_def.adt_kind());
-                            !node_set.is_empty()
+                            self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
                         }
                     });
                     if irrefutable {
index 98c5345c69d35fbc25c6d8d6260bd693e5d422eb..0f67f7bf6deb47fe14cdd2881b5d085703036ff0 100644 (file)
@@ -320,20 +320,68 @@ fn main() {
 of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
 of workarounds like `Rc`, a value cannot be owned by more than one variable.
 
-If we own the type, the easiest way to address this problem is to implement
-`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
-information in `x`, while leaving the original version owned by `x`. Subsequent
-changes to `x` will not be reflected when accessing `y`.
+Sometimes we don't need to move the value. Using a reference, we can let another
+function borrow the value without changing its ownership. In the example below,
+we don't actually have to move our string to `calculate_length`, we can give it
+a reference to it with `&` instead.
+
+```
+fn main() {
+    let s1 = String::from("hello");
+
+    let len = calculate_length(&s1);
+
+    println!("The length of '{}' is {}.", s1, len);
+}
+
+fn calculate_length(s: &String) -> usize {
+    s.len()
+}
+```
+
+A mutable reference can be created with `&mut`.
+
+Sometimes we don't want a reference, but a duplicate. All types marked `Clone`
+can be duplicated by calling `.clone()`. Subsequent changes to a clone do not
+affect the original variable.
+
+Most types in the standard library are marked `Clone`. The example below
+demonstrates using `clone()` on a string. `s1` is first set to "many", and then
+copied to `s2`. Then the first character of `s1` is removed, without affecting
+`s2`. "any many" is printed to the console.
+
+```
+fn main() {
+    let mut s1 = String::from("many");
+    let s2 = s1.clone();
+    s1.remove(0);
+    println!("{} {}", s1, s2);
+}
+```
+
+If we control the definition of a type, we can implement `Clone` on it ourselves
+with `#[derive(Clone)]`.
+
+Some types have no ownership semantics at all and are trivial to duplicate. An
+example is `i32` and the other number types. We don't have to call `.clone()` to
+clone them, because they are marked `Copy` in addition to `Clone`.  Implicit
+cloning is more convienient in this case. We can mark our own types `Copy` if
+all their members also are marked `Copy`.
+
+In the example below, we implement a `Point` type. Because it only stores two
+integers, we opt-out of ownership semantics with `Copy`. Then we can
+`let p2 = p1` without `p1` being moved.
 
 ```
 #[derive(Copy, Clone)]
-struct MyStruct { s: u32 }
+struct Point { x: i32, y: i32 }
 
 fn main() {
-    let mut x = MyStruct{ s: 5u32 };
-    let y = x;
-    x.s = 6;
-    println!("{}", x.s);
+    let mut p1 = Point{ x: -1, y: 2 };
+    let p2 = p1;
+    p1.x = 1;
+    println!("p1: {}, {}", p1.x, p1.y);
+    println!("p2: {}, {}", p2.x, p2.y);
 }
 ```
 
index 547d63fc3d4aa68f58b400bc7aa9b7a14b3a4767..d3202ba4ab53548bad0e0353c30e1eb62ef8e80d 100644 (file)
 use rustc::middle::mem_categorization::Categorization;
 use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::maps::{queries, Providers};
 use rustc::ty::subst::Substs;
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
-use rustc::util::nodemap::NodeSet;
+use rustc::util::nodemap::{ItemLocalMap, NodeSet};
 use rustc::lint::builtin::CONST_ERR;
-
 use rustc::hir::{self, PatKind, RangeEnd};
+use std::rc::Rc;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 
-use std::collections::hash_map::Entry;
 use std::cmp::Ordering;
 
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        rvalue_promotable_map,
+        const_is_rvalue_promotable_to_static,
+        ..*providers
+    };
+}
+
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    for &body_id in &tcx.hir.krate().body_ids {
+        let def_id = tcx.hir.body_owner_def_id(body_id);
+        tcx.const_is_rvalue_promotable_to_static(def_id);
+    }
+    tcx.sess.abort_if_errors();
+}
+
+fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                  def_id: DefId)
+                                                  -> bool
+{
+    assert!(def_id.is_local());
+
+    let node_id = tcx.hir.as_local_node_id(def_id)
+                     .expect("rvalue_promotable_map invoked with non-local def-id");
+    let body_id = tcx.hir.body_owned_by(node_id);
+    let body_hir_id = tcx.hir.node_to_hir_id(body_id.node_id);
+    tcx.rvalue_promotable_map(def_id).contains_key(&body_hir_id.local_id)
+}
+
+fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   def_id: DefId)
+                                   -> Rc<ItemLocalMap<bool>>
+{
+    let outer_def_id = tcx.closure_base_def_id(def_id);
+    if outer_def_id != def_id {
+        return tcx.rvalue_promotable_map(outer_def_id);
+    }
+
+    let mut visitor = CheckCrateVisitor {
+        tcx,
+        tables: &ty::TypeckTables::empty(None),
+        in_fn: false,
+        in_static: false,
+        promotable: false,
+        mut_rvalue_borrows: NodeSet(),
+        param_env: ty::ParamEnv::empty(Reveal::UserFacing),
+        identity_substs: Substs::empty(),
+        result_map: ItemLocalMap(),
+    };
+
+    // `def_id` should be a `Body` owner
+    let node_id = tcx.hir.as_local_node_id(def_id)
+                     .expect("rvalue_promotable_map invoked with non-local def-id");
+    let body_id = tcx.hir.body_owned_by(node_id);
+    visitor.visit_nested_body(body_id);
+
+    Rc::new(visitor.result_map)
+}
+
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     in_fn: bool,
@@ -62,6 +121,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     identity_substs: &'tcx Substs<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
+    result_map: ItemLocalMap<bool>,
 }
 
 impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
@@ -109,18 +169,11 @@ fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>) {
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        // note that we *do* visit nested bodies, because we override `visit_nested_body` below
         NestedVisitorMap::None
     }
 
     fn visit_nested_body(&mut self, body_id: hir::BodyId) {
-        match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body_id.node_id) {
-            Entry::Occupied(_) => return,
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(false);
-            }
-        }
-
         let item_id = self.tcx.hir.body_owner(body_id);
         let item_def_id = self.tcx.hir.local_def_id(item_id);
 
@@ -151,7 +204,7 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         let tcx = self.tcx;
         let param_env = self.param_env;
         let region_scope_tree = self.tcx.region_scope_tree(item_def_id);
-        euv::ExprUseVisitor::new(self, tcx, param_env, &region_scope_tree, self.tables)
+        euv::ExprUseVisitor::new(self, tcx, param_env, &region_scope_tree, self.tables, None)
             .consume_body(body);
 
         self.visit_body(body);
@@ -270,7 +323,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
             }
         }
 
-        self.tcx.rvalue_promotable_to_static.borrow_mut().insert(ex.id, self.promotable);
+        self.result_map.insert(ex.hir_id.local_id, self.promotable);
         self.promotable &= outer;
     }
 }
@@ -371,16 +424,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
                     let promotable = if v.tcx.trait_of_item(did).is_some() {
                         // Don't peek inside trait associated constants.
                         false
-                    } else if let Some(node_id) = v.tcx.hir.as_local_node_id(did) {
-                        match v.tcx.hir.maybe_body_owned_by(node_id) {
-                            Some(body) => {
-                                v.visit_nested_body(body);
-                                v.tcx.rvalue_promotable_to_static.borrow()[&body.node_id]
-                            }
-                            None => false
-                        }
                     } else {
-                        v.tcx.const_is_rvalue_promotable_to_static(did)
+                        queries::const_is_rvalue_promotable_to_static::try_get(v.tcx, e.span, did)
+                            .unwrap_or_else(|mut err| {
+                                // A cycle between constants ought to be reported elsewhere.
+                                err.cancel();
+                                v.tcx.sess.delay_span_bug(
+                                    e.span,
+                                    &format!("cycle encountered during const qualification: {:?}",
+                                             did));
+                                false
+                            })
                     };
 
                     // Just in case the type is more specific than the definition,
@@ -513,20 +567,6 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
     }
 }
 
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.hir.krate().visit_all_item_likes(&mut CheckCrateVisitor {
-        tcx,
-        tables: &ty::TypeckTables::empty(None),
-        in_fn: false,
-        in_static: false,
-        promotable: false,
-        mut_rvalue_borrows: NodeSet(),
-        param_env: ty::ParamEnv::empty(Reveal::UserFacing),
-        identity_substs: Substs::empty(),
-    }.as_deep_visitor());
-    tcx.sess.abort_if_errors();
-}
-
 impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
     fn consume(&mut self,
                _consume_id: ast::NodeId,
index 28b99e1185bd2d3738191b98cd317aa188370d64..9a150abea6691dd912aef649541dec6584df16f4 100644 (file)
@@ -33,6 +33,8 @@
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
 
+use rustc::ty::maps::Providers;
+
 mod diagnostics;
 
 pub mod ast_validation;
@@ -44,3 +46,7 @@
 pub mod static_recursion;
 
 __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
+
+pub fn provide(providers: &mut Providers) {
+    consts::provide(providers);
+}
index c3b6ede24b0d423179873706d7305cb4fb4c390e..6df40c34ec54ae7b820434e42a76ebf662c80d00 100644 (file)
@@ -113,6 +113,10 @@ pub fn set_dereferenceable(&mut self, bytes: u64) -> &mut Self {
         self
     }
 
+    pub fn contains(&self, attr: ArgAttribute) -> bool {
+        self.regular.contains(attr)
+    }
+
     pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
         unsafe {
             self.regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
index 8a89bfee4ac26c43626c00b1b1aeda28db437730..201d786776455483562ae6dd23976c3d0b3edf3e 100644 (file)
@@ -30,7 +30,7 @@
 use rustc::ty::subst::Substs;
 use rustc::ty::util::TypeIdHasher;
 use rustc::hir;
-use rustc_data_structures::ToHex;
+use rustc::ich::Fingerprint;
 use {type_of, machine, monomorphize};
 use common::{self, CrateContext};
 use type_::Type;
@@ -146,11 +146,10 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
 
         // The hasher we are using to generate the UniqueTypeId. We want
         // something that provides more than the 64 bits of the DefaultHasher.
-
-        let mut type_id_hasher = TypeIdHasher::<[u8; 20]>::new(cx.tcx());
+        let mut type_id_hasher = TypeIdHasher::<Fingerprint>::new(cx.tcx());
         type_id_hasher.visit_ty(type_);
-
         let unique_type_id = type_id_hasher.finish().to_hex();
+
         let key = self.unique_id_interner.intern(&unique_type_id);
         self.type_to_unique_id.insert(type_, UniqueTypeId(key));
 
index 448feb5259ddd81fe65d33ee0f2b0278e6d5aceb..4fe726364f227bc2e5d1e3ccd02b2c1142476b5e 100644 (file)
@@ -73,6 +73,8 @@ unsafe fn configure_llvm(sess: &Session) {
 
 const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];
 
+const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0"];
+
 const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                  "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                  "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
@@ -90,6 +92,7 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
 
     let whitelist = match &*sess.target.target.arch {
         "arm" => ARM_WHITELIST,
+        "aarch64" => AARCH64_WHITELIST,
         "x86" | "x86_64" => X86_WHITELIST,
         "hexagon" => HEXAGON_WHITELIST,
         "powerpc" | "powerpc64" => POWERPC_WHITELIST,
index 5206ad74e20544825e42db2f69d61643ee47c342..d5d44bfa7ba43038169add3e7f9c33ba4d4aafbc 100644 (file)
@@ -23,7 +23,7 @@
 use common::{self, CrateContext, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::Instance;
-use abi::FnType;
+use abi::{ArgAttribute, FnType};
 use type_of;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
@@ -378,6 +378,10 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
         None
     };
 
+    let deref_op = unsafe {
+        [llvm::LLVMRustDIBuilderCreateOpDeref()]
+    };
+
     mir.args_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
         let arg_ty = mircx.monomorphize(&arg_decl.ty);
@@ -432,10 +436,9 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
 
         let arg = &mircx.fn_ty.args[idx];
         idx += 1;
-        let llval = if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo {
+        let llval = if arg.is_indirect() {
             // Don't copy an indirect argument to an alloca, the caller
-            // already put it in a temporary alloca and gave it up, unless
-            // we emit extra-debug-info, which requires local allocas :(.
+            // already put it in a temporary alloca and gave it up
             // FIXME: lifetimes
             if arg.pad.is_some() {
                 llarg_idx += 1;
@@ -444,8 +447,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             llarg_idx += 1;
             llarg
         } else if !lvalue_locals.contains(local.index()) &&
-                  !arg.is_indirect() && arg.cast.is_none() &&
-                  arg_scope.is_none() {
+                  arg.cast.is_none() && arg_scope.is_none() {
             if arg.is_ignore() {
                 return LocalRef::new_operand(bcx.ccx, arg_ty);
             }
@@ -510,13 +512,26 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
         arg_scope.map(|scope| {
             // Is this a regular argument?
             if arg_index > 0 || mir.upvar_decls.is_empty() {
+                // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
+                // need to insert a deref here, but the C ABI uses a pointer and a copy using the
+                // byval attribute, for which LLVM does the deref itself, so we must not add it.
+                let variable_access = if arg.is_indirect() &&
+                    !arg.attrs.contains(ArgAttribute::ByVal) {
+                    VariableAccess::IndirectVariable {
+                        alloca: llval,
+                        address_operations: &deref_op,
+                    }
+                } else {
+                    VariableAccess::DirectVariable { alloca: llval }
+                };
+
                 declare_local(
                     bcx,
                     &mircx.debug_context,
                     arg_decl.name.unwrap_or(keywords::Invalid.name()),
                     arg_ty,
                     scope,
-                    VariableAccess::DirectVariable { alloca: llval },
+                    variable_access,
                     VariableKind::ArgumentVariable(arg_index + 1),
                     DUMMY_SP
                 );
index e40b1617d0a01d12ba9b631514e62d4af9c15123..060f02ee23e0a83d3a9afe89c93eed138c992101 100644 (file)
@@ -31,7 +31,7 @@
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst::{Subst, Substs};
 use syntax::ast;
-use syntax::attr;
+use syntax::attr::{self, InlineAttr};
 use syntax_pos::Span;
 use syntax_pos::symbol::Symbol;
 use type_of;
@@ -175,16 +175,32 @@ fn instantiation_mode(&self,
 
         match *self.as_trans_item() {
             TransItem::Fn(ref instance) => {
-                if self.explicit_linkage(tcx).is_none() &&
-                    common::requests_inline(tcx, instance)
+                // If this function isn't inlined or otherwise has explicit
+                // linkage, then we'll be creating a globally shared version.
+                if self.explicit_linkage(tcx).is_some() ||
+                    !common::requests_inline(tcx, instance)
                 {
-                    if inline_in_all_cgus {
-                        InstantiationMode::LocalCopy
-                    } else {
+                    return InstantiationMode::GloballyShared  { may_conflict: false }
+                }
+
+                // At this point we don't have explicit linkage and we're an
+                // inlined function. If we're inlining into all CGUs then we'll
+                // be creating a local copy per CGU
+                if inline_in_all_cgus {
+                    return InstantiationMode::LocalCopy
+                }
+
+                // Finally, if this is `#[inline(always)]` we're sure to respect
+                // that with an inline copy per CGU, but otherwise we'll be
+                // creating one copy of this `#[inline]` function which may
+                // conflict with upstream crates as it could be an exported
+                // symbol.
+                let attrs = instance.def.attrs(tcx);
+                match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) {
+                    InlineAttr::Always => InstantiationMode::LocalCopy,
+                    _ => {
                         InstantiationMode::GloballyShared  { may_conflict: true }
                     }
-                } else {
-                    InstantiationMode::GloballyShared  { may_conflict: false }
                 }
             }
             TransItem::Static(..) => {
index 0ebccbc835fc1bd6972af5143eec67d84d6ccfd5..d4616a7c304ae8993e8a1cd7def12ab2dffe1b41 100644 (file)
@@ -4291,6 +4291,7 @@ fn check_block_with_expected(&self,
             CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
         };
 
+        let prev_diverges = self.diverges.get();
         let ctxt = BreakableCtxt {
             coerce: Some(coerce),
             may_break: false,
@@ -4340,6 +4341,12 @@ fn check_block_with_expected(&self,
             }
         });
 
+        if ctxt.may_break {
+            // If we can break from the block, then the block's exit is always reachable
+            // (... as long as the entry is reachable) - regardless of the tail of the block.
+            self.diverges.set(prev_diverges);
+        }
+
         let mut ty = ctxt.coerce.unwrap().complete(self);
 
         if self.has_errors.get() || ty.references_error() {
index 609af638e97c65476968fc3300fd81db87284bac..ad7978480a6b1b44ccb99b0fcb127aa4d554453b 100644 (file)
@@ -815,7 +815,8 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
                 // the type of the node expr.id here *before applying
                 // adjustments*.
                 //
-                // FIXME(#6268) nested method calls requires that this rule change
+                // FIXME(https://github.com/rust-lang/rfcs/issues/811)
+                // nested method calls requires that this rule change
                 let ty0 = self.resolve_node_type(expr.hir_id);
                 self.type_must_outlive(infer::AddrOf(expr.span), ty0, expr_region);
                 intravisit::walk_expr(self, expr);
index 25a37a2c48cdbc99dd50262df65b75ac22fce665..a5b3f8cb806be49b7bc76f13746207040a6f2286 100644 (file)
@@ -1332,7 +1332,11 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
 fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            def_id: DefId)
                            -> ty::GenericPredicates<'tcx> {
-    explicit_predicates_of(tcx, def_id)
+    let explicit = explicit_predicates_of(tcx, def_id);
+    ty::GenericPredicates {
+        parent: explicit.parent,
+        predicates: [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
+    }
 }
 
 fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
index 8df973555744b31f8cc9e81a75fa4cc628d002cf..8f91d07b53fb26fc39b5c5d69f86bfbbc55f929d 100644 (file)
@@ -4676,6 +4676,7 @@ pub fn method(&self) {} // It's now public.
     E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
     E0592, // duplicate definitions with name `{}`
 //  E0613, // Removed (merged with E0609)
+    E0640, // infer outlives
     E0627, // yield statement outside of generator literal
     E0632, // cannot provide explicit type parameters when `impl Trait` is used in
            // argument position.
index 1c047ef98d831f643a1a5ee50899a8674c937c7d..49ba0499f7868bcf7268a57b343ee8f9b964de26 100644 (file)
@@ -50,6 +50,8 @@
 
 - variance: variance inference
 
+- outlives: outlives inference
+
 - check: walks over function bodies and type checks them, inferring types for
   local variables, type parameters, etc as necessary.
 
 mod constrained_type_params;
 mod impl_wf_check;
 mod coherence;
+mod outlives;
 mod variance;
 mod namespace;
 
@@ -286,6 +289,7 @@ pub fn provide(providers: &mut Providers) {
     coherence::provide(providers);
     check::provide(providers);
     variance::provide(providers);
+    outlives::provide(providers);
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
@@ -301,6 +305,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
 
     })?;
 
+    tcx.sess.track_errors(|| {
+        time(time_passes, "outlives testing", ||
+            outlives::test::test_inferred_outlives(tcx));
+    })?;
+
     tcx.sess.track_errors(|| {
         time(time_passes, "impl wf inference", ||
              impl_wf_check::impl_wf_check(tcx));
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
new file mode 100644 (file)
index 0000000..1127028
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir::def_id::DefId;
+use rustc::ty::{self, TyCtxt};
+use rustc::ty::maps::Providers;
+
+/// Code to write unit test for outlives.
+pub mod test;
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        inferred_outlives_of,
+        ..*providers
+    };
+}
+
+//todo
+fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, _def_id: DefId)
+                                  -> Vec<ty::Predicate<'tcx>> {
+    Vec::new()
+}
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
new file mode 100644 (file)
index 0000000..196e660
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::ty::TyCtxt;
+
+pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    tcx.hir.krate().visit_all_item_likes(&mut OutlivesTest { tcx });
+}
+
+struct OutlivesTest<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> {
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        let item_def_id = self.tcx.hir.local_def_id(item.id);
+
+        // For unit testing: check for a special "rustc_outlives"
+        // attribute and report an error with various results if found.
+        if self.tcx.has_attr(item_def_id, "rustc_outlives") {
+            let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
+            span_err!(self.tcx.sess,
+                      item.span,
+                      E0640,
+                      "{:?}",
+                      inferred_outlives_of);
+        }
+    }
+
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { }
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
+}
index e217978648efa21bc836f6aeeb8f9c905d67a62d..ad171c4babbce4f0f4e852ce5b42af18b7570cb8 100644 (file)
@@ -238,6 +238,7 @@ fn clean(&self, cx: &DocContext) -> ExternalCrate {
                             if prim.is_some() {
                                 break;
                             }
+                            // FIXME: should warn on unknown primitives?
                         }
                     }
                 }
@@ -1627,6 +1628,7 @@ pub enum PrimitiveType {
     Slice,
     Array,
     Tuple,
+    Unit,
     RawPointer,
     Reference,
     Fn,
@@ -1662,7 +1664,11 @@ pub fn primitive_type(&self) -> Option<PrimitiveType> {
             Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
-            Tuple(..) => Some(PrimitiveType::Tuple),
+            Tuple(ref tys) => if tys.is_empty() {
+                Some(PrimitiveType::Unit)
+            } else {
+                Some(PrimitiveType::Tuple)
+            },
             RawPointer(..) => Some(PrimitiveType::RawPointer),
             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
             BareFunction(..) => Some(PrimitiveType::Fn),
@@ -1708,7 +1714,11 @@ fn def_id(&self) -> Option<DefId> {
             BorrowedRef { type_: box Generic(..), .. } =>
                 Primitive(PrimitiveType::Reference).def_id(),
             BorrowedRef { ref type_, .. } => type_.def_id(),
-            Tuple(..) => Primitive(PrimitiveType::Tuple).def_id(),
+            Tuple(ref tys) => if tys.is_empty() {
+                Primitive(PrimitiveType::Unit).def_id()
+            } else {
+                Primitive(PrimitiveType::Tuple).def_id()
+            },
             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
             Array(..) => Primitive(PrimitiveType::Array).def_id(),
@@ -1742,6 +1752,7 @@ fn from_str(s: &str) -> Option<PrimitiveType> {
             "array" => Some(PrimitiveType::Array),
             "slice" => Some(PrimitiveType::Slice),
             "tuple" => Some(PrimitiveType::Tuple),
+            "unit" => Some(PrimitiveType::Unit),
             "pointer" => Some(PrimitiveType::RawPointer),
             "reference" => Some(PrimitiveType::Reference),
             "fn" => Some(PrimitiveType::Fn),
@@ -1772,6 +1783,7 @@ pub fn as_str(&self) -> &'static str {
             Array => "array",
             Slice => "slice",
             Tuple => "tuple",
+            Unit => "unit",
             RawPointer => "pointer",
             Reference => "reference",
             Fn => "fn",
@@ -2693,6 +2705,7 @@ fn build_deref_target_impls(cx: &DocContext,
             Slice => tcx.lang_items().slice_impl(),
             Array => tcx.lang_items().slice_impl(),
             Tuple => None,
+            Unit => None,
             RawPointer => tcx.lang_items().const_ptr_impl(),
             Reference => None,
             Fn => None,
index 6303fd662bf2b02871540c151be9e507422bbdd9..18d6b1cc1e0f06fd26c248b2a87b47ab59d3c55d 100644 (file)
@@ -614,7 +614,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
         }
         clean::Tuple(ref typs) => {
             match &typs[..] {
-                &[] => primitive_link(f, PrimitiveType::Tuple, "()"),
+                &[] => primitive_link(f, PrimitiveType::Unit, "()"),
                 &[ref one] => {
                     primitive_link(f, PrimitiveType::Tuple, "(")?;
                     //carry f.alternate() into this display w/o branching manually
index 873d978b9cb84b960cb58f47b099e32aafa884c8..79eaabe31e86b4698a10da1ee0fa1ecdd91fed9a 100644 (file)
@@ -101,6 +101,8 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
                     <dd>Move up in search results</dd>
                     <dt>↓</dt>
                     <dd>Move down in search results</dd>
+                    <dt>↹</dt>
+                    <dd>Switch tab</dd>
                     <dt>&#9166;</dt>
                     <dd>Go to active search result</dd>
                     <dt>+</dt>
index 3c789cb3a15939d3c50afa7d35356b8418e6c31f..d538428a7e9a96be8ed54f0405894dab69c4dc6f 100644 (file)
@@ -1826,37 +1826,32 @@ fn render_markdown(w: &mut fmt::Formatter,
                    prefix: &str,
                    scx: &SharedContext)
                    -> fmt::Result {
-    // We only emit warnings if the user has opted-in to Pulldown rendering.
-    let output = if render_type == RenderType::Pulldown {
-        // Save the state of USED_ID_MAP so it only gets updated once even
-        // though we're rendering twice.
-        let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone());
-        let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown));
-        USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map);
-        let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown));
-        let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
-        differences.retain(|s| {
-            match *s {
-                html_diff::Difference::NodeText { ref elem_text,
-                                                  ref opposite_elem_text,
-                                                  .. }
-                    if elem_text.split_whitespace().eq(opposite_elem_text.split_whitespace()) => {
-                        false
-                }
-                _ => true,
+    // Save the state of USED_ID_MAP so it only gets updated once even
+    // though we're rendering twice.
+    let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone());
+    let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown));
+    USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map);
+    let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown));
+    let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
+    differences.retain(|s| {
+        match *s {
+            html_diff::Difference::NodeText { ref elem_text,
+                                              ref opposite_elem_text,
+                                              .. }
+                if elem_text.split_whitespace().eq(opposite_elem_text.split_whitespace()) => {
+                    false
             }
-        });
-
-        if !differences.is_empty() {
-            scx.markdown_warnings.borrow_mut().push((span, md_text.to_owned(), differences));
+            _ => true,
         }
+    });
 
-        pulldown_output
-    } else {
-        format!("{}", Markdown(md_text, RenderType::Hoedown))
-    };
+    if !differences.is_empty() {
+        scx.markdown_warnings.borrow_mut().push((span, md_text.to_owned(), differences));
+    }
 
-    write!(w, "<div class='docblock'>{}{}</div>", prefix, output)
+    write!(w, "<div class='docblock'>{}{}</div>",
+           prefix,
+           if render_type == RenderType::Pulldown { pulldown_output } else { hoedown_output })
 }
 
 fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink,
index bccad6c89dc4fa3ada9f74606f030c7376897f29..04bf466a7804dee5fb53479542a07a2e477afe58 100644 (file)
                      "associatedconstant",
                      "union"];
 
+    // On the search screen, so you remain on the last tab you opened.
+    //
+    // 0 for "Types/modules"
+    // 1 for "As parameters"
+    // 2 for "As return value"
+    var currentTab = 0;
+
     function hasClass(elem, className) {
         if (elem && className && elem.className) {
             var elemClass = elem.className;
         return String.fromCharCode(c);
     }
 
+    function displayHelp(display, ev) {
+        if (display === true) {
+            if (hasClass(help, "hidden")) {
+                ev.preventDefault();
+                removeClass(help, "hidden");
+                addClass(document.body, "blur");
+            }
+        } else if (!hasClass(help, "hidden")) {
+            ev.preventDefault();
+            addClass(help, "hidden");
+            removeClass(document.body, "blur");
+        }
+    }
+
     function handleShortcut(ev) {
         if (document.activeElement.tagName === "INPUT")
             return;
         case "Escape":
             var search = document.getElementById("search");
             if (!hasClass(help, "hidden")) {
-                ev.preventDefault();
-                addClass(help, "hidden");
-                removeClass(document.body, "blur");
+                displayHelp(false, ev);
             } else if (!hasClass(search, "hidden")) {
                 ev.preventDefault();
                 addClass(search, "hidden");
 
         case "s":
         case "S":
+            displayHelp(false, ev);
             ev.preventDefault();
             focusSearchBar();
             break;
             break;
 
         case "?":
-            if (ev.shiftKey && hasClass(help, "hidden")) {
-                ev.preventDefault();
-                removeClass(help, "hidden");
-                addClass(document.body, "blur");
+            if (ev.shiftKey) {
+                displayHelp(true, ev);
             }
             break;
         }
             });
 
             var search_input = document.getElementsByClassName('search-input')[0];
-            search_input.onkeydown = null;
             search_input.onkeydown = function(e) {
-                var actives = [];
+                // "actives" references the currently highlighted item in each search tab.
+                // Each array in "actives" represents a tab.
+                var actives = [[], [], []];
+                // "current" is used to know which tab we're looking into.
+                var current = 0;
                 onEach(document.getElementsByClassName('search-results'), function(e) {
-                    onEach(document.getElementsByClassName('highlighted'), function(e) {
-                        actives.push(e);
+                    onEach(e.getElementsByClassName('highlighted'), function(e) {
+                        actives[current].push(e);
                     });
+                    current += 1;
                 });
 
                 if (e.which === 38) { // up
-                    if (!actives.length || !actives[0].previousElementSibling) {
+                    if (!actives[currentTab].length ||
+                        !actives[currentTab][0].previousElementSibling) {
                         return;
                     }
 
-                    addClass(actives[0].previousElementSibling, 'highlighted');
-                    removeClass(actives[0], 'highlighted');
+                    addClass(actives[currentTab][0].previousElementSibling, 'highlighted');
+                    removeClass(actives[currentTab][0], 'highlighted');
                 } else if (e.which === 40) { // down
-                    if (!actives.length) {
+                    if (!actives[currentTab].length) {
                         var results = document.getElementsByClassName('search-results');
                         if (results.length > 0) {
-                            var res = results[0].getElementsByClassName('result');
+                            var res = results[currentTab].getElementsByClassName('result');
                             if (res.length > 0) {
                                 addClass(res[0], 'highlighted');
                             }
                         }
-                    } else if (actives[0].nextElementSibling) {
-                        addClass(actives[0].nextElementSibling, 'highlighted');
-                        removeClass(actives[0], 'highlighted');
+                    } else if (actives[currentTab][0].nextElementSibling) {
+                        addClass(actives[currentTab][0].nextElementSibling, 'highlighted');
+                        removeClass(actives[currentTab][0], 'highlighted');
                     }
                 } else if (e.which === 13) { // return
-                    if (actives.length) {
-                        document.location.href = actives[0].getElementsByTagName('a')[0].href;
+                    if (actives[currentTab].length) {
+                        document.location.href =
+                            actives[currentTab][0].getElementsByTagName('a')[0].href;
+                    }
+                } else if (e.which === 9) { // tab
+                    if (e.shiftKey) {
+                        printTab(currentTab > 0 ? currentTab - 1 : 2);
+                    } else {
+                        printTab(currentTab > 1 ? 0 : currentTab + 1);
                     }
-                } else if (actives.length > 0) {
-                    removeClass(actives[0], 'highlighted');
+                    e.preventDefault();
+                } else if (e.which === 16) { // shift
+                    // Does nothing, it's just to avoid losing "focus" on the highlighted element.
+                } else if (actives[currentTab].length > 0) {
+                    removeClass(actives[currentTab][0], 'highlighted');
                 }
             };
         }
 
             var output = '';
             if (array.length > 0) {
-                output = `<table class="search-results"${extraStyle}>`;
+                output = '<table class="search-results"' + extraStyle + '>';
                 var shown = [];
 
                 array.forEach(function(item) {
                 });
                 output += '</table>';
             } else {
-                output = `<div class="search-failed"${extraStyle}>No results :(<br/>` +
+                output = '<div class="search-failed"' + extraStyle + '>No results :(<br/>' +
                     'Try on <a href="https://duckduckgo.com/?q=' +
                     encodeURIComponent('rust ' + query.query) +
                     '">DuckDuckGo</a>?</div>';
             return output;
         }
 
+        function makeTabHeader(tabNb, text) {
+            if (currentTab === tabNb) {
+                return '<div class="selected">' + text + '</div>';
+            }
+            return '<div>' + text + '</div>';
+        }
+
         function showResults(results) {
             var output, query = getQuery();
 
             output = '<h1>Results for ' + escape(query.query) +
                 (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
                 '<div id="titles">' +
-                '<div class="selected">Types/modules</div>' +
-                '<div>As parameters</div>' +
-                '<div>As return value</div></div><div id="results">';
+                makeTabHeader(0, "Types/modules") +
+                makeTabHeader(1, "As parameters") +
+                makeTabHeader(2, "As return value") +
+                '</div><div id="results">';
 
             output += addTab(results['others'], query);
             output += addTab(results['in_args'], query, false);
 
     // In the search display, allows to switch between tabs.
     function printTab(nb) {
+        if (nb === 0 || nb === 1 || nb === 2) {
+            currentTab = nb;
+        }
         var nb_copy = nb;
         onEach(document.getElementById('titles').childNodes, function(elem) {
             if (nb_copy === 0) {
index a132223a051017a90956060d345a6487da152ae7..18270654aa93c5f7ee67e36031012ef1a01d90c6 100644 (file)
@@ -552,7 +552,7 @@ body.blur > :not(#help) {
        flex: 0 0 auto;
        box-shadow: 0 0 6px rgba(0,0,0,.2);
        width: 550px;
-       height: 330px;
+       height: 354px;
        border: 1px solid;
 }
 #help dt {
index 890e1169c05918e1ea8a9024fe11acd39602cebe..20da99a6b137658acaec97ef85359666abe58db8 100644 (file)
@@ -170,6 +170,9 @@ pub fn opts() -> Vec<RustcOptGroup> {
         stable("no-default", |o| {
             o.optflag("", "no-defaults", "don't run the default passes")
         }),
+        stable("document-private-items", |o| {
+            o.optflag("", "document-private-items", "document private items")
+        }),
         stable("test", |o| o.optflag("", "test", "run code examples as tests")),
         stable("test-args", |o| {
             o.optmulti("", "test-args", "arguments to pass to the test runner",
@@ -275,6 +278,9 @@ pub fn main_args(args: &[String]) -> isize {
     // Check for unstable options.
     nightly_options::check_nightly_options(&matches, &opts());
 
+    // check for deprecated options
+    check_deprecated_options(&matches);
+
     if matches.opt_present("h") || matches.opt_present("help") {
         usage("rustdoc");
         return 0;
@@ -458,6 +464,18 @@ fn rust_input<R, F>(cratefile: &str, externs: Externs, matches: &getopts::Matche
     let mut passes = matches.opt_strs("passes");
     let mut plugins = matches.opt_strs("plugins");
 
+    // We hardcode in the passes here, as this is a new flag and we
+    // are generally deprecating passes.
+    if matches.opt_present("document-private-items") {
+        default_passes = false;
+
+        passes = vec![
+            String::from("strip-hidden"),
+            String::from("collapse-docs"),
+            String::from("unindent-comments"),
+        ];
+    }
+
     // First, parse the crate and extract all relevant information.
     let mut paths = SearchPaths::new();
     for s in &matches.opt_strs("L") {
@@ -550,3 +568,26 @@ fn rust_input<R, F>(cratefile: &str, externs: Externs, matches: &getopts::Matche
     });
     rx.recv().unwrap()
 }
+
+/// Prints deprecation warnings for deprecated options
+fn check_deprecated_options(matches: &getopts::Matches) {
+    let deprecated_flags = [
+       "input-format",
+       "output-format",
+       "plugin-path",
+       "plugins",
+       "no-defaults",
+       "passes",
+    ];
+
+    for flag in deprecated_flags.into_iter() {
+        if matches.opt_present(flag) {
+            eprintln!("WARNING: the '{}' flag is considered deprecated", flag);
+            eprintln!("WARNING: please see https://github.com/rust-lang/rust/issues/44136");
+        }
+    }
+
+    if matches.opt_present("no-defaults") {
+        eprintln!("WARNING: (you may want to use --document-private-items)");
+    }
+}
index 1edb35d8fe74120fee2f05fc346bb23a0174ebdd..9e1da318242bc550c9939102c59f4e7c548f09c7 100644 (file)
@@ -284,7 +284,6 @@ mod prim_pointer { }
 /// Arrays of sizes from 0 to 32 (inclusive) implement the following traits if
 /// the element type allows it:
 ///
-/// - [`Clone`][clone] (only if `T: `[`Copy`][copy])
 /// - [`Debug`][debug]
 /// - [`IntoIterator`][intoiterator] (implemented for `&[T; N]` and `&mut [T; N]`)
 /// - [`PartialEq`][partialeq], [`PartialOrd`][partialord], [`Eq`][eq], [`Ord`][ord]
@@ -299,8 +298,10 @@ mod prim_pointer { }
 /// entirely different types. As a stopgap, trait implementations are
 /// statically generated up to size 32.
 ///
-/// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy]. This
-/// works because the [`Copy`][copy] trait is specially known to the compiler.
+/// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy]
+/// and [`Clone`][clone] if the element type is [`Clone`][clone]. This works
+/// because [`Copy`][copy] and [`Clone`][clone] traits are specially known
+/// to the compiler.
 ///
 /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
 /// an array. Indeed, this provides most of the API for working with arrays.
index f448cffd3725c30ae6709205aa1f87976cbf710a..533f6590f83b2656a6da5464b0598cdaacf95147 100644 (file)
@@ -552,6 +552,12 @@ pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
 
     /// Configuration for the child process's standard input (stdin) handle.
     ///
+    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
+    /// defaults to [`piped`] when used with `output`.
+    ///
+    /// [`inherit`]: struct.Stdio.html#method.inherit
+    /// [`piped`]: struct.Stdio.html#method.piped
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -572,6 +578,12 @@ pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
 
     /// Configuration for the child process's standard output (stdout) handle.
     ///
+    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
+    /// defaults to [`piped`] when used with `output`.
+    ///
+    /// [`inherit`]: struct.Stdio.html#method.inherit
+    /// [`piped`]: struct.Stdio.html#method.piped
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -592,6 +604,12 @@ pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
 
     /// Configuration for the child process's standard error (stderr) handle.
     ///
+    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
+    /// defaults to [`piped`] when used with `output`.
+    ///
+    /// [`inherit`]: struct.Stdio.html#method.inherit
+    /// [`piped`]: struct.Stdio.html#method.piped
+    ///
     /// # Examples
     ///
     /// Basic usage:
index d58a3505154dd9f74b27bd60da921dbff9ec52a6..a532163f61e190c0f44f01ecae2e90b3c65db6a5 100644 (file)
@@ -393,8 +393,8 @@ pub trait MetadataExt {
     /// to. For a directory, the structure specifies when the directory was
     /// created.
     ///
-    /// If the underlying filesystem does not support the last write time
-    /// time, the returned value is 0.
+    /// If the underlying filesystem does not support the last write time,
+    /// the returned value is 0.
     ///
     /// # Examples
     ///
index a53c76a333a99dbc576ec72411c5da6433ea3df1..cb18eed8ee54b63e6eb8ce493c2a35075d7e03cd 100644 (file)
@@ -325,7 +325,10 @@ unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
     ///
     /// Once the initialization expression succeeds, the key transitions to the
     /// `Valid` state which will guarantee that future calls to [`with`] will
-    /// succeed within the thread.
+    /// succeed within the thread. Some keys might skip the `Uninitialized`
+    /// state altogether and start in the `Valid` state as an optimization
+    /// (e.g. keys initialized with a constant expression), but no guarantees
+    /// are made.
     ///
     /// When a thread exits, each key will be destroyed in turn, and as keys are
     /// destroyed they will enter the `Destroyed` state just before the
index efaa5e5e3dab2c467afd13844b20757204265791..dd46903bb88d743a38b23ea1e3e90d5d06b2f123 100644 (file)
@@ -471,6 +471,17 @@ pub fn span_until_char(&self, sp: Span, c: char) -> Span {
         }
     }
 
+    /// Given a `Span`, try to get a shorter span ending just after the first
+    /// occurrence of `char` `c`.
+    pub fn span_through_char(&self, sp: Span, c: char) -> Span {
+        if let Ok(snippet) = self.span_to_snippet(sp) {
+            if let Some(offset) = snippet.find(c) {
+                return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
+            }
+        }
+        sp
+    }
+
     pub fn def_span(&self, sp: Span) -> Span {
         self.span_until_char(sp, '{')
     }
index bd400ef6dd6dab9ecdbb0fd960171bc9c13ec94a..8fd2bad4e44a6e38947f917add4638e4d699fa43 100644 (file)
@@ -4088,11 +4088,11 @@ fn parse_stmt_without_recovery(&mut self,
                     node: StmtKind::Item(i),
                 },
                 None => {
-                    let unused_attrs = |attrs: &[_], s: &mut Self| {
+                    let unused_attrs = |attrs: &[Attribute], s: &mut Self| {
                         if !attrs.is_empty() {
                             if s.prev_token_kind == PrevTokenKind::DocComment {
                                 s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit();
-                            } else {
+                            } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
                                 s.span_err(s.span, "expected statement after outer attribute");
                             }
                         }
index 1287b94159a57f23ff80fbe32b395a946f250d9c..b397ad1e98f74e12ceb79eadf9f8403fd7bd7bee 100644 (file)
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
 #if LLVM_VERSION_GE(4, 0)
-#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
 #include "llvm/LTO/LTO.h"
+#if LLVM_VERSION_LE(4, 0)
+#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
+#endif
 #endif
 
 #include "llvm-c/Transforms/PassManagerBuilder.h"
@@ -888,6 +890,33 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
     return;
   Preserved.insert(GUID);
 
+#if LLVM_VERSION_GE(5, 0)
+  auto Info = Index.getValueInfo(GUID);
+  if (!Info) {
+    return;
+  }
+  for (auto &Summary : Info.getSummaryList()) {
+    for (auto &Ref : Summary->refs()) {
+      addPreservedGUID(Index, Preserved, Ref.getGUID());
+    }
+
+    GlobalValueSummary *GVSummary = Summary.get();
+    if (isa<FunctionSummary>(GVSummary)) {
+      auto *FS = cast<FunctionSummary>(GVSummary);
+      for (auto &Call: FS->calls()) {
+        addPreservedGUID(Index, Preserved, Call.first.getGUID());
+      }
+      for (auto &GUID: FS->type_tests()) {
+        addPreservedGUID(Index, Preserved, GUID);
+      }
+    }
+    if (isa<AliasSummary>(GVSummary)) {
+      auto *AS = cast<AliasSummary>(GVSummary);
+      auto GUID = AS->getAliasee().getOriginalName();
+      addPreservedGUID(Index, Preserved, GUID);
+    }
+  }
+#else
   auto SummaryList = Index.findGlobalValueSummaryList(GUID);
   if (SummaryList == Index.end())
     return;
@@ -919,6 +948,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
       addPreservedGUID(Index, Preserved, GUID);
     }
   }
+#endif
 }
 
 // The main entry point for creating the global ThinLTO analysis. The structure
@@ -939,6 +969,12 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
 
     Ret->ModuleMap[module->identifier] = mem_buffer;
 
+#if LLVM_VERSION_GE(5, 0)
+    if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
+      LLVMRustSetLastError(toString(std::move(Err)).c_str());
+      return nullptr;
+    }
+#else
     Expected<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
       object::ModuleSummaryIndexObjectFile::create(mem_buffer);
     if (!ObjOrErr) {
@@ -947,6 +983,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
     }
     auto Index = (*ObjOrErr)->takeIndex();
     Ret->Index.mergeFrom(std::move(Index), i);
+#endif
   }
 
   // Collect for each module the list of function it defines (GUID -> Summary)
@@ -965,6 +1002,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   // combined index
   //
   // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
+#if LLVM_VERSION_GE(5, 0)
+  computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
+  ComputeCrossModuleImport(
+    Ret->Index,
+    Ret->ModuleToDefinedGVSummaries,
+    Ret->ImportLists,
+    Ret->ExportLists
+  );
+#else
   auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
   ComputeCrossModuleImport(
     Ret->Index,
@@ -973,6 +1019,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
     Ret->ExportLists,
     &DeadSymbols
   );
+#endif
 
   // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
   // impacts the caching.
@@ -981,8 +1028,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
   DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
   for (auto &I : Ret->Index) {
+#if LLVM_VERSION_GE(5, 0)
+    if (I.second.SummaryList.size() > 1)
+      PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
+#else
     if (I.second.size() > 1)
       PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second);
+#endif
   }
   auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
     const auto &Prevailing = PrevailingCopy.find(GUID);
index ccc8f03a40ffebb2e6678e0b8f15a42c32be732a..84464a627beb10906cd0500f17416439ada47010 100644 (file)
@@ -20,7 +20,7 @@
 mod inline {
 
     //~ TRANS_ITEM fn local_inlining_but_not_all::inline[0]::inlined_function[0] @@ local_inlining_but_not_all-inline[External]
-    #[inline(always)]
+    #[inline]
     pub fn inlined_function()
     {
 
index 838cd4bf6d745625c3320c01b1ae593f7416c916..e0b37cb2f32243474a4dff376667460091cac759 100644 (file)
@@ -14,7 +14,6 @@
 
 // ignore-arm
 // ignore-aarch64
-// min-llvm-version 3.8
 
 // compile-flags: -C no-prepopulate-passes
 
index 657f4b662f728e907a028b6b7a6bd376e18ca06c..f0508bc90f20c9941b537b8fc4549d82f3ec4342 100644 (file)
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// The minimum LLVM version is set to 3.8, but really this test
-// depends on a patch that is was committed to upstream LLVM before
-// 4.0; and also backported to the Rust LLVM fork.
+// This test depends on a patch that was committed to upstream LLVM
+// before 4.0, formerly backported to the Rust LLVM fork.
 
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-llvm-version 3.8
+// min-llvm-version 4.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index cd34a1670dc7db7bd1b05f5363295cf01ff7dad3..8325318f9afc56dcecadf961d21de6b13a2acec0 100644 (file)
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// The minimum LLVM version is set to 3.8, but really this test
-// depends on a patch that is was committed to upstream LLVM before
-// 4.0; and also backported to the Rust LLVM fork.
+// This test depends on a patch that was committed to upstream LLVM
+// before 4.0, formerly backported to the Rust LLVM fork.
 
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-llvm-version 3.8
+// min-llvm-version 4.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 06b872066695393aed63937490d1779dc88bc952..ab2fe02bb147667a75677d1846e049b5d29b9f8f 100644 (file)
@@ -424,7 +424,7 @@ mod no_mangle {
     mod inner { #![no_mangle="3500"] }
 
     #[no_mangle = "3500"] fn f() { }
-    //~^ WARN function is marked #[no_mangle], but not exported
+    //~^ WARN function is marked #[no_mangle], but not exported
 
     #[no_mangle = "3500"] struct S;
 
index 216fcf9353578a594c00febb75c97bca216daee9..cd64dfa7a47dd291292e86fda10c9220c97dc4d3 100644 (file)
@@ -10,9 +10,8 @@
 
 // compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics
 
-// FIXME(#19495) no_mangle'ing main ICE's.
 #[no_mangle]
-fn foo() { //~ ERROR function foo is marked #[no_mangle], but not exported
+fn foo() { //~ ERROR function is marked #[no_mangle], but not exported
 }
 
 #[allow(dead_code)]
@@ -31,7 +30,7 @@ pub fn bar()  {
 
 #[allow(dead_code)]
 #[no_mangle]
-static PRIVATE_BAR: u64 = 1; //~ ERROR static PRIVATE_BAR is marked #[no_mangle], but not exported
+static PRIVATE_BAR: u64 = 1; //~ ERROR static is marked #[no_mangle], but not exported
 
 
 fn main() {
index bcc2c10653f9c06bd44d487db1d12ffbb33ae6e0..4afb61ab76cf7357a2be4e1d0010a54beedfc343 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no asm! support
 
 #![feature(asm, rustc_attrs)]
 #![allow(unused)]
diff --git a/src/test/compile-fail/outlives-associated-types.rs b/src/test/compile-fail/outlives-associated-types.rs
new file mode 100644 (file)
index 0000000..778394c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the outlives computation runs for now...
+
+#![feature(rustc_attrs)]
+
+//todo add all the test cases
+// https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md#example-1-a-reference
+
+#[rustc_outlives]
+struct Direct<'a, T> { //~ ERROR 19:1: 21:2: [] [E0640]
+    field: &'a T
+}
+
+fn main() { }
index 5a31be8bd502f788025d784e690d9d0fce9b6485..22788d7a8985ef32b70a9fe416dccdb7f3f4a186 100644 (file)
@@ -30,7 +30,7 @@ fn main() {
 // END RUST SOURCE
 // START rustc.node12.EraseRegions.after.mir
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[e36f]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[e36f]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]);
 //         ...
 //         return;
 //     }
@@ -62,7 +62,7 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
 //         StorageLive(_3);
 //         _3 = _2;
 //         StorageLive(_4);
index bcb21c60b269470b4e1707abbe8af3b666a60b63..d2852cf52261842c4ae865224559d094c8ae5c0d 100644 (file)
@@ -51,8 +51,8 @@ fn main() {
 // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]);
-//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[e36f]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[e36f]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]);
 //         StorageLive(_3);
 //         _3 = _2;
 //         (*_3) = const 23i32;
@@ -65,8 +65,8 @@ fn main() {
 // fn test(_1: &ReErased mut i32) -> () {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]);
-//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[e36f]::test[0] }, BrAnon(0)) mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[e36f]::test[0] }, BrAnon(0)) mut i32]);
 //         ...
 //         _3 = const write_42(_4) -> bb1;
 //     }
@@ -81,8 +81,8 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
-//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
 //         StorageLive(_3);
 //         ...
 //         _0 = const write_42(_4) -> bb1;
index 44280539c41b0cc9c2d21d8ed34de1b583c72943..98c553d6b35af1d7ec941df0ea3bbbd8f8ab2999 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
 // fn test(_1: &ReErased mut i32) -> () {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_5[8cd8]::test[0] }, BrAnon(0)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_5[e36f]::test[0] }, BrAnon(0)) mut i32]);
 //         ...
 //         Validate(Release, [_3: bool, _4: *mut i32]);
 //         _3 = const write_42(_4) -> bb1;
@@ -49,7 +49,7 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
 //         StorageLive(_3);
 //         _3 = _2;
 //         StorageLive(_4);
diff --git a/src/test/run-make/inline-always-many-cgu/Makefile b/src/test/run-make/inline-always-many-cgu/Makefile
new file mode 100644 (file)
index 0000000..edf88a6
--- /dev/null
@@ -0,0 +1,8 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2
+       if grep -w call $(TMPDIR)/*.ll; then \
+               echo "found call instruction when one wasn't expected"; \
+               exit 1; \
+       fi
diff --git a/src/test/run-make/inline-always-many-cgu/foo.rs b/src/test/run-make/inline-always-many-cgu/foo.rs
new file mode 100644 (file)
index 0000000..539dcdf
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+pub mod a {
+    #[inline(always)]
+    pub fn foo() {
+    }
+
+    pub fn bar() {
+    }
+}
+
+#[no_mangle]
+pub fn bar() {
+    a::foo();
+}
index fb257bf7b500c50f09c82713b9cb80be4e71e395..0380ccbdea47b45cfdd5bca801fd20b5180bb0d0 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
-// ignore-emscripten
+// ignore-emscripten no asm
 
 #![feature(asm)]
 
index 5b83ce48e5daddd793c9a948de233e06b20bc70e..9e782cca218fd1051e8876778877545b0aa28e96 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-windows - this is a unix-specific test
-// ignore-emscripten
+// ignore-emscripten no processes
 
 #![feature(process_exec, libc)]
 
index 5be9b97aac7e6ac6f3a432f37c46cbf8353edda7..e378f55dffa1e097e333f1098f7c72a1be9ff180 100644 (file)
@@ -10,7 +10,8 @@
 
 // ignore-windows - this is a unix-specific test
 // ignore-pretty issue #37199
-// ignore-emscripten
+// ignore-emscripten no processes
+
 #![feature(process_exec)]
 
 use std::env;
index 22fbeb2d5d0ed070b9e4f88969e1891d25ddc06a..863f3cf30e96a72b0288570d9aaad84eaa295d94 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:--test
-// ignore-emscripten
+// ignore-emscripten no processes
 
 // NB: These tests kill child processes. Valgrind sees these children as leaking
 // memory, which makes for some *confusing* logs. That's why these are here
index 89af1db7c78f1f85d273958c416c9546d0ac76ea..dddf1ae0546599101a3d37949930056bf47da1f3 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::env::args;
 use std::process::Command;
index 8b4a633d61358278058ce578dd7b765b179670ce..86ffaf1e24f62007a96823e74e8086ca6db1a404 100644 (file)
@@ -12,7 +12,7 @@
 
 // ignore-android
 // ignore-windows
-// ignore-emscripten
+// ignore-emscripten no execve
 // no-prefer-dynamic
 
 #![feature(libc)]
index bcb0c62d9fef4cc968976f9b2d8b24a02755a961..3693e86ba242808e51e28935be6823bc0fc13613 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten env vars don't work?
 
 #![feature(path)]
 
index 2606c92868004715a1fe621fc17b7c8a153a6b1a..f4ee3b6e9e8008e370c6d0dfa335ced78c11988d 100644 (file)
@@ -12,7 +12,7 @@
 
 // pretty-expanded FIXME #23616
 // ignore-msvc
-// ignore-emscripten
+// ignore-emscripten emcc asserts on an empty struct as an argument
 
 #[repr(C)]
 struct TwoU8s {
index a1b7d42a196e9e77115d96f797f98aecfc113079..f55876115c09c1bdd69c652a04e94ebe5fc0f7f0 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-windows
 // ignore-android
-// ignore-emscripten
+// ignore-emscripten no processes
 // ignore-haiku
 
 #![feature(libc)]
index 9e8a32185188a222ccc7f5965921da5e3d278c93..e23accfcc235d4f50527a0bb3087eefe0e02fbad 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten missing rust_begin_unwind
+// ignore-emscripten no no_std executables
 
 #![feature(lang_items, start, alloc)]
 #![no_std]
index e9bdfbf28ea9ca0128119cdcfb117e92f8ca47c0..8693964665d342c8a320fd2812b76673fea2d870 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no threads support
 // compile-flags: --test
 
 #![feature(generators, generator_trait)]
index 7c14d34b0ee121a3ec2b806474cd2699922dcf78..5369b138b0d584a0a91f6e523245736e64129a8b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten i128 doesn't work
 
 #![feature(i128_type, test)]
 
index b350bd1a4ccbf84526ab3be5e21bd42204b83c9d..e9d37817ee2e2fba776abb7f9e0c618e845ef1c7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 // Make sure that if a process doesn't have its stdio/stderr descriptors set up
 // that we don't die in a large ball of fire
index 5a743d7b54784357efc748cd72c025f6dfc117b0..9214d6b04bd2e3e42fe5b82a461b16fffee000bb 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
+
 #![feature(io, process_capture)]
 
 use std::env;
index 513ab91489c8d98ea96e970c8f29a4a1341ddea0..2edb45cc1c4141e1fa219eb90bf2dc8f6e0b9b96 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 #![feature(io, process_capture)]
 
index ffe6b646794e14da62dfa83ec2afdf0385b3276d..588fa63cfdfb2fdf67941d26c7b0e8097ce3e197 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::env;
 use std::process::Command;
index f86be2d7c9933fae3d7a5cb0e8449b541de2a994..cd02cbf3dad3e0f7baa919c6692edd1fdae71650 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::process::Command;
 use std::env;
index 1ee47a69d0c87dde43b489fe3a3771edaa5f64f1..c8ba5dbd84cdf17a7d3eb5ddd1f612b30d5ccbca 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
+
 #![feature(std_misc, os)]
 
 #[cfg(unix)]
index 393757035141d6e4137ff3c27ece14d55b4467e6..8cc23c883ed6a67b2aaae9a72849b60f879714f7 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
-// ignore-emscripten
+// ignore-emscripten no threads
 
 use std::thread::Builder;
 
index 9b2b474351df6f4ec14da92d4445c28d570d4ad5..ad385ee78e0c798c0bea2dc2c321f9168a822e45 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no threads
 
 use std::thread;
 use std::env;
index a70c2b3ae1b7ba03dea6fb1220116a9a63f885e7..4e4530789c8ddc7d9c8d424ffb882bf54fa9a9ed 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no threads
 // compile-flags: -O
 
 // Tests that the `vec!` macro does not overflow the stack when it is
index 9252762d1bdad191614920e1a1961858dd1b8d7a..828b495d40813febbfd90d39dea732c0e1112e07 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // aux-build:issue-29485.rs
-// ignore-emscripten
+// ignore-emscripten no threads
 
 #[feature(recover)]
 
index cf925662fc3f3ff0b9e94b73f57c40d9bba17b65..9a77be049feebbebf3c3d175933fabe5c8eccc2b 100644 (file)
@@ -10,8 +10,6 @@
 
 // write_volatile causes an LLVM assert with composite types
 
-// ignore-emscripten See #41299: probably a bad optimization
-
 #![feature(volatile)]
 use std::ptr::{read_volatile, write_volatile};
 
index 7658abc00c599636da09e54ba515c4acaece3fc0..4296107dd457e448c01baae9e2ae65a9ffb03ae0 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 // Previously libstd would set stdio descriptors of a child process
 // by `dup`ing the requested descriptors to inherit directly into the
index 76728a0d354b2c9267acccbf74561eab781d6ebf..3806270070783c3a5fe31795e8252f9f0de1db32 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::process::{Command, Stdio};
 use std::env;
index 53a8a403b6410167cd5611c4c69a3d7760aa9372..f6c03b384f23db86416efe87d2436f628bdabea6 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// min-llvm-version 3.9
-
 use std::ops::Deref;
 
 fn main() {
diff --git a/src/test/run-pass/issue-40003.rs b/src/test/run-pass/issue-40003.rs
new file mode 100644 (file)
index 0000000..103a365
--- /dev/null
@@ -0,0 +1,186 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    if false { test(); }
+}
+
+fn test() {
+    let rx = Err::<Vec<usize>, u32>(1).into_future();
+
+    rx.map(|l: Vec<usize>| stream::iter(l.into_iter().map(|i| Ok(i))))
+      .flatten_stream()
+      .chunks(50)
+      .buffer_unordered(5);
+}
+
+use future::{Future, IntoFuture};
+mod future {
+    use std::result;
+
+    use {stream, Stream};
+
+    pub trait Future {
+        type Item;
+        type Error;
+
+        fn map<F, U>(self, _: F) -> Map<Self, F>
+            where F: FnOnce(Self::Item) -> U,
+                  Self: Sized,
+        {
+            panic!()
+        }
+
+        fn flatten_stream(self) -> FlattenStream<Self>
+            where <Self as Future>::Item: stream::Stream<Error=Self::Error>,
+                  Self: Sized
+        {
+            panic!()
+        }
+    }
+
+    pub trait IntoFuture {
+        type Future: Future<Item=Self::Item, Error=Self::Error>;
+        type Item;
+        type Error;
+        fn into_future(self) -> Self::Future;
+    }
+
+    impl<F: Future> IntoFuture for F {
+        type Future = F;
+        type Item = F::Item;
+        type Error = F::Error;
+
+        fn into_future(self) -> F {
+            panic!()
+        }
+    }
+
+    impl<T, E> IntoFuture for result::Result<T, E> {
+        type Future = FutureResult<T, E>;
+        type Item = T;
+        type Error = E;
+
+        fn into_future(self) -> FutureResult<T, E> {
+            panic!()
+        }
+    }
+
+    pub struct Map<A, F> {
+        _a: (A, F),
+    }
+
+    impl<U, A, F> Future for Map<A, F>
+        where A: Future,
+              F: FnOnce(A::Item) -> U,
+    {
+        type Item = U;
+        type Error = A::Error;
+    }
+
+    pub struct FlattenStream<F> {
+        _f: F,
+    }
+
+    impl<F> Stream for FlattenStream<F>
+        where F: Future,
+              <F as Future>::Item: Stream<Error=F::Error>,
+    {
+        type Item = <F::Item as Stream>::Item;
+        type Error = <F::Item as Stream>::Error;
+    }
+
+    pub struct FutureResult<T, E> {
+        _inner: (T, E),
+    }
+
+    impl<T, E> Future for FutureResult<T, E> {
+        type Item = T;
+        type Error = E;
+    }
+}
+
+mod stream {
+    use IntoFuture;
+
+    pub trait Stream {
+        type Item;
+        type Error;
+
+        fn buffer_unordered(self, amt: usize) -> BufferUnordered<Self>
+            where Self::Item: IntoFuture<Error = <Self as Stream>::Error>,
+                  Self: Sized
+        {
+            new(self, amt)
+        }
+
+        fn chunks(self, _capacity: usize) -> Chunks<Self>
+            where Self: Sized
+        {
+            panic!()
+        }
+    }
+
+    pub struct IterStream<I> {
+        _iter: I,
+    }
+
+    pub fn iter<J, T, E>(_: J) -> IterStream<J::IntoIter>
+        where J: IntoIterator<Item=Result<T, E>>,
+    {
+        panic!()
+    }
+
+    impl<I, T, E> Stream for IterStream<I>
+        where I: Iterator<Item=Result<T, E>>,
+    {
+        type Item = T;
+        type Error = E;
+    }
+
+    pub struct Chunks<S> {
+        _stream: S
+    }
+
+    impl<S> Stream for Chunks<S>
+        where S: Stream
+    {
+        type Item = Result<Vec<<S as Stream>::Item>, u32>;
+        type Error = <S as Stream>::Error;
+    }
+
+    pub struct BufferUnordered<S> {
+        _stream: S,
+    }
+
+    enum Slot<T> {
+        Next(usize),
+        _Data { _a: T },
+    }
+
+    fn new<S>(_s: S, _amt: usize) -> BufferUnordered<S>
+        where S: Stream,
+              S::Item: IntoFuture<Error=<S as Stream>::Error>,
+    {
+        (0..0).map(|_| {
+            Slot::Next::<<S::Item as IntoFuture>::Future>(1)
+        }).collect::<Vec<_>>();
+        panic!()
+    }
+
+    impl<S> Stream for BufferUnordered<S>
+        where S: Stream,
+              S::Item: IntoFuture<Error=<S as Stream>::Error>,
+    {
+        type Item = <S::Item as IntoFuture>::Item;
+        type Error = <S as Stream>::Error;
+    }
+}
+use stream::Stream;
diff --git a/src/test/run-pass/issue-44402.rs b/src/test/run-pass/issue-44402.rs
new file mode 100644 (file)
index 0000000..244aa65
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(never_type)]
+
+// Regression test for inhabitedness check. The old
+// cache used to cause us to incorrectly decide
+// that `test_b` was invalid.
+
+struct Foo {
+    field1: !,
+    field2: Option<&'static Bar>,
+}
+
+struct Bar {
+    field1: &'static Foo
+}
+
+fn test_a() {
+    let x: Option<Foo> = None;
+    match x { None => () }
+}
+
+fn test_b() {
+    let x: Option<Bar> = None;
+    match x { None => () }
+}
+
+fn main() { }
diff --git a/src/test/run-pass/issue-45124.rs b/src/test/run-pass/issue-45124.rs
new file mode 100644 (file)
index 0000000..c65823e
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(catch_expr)]
+
+fn main() {
+    let mut a = 0;
+    let () = {
+        let _: Result<(), ()> = do catch {
+            let _ = Err(())?;
+            return
+        };
+        a += 1;
+    };
+    a += 2;
+    assert_eq!(a, 3);
+}
index 591610e88b1a6725396a44d07c1537ba5401b1e7..f12a233f493ee6a94aea237c07d4085be90b2f09 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-windows
 // ignore-macos
-// ignore-emscripten
+// ignore-emscripten doesn't support this linkage
 // aux-build:linkage1.rs
 
 #![feature(linkage)]
index 86fe06b176532faf6f5f90922fa581a5eac05311..c15b40d4dda2086f1cba52e84f4fe0f2e1f6e554 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 fn check_for_no_backtrace(test: std::process::Output) {
     assert!(!test.status.success());
index 85c63e184fe255610af84ad7b7e6d4c9d9e51fdb..7b6b711315afd9384cdb7bd6919b33bd96854dde 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 // ignore-android
 
 #![feature(libc)]
index 7e70c4a7ab38eba75bc387aaece3c10565c6d316..485335a2d8006a61adfb3e5459c4216c97fcdaa9 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-android: FIXME (#20004)
 // ignore-musl
-// ignore-emscripten
+// ignore-emscripten no processes
 
 #![feature(asm)]
 #![feature(libc)]
index d1e05e5a0184c3d1c8cac004726b958bf3b0c5c2..a4a0055785f0d6b23959171ad03affebecac182a 100644 (file)
@@ -7,8 +7,6 @@
 // <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.
-// ignore-emscripten Not sure what's happening here.
-
 
 use std::mem;
 
index ee4eb86ed0de3d04a6c30d4552810aac53646e26..18f7eff280a8469c1a195168709e24694241d285 100644 (file)
@@ -7,8 +7,6 @@
 // <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.
-// ignore-emscripten
-
 
 use std::mem;
 
index ebbb00a4a9f2322f6c0664f73eeb26d9708bf0db..d1fdc8afa653e0de8a0b1cd40ad628aea8b4ed6e 100644 (file)
@@ -11,7 +11,7 @@
 // compile-flags:-C panic=abort
 // aux-build:exit-success-if-unwind.rs
 // no-prefer-dynamic
-// ignore-emscripten Function not implemented
+// ignore-emscripten no processes
 
 extern crate exit_success_if_unwind;
 
index 3ba3bd61c2e874db646cd8094e0a5e2fa254c3f2..bb541b29d7c76d180f40d443e8e7fe7093f31982 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-C panic=abort
 // no-prefer-dynamic
-// ignore-emscripten Function not implemented.
+// ignore-emscripten no processes
 
 use std::process::Command;
 use std::env;
index e4cd4e809a4c6bf7684b9346ea325dbca9335c39..59e9474aab2ec03b53232fe6d1c2d1c8bed8fd88 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-C lto -C panic=abort
 // no-prefer-dynamic
-// ignore-emscripten Function not implemented.
+// ignore-emscripten no processes
 
 use std::process::Command;
 use std::env;
index 768b88fd09e0b3fad9c8aaa33c2b3db88e2fca0e..6d28b8d12f62bad32c48315c4a49ba1ff2cc62cb 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags:-C lto -C panic=unwind
 // no-prefer-dynamic
-// ignore-emscripten Function not implemented.
+// ignore-emscripten no processes
 
 use std::process::Command;
 use std::env;
index b3785d898baa42fe40c27c89a1e5b0fafd0c7b50..1622517198a2c6f6f9fb2b99e912901660b82e4d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::process::Command;
 use std::env;
index a5d408448a033388d4da4f69a564ba474d28beaa..5abc06b75e14e190dd5a33f40c930e4afa60b252 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::env;
 use std::process::{self, Command, Stdio};
index b7f296a65c21696b24d78b9e1d711b9d2e34574f..7a9b431d5709e4211417e1b8d1623b5d83013bee 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::process::Command;
 use std::env;
index 550c6d6ab67025a8311ec582f590b05e2f01cc38..7b85420726326a4bf5d99347cef3bf66e1fb0645 100644 (file)
@@ -16,7 +16,7 @@
 // non-ASCII characters.  The child process ensures all the strings are
 // intact.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::io::prelude::*;
 use std::io;
index ff389bec899efba23026791c97f3aaad210e03f6..5ea48a4ff33bc545d5957154f39321896c546c36 100644 (file)
@@ -7,7 +7,8 @@
 // <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.
-// ignore-emscripten Function not implemented.
+
+// ignore-emscripten no processes
 
 use std::env;
 use std::io;
index f81c3f2e99d3672ac8176fb41b45b83b094e807e..6f696c1c9cea5ceafb631530760717240750ceb8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten spawning processes is not supported
 
 #![feature(start)]
 
index 8a2bbc83c424e3eb952b4a0e20a125379d92f01f..0f6832acec8143ab22b5254451a93fe544003ae8 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-windows
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::env;
 use std::process::Command;
index 5aa4faa13656527803943c03f4ffa1544a9d8423..465feb4b7790ecf20da3cd585b74d386bedb5e97 100644 (file)
@@ -11,7 +11,7 @@
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::env;
 use std::io::prelude::*;
index ede2325b51c2fbf1fc84aedbf80d3d4d3f3357d1..ed2786edf3a3f25d9b09531b35a3dfb989578570 100644 (file)
@@ -7,7 +7,8 @@
 // <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.
-// ignore-emscripten linking with emcc failed
+
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
 
 #![feature(repr_simd, platform_intrinsics, concat_idents, test)]
 #![allow(non_camel_case_types)]
index f49320e4da4a3753945f824682249c4822953058..78a1019578e350224bb855c2a77ee1eaf629bbe6 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-arm
 // ignore-aarch64
 // ignore-wasm
-// ignore-emscripten
+// ignore-emscripten no processes
 // ignore-musl FIXME #31506
 // ignore-pretty
 // no-system-llvm
index 1d66cb602076054e7e7e20b815c3f7b1fae8515d..bb9471e1b48bc4f2d84e66310a1616111fa019d2 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-arm
 // ignore-aarch64
 // ignore-wasm
-// ignore-emscripten
+// ignore-emscripten no processes
 // ignore-musl FIXME #31506
 // no-system-llvm
 
index 448bb7de7727fc467aa98de8c8135cccc5474606..cce1077202c3fb03928559187541a48e90d6508c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 use std::env;
 use std::io::prelude::*;
index 3135a682d869d827f2133d1370cfca69f3d52776..7a71dd2bc5125f080d7c0e9804f561cc2f96fc01 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -Z thinlto -C codegen-units=8 -O
 // min-llvm-version 4.0
-// ignore-emscripten
+// ignore-emscripten can't inspect instructions on emscripten
 
 // We want to assert here that ThinLTO will inline across codegen units. There's
 // not really a great way to do that in general so we sort of hack around it by
index ed899d2b115b6b2c80cddebe804cf49df8913c3a..0e8ad08a5f6804c26caed1237fba12c5b32d3c80 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:thin-lto-inlines-aux.rs
 // min-llvm-version 4.0
 // no-prefer-dynamic
-// ignore-emscripten
+// ignore-emscripten can't inspect instructions on emscripten
 
 // We want to assert here that ThinLTO will inline across codegen units. There's
 // not really a great way to do that in general so we sort of hack around it by
index be87b7b3c87e42fbd50cd4905bc39d9bd9af7a3a..0ee2cb9238c91e768427cf11384265fa9c91ce92 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 #![feature(process_try_wait)]
 
index b16f6c7b6af55820d9fb50b49a69608c9fbd560e..bf506a712500178e0f6c6f749d9f2ef71f25a029 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten u128 not supported
 
 #![feature(i128_type, test)]
 
index f21027afac3182048a161ac87820e9c0639d1b87..56ff9cb24774b977923b96b620fbb81484b9460a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten missing rust_begin_unwind
+// ignore-emscripten no no_std executables
 
 #![feature(lang_items, start, libc, alloc)]
 #![no_std]
index 1d1c83cf12a15bb2eba21f7cba09a4f19ec62322..744f2989bcfcace577a0ba5503574e83f9b9d6f0 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-emscripten
+// ignore-emscripten no processes
 
 #![feature(libc)]
 
index 6b86af62a663a7ac3bf6cba329a6b5a3770011cb..6c6af19be88f98f4bb080e7e43d35bf366792c4d 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
+// compile-flags: --document-private-items
 
 // @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo'
 // @has 'empty_mod_private/sidebar-items.js' 'foo'
index 266a30891941dbfde7e88ccc05d2bb4df297cc59..c50df6edd484a4c9130aa90ab0d3a3b8f59c41ff 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:--no-defaults --passes collapse-docs --passes unindent-comments
+// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments
 
 // @has issue_15347/fn.foo.html
 #[doc(hidden)]
index 5998734e4a20c7fd610e885cc5889b2c62a23c1b..24d566e082eea8e01e824e1d9e8dd8c419f3cccc 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
+// compile-flags: --document-private-items
 
 #![crate_name = "foo"]
 
diff --git a/src/test/ui/issue-45296.rs b/src/test/ui/issue-45296.rs
new file mode 100644 (file)
index 0000000..7a2b4e5
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let unused = ();
+
+    #![allow(unused_variables)]
+}
diff --git a/src/test/ui/issue-45296.stderr b/src/test/ui/issue-45296.stderr
new file mode 100644 (file)
index 0000000..7bfcac9
--- /dev/null
@@ -0,0 +1,11 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/issue-45296.rs:14:7
+   |
+14 |     #![allow(unused_variables)]
+   |       ^
+   |
+   = note: inner attributes and doc comments, like `#![no_std]` or `//! My crate`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes and doc comments, like `#[test]` and
+                                              `/// My function`, annotate the item following them.
+
+error: aborting due to previous error
+
index 874124a7d36583227207344ac93128198b1e15c0..e078056ab5e0abf15b3e4d259a5d9b6509bf6e63 100644 (file)
 #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
 #![feature(no_debug)]
 
+#[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
+#[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
+
+#[no_mangle] // should suggest removal (generics can't be no-mangle)
+pub fn defiant<T>(_t: T) {}
+
+#[no_mangle]
+fn rio_grande() {} // should suggest `pub`
+
+struct Equinox {
+    warp_factor: f32,
+}
+
 #[no_debug] // should suggest removal of deprecated attribute
 fn main() {
     while true { // should suggest `loop`
         let mut a = (1); // should suggest no `mut`, no parens
+        let d = Equinox { warp_factor: 9.975 };
+        match d {
+            Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
+        }
         println!("{}", a);
     }
 }
index 9a69c52e6cfb45a78be7303a95cac92e33ef9dd2..7a498b56413a9a65929120ad5e1bf72bdc5547c2 100644 (file)
@@ -1,23 +1,23 @@
 warning: unnecessary parentheses around assigned value
-  --> $DIR/suggestions.rs:17:21
+  --> $DIR/suggestions.rs:30:21
    |
-17 |         let mut a = (1); // should suggest no `mut`, no parens
+30 |         let mut a = (1); // should suggest no `mut`, no parens
    |                     ^^^ help: remove these parentheses
    |
    = note: #[warn(unused_parens)] on by default
 
 warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
-  --> $DIR/suggestions.rs:14:1
+  --> $DIR/suggestions.rs:27:1
    |
-14 | #[no_debug] // should suggest removal of deprecated attribute
+27 | #[no_debug] // should suggest removal of deprecated attribute
    | ^^^^^^^^^^^ help: remove this attribute
    |
    = note: #[warn(deprecated)] on by default
 
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:17:13
+  --> $DIR/suggestions.rs:30:13
    |
-17 |         let mut a = (1); // should suggest no `mut`, no parens
+30 |         let mut a = (1); // should suggest no `mut`, no parens
    |             ---^^
    |             |
    |             help: remove this `mut`
@@ -28,18 +28,73 @@ note: lint level defined here
 11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
    |         ^^^^^^^^^^
 
+warning: static is marked #[no_mangle], but not exported
+  --> $DIR/suggestions.rs:14:14
+   |
+14 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
+   |              -^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              help: try making it public: `pub `
+   |
+   = note: #[warn(private_no_mangle_statics)] on by default
+
+error: const items should never be #[no_mangle]
+  --> $DIR/suggestions.rs:15:14
+   |
+15 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
+   |              -----^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              help: try a static value: `pub static`
+   |
+   = note: #[deny(no_mangle_const_items)] on by default
+
+warning: functions generic over types must be mangled
+  --> $DIR/suggestions.rs:18:1
+   |
+17 | #[no_mangle] // should suggest removal (generics can't be no-mangle)
+   | ------------ help: remove this attribute
+18 | pub fn defiant<T>(_t: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(no_mangle_generic_items)] on by default
+
+warning: function is marked #[no_mangle], but not exported
+  --> $DIR/suggestions.rs:21:1
+   |
+21 | fn rio_grande() {} // should suggest `pub`
+   | -^^^^^^^^^^^^^^^^^
+   | |
+   | help: try making it public: `pub `
+   |
+   = note: #[warn(private_no_mangle_fns)] on by default
+
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/suggestions.rs:16:5
+  --> $DIR/suggestions.rs:29:5
    |
-16 |       while true { // should suggest `loop`
+29 |       while true { // should suggest `loop`
    |       ^---------
    |       |
    |  _____help: use `loop`
    | |
-17 | |         let mut a = (1); // should suggest no `mut`, no parens
-18 | |         println!("{}", a);
-19 | |     }
+30 | |         let mut a = (1); // should suggest no `mut`, no parens
+31 | |         let d = Equinox { warp_factor: 9.975 };
+32 | |         match d {
+...  |
+35 | |         println!("{}", a);
+36 | |     }
    | |_____^
    |
    = note: #[warn(while_true)] on by default
 
+warning: the `warp_factor:` in this pattern is redundant
+  --> $DIR/suggestions.rs:33:23
+   |
+33 |             Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
+   |                       ------------^^^^^^^^^^^^
+   |                       |
+   |                       help: remove this
+   |
+   = note: #[warn(non_shorthand_field_patterns)] on by default
+
+error: aborting due to previous error
+
index d7cbd11472a64d0faac959760827b929a1ad4061..9decb0cff365f97908744cb3ff6d0c97d689fe87 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags: --error-format json
 
-// ignore-windows (see Issue #44968)
-
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
 // replacement only removes one set of parentheses, rather than naïvely
index 140224e081489c9b38edd19b5ab73c8dd53e0f76..4b4dd92855da00e0454ba83a83a2a2cc82f2657a 100644 (file)
@@ -1 +1 @@
-{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":"    let _a = 1 / (2 + 3);"}],"rendered":null}
+{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":"    let _a = 1 / (2 + 3);"}],"rendered":null}
index d61077643f1fe435c36b318f6cf097e7e1100d3d..0473c2a5405b02f12b5c5f4e4464c0d7a49df5c2 100644 (file)
@@ -2378,8 +2378,15 @@ fn get_mir_dump_dir(&self) -> PathBuf {
 
     fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
         let parent_dir = self.testpaths.file.parent().unwrap();
-        let parent_dir_str = parent_dir.display().to_string();
+        let cflags = self.props.compile_flags.join(" ");
+        let parent_dir_str = if cflags.contains("--error-format json") {
+            parent_dir.display().to_string().replace("\\", "\\\\")
+        } else {
+            parent_dir.display().to_string()
+        };
+
         let mut normalized = output.replace(&parent_dir_str, "$DIR")
+              .replace("\\\\", "\\") // denormalize for paths on windows
               .replace("\\", "/") // normalize for paths on windows
               .replace("\r\n", "\n") // normalize for linebreaks on windows
               .replace("\t", "\\t"); // makes tabs visible
index b03e4f05641eed1d4d3bb1a0b0d6b5233fad60a2..f1684f4c5acbe42f5f8eb94ba87a3408b9bd5bc9 100644 (file)
 miri = "Broken"
 
 # ping @Manishearth @llogiq @mcarton @oli-obk
-clippy = "Compiling"
+clippy = "Broken"
 
 # ping @nrc
 rls = "Testing"
 
 # ping @nrc
 rustfmt = "Testing"
-