]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
authorCorey Farwell <coreyf@rwell.org>
Fri, 14 Apr 2017 21:41:05 +0000 (17:41 -0400)
committerGitHub <noreply@github.com>
Fri, 14 Apr 2017 21:41:05 +0000 (17:41 -0400)
Fix invalid associated type rendering in rustdoc

Fixes #41036.

r? @rust-lang/docs

275 files changed:
.gitmodules
COPYRIGHT
cargo
configure
rls [new submodule]
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/dist.rs
src/bootstrap/install.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/step.rs
src/ci/docker/cross/Dockerfile
src/ci/docker/dist-android/Dockerfile
src/ci/docker/dist-fuchsia/Dockerfile
src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
src/ci/docker/dist-i686-linux/Dockerfile
src/ci/docker/dist-x86_64-linux/Dockerfile
src/ci/docker/dist-x86_64-musl/Dockerfile
src/ci/docker/run.sh
src/ci/run.sh
src/doc/book
src/doc/reference
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/asm.md
src/doc/unstable-book/src/global_asm.md [new file with mode: 0644]
src/doc/unstable-book/src/manually-drop.md [new file with mode: 0644]
src/doc/unstable-book/src/toowned-clone-into.md [new file with mode: 0644]
src/liballoc/arc.rs
src/liballoc/rc.rs
src/libcollections/borrow.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/tests/cow_str.rs
src/libcollections/vec.rs
src/libcompiler_builtins/lib.rs
src/libcore/intrinsics.rs
src/libcore/iter/iterator.rs
src/libcore/mem.rs
src/libcore/slice/sort.rs
src/librand/distributions/gamma.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/def.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/hcx.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_ty.rs
src/librustc/ich/mod.rs
src/librustc/infer/bivariate.rs [deleted file]
src/librustc/infer/combine.rs
src/librustc/infer/equate.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/note.rs
src/librustc/infer/fudge.rs
src/librustc/infer/glb.rs
src/librustc/infer/lattice.rs
src/librustc/infer/lub.rs
src/librustc/infer/mod.rs
src/librustc/infer/sub.rs
src/librustc/infer/type_variable.rs
src/librustc/lib.rs
src/librustc/middle/cstore.rs
src/librustc/middle/effect.rs
src/librustc/middle/free_region.rs
src/librustc/middle/liveness.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/mir/mod.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc/traits/util.rs
src/librustc/ty/adjustment.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/util.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/lib.rs
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/blake2b.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/obligation_forest/mod.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/lib.rs
src/librustc_incremental/persist/data.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/preds/mod.rs
src/librustc_incremental/persist/save.rs
src/librustc_llvm/ffi.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/index_builder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/expr/as_lvalue.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/diagnostics.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir/util/patch.rs
src/librustc_mir/util/pretty.rs
src/librustc_passes/diagnostics.rs
src/librustc_passes/lib.rs
src/librustc_passes/loops.rs
src/librustc_passes/rvalues.rs [deleted file]
src/librustc_passes/static_recursion.rs
src/librustc_plugin/load.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/abi.rs
src/librustc_trans/asm.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/base.rs
src/librustc_trans/cabi_x86_64.rs
src/librustc_trans/collector.rs
src/librustc_trans/context.rs
src/librustc_trans/debuginfo/create_scope_map.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/utils.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/mir/operand.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/partitioning.rs
src/librustc_trans/symbol_map.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/markdown.rs
src/librustdoc/visit_ast.rs
src/librustdoc/visit_lib.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/lib.rs
src/libstd/primitive_docs.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libsyntax_ext/global_asm.rs [new file with mode: 0644]
src/libsyntax_ext/lib.rs
src/rustllvm/RustWrapper.cpp
src/test/codegen/foo.s [new file with mode: 0644]
src/test/codegen/global_asm.rs [new file with mode: 0644]
src/test/codegen/global_asm_include.rs [new file with mode: 0644]
src/test/codegen/global_asm_x2.rs [new file with mode: 0644]
src/test/codegen/naked-functions.rs
src/test/compile-fail/E0102.rs
src/test/compile-fail/binop-move-semantics.rs
src/test/compile-fail/borrowck/borrowck-lend-flow-loop.rs
src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
src/test/compile-fail/default_ty_param_conflict.rs [deleted file]
src/test/compile-fail/default_ty_param_conflict_cross_crate.rs [deleted file]
src/test/compile-fail/destructure-trait-ref.rs
src/test/compile-fail/feature-gate-global_asm.rs [new file with mode: 0644]
src/test/compile-fail/forget-init-unsafe.rs
src/test/compile-fail/issue-12187-1.rs
src/test/compile-fail/issue-12187-2.rs
src/test/compile-fail/issue-25579.rs
src/test/compile-fail/issue-30225.rs [new file with mode: 0644]
src/test/compile-fail/issue-38412.rs
src/test/compile-fail/issue-41139.rs [new file with mode: 0644]
src/test/compile-fail/issue-7813.rs
src/test/compile-fail/lint-unused-imports.rs
src/test/compile-fail/union/union-borrow-move-parent-sibling.rs [new file with mode: 0644]
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/extern_mods.rs
src/test/incremental/hashes/function_interfaces.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/struct_defs.rs
src/test/incremental/hashes/trait_defs.rs
src/test/incremental/hashes/trait_impls.rs
src/test/incremental/unchecked_dirty_clean_metadata.rs
src/test/parse-fail/tuple-float-index.rs [deleted file]
src/test/run-make/extern-fn-struct-passing-abi/test.c
src/test/run-make/extern-fn-struct-passing-abi/test.rs
src/test/run-pass/default_ty_param_default_dependent_associated_type.rs [deleted file]
src/test/run-pass/default_ty_param_dependent_defaults.rs [deleted file]
src/test/run-pass/default_ty_param_method_call_test.rs [deleted file]
src/test/run-pass/default_ty_param_struct.rs [deleted file]
src/test/run-pass/default_ty_param_struct_and_type_alias.rs [deleted file]
src/test/run-pass/default_ty_param_trait_impl.rs [deleted file]
src/test/run-pass/default_ty_param_trait_impl_simple.rs [deleted file]
src/test/run-pass/default_ty_param_type_alias.rs [deleted file]
src/test/run-pass/empty_global_asm.rs [new file with mode: 0644]
src/test/run-pass/i128.rs
src/test/run-pass/issue-40951.rs [new file with mode: 0644]
src/test/run-pass/issue-41213.rs [new file with mode: 0644]
src/test/run-pass/optimization-fuel-0.rs [new file with mode: 0644]
src/test/run-pass/optimization-fuel-1.rs [new file with mode: 0644]
src/test/run-pass/simple_global_asm.rs [new file with mode: 0644]
src/test/run-pass/type-infer-generalize-ty-var.rs [new file with mode: 0644]
src/test/run-pass/type-sizes.rs
src/test/run-pass/u128.rs
src/test/rustdoc/auxiliary/issue-40936.rs [new file with mode: 0644]
src/test/rustdoc/issue-40936.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
src/test/ui/mismatched_types/abridged.rs [new file with mode: 0644]
src/test/ui/mismatched_types/abridged.stderr [new file with mode: 0644]
src/test/ui/print-fuel/print-fuel.rs [new file with mode: 0644]
src/test/ui/print-fuel/print-fuel.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/nullable.stdout
src/test/ui/print_type_sizes/packed.stdout
src/test/ui/print_type_sizes/padding.stdout
src/test/ui/suggestions/tuple-float-index.rs [new file with mode: 0644]
src/test/ui/suggestions/tuple-float-index.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/compiletest/src/json.rs
src/tools/compiletest/src/runtest.rs
src/tools/tidy/src/main.rs

index 3533f0df5d1ce82d13e9aa992c7ee62798b5aa0c..4f29cef85700ee18bfa7387167718929abfe2910 100644 (file)
@@ -26,3 +26,7 @@
 [submodule "book"]
        path = src/doc/book
        url = https://github.com/rust-lang/book.git
+[submodule "rls"]
+       path = rls
+       url = https://github.com/rust-lang-nursery/rls.git
+
index abe899803087120379021a1b88dd85ca4533cca0..19559fa2950ea814798b5637d2eec2f1fd6292aa 100644 (file)
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -197,28 +197,6 @@ their own copyright notices and license terms:
     USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
     OF SUCH DAMAGE.
 
-* Hoedown, the markdown parser, under src/rt/hoedown, is
-  licensed as follows.
-
-    Copyright (c) 2008, Natacha Porté
-    Copyright (c) 2011, Vicent Martí
-    Copyright (c) 2013, Devin Torres and the Hoedown authors
-
-    Permission to use, copy, modify, and distribute this
-    software for any purpose with or without fee is hereby
-    granted, provided that the above copyright notice and
-    this permission notice appear in all copies.
-
-    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR
-    DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
-    INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-    FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-    SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR
-    ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
-    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-    OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-    CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
 * libbacktrace, under src/libbacktrace:
 
     Copyright (C) 2012-2014 Free Software Foundation, Inc.
diff --git a/cargo b/cargo
index 4729175045b41b688ab903120860866ce7a22ba9..c416fb60b11ecfd2a1ba0fb8567c9a92590b5d28 160000 (submodule)
--- a/cargo
+++ b/cargo
@@ -1 +1 @@
-Subproject commit 4729175045b41b688ab903120860866ce7a22ba9
+Subproject commit c416fb60b11ecfd2a1ba0fb8567c9a92590b5d28
index d6dded6dc5f7bccfbeb0d57a48f394d7b326f1f7..35b376d5f27b8c498d3691e720c9d3dcde558f45 100755 (executable)
--- a/configure
+++ b/configure
@@ -445,7 +445,6 @@ opt dist-host-only 0 "only install bins for the host architecture"
 opt inject-std-version 1 "inject the current compiler version of libstd into programs"
 opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
 opt codegen-tests 1 "run the src/test/codegen tests"
-opt save-analysis 0 "save API analysis data"
 opt option-checking 1 "complain about unrecognized options in this configure script"
 opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
 opt locked-deps 0 "force Cargo.lock to be up to date"
diff --git a/rls b/rls
new file mode 160000 (submodule)
index 0000000..016cbc5
--- /dev/null
+++ b/rls
@@ -0,0 +1 @@
+Subproject commit 016cbc514cf44a2bd3fe806e8afa6b9c50287373
index eeec7eb029e5c054590f04415afc7a741e8a2ed6..bddd570a13d2640bfc26b8d63fb769e9f76fad95 100644 (file)
@@ -275,6 +275,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
         cargo.env("CFG_DEFAULT_AR", s);
     }
     build.run(&mut cargo);
+    update_mtime(build, &librustc_stamp(build, compiler, target));
 }
 
 /// Same as `std_link`, only for librustc
@@ -305,6 +306,12 @@ fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
     build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
 }
 
+/// Cargo's output path for librustc in a given stage, compiled by a particular
+/// compiler for the specified target.
+fn librustc_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
+    build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
+}
+
 fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
     let out = output(Command::new(compiler)
                             .arg(format!("-print-file-name={}", file)));
@@ -407,6 +414,23 @@ fn add_to_sysroot(out_dir: &Path, sysroot_dst: &Path) {
     }
 }
 
+/// Build a tool in `src/tools`
+///
+/// This will build the specified tool with the specified `host` compiler in
+/// `stage` into the normal cargo output directory.
+pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) {
+    let compiler = Compiler::new(stage, &build.config.build);
+
+    let stamp = match mode {
+        Mode::Libstd => libstd_stamp(build, &compiler, target),
+        Mode::Libtest => libtest_stamp(build, &compiler, target),
+        Mode::Librustc => librustc_stamp(build, &compiler, target),
+        _ => panic!(),
+    };
+    let out_dir = build.cargo_out(&compiler, Mode::Tool, target);
+    build.clear_if_dirty(&out_dir, &stamp);
+}
+
 /// Build a tool in `src/tools`
 ///
 /// This will build the specified tool with the specified `host` compiler in
@@ -416,15 +440,6 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
 
     let compiler = Compiler::new(stage, &build.config.build);
 
-    // FIXME: need to clear out previous tool and ideally deps, may require
-    //        isolating output directories or require a pseudo shim step to
-    //        clear out all the info.
-    //
-    //        Maybe when libstd is compiled it should clear out the rustc of the
-    //        corresponding stage?
-    // let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
-    // build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
-
     let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
     let mut dir = build.src.join(tool);
     if !dir.exists() {
index 52ebf401aefd6d3eff0eab632e4dee97b1df6ac7..693114d01ad9c56fc04409c7d02706e888695e88 100644 (file)
@@ -74,7 +74,6 @@ pub struct Config {
     pub rustc_default_ar: Option<String>,
     pub rust_optimize_tests: bool,
     pub rust_debuginfo_tests: bool,
-    pub rust_save_analysis: bool,
     pub rust_dist_src: bool,
 
     pub build: String,
@@ -226,7 +225,6 @@ struct Rust {
     optimize_tests: Option<bool>,
     debuginfo_tests: Option<bool>,
     codegen_tests: Option<bool>,
-    save_analysis: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -352,7 +350,6 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
             set(&mut config.rust_optimize_tests, rust.optimize_tests);
             set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
             set(&mut config.codegen_tests, rust.codegen_tests);
-            set(&mut config.rust_save_analysis, rust.save_analysis);
             set(&mut config.rust_rpath, rust.rpath);
             set(&mut config.debug_jemalloc, rust.debug_jemalloc);
             set(&mut config.use_jemalloc, rust.use_jemalloc);
@@ -460,7 +457,6 @@ macro_rules! check {
                 ("LOCAL_REBUILD", self.local_rebuild),
                 ("NINJA", self.ninja),
                 ("CODEGEN_TESTS", self.codegen_tests),
-                ("SAVE_ANALYSIS", self.rust_save_analysis),
                 ("LOCKED_DEPS", self.locked_deps),
                 ("VENDOR", self.vendor),
                 ("FULL_BOOTSTRAP", self.full_bootstrap),
index 6b2cc6eb6474c868544c204d0b1f02f9e19f7e42..fad79022043e33dbc800288edc60bd5174dc4f93 100644 (file)
 # saying that the FileCheck executable is missing, you may want to disable this.
 #codegen-tests = true
 
-# Flag indicating whether the API analysis data should be saved.
-#save-analysis = false
-
 # =============================================================================
 # Options for specific targets
 #
index 6472b1a928cafd92cd9298da7ca0ef060ac3ad5f..4328c4e3f1d4c58126c11d62b428557f8b2845be 100644 (file)
@@ -39,6 +39,8 @@
 fn pkgname(build: &Build, component: &str) -> String {
     if component == "cargo" {
         format!("{}-{}", component, build.cargo_package_vers())
+    } else if component == "rls" {
+        format!("{}-{}", component, build.package_vers(&build.release_num("rls")))
     } else {
         assert!(component.starts_with("rust"));
         format!("{}-{}", component, build.rust_package_vers())
@@ -315,15 +317,12 @@ pub fn rust_src_location(build: &Build) -> PathBuf {
 
 /// Creates a tarball of save-analysis metadata, if available.
 pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
-    if !build.config.rust_save_analysis {
-        return
-    }
-
+    assert!(build.config.extended);
     println!("Dist analysis");
 
     if compiler.host != build.config.build {
         println!("\tskipping, not a build host");
-        return
+        return;
     }
 
     // Package save-analysis from stage1 if not doing a full bootstrap, as the
@@ -393,6 +392,7 @@ pub fn rust_src(build: &Build) {
         "man",
         "src",
         "cargo",
+        "rls",
     ];
 
     let filter_fn = move |path: &Path| {
@@ -539,7 +539,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
 
     let src = build.src.join("cargo");
     let etc = src.join("src/etc");
-    let release_num = build.cargo_release_num();
+    let release_num = build.release_num("cargo");
     let name = pkgname(build, "cargo");
     let version = build.cargo_info.version(build, &release_num);
 
@@ -593,6 +593,55 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
     build.run(&mut cmd);
 }
 
+pub fn rls(build: &Build, stage: u32, target: &str) {
+    assert!(build.config.extended);
+    println!("Dist RLS stage{} ({})", stage, target);
+    let compiler = Compiler::new(stage, &build.config.build);
+
+    let src = build.src.join("rls");
+    let release_num = build.release_num("rls");
+    let name = pkgname(build, "rls");
+    let version = build.rls_info.version(build, &release_num);
+
+    let tmp = tmpdir(build);
+    let image = tmp.join("rls-image");
+    drop(fs::remove_dir_all(&image));
+    t!(fs::create_dir_all(&image));
+
+    // Prepare the image directory
+    let rls = build.cargo_out(&compiler, Mode::Tool, target)
+                     .join(exe("rls", target));
+    install(&rls, &image.join("bin"), 0o755);
+    let doc = image.join("share/doc/rls");
+    install(&src.join("README.md"), &doc, 0o644);
+    install(&src.join("LICENSE-MIT"), &doc, 0o644);
+    install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+
+    // Prepare the overlay
+    let overlay = tmp.join("rls-overlay");
+    drop(fs::remove_dir_all(&overlay));
+    t!(fs::create_dir_all(&overlay));
+    install(&src.join("README.md"), &overlay, 0o644);
+    install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+    install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+    t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
+
+    // Generate the installer tarball
+    let mut cmd = Command::new("sh");
+    cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
+       .arg("--product-name=Rust")
+       .arg("--rel-manifest-dir=rustlib")
+       .arg("--success-message=RLS-ready-to-serve.")
+       .arg(format!("--image-dir={}", sanitize_sh(&image)))
+       .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build))))
+       .arg(format!("--output-dir={}", sanitize_sh(&distdir(build))))
+       .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay)))
+       .arg(format!("--package-name={}-{}", name, target))
+       .arg("--component-name=rls")
+       .arg("--legacy-manifest-dirs=rustlib,cargo");
+    build.run(&mut cmd);
+}
+
 /// Creates a combined installer for the specified target in the provided stage.
 pub fn extended(build: &Build, stage: u32, target: &str) {
     println!("Dist extended stage{} ({})", stage, target);
@@ -604,6 +653,12 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
     let cargo_installer = dist.join(format!("{}-{}.tar.gz",
                                             pkgname(build, "cargo"),
                                             target));
+    let rls_installer = dist.join(format!("{}-{}.tar.gz",
+                                          pkgname(build, "rls"),
+                                          target));
+    let analysis_installer = dist.join(format!("{}-{}.tar.gz",
+                                               pkgname(build, "rust-analysis"),
+                                               target));
     let docs_installer = dist.join(format!("{}-{}.tar.gz",
                                            pkgname(build, "rust-docs"),
                                            target));
@@ -631,9 +686,11 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
     // 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 input_tarballs = format!("{},{},{},{}",
+    let mut input_tarballs = format!("{},{},{},{},{},{}",
                                      sanitize_sh(&rustc_installer),
                                      sanitize_sh(&cargo_installer),
+                                     sanitize_sh(&rls_installer),
+                                     sanitize_sh(&analysis_installer),
                                      sanitize_sh(&docs_installer),
                                      sanitize_sh(&std_installer));
     if target.contains("pc-windows-gnu") {
@@ -946,7 +1003,8 @@ pub fn hash_and_sign(build: &Build) {
     cmd.arg(distdir(build));
     cmd.arg(today.trim());
     cmd.arg(build.rust_package_vers());
-    cmd.arg(build.package_vers(&build.cargo_release_num()));
+    cmd.arg(build.package_vers(&build.release_num("cargo")));
+    cmd.arg(build.package_vers(&build.release_num("rls")));
     cmd.arg(addr);
 
     t!(fs::create_dir_all(distdir(build)));
index 25082e3a9d095645d68c8528c1a1fb915d62ddcc..d508616e4b1cc2e6caf285737c09137305f1e894 100644 (file)
@@ -55,11 +55,6 @@ pub fn install(build: &Build, stage: u32, host: &str) {
                    &docdir, &libdir, &mandir, &empty_dir);
     }
 
-    if build.config.rust_save_analysis {
-        install_sh(&build, "analysis", "rust-analysis", stage, host, &prefix,
-                   &docdir, &libdir, &mandir, &empty_dir);
-    }
-
     install_sh(&build, "rustc", "rustc", stage, host, &prefix,
                &docdir, &libdir, &mandir, &empty_dir);
     t!(fs::remove_dir_all(&empty_dir));
index 8303a40bb6965fffc48bfa7ce4e2f3c8a485dbce..d711b63ea2e26f348b9c4e679c32e88cc076cf15 100644 (file)
@@ -151,6 +151,7 @@ pub struct Build {
     out: PathBuf,
     rust_info: channel::GitInfo,
     cargo_info: channel::GitInfo,
+    rls_info: channel::GitInfo,
     local_rebuild: bool,
 
     // Probed tools at runtime
@@ -234,6 +235,7 @@ pub fn new(flags: Flags, config: Config) -> Build {
         };
         let rust_info = channel::GitInfo::new(&src);
         let cargo_info = channel::GitInfo::new(&src.join("cargo"));
+        let rls_info = channel::GitInfo::new(&src.join("rls"));
         let src_is_git = src.join(".git").exists();
 
         Build {
@@ -246,6 +248,7 @@ pub fn new(flags: Flags, config: Config) -> Build {
 
             rust_info: rust_info,
             cargo_info: cargo_info,
+            rls_info: rls_info,
             local_rebuild: local_rebuild,
             cc: HashMap::new(),
             cxx: HashMap::new(),
@@ -545,7 +548,7 @@ fn cargo(&self,
                  .env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
         }
 
-        if self.config.rust_save_analysis && compiler.is_final_stage(self) {
+        if self.config.extended && compiler.is_final_stage(self) {
             cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string());
         }
 
@@ -1017,7 +1020,7 @@ fn rust_package_vers(&self) -> String {
 
     /// Returns the value of `package_vers` above for Cargo
     fn cargo_package_vers(&self) -> String {
-        self.package_vers(&self.cargo_release_num())
+        self.package_vers(&self.release_num("cargo"))
     }
 
     /// Returns the `version` string associated with this compiler for Rust
@@ -1029,10 +1032,11 @@ fn rust_version(&self) -> String {
         self.rust_info.version(self, channel::CFG_RELEASE_NUM)
     }
 
-    /// Returns the `a.b.c` version that Cargo is at.
-    fn cargo_release_num(&self) -> String {
+    /// Returns the `a.b.c` version that the given package is at.
+    fn release_num(&self, package: &str) -> String {
         let mut toml = String::new();
-        t!(t!(File::open(self.src.join("cargo/Cargo.toml"))).read_to_string(&mut toml));
+        let toml_file_name = self.src.join(&format!("{}/Cargo.toml", package));
+        t!(t!(File::open(toml_file_name)).read_to_string(&mut toml));
         for line in toml.lines() {
             let prefix = "version = \"";
             let suffix = "\"";
@@ -1041,7 +1045,7 @@ fn cargo_release_num(&self) -> String {
             }
         }
 
-        panic!("failed to find version in cargo's Cargo.toml")
+        panic!("failed to find version in {}'s Cargo.toml", package)
     }
 
     /// Returns whether unstable features should be enabled for the compiler
index 62eed8be3ccb70764c9dacc9be320ddf855e2e8c..726e94e49a19ecf279e980438603df346dde52ab 100644 (file)
@@ -147,7 +147,7 @@ pub fn llvm(build: &Build, target: &str) {
     }
 
     if env::var_os("SCCACHE_ERROR_LOG").is_some() {
-        cfg.env("RUST_LOG", "sccache=debug");
+        cfg.env("RUST_LOG", "sccache=info");
     }
 
     // FIXME: we don't actually need to build all LLVM tools and all LLVM
index 5560b5b0333c862b3c7b64bb23c00e7fcfb5f6c5..6008fa81c66537cc15765787d1bf5f202ddcd2bd 100644 (file)
@@ -26,7 +26,7 @@
 //! along with the actual implementation elsewhere. You can find more comments
 //! about how to define rules themselves below.
 
-use std::collections::{BTreeMap, HashSet};
+use std::collections::{BTreeMap, HashSet, HashMap};
 use std::mem;
 
 use check::{self, TestKind};
@@ -533,34 +533,44 @@ fn crate_rule<'a, 'b>(build: &'a Build,
     //
     // Tools used during the build system but not shipped
     rules.build("tool-rustbook", "src/tools/rustbook")
-         .dep(|s| s.name("librustc"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("librustc-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "rustbook"));
     rules.build("tool-error-index", "src/tools/error_index_generator")
-         .dep(|s| s.name("librustc"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("librustc-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator"));
     rules.build("tool-tidy", "src/tools/tidy")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "tidy"));
     rules.build("tool-linkchecker", "src/tools/linkchecker")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker"));
     rules.build("tool-cargotest", "src/tools/cargotest")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "cargotest"));
     rules.build("tool-compiletest", "src/tools/compiletest")
-         .dep(|s| s.name("libtest"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libtest-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "compiletest"));
     rules.build("tool-build-manifest", "src/tools/build-manifest")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest"));
     rules.build("tool-qemu-test-server", "src/tools/qemu-test-server")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-server"));
     rules.build("tool-qemu-test-client", "src/tools/qemu-test-client")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-client"));
     rules.build("tool-cargo", "cargo")
-         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("maybe-clean-tools"))
+         .dep(|s| s.name("libstd-tool"))
          .dep(|s| s.stage(0).host(s.target).name("openssl"))
          .dep(move |s| {
              // Cargo depends on procedural macros, which requires a full host
@@ -570,6 +580,36 @@ fn crate_rule<'a, 'b>(build: &'a Build,
               .host(&build.config.build)
          })
          .run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
+    rules.build("tool-rls", "rls")
+         .host(true)
+         .dep(|s| s.name("librustc-tool"))
+         .dep(|s| s.stage(0).host(s.target).name("openssl"))
+         .dep(move |s| {
+             // rls, like cargo, uses procedural macros
+             s.name("librustc-link")
+              .target(&build.config.build)
+              .host(&build.config.build)
+         })
+         .run(move |s| compile::tool(build, s.stage, s.target, "rls"));
+
+    // "pseudo rule" which represents completely cleaning out the tools dir in
+    // one stage. This needs to happen whenever a dependency changes (e.g.
+    // libstd, libtest, librustc) and all of the tool compilations above will
+    // be sequenced after this rule.
+    rules.build("maybe-clean-tools", "path/to/nowhere")
+         .after("librustc-tool")
+         .after("libtest-tool")
+         .after("libstd-tool");
+
+    rules.build("librustc-tool", "path/to/nowhere")
+         .dep(|s| s.name("librustc"))
+         .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc));
+    rules.build("libtest-tool", "path/to/nowhere")
+         .dep(|s| s.name("libtest"))
+         .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest));
+    rules.build("libstd-tool", "path/to/nowhere")
+         .dep(|s| s.name("libstd"))
+         .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd));
 
     // ========================================================================
     // Documentation targets
@@ -690,10 +730,15 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .dep(|s| s.name("default:doc"))
          .run(move |s| dist::docs(build, s.stage, s.target));
     rules.dist("dist-analysis", "analysis")
+         .default(build.config.extended)
          .dep(|s| s.name("dist-std"))
-         .default(true)
          .only_host_build(true)
          .run(move |s| dist::analysis(build, &s.compiler(), s.target));
+    rules.dist("dist-rls", "rls")
+         .host(true)
+         .only_host_build(true)
+         .dep(|s| s.name("tool-rls"))
+         .run(move |s| dist::rls(build, s.stage, s.target));
     rules.dist("install", "path/to/nowhere")
          .dep(|s| s.name("default:dist"))
          .run(move |s| install::install(build, s.stage, s.target));
@@ -711,6 +756,8 @@ fn crate_rule<'a, 'b>(build: &'a Build,
          .dep(|d| d.name("dist-mingw"))
          .dep(|d| d.name("dist-docs"))
          .dep(|d| d.name("dist-cargo"))
+         .dep(|d| d.name("dist-rls"))
+         .dep(|d| d.name("dist-analysis"))
          .run(move |s| dist::extended(build, s.stage, s.target));
 
     rules.dist("dist-sign", "hash-and-sign")
@@ -811,6 +858,11 @@ struct Rule<'a> {
     /// Whether this rule is only for the build triple, not anything in hosts or
     /// targets.
     only_build: bool,
+
+    /// A list of "order only" dependencies. This rules does not actually
+    /// depend on these rules, but if they show up in the dependency graph then
+    /// this rule must be executed after all these rules.
+    after: Vec<&'a str>,
 }
 
 #[derive(PartialEq)]
@@ -834,6 +886,7 @@ fn new(name: &'a str, path: &'a str, kind: Kind) -> Rule<'a> {
             host: false,
             only_host_build: false,
             only_build: false,
+            after: Vec::new(),
         }
     }
 }
@@ -853,6 +906,11 @@ fn dep<F>(&mut self, f: F) -> &mut Self
         self
     }
 
+    fn after(&mut self, step: &'a str) -> &mut Self {
+        self.rule.after.push(step);
+        self
+    }
+
     fn run<F>(&mut self, f: F) -> &mut Self
         where F: Fn(&Step<'a>) + 'a,
     {
@@ -1136,31 +1194,52 @@ fn run(&self, steps: &[Step<'a>]) {
     /// From the top level targets `steps` generate a topological ordering of
     /// all steps needed to run those steps.
     fn expand(&self, steps: &[Step<'a>]) -> Vec<Step<'a>> {
+        // First up build a graph of steps and their dependencies. The `nodes`
+        // map is a map from step to a unique number. The `edges` map is a
+        // map from these unique numbers to a list of other numbers,
+        // representing dependencies.
+        let mut nodes = HashMap::new();
+        nodes.insert(Step::noop(), 0);
+        let mut edges = HashMap::new();
+        edges.insert(0, HashSet::new());
+        for step in steps {
+            self.build_graph(step.clone(), &mut nodes, &mut edges);
+        }
+
+        // Now that we've built up the actual dependency graph, draw more
+        // dependency edges to satisfy the `after` dependencies field for each
+        // rule.
+        self.satisfy_after_deps(&nodes, &mut edges);
+
+        // And finally, perform a topological sort to return a list of steps to
+        // execute.
         let mut order = Vec::new();
-        let mut added = HashSet::new();
-        added.insert(Step::noop());
-        for step in steps.iter().cloned() {
-            self.fill(step, &mut order, &mut added);
+        let mut visited = HashSet::new();
+        visited.insert(0);
+        let idx_to_node = nodes.iter().map(|p| (*p.1, p.0)).collect::<HashMap<_, _>>();
+        for idx in nodes.values() {
+            self.topo_sort(*idx, &idx_to_node, &edges, &mut visited, &mut order);
         }
         return order
     }
 
-    /// Performs topological sort of dependencies rooted at the `step`
-    /// specified, pushing all results onto the `order` vector provided.
-    ///
-    /// In other words, when this method returns, the `order` vector will
-    /// contain a list of steps which if executed in order will eventually
-    /// complete the `step` specified as well.
+    /// Builds the dependency graph rooted at `step`.
     ///
-    /// The `added` set specified here is the set of steps that are already
-    /// present in `order` (and hence don't need to be added again).
-    fn fill(&self,
-            step: Step<'a>,
-            order: &mut Vec<Step<'a>>,
-            added: &mut HashSet<Step<'a>>) {
-        if !added.insert(step.clone()) {
-            return
+    /// The `nodes` and `edges` maps are filled out according to the rule
+    /// described by `step.name`.
+    fn build_graph(&self,
+                   step: Step<'a>,
+                   nodes: &mut HashMap<Step<'a>, usize>,
+                   edges: &mut HashMap<usize, HashSet<usize>>) -> usize {
+        use std::collections::hash_map::Entry;
+
+        let idx = nodes.len();
+        match nodes.entry(step.clone()) {
+            Entry::Vacant(e) => { e.insert(idx); }
+            Entry::Occupied(e) => return *e.get(),
         }
+
+        let mut deps = Vec::new();
         for dep in self.rules[step.name].deps.iter() {
             let dep = dep(&step);
             if dep.name.starts_with("default:") {
@@ -1172,13 +1251,61 @@ fn fill(&self,
                 let host = self.build.config.host.iter().any(|h| h == dep.target);
                 let rules = self.rules.values().filter(|r| r.default);
                 for rule in rules.filter(|r| r.kind == kind && (!r.host || host)) {
-                    self.fill(dep.name(rule.name), order, added);
+                    deps.push(self.build_graph(dep.name(rule.name), nodes, edges));
                 }
             } else {
-                self.fill(dep, order, added);
+                deps.push(self.build_graph(dep, nodes, edges));
             }
         }
-        order.push(step);
+
+        edges.entry(idx).or_insert(HashSet::new()).extend(deps);
+        return idx
+    }
+
+    /// Given a dependency graph with a finished list of `nodes`, fill out more
+    /// dependency `edges`.
+    ///
+    /// This is the step which satisfies all `after` listed dependencies in
+    /// `Rule` above.
+    fn satisfy_after_deps(&self,
+                          nodes: &HashMap<Step<'a>, usize>,
+                          edges: &mut HashMap<usize, HashSet<usize>>) {
+        // Reverse map from the name of a step to the node indices that it
+        // appears at.
+        let mut name_to_idx = HashMap::new();
+        for (step, &idx) in nodes {
+            name_to_idx.entry(step.name).or_insert(Vec::new()).push(idx);
+        }
+
+        for (step, idx) in nodes {
+            if *step == Step::noop() {
+                continue
+            }
+            for after in self.rules[step.name].after.iter() {
+                // This is the critical piece of an `after` dependency. If the
+                // dependency isn't actually in our graph then no edge is drawn,
+                // only if it's already present do we draw the edges.
+                if let Some(idxs) = name_to_idx.get(after) {
+                    edges.get_mut(idx).unwrap()
+                         .extend(idxs.iter().cloned());
+                }
+            }
+        }
+    }
+
+    fn topo_sort(&self,
+                 cur: usize,
+                 nodes: &HashMap<usize, &Step<'a>>,
+                 edges: &HashMap<usize, HashSet<usize>>,
+                 visited: &mut HashSet<usize>,
+                 order: &mut Vec<Step<'a>>) {
+        if !visited.insert(cur) {
+            return
+        }
+        for dep in edges[&cur].iter() {
+            self.topo_sort(*dep, nodes, edges, visited, order);
+        }
+        order.push(nodes[&cur].clone());
     }
 }
 
index 7c1984410078f990c969c74e836638c4a248ddce..02d4eaf534acdd4d152bd963cef2655e91aaee65 100644 (file)
@@ -74,6 +74,7 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
 ENV STAGING_DIR=/tmp
 
 ENV RUST_CONFIGURE_ARGS \
+      --enable-extended \
       --target=$TARGETS \
       --musl-root-arm=/usr/local/arm-linux-musleabi \
       --musl-root-armhf=/usr/local/arm-linux-musleabihf \
index 31f4b8b777be5be44967e61694dbea67144ff069..99c176aa820c733473a592781a91f0728dc5443d 100644 (file)
@@ -42,6 +42,7 @@ ENV TARGETS=$TARGETS,armv7-linux-androideabi
 
 ENV RUST_CONFIGURE_ARGS \
       --target=$TARGETS \
+      --enable-extended \
       --arm-linux-androideabi-ndk=/android/ndk-arm-9 \
       --armv7-linux-androideabi-ndk=/android/ndk-arm-9 \
       --i686-linux-android-ndk=/android/ndk-x86-9 \
index 4a401bbb3031fd1aa8240ee1f5e1ab84cd105c1c..294460ed7604e93b1db7ca4afe365296c3e8278c 100644 (file)
@@ -44,5 +44,5 @@ ENV \
 ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 
-ENV RUST_CONFIGURE_ARGS --target=$TARGETS
+ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
index d2727cbdb3508b35a5a8cc223597397fbed9bacd..1ef3e569cb4bf15c85305e90adeb7b6bd74d9a13 100644 (file)
@@ -31,7 +31,8 @@ RUN curl -o /usr/local/bin/sccache \
 
 ENV RUST_CONFIGURE_ARGS \
       --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
-      --musl-root-i686=/musl-i686
+      --musl-root-i686=/musl-i686 \
+      --enable-extended
 
 # Newer binutils broke things on some vms/distros (i.e., linking against
 # unknown relocs disabled by the following flag), so we need to go out of our
index b322f56f0d0480aade00539c8795aec18ddfb23f..c25c770136f90c9a406c7d3262eec4634b745728 100644 (file)
@@ -6,7 +6,7 @@ WORKDIR /build
 # to http://vault.centos.org/
 RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf
 RUN sed -i 's/mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo
-RUN sed -i 's/#\(baseurl.*\)mirror.centos.org/\1107.158.252.35/' /etc/yum.repos.d/*.repo
+RUN sed -i 's|#\(baseurl.*\)mirror.centos.org/centos/$releasever|\1vault.centos.org/5.11|' /etc/yum.repos.d/*.repo
 
 RUN yum upgrade -y && yum install -y \
       curl \
index cbe5f5936a506a404004fb5eeef0c29c342fb03a..e835e8d2f7161b451d0403fbcfae52a5e8cda92d 100644 (file)
@@ -6,7 +6,7 @@ WORKDIR /build
 # to http://vault.centos.org/
 RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf
 RUN sed -i 's/mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo
-RUN sed -i 's/#\(baseurl.*\)mirror.centos.org/\1107.158.252.35/' /etc/yum.repos.d/*.repo
+RUN sed -i 's|#\(baseurl.*\)mirror.centos.org/centos/$releasever|\1vault.centos.org/5.11|' /etc/yum.repos.d/*.repo
 
 RUN yum upgrade -y && yum install -y \
       curl \
index a41c0cca3b5f0e5b086b2da1243faadce941bd9b..f462ccbb9119afcd1887e606a013dd9a014d11fd 100644 (file)
@@ -31,7 +31,8 @@ RUN curl -o /usr/local/bin/sccache \
 
 ENV RUST_CONFIGURE_ARGS \
       --target=x86_64-unknown-linux-musl \
-      --musl-root-x86_64=/musl-x86_64
+      --musl-root-x86_64=/musl-x86_64 \
+      --enable-extended
 
 # Newer binutils broke things on some vms/distros (i.e., linking against
 # unknown relocs disabled by the following flag), so we need to go out of our
index 71a4bfae3caf9424b930bf81aeba9a26b15e1a7e..59b93b784b2f6f27db319fc06d23c2fa93a4600c 100755 (executable)
@@ -38,7 +38,6 @@ if [ "$SCCACHE_BUCKET" != "" ]; then
     args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
     args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
     args="$args --env SCCACHE_ERROR_LOG=/tmp/sccache/sccache.log"
-    args="$args --env SCCACHE_LOG_LEVEL=debug"
     args="$args --volume $objdir/tmp:/tmp/sccache"
 else
     mkdir -p $HOME/.cache/sccache
index 6c6a49ada15d9b72fb97eb0015c84bd5dbaea513..c6510120b47ae7ec3fb500d71df5db6ba5dc52ff 100755 (executable)
@@ -42,7 +42,6 @@ fi
 if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=nightly"
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
-  RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-save-analysis"
 
   if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
index a2c56870d4dc589237102cc5e0fe7b9ebd0d14a1..beea82b9230cd641dd1ca263cf31025ace4aebb5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a2c56870d4dc589237102cc5e0fe7b9ebd0d14a1
+Subproject commit beea82b9230cd641dd1ca263cf31025ace4aebb5
index acedc32cacae80cf2f4925753a4ce7f7ffd7c86a..b060f732145f2fa16df84c74e511df08a3a47c5d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit acedc32cacae80cf2f4925753a4ce7f7ffd7c86a
+Subproject commit b060f732145f2fa16df84c74e511df08a3a47c5d
index 81c75e1326e412d7e2f7bc6b75168aff61553169..a5599395f796564928da250b10bf7abfa4bdc453 100644 (file)
@@ -83,6 +83,7 @@
 - [future_atomic_orderings](future-atomic-orderings.md)
 - [generic_param_attrs](generic-param-attrs.md)
 - [get_type_id](get-type-id.md)
+- [global_asm](global_asm.md)
 - [heap_api](heap-api.md)
 - [i128](i128.md)
 - [i128_type](i128-type.md)
 - [loop_break_value](loop-break-value.md)
 - [macro_reexport](macro-reexport.md)
 - [main](main.md)
+- [manually_drop](manually-drop.md)
 - [map_entry_recover_keys](map-entry-recover-keys.md)
 - [mpsc_select](mpsc-select.md)
 - [n16](n16.md)
 - [thread_local](thread-local.md)
 - [thread_local_internals](thread-local-internals.md)
 - [thread_local_state](thread-local-state.md)
+- [toowned_clone_into](toowned-clone-into.md)
 - [trace_macros](trace-macros.md)
 - [trusted_len](trusted-len.md)
 - [try_from](try-from.md)
index 032d9d81240266ec346bcf03dceaf1ac46de3fb6..5e68be633e7ab2d69aa066853c888b7ccf5c3467 100644 (file)
@@ -189,3 +189,5 @@ constraints, etc.
 
 [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
 
+If you need more power and don't mind losing some of the niceties of
+`asm!`, check out [global_asm](global_asm.html).
diff --git a/src/doc/unstable-book/src/global_asm.md b/src/doc/unstable-book/src/global_asm.md
new file mode 100644 (file)
index 0000000..44921aa
--- /dev/null
@@ -0,0 +1,78 @@
+# `global_asm`
+
+The tracking issue for this feature is: [#35119]
+
+[#35119]: https://github.com/rust-lang/rust/issues/35119
+
+------------------------
+
+The `global_asm!` macro allows the programmer to write arbitrary
+assembly outside the scope of a function body, passing it through
+`rustc` and `llvm` to the assembler. The macro is a no-frills
+interface to LLVM's concept of [module-level inline assembly]. That is,
+all caveats applicable to LLVM's module-level inline assembly apply
+to `global_asm!`.
+
+[module-level inline assembly]: http://llvm.org/docs/LangRef.html#module-level-inline-assembly
+
+`global_asm!` fills a role not currently satisfied by either `asm!`
+or `#[naked]` functions. The programmer has _all_ features of the
+assembler at their disposal. The linker will expect to resolve any
+symbols defined in the inline assembly, modulo any symbols marked as
+external. It also means syntax for directives and assembly follow the
+conventions of the assembler in your toolchain.
+
+A simple usage looks like this:
+
+```rust,ignore
+# #![feature(global_asm)]
+# you also need relevant target_arch cfgs
+global_asm!(include_str!("something_neato.s"));
+```
+
+And a more complicated usage looks like this:
+
+```rust,ignore
+# #![feature(global_asm)]
+# #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+
+pub mod sally {
+    global_asm!(r#"
+        .global foo
+      foo:
+        jmp baz
+    "#);
+
+    #[no_mangle]
+    pub unsafe extern "C" fn baz() {}
+}
+
+// the symbols `foo` and `bar` are global, no matter where
+// `global_asm!` was used.
+extern "C" {
+    fn foo();
+    fn bar();
+}
+
+pub mod harry {
+    global_asm!(r#"
+        .global bar
+      bar:
+        jmp quux
+    "#);
+
+    #[no_mangle]
+    pub unsafe extern "C" fn quux() {}
+}
+```
+
+You may use `global_asm!` multiple times, anywhere in your crate, in
+whatever way suits you. The effect is as if you concatenated all
+usages and placed the larger, single usage in the crate root.
+
+------------------------
+
+If you don't need quite as much power and flexibility as
+`global_asm!` provides, and you don't mind restricting your inline
+assembly to `fn` bodies only, you might try the [asm](asm.html)
+feature instead.
diff --git a/src/doc/unstable-book/src/manually-drop.md b/src/doc/unstable-book/src/manually-drop.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/doc/unstable-book/src/toowned-clone-into.md b/src/doc/unstable-book/src/toowned-clone-into.md
new file mode 100644 (file)
index 0000000..eccc7e0
--- /dev/null
@@ -0,0 +1,7 @@
+# `toowned_clone_into`
+
+The tracking issue for this feature is: [#41263]
+
+[#41263]: https://github.com/rust-lang/rust/issues/41263
+
+------------------------
index 28f6d97756f2c4c0f2808d49de7b461edf7ec876..182a107e3f76915b24151ecda567306c012d42f4 100644 (file)
@@ -165,18 +165,29 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
-/// A weak version of [`Arc`][arc].
+/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
+/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
+/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
 ///
-/// `Weak` pointers do not count towards determining if the inner value
-/// should be dropped.
+/// Since a `Weak` reference does not count towards ownership, it will not
+/// prevent the inner value from being dropped, and `Weak` itself makes no
+/// guarantees about the value still being present and may return [`None`]
+/// when [`upgrade`]d.
 ///
-/// The typical way to obtain a `Weak` pointer is to call
-/// [`Arc::downgrade`][downgrade].
+/// A `Weak` pointer is useful for keeping a temporary reference to the value
+/// within [`Arc`] without extending its lifetime. It is also used to prevent
+/// circular references between [`Arc`] pointers, since mutual owning references
+/// would never allow either [`Arc`] to be dropped. For example, a tree could
+/// have strong [`Arc`] pointers from parent nodes to children, and `Weak`
+/// pointers from children back to their parents.
 ///
-/// See the [`Arc`][arc] documentation for more details.
+/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`].
 ///
-/// [arc]: struct.Arc.html
-/// [downgrade]: struct.Arc.html#method.downgrade
+/// [`Arc`]: struct.Arc.html
+/// [`Arc::downgrade`]: struct.Arc.html#method.downgrade
+/// [`upgrade`]: struct.Weak.html#method.upgrade
+/// [`Option`]: ../../std/option/enum.Option.html
+/// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     ptr: Shared<ArcInner<T>>,
@@ -766,14 +777,11 @@ fn drop(&mut self) {
 }
 
 impl<T> Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
-    ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -798,13 +806,13 @@ pub fn new() -> Weak<T> {
 }
 
 impl<T: ?Sized> Weak<T> {
-    /// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible.
+    /// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending
+    /// the lifetime of the value if successful.
     ///
-    /// Returns [`None`][option] if the strong count has reached zero and the
-    /// inner value was destroyed.
+    /// Returns [`None`] if the value has since been dropped.
     ///
-    /// [arc]: struct.Arc.html
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`Arc`]: struct.Arc.html
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -865,10 +873,7 @@ fn inner(&self) -> &ArcInner<T> {
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized> Clone for Weak<T> {
-    /// Makes a clone of the `Weak` pointer.
-    ///
-    /// This creates another pointer to the same inner value, increasing the
-    /// weak reference count.
+    /// Makes a clone of the `Weak` pointer that points to the same value.
     ///
     /// # Examples
     ///
@@ -900,14 +905,11 @@ fn clone(&self) -> Weak<T> {
 
 #[stable(feature = "downgraded_weak", since = "1.10.0")]
 impl<T> Default for Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
-    ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -926,8 +928,6 @@ fn default() -> Weak<T> {
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak` pointer.
     ///
-    /// This will decrement the weak reference count.
-    ///
     /// # Examples
     ///
     /// ```
index 561ccaa5ef5ca6c0c8f4e78c58591b7bdd4cfc4b..fed718e9be4c6aa6ec5eba5c7b184a23c34e47dc 100644 (file)
@@ -922,18 +922,29 @@ fn from(t: T) -> Self {
     }
 }
 
-/// A weak version of [`Rc`][rc].
+/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
+/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
+/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
 ///
-/// `Weak` pointers do not count towards determining if the inner value
-/// should be dropped.
+/// Since a `Weak` reference does not count towards ownership, it will not
+/// prevent the inner value from being dropped, and `Weak` itself makes no
+/// guarantees about the value still being present and may return [`None`]
+/// when [`upgrade`]d.
 ///
-/// The typical way to obtain a `Weak` pointer is to call
-/// [`Rc::downgrade`][downgrade].
+/// A `Weak` pointer is useful for keeping a temporary reference to the value
+/// within [`Rc`] without extending its lifetime. It is also used to prevent
+/// circular references between [`Rc`] pointers, since mutual owning references
+/// would never allow either [`Arc`] to be dropped. For example, a tree could
+/// have strong [`Rc`] pointers from parent nodes to children, and `Weak`
+/// pointers from children back to their parents.
 ///
-/// See the [module-level documentation](./index.html) for more details.
+/// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`].
 ///
-/// [rc]: struct.Rc.html
-/// [downgrade]: struct.Rc.html#method.downgrade
+/// [`Rc`]: struct.Rc.html
+/// [`Rc::downgrade`]: struct.Rc.html#method.downgrade
+/// [`upgrade`]: struct.Weak.html#method.upgrade
+/// [`Option`]: ../../std/option/enum.Option.html
+/// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "rc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     ptr: Shared<RcBox<T>>,
@@ -948,14 +959,11 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
 impl<T> Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
-    ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples
     ///
@@ -980,13 +988,13 @@ pub fn new() -> Weak<T> {
 }
 
 impl<T: ?Sized> Weak<T> {
-    /// Upgrades the `Weak` pointer to an [`Rc`][rc], if possible.
+    /// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending
+    /// the lifetime of the value if successful.
     ///
-    /// Returns [`None`][option] if the strong count has reached zero and the
-    /// inner value was destroyed.
+    /// Returns [`None`] if the value has since been dropped.
     ///
-    /// [rc]: struct.Rc.html
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`Rc`]: struct.Rc.html
+    /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples
     ///
@@ -1021,8 +1029,6 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak` pointer.
     ///
-    /// This will decrement the weak reference count.
-    ///
     /// # Examples
     ///
     /// ```
@@ -1061,10 +1067,7 @@ fn drop(&mut self) {
 
 #[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> Clone for Weak<T> {
-    /// Makes a clone of the `Weak` pointer.
-    ///
-    /// This creates another pointer to the same inner value, increasing the
-    /// weak reference count.
+    /// Makes a clone of the `Weak` pointer that points to the same value.
     ///
     /// # Examples
     ///
@@ -1091,14 +1094,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[stable(feature = "downgraded_weak", since = "1.10.0")]
 impl<T> Default for Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
-    ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples
     ///
index 65056121f05a0c00da140d6a0081d5e70b2b5976..0de52b6696fcf02febb16085c5eb2860edbb52c1 100644 (file)
@@ -60,6 +60,29 @@ pub trait ToOwned {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn to_owned(&self) -> Self::Owned;
+
+    /// Uses borrowed data to replace owned data, usually by cloning.
+    ///
+    /// This is borrow-generalized version of `Clone::clone_from`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// # #![feature(toowned_clone_into)]
+    /// let mut s: String = String::new();
+    /// "hello".clone_into(&mut s);
+    ///
+    /// let mut v: Vec<i32> = Vec::new();
+    /// [1, 2][..].clone_into(&mut v);
+    /// ```
+    #[unstable(feature = "toowned_clone_into",
+               reason = "recently added",
+               issue = "41263")]
+    fn clone_into(&self, target: &mut Self::Owned) {
+        *target = self.to_owned();
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -70,6 +93,10 @@ impl<T> ToOwned for T
     fn to_owned(&self) -> T {
         self.clone()
     }
+
+    fn clone_into(&self, target: &mut T) {
+        target.clone_from(self);
+    }
 }
 
 /// A clone-on-write smart pointer.
@@ -141,6 +168,17 @@ fn clone(&self) -> Cow<'a, B> {
             }
         }
     }
+
+    fn clone_from(&mut self, source: &Cow<'a, B>) {
+        if let Owned(ref mut dest) = *self {
+            if let Owned(ref o) = *source {
+                o.borrow().clone_into(dest);
+                return;
+            }
+        }
+
+        *self = source.clone();
+    }
 }
 
 impl<'a, B: ?Sized> Cow<'a, B>
index 5360804f9e1d7a896a0b215385667eeff922be5c..99afd08e81183eb451df419c93a633b43456bb9c 100644 (file)
@@ -44,6 +44,7 @@
 #![feature(heap_api)]
 #![feature(inclusive_range)]
 #![feature(lang_items)]
+#![feature(manually_drop)]
 #![feature(nonzero)]
 #![feature(pattern)]
 #![feature(placement_in)]
index 6cff315a6ccd9eb28083d2b1f5b2afa9e8dc2430..7c3c825cfd1f5dc309980514d74af6b7203b6b12 100644 (file)
@@ -1527,6 +1527,19 @@ fn to_owned(&self) -> Vec<T> {
     fn to_owned(&self) -> Vec<T> {
         panic!("not available with cfg(test)")
     }
+
+    fn clone_into(&self, target: &mut Vec<T>) {
+        // drop anything in target that will not be overwritten
+        target.truncate(self.len());
+        let len = target.len();
+
+        // reuse the contained values' allocations/resources.
+        target.clone_from_slice(&self[..len]);
+
+        // target.len <= self.len due to the truncate above, so the
+        // slice here is always in-bounds.
+        target.extend_from_slice(&self[len..]);
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1558,7 +1571,7 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
             //    performance than with the 2nd method.
             //
             // All methods were benchmarked, and the 3rd showed best results. So we chose that one.
-            let mut tmp = NoDrop { value: ptr::read(&v[0]) };
+            let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0]));
 
             // Intermediate state of the insertion process is always tracked by `hole`, which
             // serves two purposes:
@@ -1571,13 +1584,13 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
             // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
             // initially held exactly once.
             let mut hole = InsertionHole {
-                src: &mut tmp.value,
+                src: &mut *tmp,
                 dest: &mut v[1],
             };
             ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
 
             for i in 2..v.len() {
-                if !is_less(&v[i], &tmp.value) {
+                if !is_less(&v[i], &*tmp) {
                     break;
                 }
                 ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
@@ -1587,12 +1600,6 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
         }
     }
 
-    // Holds a value, but never drops it.
-    #[allow(unions_with_drop_fields)]
-    union NoDrop<T> {
-        value: T
-    }
-
     // When dropped, copies from `src` into `dest`.
     struct InsertionHole<T> {
         src: *mut T,
index d04f414250ade9ee8a70f00a6e571fda980b481d..8168e02bf8261828d8f8685000e43197fd4f189c 100644 (file)
@@ -199,6 +199,12 @@ impl ToOwned for str {
     fn to_owned(&self) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
     }
+
+    fn clone_into(&self, target: &mut String) {
+        let mut b = mem::replace(target, String::new()).into_bytes();
+        self.as_bytes().clone_into(&mut b);
+        *target = unsafe { String::from_utf8_unchecked(b) }
+    }
 }
 
 /// Methods for string slices.
@@ -325,8 +331,10 @@ pub fn as_ptr(&self) -> *const u8 {
 
     /// Returns a subslice of `str`.
     ///
-    /// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever
-    /// equivalent indexing operation would panic.
+    /// This is the non-panicking alternative to indexing the `str`. Returns
+    /// [`None`] whenever equivalent indexing operation would panic.
+    ///
+    /// [`None`]: option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -346,8 +354,10 @@ pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
 
     /// Returns a mutable subslice of `str`.
     ///
-    /// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever
-    /// equivalent indexing operation would panic.
+    /// This is the non-panicking alternative to indexing the `str`. Returns
+    /// [`None`] whenever equivalent indexing operation would panic.
+    ///
+    /// [`None`]: option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -570,7 +580,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         core_str::StrExt::split_at_mut(self, mid)
     }
 
-    /// Returns an iterator over the `char`s of a string slice.
+    /// Returns an iterator over the [`char`]s of a string slice.
     ///
     /// As a string slice consists of valid UTF-8, we can iterate through a
     /// string slice by [`char`]. This method returns such an iterator.
@@ -1657,13 +1667,13 @@ pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
 
     /// Parses this string slice into another type.
     ///
-    /// Because `parse()` is so general, it can cause problems with type
-    /// inference. As such, `parse()` is one of the few times you'll see
+    /// Because `parse` is so general, it can cause problems with type
+    /// inference. As such, `parse` is one of the few times you'll see
     /// the syntax affectionately known as the 'turbofish': `::<>`. This
     /// helps the inference algorithm understand specifically which type
     /// you're trying to parse into.
     ///
-    /// `parse()` can parse any type that implements the [`FromStr`] trait.
+    /// `parse` can parse any type that implements the [`FromStr`] trait.
     ///
     /// [`FromStr`]: str/trait.FromStr.html
     ///
@@ -1746,7 +1756,7 @@ pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
     ///
     /// `replacen` creates a new [`String`], and copies the data from this string slice into it.
     /// While doing so, it attempts to find matches of a pattern. If it finds any, it
-    /// replaces them with the replacement string slice at most `N` times.
+    /// replaces them with the replacement string slice at most `count` times.
     ///
     /// [`String`]: string/struct.String.html
     ///
@@ -1892,7 +1902,9 @@ pub fn to_uppercase(&self) -> String {
         return s;
     }
 
-    /// Escapes each char in `s` with `char::escape_debug`.
+    /// Escapes each char in `s` with [`char::escape_debug`].
+    ///
+    /// [`char::escape_debug`]: primitive.char.html#method.escape_debug
     #[unstable(feature = "str_escape",
                reason = "return type may change to be an iterator",
                issue = "27791")]
@@ -1900,7 +1912,9 @@ pub fn escape_debug(&self) -> String {
         self.chars().flat_map(|c| c.escape_debug()).collect()
     }
 
-    /// Escapes each char in `s` with `char::escape_default`.
+    /// Escapes each char in `s` with [`char::escape_default`].
+    ///
+    /// [`char::escape_default`]: primitive.char.html#method.escape_default
     #[unstable(feature = "str_escape",
                reason = "return type may change to be an iterator",
                issue = "27791")]
@@ -1908,7 +1922,9 @@ pub fn escape_default(&self) -> String {
         self.chars().flat_map(|c| c.escape_default()).collect()
     }
 
-    /// Escapes each char in `s` with `char::escape_unicode`.
+    /// Escapes each char in `s` with [`char::escape_unicode`].
+    ///
+    /// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode
     #[unstable(feature = "str_escape",
                reason = "return type may change to be an iterator",
                issue = "27791")]
@@ -1916,9 +1932,10 @@ pub fn escape_unicode(&self) -> String {
         self.chars().flat_map(|c| c.escape_unicode()).collect()
     }
 
-    /// Converts a `Box<str>` into a [`String`] without copying or allocating.
+    /// Converts a [`Box<str>`] into a [`String`] without copying or allocating.
     ///
     /// [`String`]: string/struct.String.html
+    /// [`Box<str>`]: boxed/struct.Box.html
     ///
     /// # Examples
     ///
index b29245121daadeb52d6c206130090d43e9406008..aa87ee84b3e9769ea36625c20afc7ec77a3698f6 100644 (file)
@@ -139,3 +139,13 @@ fn check_cow_add_assign_str() {
     assert_eq!("Hi, World!", owned);
     assert_eq!("Hello, World!", borrowed);
 }
+
+#[test]
+fn check_cow_clone_from() {
+    let mut c1: Cow<str> = Cow::Owned(String::with_capacity(25));
+    let s: String = "hi".to_string();
+    assert!(s.capacity() < 25);
+    let c2: Cow<str> = Cow::Owned(s);
+    c1.clone_from(&c2);
+    assert!(c1.into_owned().capacity() >= 25);
+}
\ No newline at end of file
index 35ecf411db4e0b2a998b03a18be4fcd7404ec701..8824185d2809b1c5659fc2c7e98ebdcc898b6628 100644 (file)
@@ -1396,16 +1396,7 @@ fn clone(&self) -> Vec<T> {
     }
 
     fn clone_from(&mut self, other: &Vec<T>) {
-        // drop anything in self that will not be overwritten
-        self.truncate(other.len());
-        let len = self.len();
-
-        // reuse the contained values' allocations/resources.
-        self.clone_from_slice(&other[..len]);
-
-        // self.len <= other.len due to the truncate above, so the
-        // slice here is always in-bounds.
-        self.extend_from_slice(&other[len..]);
+        other.as_slice().clone_into(self);
     }
 }
 
index 58aba11e4394f6e619c60775d353cb0df68b35c8..09b3d63950705001ed439d06d5c7a85d73d2ff75 100644 (file)
@@ -180,7 +180,7 @@ pub extern "C" fn u128_div_mod(n: u128, d: u128, rem: *mut u128) -> u128 {
             sr = sr.wrapping_add(1);
 
             // 1 <= sr <= u64::bits() - 1
-            q = n.wrapping_shl(64u32.wrapping_sub(sr));
+            q = n.wrapping_shl(128u32.wrapping_sub(sr));
             r = n.wrapping_shr(sr);
         } else {
             if d.high() == 0 {
index e0a4707ff665f58c0bdedbb8fed6f6e29bc897be..b0287631585125a9febd3fb903e5d51e2358ae8e 100644 (file)
     /// initialize memory previous set to the result of `uninit`.
     pub fn uninit<T>() -> T;
 
-    /// Moves a value out of scope without running drop glue.
-    pub fn forget<T>(_: T) -> ();
-
     /// Reinterprets the bits of a value of one type as another type.
     ///
     /// Both types must have the same size. Neither the original, nor the result,
index 618edf48abd04370a43073368ac33bedb3129754..8bf641e37fe467c2120defd6b1a90afc79b0674c 100644 (file)
@@ -1532,14 +1532,18 @@ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
     /// Stopping at the first `true`:
     ///
     /// ```
-    /// let a = [1, 2, 3];
+    /// let a = [1, 2, 3, 4];
     ///
     /// let mut iter = a.iter();
     ///
-    /// assert_eq!(iter.position(|&x| x == 2), Some(1));
+    /// assert_eq!(iter.position(|&x| x >= 2), Some(1));
     ///
     /// // we can still use `iter`, as there are more elements.
     /// assert_eq!(iter.next(), Some(&3));
+    ///
+    /// // The returned index depends on iterator state
+    /// assert_eq!(iter.position(|&x| x == 4), Some(0));
+    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
index f5cf3724d0711d8183e685a02d08878f37ad3e95..7be927b28ed7eb7ecfef5fcc8da2ab1d0cdc9410 100644 (file)
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn forget<T>(t: T) {
-    unsafe { intrinsics::forget(t) }
+    ManuallyDrop::new(t);
 }
 
 /// Returns the size of a type in bytes.
@@ -736,3 +736,121 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
     }
 }
 
+
+/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
+///
+/// This wrapper is 0-cost.
+///
+/// # Examples
+///
+/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
+/// the type:
+///
+/// ```rust
+/// # #![feature(manually_drop)]
+/// use std::mem::ManuallyDrop;
+/// struct Peach;
+/// struct Banana;
+/// struct Melon;
+/// struct FruitBox {
+///     // Immediately clear there’s something non-trivial going on with these fields.
+///     peach: ManuallyDrop<Peach>,
+///     melon: Melon, // Field that’s independent of the other two.
+///     banana: ManuallyDrop<Banana>,
+/// }
+///
+/// impl Drop for FruitBox {
+///     fn drop(&mut self) {
+///         unsafe {
+///             // Explicit ordering in which field destructors are run specified in the intuitive
+///             // location â€“ the destructor of the structure containing the fields.
+///             // Moreover, one can now reorder fields within the struct however much they want.
+///             ManuallyDrop::drop(&mut self.peach);
+///             ManuallyDrop::drop(&mut self.banana);
+///         }
+///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
+///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
+///     }
+/// }
+/// ```
+#[unstable(feature = "manually_drop", issue = "40673")]
+#[allow(unions_with_drop_fields)]
+pub union ManuallyDrop<T>{ value: T }
+
+impl<T> ManuallyDrop<T> {
+    /// Wrap a value to be manually dropped.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(manually_drop)]
+    /// use std::mem::ManuallyDrop;
+    /// ManuallyDrop::new(Box::new(()));
+    /// ```
+    #[unstable(feature = "manually_drop", issue = "40673")]
+    #[inline]
+    pub fn new(value: T) -> ManuallyDrop<T> {
+        ManuallyDrop { value: value }
+    }
+
+    /// Extract the value from the ManuallyDrop container.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(manually_drop)]
+    /// use std::mem::ManuallyDrop;
+    /// let x = ManuallyDrop::new(Box::new(()));
+    /// let _: Box<()> = ManuallyDrop::into_inner(x);
+    /// ```
+    #[unstable(feature = "manually_drop", issue = "40673")]
+    #[inline]
+    pub fn into_inner(slot: ManuallyDrop<T>) -> T {
+        unsafe {
+            slot.value
+        }
+    }
+
+    /// Manually drops the contained value.
+    ///
+    /// # Unsafety
+    ///
+    /// This function runs the destructor of the contained value and thus the wrapped value
+    /// now represents uninitialized data. It is up to the user of this method to ensure the
+    /// uninitialized data is not actually used.
+    #[unstable(feature = "manually_drop", issue = "40673")]
+    #[inline]
+    pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
+        ptr::drop_in_place(&mut slot.value)
+    }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T> ::ops::Deref for ManuallyDrop<T> {
+    type Target = T;
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            &self.value
+        }
+    }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T> ::ops::DerefMut for ManuallyDrop<T> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            &mut self.value
+        }
+    }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
+    fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
+        unsafe {
+            fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
+        }
+    }
+}
index 7065fdb79fc4040a6ca225634408141e1871a830..6f9f2915dfe102c1fe6022d660816e69279152ed 100644 (file)
 use mem;
 use ptr;
 
-/// Holds a value, but never drops it.
-#[allow(unions_with_drop_fields)]
-union NoDrop<T> {
-    value: T
-}
-
 /// When dropped, copies from `src` into `dest`.
 struct CopyOnDrop<T> {
     src: *mut T,
@@ -49,15 +43,15 @@ fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
             // Read the first element into a stack-allocated variable. If a following comparison
             // operation panics, `hole` will get dropped and automatically write the element back
             // into the slice.
-            let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) };
+            let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
             let mut hole = CopyOnDrop {
-                src: &mut tmp.value,
+                src: &mut *tmp,
                 dest: v.get_unchecked_mut(1),
             };
             ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);
 
             for i in 2..len {
-                if !is_less(v.get_unchecked(i), &tmp.value) {
+                if !is_less(v.get_unchecked(i), &*tmp) {
                     break;
                 }
 
@@ -81,15 +75,15 @@ fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
             // Read the last element into a stack-allocated variable. If a following comparison
             // operation panics, `hole` will get dropped and automatically write the element back
             // into the slice.
-            let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) };
+            let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
             let mut hole = CopyOnDrop {
-                src: &mut tmp.value,
+                src: &mut *tmp,
                 dest: v.get_unchecked_mut(len - 2),
             };
             ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);
 
             for i in (0..len-2).rev() {
-                if !is_less(&tmp.value, v.get_unchecked(i)) {
+                if !is_less(&*tmp, v.get_unchecked(i)) {
                     break;
                 }
 
@@ -403,12 +397,12 @@ fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
 
         // Read the pivot into a stack-allocated variable for efficiency. If a following comparison
         // operation panics, the pivot will be automatically written back into the slice.
-        let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+        let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
         let _pivot_guard = CopyOnDrop {
-            src: unsafe { &mut tmp.value },
+            src: &mut *tmp,
             dest: pivot,
         };
-        let pivot = unsafe { &tmp.value };
+        let pivot = &*tmp;
 
         // Find the first pair of out-of-order elements.
         let mut l = 0;
@@ -452,12 +446,12 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
 
     // Read the pivot into a stack-allocated variable for efficiency. If a following comparison
     // operation panics, the pivot will be automatically written back into the slice.
-    let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+    let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
     let _pivot_guard = CopyOnDrop {
-        src: unsafe { &mut tmp.value },
+        src: &mut *tmp,
         dest: pivot,
     };
-    let pivot = unsafe { &tmp.value };
+    let pivot = &*tmp;
 
     // Now partition the slice.
     let mut l = 0;
index e024b62adfb15c4756b395215e7abead5016e77c..9a42b82beff67ef674e45aab0779d3cd40e8ac3e 100644 (file)
@@ -103,12 +103,14 @@ pub fn new(shape: f64, scale: f64) -> Gamma {
         assert!(shape > 0.0, "Gamma::new called with shape <= 0");
         assert!(scale > 0.0, "Gamma::new called with scale <= 0");
 
-        let repr = match shape {
-            1.0 => One(Exp::new(1.0 / scale)),
-            0.0...1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
-            _ => Large(GammaLargeShape::new_raw(shape, scale)),
+        let repr = if shape == 1.0 {
+            One(Exp::new(1.0 / scale))
+        } else if 0.0 <= shape && shape < 1.0 {
+            Small(GammaSmallShape::new_raw(shape, scale))
+        } else {
+            Large(GammaLargeShape::new_raw(shape, scale))
         };
-        Gamma { repr: repr }
+        Gamma { repr }
     }
 }
 
index 5aea2bcaa4f5c5fd5f4979df6ddb5183f4a9dcc5..59d04ea8c771cc7ec1867e887b53e0fd6e2d38a7 100644 (file)
@@ -57,17 +57,13 @@ pub enum DepNode<D: Clone + Debug> {
 
     // Represents different phases in the compiler.
     CollectLanguageItems,
-    CheckStaticRecursion,
     ResolveLifetimes,
     RegionResolveCrate,
-    CheckLoops,
     PluginRegistrar,
     StabilityIndex,
     CollectItem(D),
     CollectItemSig(D),
     Coherence,
-    EffectCheck,
-    Liveness,
     Resolve,
     EntryPoint,
     CheckEntryFn,
@@ -216,15 +212,11 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             MirKrate => Some(MirKrate),
             TypeckBodiesKrate => Some(TypeckBodiesKrate),
             CollectLanguageItems => Some(CollectLanguageItems),
-            CheckStaticRecursion => Some(CheckStaticRecursion),
             ResolveLifetimes => Some(ResolveLifetimes),
             RegionResolveCrate => Some(RegionResolveCrate),
-            CheckLoops => Some(CheckLoops),
             PluginRegistrar => Some(PluginRegistrar),
             StabilityIndex => Some(StabilityIndex),
             Coherence => Some(Coherence),
-            EffectCheck => Some(EffectCheck),
-            Liveness => Some(Liveness),
             Resolve => Some(Resolve),
             EntryPoint => Some(EntryPoint),
             CheckEntryFn => Some(CheckEntryFn),
index 7bab4a8d725dc2bcdfd87fdde54c44d639c3973c..771031db0c045f99e985f96b2e7caf05332c55da 100644 (file)
@@ -57,6 +57,8 @@ pub enum Def {
     // Macro namespace
     Macro(DefId, MacroKind),
 
+    GlobalAsm(DefId),
+
     // Both namespaces
     Err,
 }
@@ -144,7 +146,8 @@ pub fn def_id(&self) -> DefId {
             Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
-            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
+            Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) |
+            Def::GlobalAsm(id) => {
                 id
             }
 
@@ -185,6 +188,7 @@ pub fn kind_name(&self) -> &'static str {
             Def::Label(..) => "label",
             Def::SelfTy(..) => "self type",
             Def::Macro(..) => "macro",
+            Def::GlobalAsm(..) => "global asm",
             Def::Err => "unresolved item",
         }
     }
index 2c8b145f126cd17ffb05ddd7c805dc4dc9c21132..2b0d53b2bc35645403aed989624f577e69c3abd1 100644 (file)
@@ -474,6 +474,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
+        ItemGlobalAsm(_) => {
+            visitor.visit_id(item.id);
+        }
         ItemTy(ref typ, ref type_parameters) => {
             visitor.visit_id(item.id);
             visitor.visit_ty(typ);
index 30fec50d4eb6fef66ea3cc62a28353977f6bf9be..c86aaa7bf672745a9fd74bababce0979e59bcd20 100644 (file)
@@ -646,6 +646,13 @@ fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
         }
     }
 
+    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
+        P(hir::GlobalAsm {
+            asm: ga.asm,
+            ctxt: ga.ctxt,
+        })
+    }
+
     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
         Spanned {
             node: hir::Variant_ {
@@ -1288,6 +1295,7 @@ fn lower_item_kind(&mut self,
             }
             ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
+            ItemKind::GlobalAsm(ref ga) => hir::ItemGlobalAsm(self.lower_global_asm(ga)),
             ItemKind::Ty(ref t, ref generics) => {
                 hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
             }
index c1417f718b27abbecf88081040cf9a25adaab858..7ff5152c71a2cd6f29e306f01502dc68ed775a0b 100644 (file)
@@ -109,6 +109,7 @@ fn visit_item(&mut self, i: &'a Item) {
                 DefPathData::ValueNs(i.ident.name.as_str()),
             ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
+            ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(ref view_path) => {
                 match view_path.node {
                     ViewPathGlob(..) => {}
index d7aa36b24f94279ba345399f7276a1e6fe609fff..48b8a819fff03eb53d018baebac65a13f04db6de 100644 (file)
@@ -442,6 +442,27 @@ pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
         self.local_def_id(self.body_owner(id))
     }
 
+    /// Given a body owner's id, returns the `BodyId` associated with it.
+    pub fn body_owned_by(&self, id: NodeId) -> BodyId {
+        if let Some(entry) = self.find_entry(id) {
+            if let Some(body_id) = entry.associated_body() {
+                // For item-like things and closures, the associated
+                // body has its own distinct id, and that is returned
+                // by `associated_body`.
+                body_id
+            } else {
+                // For some expressions, the expression is its own body.
+                if let EntryExpr(_, expr) = entry {
+                    BodyId { node_id: expr.id }
+                } else {
+                    span_bug!(self.span(id), "id `{}` has no associated body", id);
+                }
+            }
+        } else {
+            bug!("no entry for id `{}`", id)
+        }
+    }
+
     pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
         match self.get(id) {
             NodeItem(&Item { node: ItemTrait(..), .. }) => id,
@@ -1056,6 +1077,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemFn(..) => "fn",
                 ItemMod(..) => "mod",
                 ItemForeignMod(..) => "foreign mod",
+                ItemGlobalAsm(..) => "global asm",
                 ItemTy(..) => "ty",
                 ItemEnum(..) => "enum",
                 ItemStruct(..) => "struct",
index 0da405d1821d360d8d804ae6463a7f42af706e86..562b58844409dc495da711300e5cd3aae63f3af1 100644 (file)
@@ -1495,6 +1495,12 @@ pub struct ForeignMod {
     pub items: HirVec<ForeignItem>,
 }
 
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct GlobalAsm {
+    pub asm: Symbol,
+    pub ctxt: SyntaxContext,
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct EnumDef {
     pub variants: HirVec<Variant>,
@@ -1686,6 +1692,8 @@ pub enum Item_ {
     ItemMod(Mod),
     /// An external module
     ItemForeignMod(ForeignMod),
+    /// Module-level inline assembly (from global_asm!)
+    ItemGlobalAsm(P<GlobalAsm>),
     /// A type alias, e.g. `type Foo = Bar<u8>`
     ItemTy(P<Ty>, Generics),
     /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
@@ -1720,6 +1728,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemFn(..) => "function",
             ItemMod(..) => "module",
             ItemForeignMod(..) => "foreign module",
+            ItemGlobalAsm(..) => "global asm",
             ItemTy(..) => "type alias",
             ItemEnum(..) => "enum",
             ItemStruct(..) => "struct",
index 4a5a35aa82ca0ef5799733d4021f2c4d86e49c50..5144f75b1a3634d8449f82d8ca5d6b073ce05ab8 100644 (file)
@@ -633,6 +633,11 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.print_foreign_mod(nmod, &item.attrs)?;
                 self.bclose(item.span)?;
             }
+            hir::ItemGlobalAsm(ref ga) => {
+                self.head(&visibility_qualified(&item.vis, "global asm"))?;
+                word(&mut self.s, &ga.asm.as_str())?;
+                self.end()?
+            }
             hir::ItemTy(ref ty, ref params) => {
                 self.ibox(indent_unit)?;
                 self.ibox(0)?;
index 5ef30550f1155ec017d1eb3b713d248a85560807..3a6367c353c1eec7cdcc32a756281ef81c8f528e 100644 (file)
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty;
+use util::nodemap::NodeMap;
 
 use std::hash as std_hash;
+use std::collections::{HashMap, HashSet};
 
 use syntax::ast;
 use syntax::attr;
@@ -296,3 +298,53 @@ fn hash_stable<W: StableHasherResult>(&self,
         }
     }
 }
+
+pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                                        hasher: &mut StableHasher<W>,
+                                                        map: &HashMap<K, V, R>,
+                                                        extract_stable_key: F)
+    where K: Eq + std_hash::Hash,
+          V: HashStable<StableHashingContext<'a, 'tcx>>,
+          R: std_hash::BuildHasher,
+          SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
+          F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
+          W: StableHasherResult,
+{
+    let mut keys: Vec<_> = map.keys()
+                              .map(|k| (extract_stable_key(hcx, k), k))
+                              .collect();
+    keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
+    keys.len().hash_stable(hcx, hasher);
+    for (stable_key, key) in keys {
+        stable_key.hash_stable(hcx, hasher);
+        map[key].hash_stable(hcx, hasher);
+    }
+}
+
+pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                                     hasher: &mut StableHasher<W>,
+                                                     set: &HashSet<K, R>,
+                                                     extract_stable_key: F)
+    where K: Eq + std_hash::Hash,
+          R: std_hash::BuildHasher,
+          SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
+          F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
+          W: StableHasherResult,
+{
+    let mut keys: Vec<_> = set.iter()
+                              .map(|k| extract_stable_key(hcx, k))
+                              .collect();
+    keys.sort_unstable();
+    keys.hash_stable(hcx, hasher);
+}
+
+pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
+                                           hasher: &mut StableHasher<W>,
+                                           map: &NodeMap<V>)
+    where V: HashStable<StableHashingContext<'a, 'tcx>>,
+          W: StableHasherResult,
+{
+    hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| {
+        hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
+    });
+}
index 9cf8a0693d3636383133b2cbf0198e7bdb6141e0..82e03a9fddc35a94564c2fae13cc815cfdd78541 100644 (file)
@@ -881,6 +881,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             hir::ItemFn(..)          |
             hir::ItemMod(..)         |
             hir::ItemForeignMod(..)  |
+            hir::ItemGlobalAsm(..)   |
             hir::ItemTy(..)          |
             hir::ItemEnum(..)        |
             hir::ItemStruct(..)      |
@@ -925,6 +926,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
     ItemMod(module),
     ItemForeignMod(foreign_mod),
+    ItemGlobalAsm(global_asm),
     ItemTy(ty, generics),
     ItemEnum(enum_def, generics),
     ItemStruct(variant_data, generics),
@@ -1014,6 +1016,19 @@ fn hash_stable<W: StableHasherResult>(&self,
     is_indirect
 });
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::GlobalAsm {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::GlobalAsm {
+            asm,
+            ctxt: _
+        } = *self;
+
+        asm.hash_stable(hcx, hasher);
+    }
+}
+
 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::InlineAsm {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
@@ -1070,6 +1085,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     Upvar(def_id, index, expr_id),
     Label(node_id),
     Macro(def_id, macro_kind),
+    GlobalAsm(def_id),
     Err
 });
 
index 401f7e1921ab49a3561cedb8ac808a87ef53395a..3ff8ffb35054ad4be9764f6c80ea5b4f8b1481a1 100644 (file)
@@ -22,7 +22,8 @@
 impl_stable_hash_for!(enum mir::Mutability { Mut, Not });
 impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut });
 impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
-impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info });
+impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info,
+is_user_variable});
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
 impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
 impl_stable_hash_for!(struct mir::Terminator<'tcx> { source_info, kind });
index 7b6f3af2a11ec88582d572128185e17c029b4a43..f55462fb5deb636925504c6105ac71869b434d89 100644 (file)
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::StableHashingContext;
+use ich::{self, StableHashingContext, NodeIdHashingMode};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use std::hash as std_hash;
 use std::mem;
+use syntax_pos::symbol::InternedString;
 use ty;
 
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Ty<'tcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let type_hash = hcx.tcx().type_id_hash(*self);
-        type_hash.hash_stable(hcx, hasher);
-    }
-}
-
 impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
 
-impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Slice<T>
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for &'tcx ty::Slice<T>
     where T: HashStable<StableHashingContext<'a, 'tcx>> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        (&**self).hash_stable(hcx, hasher);
+        (&self[..]).hash_stable(hcx, hasher);
     }
 }
 
@@ -67,9 +58,13 @@ fn hash_stable<W: StableHasherResult>(&self,
                 index.hash_stable(hcx, hasher);
                 name.hash_stable(hcx, hasher);
             }
+            ty::ReScope(code_extent) => {
+                code_extent.hash_stable(hcx, hasher);
+            }
+            ty::ReFree(ref free_region) => {
+                free_region.hash_stable(hcx, hasher);
+            }
             ty::ReLateBound(..) |
-            ty::ReFree(..) |
-            ty::ReScope(..) |
             ty::ReVar(..) |
             ty::ReSkolemized(..) => {
                 bug!("TypeIdHasher: unexpected region {:?}", *self)
@@ -127,7 +122,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     MutBorrow
 });
 
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
@@ -170,6 +164,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
 impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
 impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
+impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
 
 impl<'a, 'tcx, A, B> HashStable<StableHashingContext<'a, 'tcx>> for ty::OutlivesPredicate<A, B>
     where A: HashStable<StableHashingContext<'a, 'tcx>>,
@@ -200,6 +195,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             ty::Predicate::Equate(ref pred) => {
                 pred.hash_stable(hcx, hasher);
             }
+            ty::Predicate::Subtype(ref pred) => {
+                pred.hash_stable(hcx, hasher);
+            }
             ty::Predicate::RegionOutlives(ref pred) => {
                 pred.hash_stable(hcx, hasher);
             }
@@ -223,7 +221,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
     fn hash_stable<W: StableHasherResult>(&self,
                                           _: &mut StableHashingContext<'a, 'tcx>,
@@ -280,9 +277,14 @@ fn hash_stable<W: StableHasherResult>(&self,
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            ConstVal::Struct(ref _name_value_map) => {
-                // BTreeMap<ast::Name, ConstVal<'tcx>>),
-                panic!("Ordering still unstable")
+            ConstVal::Struct(ref name_value_map) => {
+                let mut values: Vec<(InternedString, &ConstVal)> =
+                    name_value_map.iter()
+                                  .map(|(name, val)| (name.as_str(), val))
+                                  .collect();
+
+                values.sort_unstable_by_key(|&(ref name, _)| name.clone());
+                values.hash_stable(hcx, hasher);
             }
             ConstVal::Tuple(ref value) => {
                 value.hash_stable(hcx, hasher);
@@ -303,7 +305,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
 
-
 impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
     parent,
     predicates
@@ -413,3 +414,265 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct ty::DebruijnIndex {
     depth
 });
+
+impl_stable_hash_for!(enum ty::cast::CastKind {
+    CoercionCast,
+    PtrPtrCast,
+    PtrAddrCast,
+    AddrPtrCast,
+    NumericCast,
+    EnumCast,
+    PrimIntCast,
+    U8CharCast,
+    ArrayPtrCast,
+    FnPtrPtrCast,
+    FnPtrAddrCast
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            hcx.tcx().region_maps.code_extent_data(*self).hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use middle::region::CodeExtentData;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            CodeExtentData::Misc(node_id) |
+            CodeExtentData::DestructionScope(node_id) => {
+                node_id.hash_stable(hcx, hasher);
+            }
+            CodeExtentData::CallSiteScope { fn_id, body_id } |
+            CodeExtentData::ParameterScope { fn_id, body_id } => {
+                fn_id.hash_stable(hcx, hasher);
+                body_id.hash_stable(hcx, hasher);
+            }
+            CodeExtentData::Remainder(block_remainder) => {
+                block_remainder.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ::middle::region::BlockRemainder {
+    block,
+    first_statement_index
+});
+
+impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
+    custom_kind
+});
+
+impl_stable_hash_for!(struct ty::FreeRegion {
+    scope,
+    bound_region
+});
+
+impl_stable_hash_for!(enum ty::BoundRegion {
+    BrAnon(index),
+    BrNamed(def_id, name),
+    BrFresh(index),
+    BrEnv
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeVariants<'tcx>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use ty::TypeVariants::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            TyBool  |
+            TyChar  |
+            TyStr   |
+            TyNever => {
+                // Nothing more to hash.
+            }
+            TyInt(int_ty) => {
+                int_ty.hash_stable(hcx, hasher);
+            }
+            TyUint(uint_ty) => {
+                uint_ty.hash_stable(hcx, hasher);
+            }
+            TyFloat(float_ty)  => {
+                float_ty.hash_stable(hcx, hasher);
+            }
+            TyAdt(adt_def, substs) => {
+                adt_def.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+            }
+            TyArray(inner_ty, len) => {
+                inner_ty.hash_stable(hcx, hasher);
+                len.hash_stable(hcx, hasher);
+            }
+            TySlice(inner_ty) => {
+                inner_ty.hash_stable(hcx, hasher);
+            }
+            TyRawPtr(pointee_ty) => {
+                pointee_ty.hash_stable(hcx, hasher);
+            }
+            TyRef(region, pointee_ty) => {
+                region.hash_stable(hcx, hasher);
+                pointee_ty.hash_stable(hcx, hasher);
+            }
+            TyFnDef(def_id, substs, ref sig) => {
+                def_id.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+                sig.hash_stable(hcx, hasher);
+            }
+            TyFnPtr(ref sig) => {
+                sig.hash_stable(hcx, hasher);
+            }
+            TyDynamic(ref existential_predicates, region) => {
+                existential_predicates.hash_stable(hcx, hasher);
+                region.hash_stable(hcx, hasher);
+            }
+            TyClosure(def_id, closure_substs) => {
+                def_id.hash_stable(hcx, hasher);
+                closure_substs.hash_stable(hcx, hasher);
+            }
+            TyTuple(inner_tys, from_diverging_type_var) => {
+                inner_tys.hash_stable(hcx, hasher);
+                from_diverging_type_var.hash_stable(hcx, hasher);
+            }
+            TyProjection(ref projection_ty) => {
+                projection_ty.hash_stable(hcx, hasher);
+            }
+            TyAnon(def_id, substs) => {
+                def_id.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+            }
+            TyParam(param_ty) => {
+                param_ty.hash_stable(hcx, hasher);
+            }
+
+            TyError     |
+            TyInfer(..) => {
+                bug!("ty::TypeVariants::hash_stable() - Unexpected variant.")
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ty::ParamTy {
+    idx,
+    name
+});
+
+impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> {
+    ty,
+    mutbl
+});
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::ExistentialPredicate<'tcx>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            ty::ExistentialPredicate::Trait(ref trait_ref) => {
+                trait_ref.hash_stable(hcx, hasher);
+            }
+            ty::ExistentialPredicate::Projection(ref projection) => {
+                projection.hash_stable(hcx, hasher);
+            }
+            ty::ExistentialPredicate::AutoTrait(def_id) => {
+                def_id.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> {
+    def_id,
+    substs
+});
+
+impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> {
+    trait_ref,
+    item_name,
+    ty
+});
+
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::TypeckTables {
+            ref type_relative_path_defs,
+            ref node_types,
+            ref item_substs,
+            ref adjustments,
+            ref method_map,
+            ref upvar_capture_map,
+            ref closure_tys,
+            ref closure_kinds,
+            ref liberated_fn_sigs,
+            ref fru_field_types,
+
+            ref cast_kinds,
+
+            // FIXME(#41184): This is still ignored at the moment.
+            lints: _,
+            ref used_trait_imports,
+            tainted_by_errors,
+            ref free_region_map,
+        } = *self;
+
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+            ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs);
+            ich::hash_stable_nodemap(hcx, hasher, node_types);
+            ich::hash_stable_nodemap(hcx, hasher, item_substs);
+            ich::hash_stable_nodemap(hcx, hasher, adjustments);
+
+            ich::hash_stable_hashmap(hcx, hasher, method_map, |hcx, method_call| {
+                let ty::MethodCall {
+                    expr_id,
+                    autoderef
+                } = *method_call;
+
+                let def_id = hcx.tcx().hir.local_def_id(expr_id);
+                (hcx.def_path_hash(def_id), autoderef)
+            });
+
+            ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
+                let ty::UpvarId {
+                    var_id,
+                    closure_expr_id
+                } = *up_var_id;
+
+                let var_def_id = hcx.tcx().hir.local_def_id(var_id);
+                let closure_def_id = hcx.tcx().hir.local_def_id(closure_expr_id);
+                (hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id))
+            });
+
+            ich::hash_stable_nodemap(hcx, hasher, closure_tys);
+            ich::hash_stable_nodemap(hcx, hasher, closure_kinds);
+            ich::hash_stable_nodemap(hcx, hasher, liberated_fn_sigs);
+            ich::hash_stable_nodemap(hcx, hasher, fru_field_types);
+            ich::hash_stable_nodemap(hcx, hasher, cast_kinds);
+
+            ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
+                hcx.def_path_hash(*def_id)
+            });
+
+            tainted_by_errors.hash_stable(hcx, hasher);
+            free_region_map.hash_stable(hcx, hasher);
+        })
+    }
+}
index f932c90a331e145509f86322f3692ee8cefcdf4c..d70ed051ac4107ad2d3b31ca3d8fc2c1ed6183ac 100644 (file)
@@ -12,8 +12,8 @@
 
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
-pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
-
+pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
+                    hash_stable_hashset, hash_stable_nodemap};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs
deleted file mode 100644 (file)
index 4acb8b8..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Applies the "bivariance relationship" to two types and/or regions.
-//! If (A,B) are bivariant then either A <: B or B <: A. It occurs
-//! when type/lifetime parameters are unconstrained. Usually this is
-//! an error, but we permit it in the specific case where a type
-//! parameter is constrained in a where-clause via an associated type.
-//!
-//! There are several ways one could implement bivariance. You could
-//! just do nothing at all, for example, or you could fully verify
-//! that one of the two subtyping relationships hold. We choose to
-//! thread a middle line: we relate types up to regions, but ignore
-//! all region relationships.
-//!
-//! At one point, handling bivariance in this fashion was necessary
-//! for inference, but I'm actually not sure if that is true anymore.
-//! In particular, it might be enough to say (A,B) are bivariant for
-//! all (A,B).
-
-use super::combine::CombineFields;
-use super::type_variable::{BiTo};
-
-use ty::{self, Ty, TyCtxt};
-use ty::TyVar;
-use ty::relate::{Relate, RelateResult, TypeRelation};
-
-pub struct Bivariate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
-    fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
-    a_is_expected: bool,
-}
-
-impl<'combine, 'infcx, 'gcx, 'tcx> Bivariate<'combine, 'infcx, 'gcx, 'tcx> {
-    pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
-        -> Bivariate<'combine, 'infcx, 'gcx, 'tcx>
-    {
-        Bivariate { fields: fields, a_is_expected: a_is_expected }
-    }
-}
-
-impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
-    for Bivariate<'combine, 'infcx, 'gcx, 'tcx>
-{
-    fn tag(&self) -> &'static str { "Bivariate" }
-
-    fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
-
-    fn a_is_expected(&self) -> bool { self.a_is_expected }
-
-    fn relate_with_variance<T: Relate<'tcx>>(&mut self,
-                                             variance: ty::Variance,
-                                             a: &T,
-                                             b: &T)
-                                             -> RelateResult<'tcx, T>
-    {
-        match variance {
-            // If we have Foo<A> and Foo is invariant w/r/t A,
-            // and we want to assert that
-            //
-            //     Foo<A> <: Foo<B> ||
-            //     Foo<B> <: Foo<A>
-            //
-            // then still A must equal B.
-            ty::Invariant => self.relate(a, b),
-
-            ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.relate(a, b),
-            ty::Contravariant => self.relate(a, b),
-        }
-    }
-
-    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({:?}, {:?})", self.tag(),
-               a, b);
-        if a == b { return Ok(a); }
-
-        let infcx = self.fields.infcx;
-        let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
-        let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
-        match (&a.sty, &b.sty) {
-            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
-                infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id);
-                Ok(a)
-            }
-
-            (&ty::TyInfer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, BiTo, a_id, self.a_is_expected)?;
-                Ok(a)
-            }
-
-            (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, BiTo, b_id, self.a_is_expected)?;
-                Ok(a)
-            }
-
-            _ => {
-                self.fields.infcx.super_combine_tys(self, a, b)
-            }
-        }
-    }
-
-    fn regions(&mut self, a: &'tcx ty::Region, _: &'tcx ty::Region)
-               -> RelateResult<'tcx, &'tcx ty::Region> {
-        Ok(a)
-    }
-
-    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-                  -> RelateResult<'tcx, ty::Binder<T>>
-        where T: Relate<'tcx>
-    {
-        let a1 = self.tcx().erase_late_bound_regions(a);
-        let b1 = self.tcx().erase_late_bound_regions(b);
-        let c = self.relate(&a1, &b1)?;
-        Ok(ty::Binder(c))
-    }
-}
index 5d33d6e6d2e71ee443d443188eea09c08995aa99..b73079b02bdd94ab0d050939f8de38716cbcadb7 100644 (file)
 // is also useful to track which value is the "expected" value in
 // terms of error reporting.
 
-use super::bivariate::Bivariate;
 use super::equate::Equate;
 use super::glb::Glb;
 use super::lub::Lub;
 use super::sub::Sub;
 use super::InferCtxt;
 use super::{MiscVariable, TypeTrace};
-use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf};
 
 use ty::{IntType, UintType};
 use ty::{self, Ty, TyCtxt};
@@ -49,7 +47,6 @@
 use traits::PredicateObligations;
 
 use syntax::ast;
-use syntax::util::small_vector::SmallVector;
 use syntax_pos::Span;
 
 #[derive(Clone)]
@@ -60,6 +57,11 @@ pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
     pub obligations: PredicateObligations<'tcx>,
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum RelationDir {
+    SubtypeOf, SupertypeOf, EqTo
+}
+
 impl<'infcx, 'gcx, 'tcx> InferCtxt<'infcx, 'gcx, 'tcx> {
     pub fn super_combine_tys<R>(&self,
                                 relation: &mut R,
@@ -159,10 +161,6 @@ pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'gcx,
         Equate::new(self, a_is_expected)
     }
 
-    pub fn bivariate<'a>(&'a mut self, a_is_expected: bool) -> Bivariate<'a, 'infcx, 'gcx, 'tcx> {
-        Bivariate::new(self, a_is_expected)
-    }
-
     pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'gcx, 'tcx> {
         Sub::new(self, a_is_expected)
     }
@@ -175,6 +173,15 @@ pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'gcx, 'tcx>
         Glb::new(self, a_is_expected)
     }
 
+    /// Here dir is either EqTo, SubtypeOf, or SupertypeOf. The
+    /// idea is that we should ensure that the type `a_ty` is equal
+    /// to, a subtype of, or a supertype of (respectively) the type
+    /// to which `b_vid` is bound.
+    ///
+    /// Since `b_vid` has not yet been instantiated with a type, we
+    /// will first instantiate `b_vid` with a *generalized* version
+    /// of `a_ty`. Generalization introduces other inference
+    /// variables wherever subtyping could occur.
     pub fn instantiate(&mut self,
                        a_ty: Ty<'tcx>,
                        dir: RelationDir,
@@ -182,101 +189,66 @@ pub fn instantiate(&mut self,
                        a_is_expected: bool)
                        -> RelateResult<'tcx, ()>
     {
-        // We use SmallVector here instead of Vec because this code is hot and
-        // it's rare that the stack length exceeds 1.
-        let mut stack = SmallVector::new();
-        stack.push((a_ty, dir, b_vid));
-        loop {
-            // For each turn of the loop, we extract a tuple
-            //
-            //     (a_ty, dir, b_vid)
-            //
-            // to relate. Here dir is either SubtypeOf or
-            // SupertypeOf. The idea is that we should ensure that
-            // the type `a_ty` is a subtype or supertype (respectively) of the
-            // type to which `b_vid` is bound.
-            //
-            // If `b_vid` has not yet been instantiated with a type
-            // (which is always true on the first iteration, but not
-            // necessarily true on later iterations), we will first
-            // instantiate `b_vid` with a *generalized* version of
-            // `a_ty`. Generalization introduces other inference
-            // variables wherever subtyping could occur (at time of
-            // this writing, this means replacing free regions with
-            // region variables).
-            let (a_ty, dir, b_vid) = match stack.pop() {
-                None => break,
-                Some(e) => e,
-            };
-            // Get the actual variable that b_vid has been inferred to
-            let (b_vid, b_ty) = {
-                let mut variables = self.infcx.type_variables.borrow_mut();
-                let b_vid = variables.root_var(b_vid);
-                (b_vid, variables.probe_root(b_vid))
-            };
-
-            debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})",
-                   a_ty,
-                   dir,
-                   b_vid);
-
-            // Check whether `vid` has been instantiated yet.  If not,
-            // make a generalized form of `ty` and instantiate with
-            // that.
-            let b_ty = match b_ty {
-                Some(t) => t, // ...already instantiated.
-                None => {     // ...not yet instantiated:
-                    // Generalize type if necessary.
-                    let generalized_ty = match dir {
-                        EqTo => self.generalize(a_ty, b_vid, false),
-                        BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
-                    }?;
-                    debug!("instantiate(a_ty={:?}, dir={:?}, \
-                                        b_vid={:?}, generalized_ty={:?})",
-                           a_ty, dir, b_vid,
-                           generalized_ty);
-                    self.infcx.type_variables
-                        .borrow_mut()
-                        .instantiate_and_push(
-                            b_vid, generalized_ty, &mut stack);
-                    generalized_ty
-                }
-            };
-
-            // The original triple was `(a_ty, dir, b_vid)` -- now we have
-            // resolved `b_vid` to `b_ty`, so apply `(a_ty, dir, b_ty)`:
-            //
-            // FIXME(#16847): This code is non-ideal because all these subtype
-            // relations wind up attributed to the same spans. We need
-            // to associate causes/spans with each of the relations in
-            // the stack to get this right.
-            match dir {
-                BiTo => self.bivariate(a_is_expected).relate(&a_ty, &b_ty),
-                EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
-                SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
-                SupertypeOf => self.sub(a_is_expected).relate_with_variance(
-                    ty::Contravariant, &a_ty, &b_ty),
-            }?;
-        }
+        use self::RelationDir::*;
+
+        // Get the actual variable that b_vid has been inferred to
+        debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_none());
+
+        debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
+
+        // Generalize type of `a_ty` appropriately depending on the
+        // direction.  As an example, assume:
+        //
+        // - `a_ty == &'x ?1`, where `'x` is some free region and `?1` is an
+        //   inference variable,
+        // - and `dir` == `SubtypeOf`.
+        //
+        // Then the generalized form `b_ty` would be `&'?2 ?3`, where
+        // `'?2` and `?3` are fresh region/type inference
+        // variables. (Down below, we will relate `a_ty <: b_ty`,
+        // adding constraints like `'x: '?2` and `?1 <: ?3`.)
+        let b_ty = self.generalize(a_ty, b_vid, dir == EqTo)?;
+        debug!("instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
+               a_ty, dir, b_vid, b_ty);
+        self.infcx.type_variables.borrow_mut().instantiate(b_vid, b_ty);
+
+        // Finally, relate `b_ty` to `a_ty`, as described in previous comment.
+        //
+        // FIXME(#16847): This code is non-ideal because all these subtype
+        // relations wind up attributed to the same spans. We need
+        // to associate causes/spans with each of the relations in
+        // the stack to get this right.
+        match dir {
+            EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
+            SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
+            SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+                ty::Contravariant, &a_ty, &b_ty),
+        }?;
 
         Ok(())
     }
 
-    /// Attempts to generalize `ty` for the type variable `for_vid`.  This checks for cycle -- that
-    /// is, whether the type `ty` references `for_vid`. If `make_region_vars` is true, it will also
-    /// replace all regions with fresh variables. Returns `TyError` in the case of a cycle, `Ok`
+    /// Attempts to generalize `ty` for the type variable `for_vid`.
+    /// This checks for cycle -- that is, whether the type `ty`
+    /// references `for_vid`. If `is_eq_relation` is false, it will
+    /// also replace all regions/unbound-type-variables with fresh
+    /// variables. Returns `TyError` in the case of a cycle, `Ok`
     /// otherwise.
+    ///
+    /// Preconditions:
+    ///
+    /// - `for_vid` is a "root vid"
     fn generalize(&self,
                   ty: Ty<'tcx>,
                   for_vid: ty::TyVid,
-                  make_region_vars: bool)
+                  is_eq_relation: bool)
                   -> RelateResult<'tcx, Ty<'tcx>>
     {
         let mut generalize = Generalizer {
             infcx: self.infcx,
             span: self.trace.cause.span,
-            for_vid: for_vid,
-            make_region_vars: make_region_vars,
+            for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid),
+            is_eq_relation: is_eq_relation,
             cycle_detected: false
         };
         let u = ty.fold_with(&mut generalize);
@@ -291,8 +263,8 @@ fn generalize(&self,
 struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
     span: Span,
-    for_vid: ty::TyVid,
-    make_region_vars: bool,
+    for_vid_sub_root: ty::TyVid,
+    is_eq_relation: bool,
     cycle_detected: bool,
 }
 
@@ -303,17 +275,17 @@ fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         // Check to see whether the type we are genealizing references
-        // `vid`. At the same time, also update any type variables to
-        // the values that they are bound to. This is needed to truly
-        // check for cycles, but also just makes things readable.
-        //
-        // (In particular, you could have something like `$0 = Box<$1>`
-        //  where `$1` has already been instantiated with `Box<$0>`)
+        // any other type variable related to `vid` via
+        // subtyping. This is basically our "occurs check", preventing
+        // us from creating infinitely sized types.
         match t.sty {
             ty::TyInfer(ty::TyVar(vid)) => {
                 let mut variables = self.infcx.type_variables.borrow_mut();
                 let vid = variables.root_var(vid);
-                if vid == self.for_vid {
+                let sub_vid = variables.sub_root_var(vid);
+                if sub_vid == self.for_vid_sub_root {
+                    // If sub-roots are equal, then `for_vid` and
+                    // `vid` are related via subtyping.
                     self.cycle_detected = true;
                     self.tcx().types.err
                 } else {
@@ -322,7 +294,18 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                             drop(variables);
                             self.fold_ty(u)
                         }
-                        None => t,
+                        None => {
+                            if !self.is_eq_relation {
+                                let origin = variables.origin(vid);
+                                let new_var_id = variables.new_var(false, origin, None);
+                                let u = self.tcx().mk_var(new_var_id);
+                                debug!("generalize: replacing original vid={:?} with new={:?}",
+                                       vid, u);
+                                u
+                            } else {
+                                t
+                            }
+                        }
                     }
                 }
             }
@@ -359,7 +342,7 @@ fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
             ty::ReScope(..) |
             ty::ReVar(..) |
             ty::ReFree(..) => {
-                if !self.make_region_vars {
+                if self.is_eq_relation {
                     return r;
                 }
             }
index bf247acec5a2d31112c5a787ac2b7772ab029318..f620965ced84590e5c1b32d769374248dc66342f 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::CombineFields;
+use super::combine::{CombineFields, RelationDir};
 use super::{Subtype};
-use super::type_variable::{EqTo};
 
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
@@ -58,17 +57,17 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
         match (&a.sty, &b.sty) {
             (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
-                infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id);
+                infcx.type_variables.borrow_mut().equate(a_id, b_id);
                 Ok(a)
             }
 
             (&ty::TyInfer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, EqTo, a_id, self.a_is_expected)?;
+                self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
                 Ok(a)
             }
 
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, EqTo, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
index 9fa2bc8a2a7a96f5290c4be26adaaccdc78b3918..dcbe50de2e9b2ec8ac6ba66a6a56bb94faf3131e 100644 (file)
@@ -70,7 +70,7 @@
 use ty::{Region, Issue32330};
 use ty::error::TypeError;
 use syntax_pos::{Pos, Span};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticStyledString};
 
 mod note;
 
@@ -365,6 +365,262 @@ fn note_error_origin(&self,
         }
     }
 
+    /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
+    /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
+    /// populate `other_value` with `other_ty`.
+    ///
+    /// ```text
+    /// Foo<Bar<Qux>>
+    /// ^^^^--------^ this is highlighted
+    /// |   |
+    /// |   this type argument is exactly the same as the other type, not highlighted
+    /// this is highlighted
+    /// Bar<Qux>
+    /// -------- this type is the same as a type argument in the other type, not highlighted
+    /// ```
+    fn highlight_outer(&self,
+                       mut value: &mut DiagnosticStyledString,
+                       mut other_value: &mut DiagnosticStyledString,
+                       name: String,
+                       sub: &ty::subst::Substs<'tcx>,
+                       pos: usize,
+                       other_ty: &ty::Ty<'tcx>) {
+        // `value` and `other_value` hold two incomplete type representation for display.
+        // `name` is the path of both types being compared. `sub`
+        value.push_highlighted(name);
+        let len = sub.len();
+        if len > 0 {
+            value.push_highlighted("<");
+        }
+
+        // Output the lifetimes fot the first type
+        let lifetimes = sub.regions().map(|lifetime| {
+            let s = format!("{}", lifetime);
+            if s.is_empty() {
+                "'_".to_string()
+            } else {
+                s
+            }
+        }).collect::<Vec<_>>().join(", ");
+        if !lifetimes.is_empty() {
+            if sub.regions().count() < len {
+                value.push_normal(lifetimes + &", ");
+            } else {
+                value.push_normal(lifetimes);
+            }
+        }
+
+        // Highlight all the type arguments that aren't at `pos` and compare the type argument at
+        // `pos` and `other_ty`.
+        for (i, type_arg) in sub.types().enumerate() {
+            if i == pos {
+                let values = self.cmp(type_arg, other_ty);
+                value.0.extend((values.0).0);
+                other_value.0.extend((values.1).0);
+            } else {
+                value.push_highlighted(format!("{}", type_arg));
+            }
+
+            if len > 0 && i != len - 1 {
+                value.push_normal(", ");
+            }
+            //self.push_comma(&mut value, &mut other_value, len, i);
+        }
+        if len > 0 {
+            value.push_highlighted(">");
+        }
+    }
+
+    /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
+    /// as that is the difference to the other type.
+    ///
+    /// For the following code:
+    ///
+    /// ```norun
+    /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
+    /// ```
+    ///
+    /// The type error output will behave in the following way:
+    ///
+    /// ```text
+    /// Foo<Bar<Qux>>
+    /// ^^^^--------^ this is highlighted
+    /// |   |
+    /// |   this type argument is exactly the same as the other type, not highlighted
+    /// this is highlighted
+    /// Bar<Qux>
+    /// -------- this type is the same as a type argument in the other type, not highlighted
+    /// ```
+    fn cmp_type_arg(&self,
+                    mut t1_out: &mut DiagnosticStyledString,
+                    mut t2_out: &mut DiagnosticStyledString,
+                    path: String,
+                    sub: &ty::subst::Substs<'tcx>,
+                    other_path: String,
+                    other_ty: &ty::Ty<'tcx>) -> Option<()> {
+        for (i, ta) in sub.types().enumerate() {
+            if &ta == other_ty {
+                self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
+                return Some(());
+            }
+            if let &ty::TyAdt(def, _) = &ta.sty {
+                let path_ = self.tcx.item_path_str(def.did.clone());
+                if path_ == other_path {
+                    self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
+                    return Some(());
+                }
+            }
+        }
+        None
+    }
+
+    /// Add a `,` to the type representation only if it is appropriate.
+    fn push_comma(&self,
+                  value: &mut DiagnosticStyledString,
+                  other_value: &mut DiagnosticStyledString,
+                  len: usize,
+                  pos: usize) {
+        if len > 0 && pos != len - 1 {
+            value.push_normal(", ");
+            other_value.push_normal(", ");
+        }
+    }
+
+    /// Compare two given types, eliding parts that are the same between them and highlighting
+    /// relevant differences, and return two representation of those types for highlighted printing.
+    fn cmp(&self, t1: ty::Ty<'tcx>, t2: ty::Ty<'tcx>)
+        -> (DiagnosticStyledString, DiagnosticStyledString)
+    {
+        match (&t1.sty, &t2.sty) {
+            (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
+                let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
+                let path1 = self.tcx.item_path_str(def1.did.clone());
+                let path2 = self.tcx.item_path_str(def2.did.clone());
+                if def1.did == def2.did {
+                    // Easy case. Replace same types with `_` to shorten the output and highlight
+                    // the differing ones.
+                    //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
+                    //     Foo<Bar, _>
+                    //     Foo<Quz, _>
+                    //         ---  ^ type argument elided
+                    //         |
+                    //         highlighted in output
+                    values.0.push_normal(path1);
+                    values.1.push_normal(path2);
+
+                    // Only draw `<...>` if there're lifetime/type arguments.
+                    let len = sub1.len();
+                    if len > 0 {
+                        values.0.push_normal("<");
+                        values.1.push_normal("<");
+                    }
+
+                    fn lifetime_display(lifetime: &Region) -> String {
+                        let s = format!("{}", lifetime);
+                        if s.is_empty() {
+                            "'_".to_string()
+                        } else {
+                            s
+                        }
+                    }
+                    // At one point we'd like to elide all lifetimes here, they are irrelevant for
+                    // all diagnostics that use this output
+                    //
+                    //     Foo<'x, '_, Bar>
+                    //     Foo<'y, '_, Qux>
+                    //         ^^  ^^  --- type arguments are not elided
+                    //         |   |
+                    //         |   elided as they were the same
+                    //         not elided, they were different, but irrelevant
+                    let lifetimes = sub1.regions().zip(sub2.regions());
+                    for (i, lifetimes) in lifetimes.enumerate() {
+                        let l1 = lifetime_display(lifetimes.0);
+                        let l2 = lifetime_display(lifetimes.1);
+                        if l1 == l2 {
+                            values.0.push_normal("'_");
+                            values.1.push_normal("'_");
+                        } else {
+                            values.0.push_highlighted(l1);
+                            values.1.push_highlighted(l2);
+                        }
+                        self.push_comma(&mut values.0, &mut values.1, len, i);
+                    }
+
+                    // We're comparing two types with the same path, so we compare the type
+                    // arguments for both. If they are the same, do not highlight and elide from the
+                    // output.
+                    //     Foo<_, Bar>
+                    //     Foo<_, Qux>
+                    //         ^ elided type as this type argument was the same in both sides
+                    let type_arguments = sub1.types().zip(sub2.types());
+                    let regions_len = sub1.regions().collect::<Vec<_>>().len();
+                    for (i, (ta1, ta2)) in type_arguments.enumerate() {
+                        let i = i + regions_len;
+                        if ta1 == ta2 {
+                            values.0.push_normal("_");
+                            values.1.push_normal("_");
+                        } else {
+                            let (x1, x2) = self.cmp(ta1, ta2);
+                            (values.0).0.extend(x1.0);
+                            (values.1).0.extend(x2.0);
+                        }
+                        self.push_comma(&mut values.0, &mut values.1, len, i);
+                    }
+
+                    // Close the type argument bracket.
+                    // Only draw `<...>` if there're lifetime/type arguments.
+                    if len > 0 {
+                        values.0.push_normal(">");
+                        values.1.push_normal(">");
+                    }
+                    values
+                } else {
+                    // Check for case:
+                    //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
+                    //     Foo<Bar<Qux>
+                    //         ------- this type argument is exactly the same as the other type
+                    //     Bar<Qux>
+                    if self.cmp_type_arg(&mut values.0,
+                                         &mut values.1,
+                                         path1.clone(),
+                                         sub1,
+                                         path2.clone(),
+                                         &t2).is_some() {
+                        return values;
+                    }
+                    // Check for case:
+                    //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
+                    //     Bar<Qux>
+                    //     Foo<Bar<Qux>>
+                    //         ------- this type argument is exactly the same as the other type
+                    if self.cmp_type_arg(&mut values.1,
+                                         &mut values.0,
+                                         path2,
+                                         sub2,
+                                         path1,
+                                         &t1).is_some() {
+                        return values;
+                    }
+
+                    // We couldn't find anything in common, highlight everything.
+                    //     let x: Bar<Qux> = y::<Foo<Zar>>();
+                    (DiagnosticStyledString::highlighted(format!("{}", t1)),
+                     DiagnosticStyledString::highlighted(format!("{}", t2)))
+                }
+            }
+            _ => {
+                if t1 == t2 {
+                    // The two types are the same, elide and don't highlight.
+                    (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
+                } else {
+                    // We couldn't find anything in common, highlight everything.
+                    (DiagnosticStyledString::highlighted(format!("{}", t1)),
+                     DiagnosticStyledString::highlighted(format!("{}", t2)))
+                }
+            }
+        }
+    }
+
     pub fn note_type_err(&self,
                          diag: &mut DiagnosticBuilder<'tcx>,
                          cause: &ObligationCause<'tcx>,
@@ -397,14 +653,14 @@ pub fn note_type_err(&self,
 
         if let Some((expected, found)) = expected_found {
             match (terr, is_simple_error, expected == found) {
-                (&TypeError::Sorts(ref values), false,  true) => {
+                (&TypeError::Sorts(ref values), false, true) => {
                     diag.note_expected_found_extra(
-                        &"type", &expected, &found,
+                        &"type", expected, found,
                         &format!(" ({})", values.expected.sort_string(self.tcx)),
                         &format!(" ({})", values.found.sort_string(self.tcx)));
                 }
                 (_, false,  _) => {
-                    diag.note_expected_found(&"type", &expected, &found);
+                    diag.note_expected_found(&"type", expected, found);
                 }
                 _ => (),
             }
@@ -472,26 +728,40 @@ pub fn report_and_explain_type_error(&self,
         diag
     }
 
-    /// Returns a string of the form "expected `{}`, found `{}`".
-    fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> {
+    fn values_str(&self, values: &ValuePairs<'tcx>)
+        -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
+    {
         match *values {
-            infer::Types(ref exp_found) => self.expected_found_str(exp_found),
+            infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
             infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
         }
     }
 
+    fn expected_found_str_ty(&self,
+                             exp_found: &ty::error::ExpectedFound<ty::Ty<'tcx>>)
+                             -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+        let exp_found = self.resolve_type_vars_if_possible(exp_found);
+        if exp_found.references_error() {
+            return None;
+        }
+
+        Some(self.cmp(exp_found.expected, exp_found.found))
+    }
+
+    /// Returns a string of the form "expected `{}`, found `{}`".
     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: &ty::error::ExpectedFound<T>)
-        -> Option<(String, String)>
+        -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
     {
         let exp_found = self.resolve_type_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
         }
 
-        Some((format!("{}", exp_found.expected), format!("{}", exp_found.found)))
+        Some((DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)),
+              DiagnosticStyledString::highlighted(format!("{}", exp_found.found))))
     }
 
     fn report_generic_bound_failure(&self,
index 8f8b2603dad8496de6358bdfa77c7748d5165c43..8b753e0d22be7c4bf2b37a7beed1e0e507b620ac 100644 (file)
@@ -20,6 +20,8 @@ pub(super) fn note_region_origin(&self,
         match *origin {
             infer::Subtype(ref trace) => {
                 if let Some((expected, found)) = self.values_str(&trace.values) {
+                    let expected = expected.content();
+                    let found = found.content();
                     // FIXME: do we want a "the" here?
                     err.span_note(trace.cause.span,
                                   &format!("...so that {} (expected {}, found {})",
index 806b94486615fcd7d313796effbeeeab0ce3663f..72b23a3bc181cc0f1ed060dc7d12c4c9fcc49ef6 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ty::{self, TyCtxt};
+use infer::type_variable::TypeVariableMap;
+use ty::{self, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder};
 
 use super::InferCtxt;
@@ -54,57 +55,52 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// the actual types (`?T`, `Option<?T`) -- and remember that
     /// after the snapshot is popped, the variable `?T` is no longer
     /// unified.
-    ///
-    /// Assumptions:
-    /// - no new type variables are created during `f()` (asserted
-    ///   below); this simplifies our logic since we don't have to
-    ///   check for escaping type variables
     pub fn fudge_regions_if_ok<T, E, F>(&self,
                                         origin: &RegionVariableOrigin,
                                         f: F) -> Result<T, E> where
         F: FnOnce() -> Result<T, E>,
         T: TypeFoldable<'tcx>,
     {
-        let (region_vars, value) = self.probe(|snapshot| {
-            let vars_at_start = self.type_variables.borrow().num_vars();
+        debug!("fudge_regions_if_ok(origin={:?})", origin);
 
+        let (type_variables, region_vars, value) = self.probe(|snapshot| {
             match f() {
                 Ok(value) => {
                     let value = self.resolve_type_vars_if_possible(&value);
 
                     // At this point, `value` could in principle refer
-                    // to regions that have been created during the
-                    // snapshot (we assert below that `f()` does not
-                    // create any new type variables, so there
-                    // shouldn't be any of those). Once we exit
-                    // `probe()`, those are going to be popped, so we
-                    // will have to eliminate any references to them.
-
-                    assert_eq!(self.type_variables.borrow().num_vars(), vars_at_start,
-                               "type variables were created during fudge_regions_if_ok");
+                    // to types/regions that have been created during
+                    // the snapshot. Once we exit `probe()`, those are
+                    // going to be popped, so we will have to
+                    // eliminate any references to them.
+
+                    let type_variables =
+                        self.type_variables.borrow_mut().types_created_since_snapshot(
+                            &snapshot.type_snapshot);
                     let region_vars =
                         self.region_vars.vars_created_since_snapshot(
                             &snapshot.region_vars_snapshot);
 
-                    Ok((region_vars, value))
+                    Ok((type_variables, region_vars, value))
                 }
                 Err(e) => Err(e),
             }
         })?;
 
         // At this point, we need to replace any of the now-popped
-        // region variables that appear in `value` with a fresh region
-        // variable. We can't do this during the probe because they
-        // would just get popped then too. =)
+        // type/region variables that appear in `value` with a fresh
+        // variable of the appropriate kind. We can't do this during
+        // the probe because they would just get popped then too. =)
 
         // Micro-optimization: if no variables have been created, then
         // `value` can't refer to any of them. =) So we can just return it.
-        if region_vars.is_empty() {
+        if type_variables.is_empty() && region_vars.is_empty() {
             return Ok(value);
         }
 
         let mut fudger = RegionFudger {
             infcx: self,
+            type_variables: &type_variables,
             region_vars: &region_vars,
             origin: origin
         };
@@ -115,6 +111,7 @@ pub fn fudge_regions_if_ok<T, E, F>(&self,
 
 pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    type_variables: &'a TypeVariableMap,
     region_vars: &'a Vec<ty::RegionVid>,
     origin: &'a RegionVariableOrigin,
 }
@@ -124,6 +121,32 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.sty {
+            ty::TyInfer(ty::InferTy::TyVar(vid)) => {
+                match self.type_variables.get(&vid) {
+                    None => {
+                        // This variable was created before the
+                        // "fudging".  Since we refresh all type
+                        // variables to their binding anyhow, we know
+                        // that it is unbound, so we can just return
+                        // it.
+                        debug_assert!(self.infcx.type_variables.borrow_mut().probe(vid).is_none());
+                        ty
+                    }
+
+                    Some(&origin) => {
+                        // This variable was created during the
+                        // fudging. Recreate it with a fresh variable
+                        // here.
+                        self.infcx.next_ty_var(origin)
+                    }
+                }
+            }
+            _ => ty.super_fold_with(self),
+        }
+    }
+
     fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
         match *r {
             ty::ReVar(v) if self.region_vars.contains(&v) => {
index 8ccadc6b2af044819d5c7a2f4586d4ef6cf5b8f8..a6dd18c113f1af57b886a0cbb6ed72f4e040c930 100644 (file)
@@ -49,7 +49,8 @@ fn relate_with_variance<T: Relate<'tcx>>(&mut self,
         match variance {
             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
             ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+            // FIXME(#41044) -- not correct, need test
+            ty::Bivariant => Ok(a.clone()),
             ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
         }
     }
index f7b26a918b3a200d182c5651aab55e7ea562cac1..d4d090f0153d015b5b779dabf724dd4bfbf18d57 100644 (file)
@@ -44,6 +44,10 @@ pub trait LatticeDir<'f, 'gcx: 'f+'tcx, 'tcx: 'f> : TypeRelation<'f, 'gcx, 'tcx>
 
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
+    //
+    // Subtle hack: ordering *may* be significant here. This method
+    // relates `v` to `a` first, which may help us to avoid unecessary
+    // type variable obligations. See caller for details.
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
 }
 
@@ -74,7 +78,29 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
             Ok(v)
         }
 
-        (&ty::TyInfer(TyVar(..)), _) |
+        // If one side is known to be a variable and one is not,
+        // create a variable (`v`) to represent the LUB. Make sure to
+        // relate `v` to the non-type-variable first (by passing it
+        // first to `relate_bound`). Otherwise, we would produce a
+        // subtype obligation that must then be processed.
+        //
+        // Example: if the LHS is a type variable, and RHS is
+        // `Box<i32>`, then we current compare `v` to the RHS first,
+        // which will instantiate `v` with `Box<i32>`.  Then when `v`
+        // is compared to the LHS, we instantiate LHS with `Box<i32>`.
+        // But if we did in reverse order, we would create a `v <:
+        // LHS` (or vice versa) constraint and then instantiate
+        // `v`. This would require further processing to achieve same
+        // end-result; in partiular, this screws up some of the logic
+        // in coercion, which expects LUB to figure out that the LHS
+        // is (e.g.) `Box<i32>`. A more obvious solution might be to
+        // iterate on the subtype obligations that are returned, but I
+        // think this suffices. -nmatsakis
+        (&ty::TyInfer(TyVar(..)), _) => {
+            let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
+            this.relate_bound(v, b, a)?;
+            Ok(v)
+        }
         (_, &ty::TyInfer(TyVar(..))) => {
             let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
             this.relate_bound(v, a, b)?;
index 89571dea10c3425b56c3cdefadcc0d59f0994a96..d7e5c92b6e17b20e6882c8c23f9da025ab8e9e41 100644 (file)
@@ -49,7 +49,8 @@ fn relate_with_variance<T: Relate<'tcx>>(&mut self,
         match variance {
             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
             ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+            // FIXME(#41044) -- not correct, need test
+            ty::Bivariant => Ok(a.clone()),
             ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
         }
     }
index b07ef4dfd448e45f1a3651110b4dd6b79838e836..e98792b120de284c332e144571439a39a69e11af 100644 (file)
@@ -48,7 +48,6 @@
 use self::type_variable::TypeVariableOrigin;
 use self::unify_key::ToType;
 
-mod bivariate;
 mod combine;
 mod equate;
 pub mod error_reporting;
@@ -552,7 +551,7 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
 }
 
 impl<T> ExpectedFound<T> {
-    fn new(a_is_expected: bool, a: T, b: T) -> Self {
+    pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
         if a_is_expected {
             ExpectedFound {expected: a, found: b}
         } else {
@@ -1037,9 +1036,9 @@ pub fn can_sub_types(&self,
         self.probe(|_| {
             let origin = &ObligationCause::dummy();
             let trace = TypeTrace::types(origin, true, a, b);
-            self.sub(true, trace, &a, &b).map(|InferOk { obligations, .. }| {
-                // FIXME(#32730) propagate obligations
-                assert!(obligations.is_empty());
+            self.sub(true, trace, &a, &b).map(|InferOk { obligations: _, .. }| {
+                // Ignore obligations, since we are unrolling
+                // everything anyway.
             })
         })
     }
@@ -1130,6 +1129,43 @@ pub fn equality_predicate(&self,
         })
     }
 
+    pub fn subtype_predicate(&self,
+                             cause: &ObligationCause<'tcx>,
+                             predicate: &ty::PolySubtypePredicate<'tcx>)
+        -> Option<InferResult<'tcx, ()>>
+    {
+        // Subtle: it's ok to skip the binder here and resolve because
+        // `shallow_resolve` just ignores anything that is not a type
+        // variable, and because type variable's can't (at present, at
+        // least) capture any of the things bound by this binder.
+        //
+        // Really, there is no *particular* reason to do this
+        // `shallow_resolve` here except as a
+        // micro-optimization. Naturally I could not
+        // resist. -nmatsakis
+        let two_unbound_type_vars = {
+            let a = self.shallow_resolve(predicate.skip_binder().a);
+            let b = self.shallow_resolve(predicate.skip_binder().b);
+            a.is_ty_var() && b.is_ty_var()
+        };
+
+        if two_unbound_type_vars {
+            // Two unbound type variables? Can't make progress.
+            return None;
+        }
+
+        Some(self.commit_if_ok(|snapshot| {
+            let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) =
+                self.skolemize_late_bound_regions(predicate, snapshot);
+
+            let cause_span = cause.span;
+            let ok = self.sub_types(a_is_expected, cause, a, b)?;
+            self.leak_check(false, cause_span, &skol_map, snapshot)?;
+            self.pop_skolemized(skol_map, snapshot);
+            Ok(ok.unit())
+        }))
+    }
+
     pub fn region_outlives_predicate(&self,
                                      cause: &traits::ObligationCause<'tcx>,
                                      predicate: &ty::PolyRegionOutlivesPredicate<'tcx>)
index dae30ea97c80d5169e57498f7706f2c6144f35c4..2a7dbbc026bc0bda28f84ce3236871ee60b4497a 100644 (file)
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use super::SubregionOrigin;
-use super::combine::CombineFields;
-use super::type_variable::{SubtypeOf, SupertypeOf};
+use super::combine::{CombineFields, RelationDir};
 
+use traits::Obligation;
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
+use ty::fold::TypeFoldable;
 use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
 use std::mem;
 
@@ -65,7 +66,7 @@ fn relate_with_variance<T: Relate<'tcx>>(&mut self,
         match variance {
             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
             ty::Covariant => self.relate(a, b),
-            ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
+            ty::Bivariant => Ok(a.clone()),
             ty::Contravariant => self.with_expected_switched(|this| { this.relate(b, a) }),
         }
     }
@@ -79,19 +80,38 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
         let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
-                infcx.type_variables
-                    .borrow_mut()
-                    .relate_vars(a_id, SubtypeOf, b_id);
+            (&ty::TyInfer(TyVar(a_vid)), &ty::TyInfer(TyVar(b_vid))) => {
+                // Shouldn't have any LBR here, so we can safely put
+                // this under a binder below without fear of accidental
+                // capture.
+                assert!(!a.has_escaping_regions());
+                assert!(!b.has_escaping_regions());
+
+                // can't make progress on `A <: B` if both A and B are
+                // type variables, so record an obligation. We also
+                // have to record in the `type_variables` tracker that
+                // the two variables are equal modulo subtyping, which
+                // is important to the occurs check later on.
+                infcx.type_variables.borrow_mut().sub(a_vid, b_vid);
+                self.fields.obligations.push(
+                    Obligation::new(
+                        self.fields.trace.cause.clone(),
+                        ty::Predicate::Subtype(
+                            ty::Binder(ty::SubtypePredicate {
+                                a_is_expected: self.a_is_expected,
+                                a,
+                                b,
+                            }))));
+
                 Ok(a)
             }
             (&ty::TyInfer(TyVar(a_id)), _) => {
                 self.fields
-                    .instantiate(b, SupertypeOf, a_id, !self.a_is_expected)?;
+                    .instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
                 Ok(a)
             }
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, SubtypeOf, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
index 67f37e5f9272e85c058beb616995a89dbd92b227..4ae2a8026409d3fcd4082562c4f8d850041da957 100644 (file)
@@ -8,11 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::RelationDir::*;
 use self::TypeVariableValue::*;
-use self::UndoEntry::*;
 use hir::def_id::{DefId};
-use syntax::util::small_vector::SmallVector;
 use syntax::ast;
 use syntax_pos::Span;
 use ty::{self, Ty};
 use std::marker::PhantomData;
 use std::mem;
 use std::u32;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::snapshot_vec as sv;
 use rustc_data_structures::unify as ut;
 
 pub struct TypeVariableTable<'tcx> {
     values: sv::SnapshotVec<Delegate<'tcx>>,
+
+    /// Two variables are unified in `eq_relations` when we have a
+    /// constraint `?X == ?Y`.
     eq_relations: ut::UnificationTable<ty::TyVid>,
+
+    /// Two variables are unified in `eq_relations` when we have a
+    /// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second
+    /// table exists only to help with the occurs check. In particular,
+    /// we want to report constraints like these as an occurs check
+    /// violation:
+    ///
+    ///     ?1 <: ?3
+    ///     Box<?3> <: ?1
+    ///
+    /// This works because `?1` and `?3` are unified in the
+    /// `sub_relations` relation (not in `eq_relations`). Then when we
+    /// process the `Box<?3> <: ?1` constraint, we do an occurs check
+    /// on `Box<?3>` and find a potential cycle.
+    ///
+    /// This is reasonable because, in Rust, subtypes have the same
+    /// "skeleton" and hence there is no possible type such that
+    /// (e.g.)  `Box<?3> <: ?3` for any `?3`.
+    sub_relations: ut::UnificationTable<ty::TyVid>,
 }
 
 /// Reasons to create a type inference variable
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum TypeVariableOrigin {
     MiscVariable(Span),
     NormalizeProjectionType(Span),
@@ -44,8 +64,11 @@ pub enum TypeVariableOrigin {
     DivergingBlockExpr(Span),
     DivergingFn(Span),
     LatticeVariable(Span),
+    Generalized(ty::TyVid),
 }
 
+pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
+
 struct TypeVariableData<'tcx> {
     value: TypeVariableValue<'tcx>,
     origin: TypeVariableOrigin,
@@ -55,7 +78,6 @@ struct TypeVariableData<'tcx> {
 enum TypeVariableValue<'tcx> {
     Known(Ty<'tcx>),
     Bounded {
-        relations: Vec<Relation>,
         default: Option<Default<'tcx>>
     }
 }
@@ -74,47 +96,25 @@ pub struct Default<'tcx> {
 pub struct Snapshot {
     snapshot: sv::Snapshot,
     eq_snapshot: ut::Snapshot<ty::TyVid>,
+    sub_snapshot: ut::Snapshot<ty::TyVid>,
 }
 
-enum UndoEntry<'tcx> {
-    // The type of the var was specified.
-    SpecifyVar(ty::TyVid, Vec<Relation>, Option<Default<'tcx>>),
-    Relate(ty::TyVid, ty::TyVid),
-    RelateRange(ty::TyVid, usize),
+struct Instantiate<'tcx> {
+    vid: ty::TyVid,
+    default: Option<Default<'tcx>>,
 }
 
 struct Delegate<'tcx>(PhantomData<&'tcx ()>);
 
-type Relation = (RelationDir, ty::TyVid);
-
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub enum RelationDir {
-    SubtypeOf, SupertypeOf, EqTo, BiTo
-}
-
-impl RelationDir {
-    fn opposite(self) -> RelationDir {
-        match self {
-            SubtypeOf => SupertypeOf,
-            SupertypeOf => SubtypeOf,
-            EqTo => EqTo,
-            BiTo => BiTo,
-        }
-    }
-}
-
 impl<'tcx> TypeVariableTable<'tcx> {
     pub fn new() -> TypeVariableTable<'tcx> {
         TypeVariableTable {
             values: sv::SnapshotVec::new(),
             eq_relations: ut::UnificationTable::new(),
+            sub_relations: ut::UnificationTable::new(),
         }
     }
 
-    fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
-        relations(self.values.get_mut(a.index as usize))
-    }
-
     pub fn default(&self, vid: ty::TyVid) -> Option<Default<'tcx>> {
         match &self.values.get(vid.index as usize).value {
             &Known(_) => None,
@@ -130,68 +130,46 @@ pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
         &self.values.get(vid.index as usize).origin
     }
 
-    /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
+    /// Records that `a == b`, depending on `dir`.
     ///
     /// Precondition: neither `a` nor `b` are known.
-    pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) {
-        let a = self.root_var(a);
-        let b = self.root_var(b);
-        if a != b {
-            if dir == EqTo {
-                // a and b must be equal which we mark in the unification table
-                let root = self.eq_relations.union(a, b);
-                // In addition to being equal, all relations from the variable which is no longer
-                // the root must be added to the root so they are not forgotten as the other
-                // variable should no longer be referenced (other than to get the root)
-                let other = if a == root { b } else { a };
-                let count = {
-                    let (relations, root_relations) = if other.index < root.index {
-                        let (pre, post) = self.values.split_at_mut(root.index as usize);
-                        (relations(&mut pre[other.index as usize]), relations(&mut post[0]))
-                    } else {
-                        let (pre, post) = self.values.split_at_mut(other.index as usize);
-                        (relations(&mut post[0]), relations(&mut pre[root.index as usize]))
-                    };
-                    root_relations.extend_from_slice(relations);
-                    relations.len()
-                };
-                self.values.record(RelateRange(root, count));
-            } else {
-                self.relations(a).push((dir, b));
-                self.relations(b).push((dir.opposite(), a));
-                self.values.record(Relate(a, b));
-            }
-        }
+    pub fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
+        debug_assert!(self.probe(a).is_none());
+        debug_assert!(self.probe(b).is_none());
+        self.eq_relations.union(a, b);
+        self.sub_relations.union(a, b);
     }
 
-    /// Instantiates `vid` with the type `ty` and then pushes an entry onto `stack` for each of the
-    /// relations of `vid` to other variables. The relations will have the form `(ty, dir, vid1)`
-    /// where `vid1` is some other variable id.
+    /// Records that `a <: b`, depending on `dir`.
     ///
-    /// Precondition: `vid` must be a root in the unification table
-    pub fn instantiate_and_push(
-        &mut self,
-        vid: ty::TyVid,
-        ty: Ty<'tcx>,
-        stack: &mut SmallVector<(Ty<'tcx>, RelationDir, ty::TyVid)>)
-    {
-        debug_assert!(self.root_var(vid) == vid);
-        let old_value = {
-            let value_ptr = &mut self.values.get_mut(vid.index as usize).value;
-            mem::replace(value_ptr, Known(ty))
-        };
+    /// Precondition: neither `a` nor `b` are known.
+    pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
+        debug_assert!(self.probe(a).is_none());
+        debug_assert!(self.probe(b).is_none());
+        self.sub_relations.union(a, b);
+    }
+
+    /// Instantiates `vid` with the type `ty`.
+    ///
+    /// Precondition: `vid` must not have been previously instantiated.
+    pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
+        let vid = self.root_var(vid);
+        debug_assert!(self.probe_root(vid).is_none());
 
-        let (relations, default) = match old_value {
-            Bounded { relations, default } => (relations, default),
-            Known(_) => bug!("Asked to instantiate variable that is \
-                              already instantiated")
+        let old_value = {
+            let vid_data = &mut self.values[vid.index as usize];
+            mem::replace(&mut vid_data.value, TypeVariableValue::Known(ty))
         };
 
-        for &(dir, vid) in &relations {
-            stack.push((ty, dir, vid));
+        match old_value {
+            TypeVariableValue::Bounded { default } => {
+                self.values.record(Instantiate { vid: vid, default: default });
+            }
+            TypeVariableValue::Known(old_ty) => {
+                bug!("instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
+                     vid, ty, old_ty)
+            }
         }
-
-        self.values.record(SpecifyVar(vid, relations, default));
     }
 
     pub fn new_var(&mut self,
@@ -200,8 +178,9 @@ pub fn new_var(&mut self,
                    default: Option<Default<'tcx>>,) -> ty::TyVid {
         debug!("new_var(diverging={:?}, origin={:?})", diverging, origin);
         self.eq_relations.new_key(());
+        self.sub_relations.new_key(());
         let index = self.values.push(TypeVariableData {
-            value: Bounded { relations: vec![], default: default },
+            value: Bounded { default: default },
             origin: origin,
             diverging: diverging
         });
@@ -214,15 +193,41 @@ pub fn num_vars(&self) -> usize {
         self.values.len()
     }
 
+    /// Returns the "root" variable of `vid` in the `eq_relations`
+    /// equivalence table. All type variables that have been equated
+    /// will yield the same root variable (per the union-find
+    /// algorithm), so `root_var(a) == root_var(b)` implies that `a ==
+    /// b` (transitively).
     pub fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
         self.eq_relations.find(vid)
     }
 
+    /// Returns the "root" variable of `vid` in the `sub_relations`
+    /// equivalence table. All type variables that have been are
+    /// related via equality or subtyping will yield the same root
+    /// variable (per the union-find algorithm), so `sub_root_var(a)
+    /// == sub_root_var(b)` implies that:
+    ///
+    ///     exists X. (a <: X || X <: a) && (b <: X || X <: b)
+    pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
+        self.sub_relations.find(vid)
+    }
+
+    /// True if `a` and `b` have same "sub-root" (i.e., exists some
+    /// type X such that `forall i in {a, b}. (i <: X || X <: i)`.
+    pub fn sub_unified(&mut self, a: ty::TyVid, b: ty::TyVid) -> bool {
+        self.sub_root_var(a) == self.sub_root_var(b)
+    }
+
     pub fn probe(&mut self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
         let vid = self.root_var(vid);
         self.probe_root(vid)
     }
 
+    pub fn origin(&self, vid: ty::TyVid) -> TypeVariableOrigin {
+        self.values.get(vid.index as usize).origin.clone()
+    }
+
     /// Retrieves the type of `vid` given that it is currently a root in the unification table
     pub fn probe_root(&mut self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
         debug_assert!(self.root_var(vid) == vid);
@@ -248,6 +253,7 @@ pub fn snapshot(&mut self) -> Snapshot {
         Snapshot {
             snapshot: self.values.start_snapshot(),
             eq_snapshot: self.eq_relations.snapshot(),
+            sub_snapshot: self.sub_relations.snapshot(),
         }
     }
 
@@ -263,13 +269,37 @@ pub fn rollback_to(&mut self, s: Snapshot) {
             }
         });
 
-        self.values.rollback_to(s.snapshot);
-        self.eq_relations.rollback_to(s.eq_snapshot);
+        let Snapshot { snapshot, eq_snapshot, sub_snapshot } = s;
+        self.values.rollback_to(snapshot);
+        self.eq_relations.rollback_to(eq_snapshot);
+        self.sub_relations.rollback_to(sub_snapshot);
     }
 
     pub fn commit(&mut self, s: Snapshot) {
-        self.values.commit(s.snapshot);
-        self.eq_relations.commit(s.eq_snapshot);
+        let Snapshot { snapshot, eq_snapshot, sub_snapshot } = s;
+        self.values.commit(snapshot);
+        self.eq_relations.commit(eq_snapshot);
+        self.sub_relations.commit(sub_snapshot);
+    }
+
+    /// Returns a map `{V1 -> V2}`, where the keys `{V1}` are
+    /// ty-variables created during the snapshot, and the values
+    /// `{V2}` are the root variables that they were unified with,
+    /// along with their origin.
+    pub fn types_created_since_snapshot(&mut self, s: &Snapshot) -> TypeVariableMap {
+        let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
+
+        actions_since_snapshot
+            .iter()
+            .filter_map(|action| match action {
+                &sv::UndoLog::NewElem(index) => Some(ty::TyVid { index: index as u32 }),
+                _ => None,
+            })
+            .map(|vid| {
+                let origin = self.values.get(vid.index as usize).origin.clone();
+                (vid, origin)
+            })
+            .collect()
     }
 
     pub fn types_escaping_snapshot(&mut self, s: &Snapshot) -> Vec<Ty<'tcx>> {
@@ -298,7 +328,7 @@ pub fn types_escaping_snapshot(&mut self, s: &Snapshot) -> Vec<Ty<'tcx>> {
                     debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
                 }
 
-                sv::UndoLog::Other(SpecifyVar(vid, ..)) => {
+                sv::UndoLog::Other(Instantiate { vid, .. }) => {
                     if vid.index < new_elem_threshold {
                         // quick check to see if this variable was
                         // created since the snapshot started or not.
@@ -334,35 +364,12 @@ pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
 
 impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
     type Value = TypeVariableData<'tcx>;
-    type Undo = UndoEntry<'tcx>;
-
-    fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry<'tcx>) {
-        match action {
-            SpecifyVar(vid, relations, default) => {
-                values[vid.index as usize].value = Bounded {
-                    relations: relations,
-                    default: default
-                };
-            }
+    type Undo = Instantiate<'tcx>;
 
-            Relate(a, b) => {
-                relations(&mut (*values)[a.index as usize]).pop();
-                relations(&mut (*values)[b.index as usize]).pop();
-            }
-
-            RelateRange(i, n) => {
-                let relations = relations(&mut (*values)[i.index as usize]);
-                for _ in 0..n {
-                    relations.pop();
-                }
-            }
-        }
-    }
-}
-
-fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
-    match v.value {
-        Known(_) => bug!("var_sub_var: variable is known"),
-        Bounded { ref mut relations, .. } => relations
+    fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: Instantiate<'tcx>) {
+        let Instantiate { vid, default } = action;
+        values[vid.index as usize].value = Bounded {
+            default: default
+        };
     }
 }
index 3b002fd4dfc1a210e8445eb9e2cd8469beac0c68..e5a6930fefd228ad690bbe71b889a93b0c3708ec 100644 (file)
@@ -32,6 +32,7 @@
 #![feature(i128_type)]
 #![feature(libc)]
 #![feature(loop_break_value)]
+#![feature(never_type)]
 #![feature(nonzero)]
 #![cfg_attr(stage0, feature(pub_restricted))]
 #![feature(quote)]
@@ -42,6 +43,7 @@
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(discriminant_value)]
+#![feature(sort_unstable)]
 
 extern crate arena;
 extern crate core;
index 694321812836b2b943cebea312515ab54118ec5a..cbbfeacadb4087a2e8912bb415986d57435ec605 100644 (file)
@@ -27,6 +27,7 @@
 use hir::map as hir_map;
 use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
 use hir::svh::Svh;
+use ich;
 use middle::lang_items;
 use ty::{self, TyCtxt};
 use session::Session;
@@ -52,7 +53,6 @@
 
 #[derive(Clone, Debug)]
 pub struct LinkMeta {
-    pub crate_name: Symbol,
     pub crate_hash: Svh,
 }
 
@@ -161,6 +161,20 @@ pub struct ExternCrate {
     pub path_len: usize,
 }
 
+pub struct EncodedMetadata {
+    pub raw_data: Vec<u8>,
+    pub hashes: Vec<EncodedMetadataHash>,
+}
+
+/// The hash for some metadata that (when saving) will be exported
+/// from this crate, or which (when importing) was exported by an
+/// upstream crate.
+#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+pub struct EncodedMetadataHash {
+    pub def_index: DefIndex,
+    pub hash: ich::Fingerprint,
+}
+
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 pub trait CrateStore {
@@ -258,7 +272,8 @@ fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
-                                 reachable: &NodeSet) -> Vec<u8>;
+                                 reachable: &NodeSet)
+                                 -> EncodedMetadata;
     fn metadata_encoding_version(&self) -> &[u8];
 }
 
@@ -417,7 +432,10 @@ fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
-                                 reachable: &NodeSet) -> Vec<u8> { vec![] }
+                                 reachable: &NodeSet)
+                                 -> EncodedMetadata {
+        bug!("encode_metadata")
+    }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
 }
 
index 5af8e7e52d888407f57518c0bfd4addaedda1f6e..d2b8ed8c2970770250d35fe78699d06d548d4316 100644 (file)
@@ -12,7 +12,6 @@
 //! `unsafe`.
 use self::RootUnsafeContext::*;
 
-use dep_graph::DepNode;
 use ty::{self, Ty, TyCtxt};
 use ty::MethodCall;
 use lint;
@@ -241,8 +240,6 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let _task = tcx.dep_graph.in_task(DepNode::EffectCheck);
-
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
         tables: &ty::TypeckTables::empty(),
index cdb081ab40098655ab325fec2aa5bc29a0c2a3d2..2bfa8dec0bfc78a48bc75582108836fbde00c010 100644 (file)
@@ -60,6 +60,7 @@ pub fn relate_free_regions_from_predicates(&mut self,
                 ty::Predicate::Projection(..) |
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Equate(..) |
+                ty::Predicate::Subtype(..) |
                 ty::Predicate::WellFormed(..) |
                 ty::Predicate::ObjectSafe(..) |
                 ty::Predicate::ClosureKind(..) |
@@ -180,3 +181,7 @@ fn lub() {
     map.relate_free_regions(frs[1], frs[2]);
     assert_eq!(map.lub_free_regions(frs[0], frs[1]), ty::ReFree(frs[2]));
 }
+
+impl_stable_hash_for!(struct FreeRegionMap {
+    relation
+});
index 7cae08efc0de057a14815832c82db859f5c907c7..b7da8480c1cefdf6cf740699ff6e6249b442edd8 100644 (file)
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
-use dep_graph::DepNode;
 use hir::def::*;
 use ty::{self, TyCtxt, ParameterEnvironment};
 use traits::{self, Reveal};
@@ -196,7 +195,6 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let _task = tcx.dep_graph.in_task(DepNode::Liveness);
     tcx.hir.krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor());
     tcx.sess.abort_if_errors();
 }
index e5dd48534a6a136ad452e09c9a01226dd1f7196e..63455f94cedff32370213bbaf6f1e200fc8db518 100644 (file)
@@ -267,7 +267,8 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) |
                     hir::ItemStruct(..) | hir::ItemEnum(..) |
-                    hir::ItemUnion(..) | hir::ItemDefaultImpl(..) => {}
+                    hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
+                    hir::ItemGlobalAsm(..) => {}
                 }
             }
             hir_map::NodeTraitItem(trait_method) => {
index 8037570d24a808bb6ab7983d85d4ae7c4686d400..b9938a04047c96b141fc5a47b7484dcffe5d1c87 100644 (file)
@@ -314,7 +314,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemUse(..) |
             hir::ItemMod(..) |
             hir::ItemDefaultImpl(..) |
-            hir::ItemForeignMod(..) => {
+            hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
             }
index aea4684e526ce3a04c454a23bb93075c0b8ebf9d..9ff64b295b765ee8a5f67026f15312c2938cadc0 100644 (file)
@@ -197,10 +197,10 @@ pub fn local_kind(&self, local: Local) -> LocalKind {
     pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
         (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].source_info.is_none() {
-                Some(local)
-            } else {
+            if self.local_decls[local].is_user_variable {
                 None
+            } else {
+                Some(local)
             }
         })
     }
@@ -210,10 +210,10 @@ pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
     pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
         (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].source_info.is_none() {
-                None
-            } else {
+            if self.local_decls[local].is_user_variable {
                 Some(local)
+            } else {
+                None
             }
         })
     }
@@ -370,6 +370,9 @@ pub struct LocalDecl<'tcx> {
     /// Temporaries and the return pointer are always mutable.
     pub mutability: Mutability,
 
+    /// True if this corresponds to a user-declared local variable.
+    pub is_user_variable: bool,
+
     /// Type of this local.
     pub ty: Ty<'tcx>,
 
@@ -379,24 +382,23 @@ pub struct LocalDecl<'tcx> {
     /// to generate better debuginfo.
     pub name: Option<Name>,
 
-    /// For user-declared variables, stores their source information.
-    ///
-    /// For temporaries, this is `None`.
-    ///
-    /// This is the primary way to differentiate between user-declared
-    /// variables and compiler-generated temporaries.
-    pub source_info: Option<SourceInfo>,
+    /// Source info of the local.
+    pub source_info: SourceInfo,
 }
 
 impl<'tcx> LocalDecl<'tcx> {
     /// Create a new `LocalDecl` for a temporary.
     #[inline]
-    pub fn new_temp(ty: Ty<'tcx>) -> Self {
+    pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
         LocalDecl {
             mutability: Mutability::Mut,
             ty: ty,
             name: None,
-            source_info: None,
+            source_info: SourceInfo {
+                span: span,
+                scope: ARGUMENT_VISIBILITY_SCOPE
+            },
+            is_user_variable: false
         }
     }
 
@@ -404,12 +406,16 @@ pub fn new_temp(ty: Ty<'tcx>) -> Self {
     ///
     /// This must be inserted into the `local_decls` list as the first local.
     #[inline]
-    pub fn new_return_pointer(return_ty: Ty) -> LocalDecl {
+    pub fn new_return_pointer(return_ty: Ty, span: Span) -> LocalDecl {
         LocalDecl {
             mutability: Mutability::Mut,
             ty: return_ty,
-            source_info: None,
+            source_info: SourceInfo {
+                span: span,
+                scope: ARGUMENT_VISIBILITY_SCOPE
+            },
             name: None,     // FIXME maybe we do want some name here?
+            is_user_variable: false
         }
     }
 }
index 733ad36de90e3febf6757a6b8a41a5ade16028a0..83963de8b0014e69df865ebad04a3db22be49328 100644 (file)
@@ -630,12 +630,11 @@ fn super_local_decl(&mut self,
                     ref $($mutability)* ty,
                     name: _,
                     ref $($mutability)* source_info,
+                    is_user_variable: _,
                 } = *local_decl;
 
                 self.visit_ty(ty);
-                if let Some(ref $($mutability)* info) = *source_info {
-                    self.visit_source_info(info);
-                }
+                self.visit_source_info(source_info);
             }
 
             fn super_visibility_scope(&mut self,
index ef825a6854cec9b4ad7ea1f30e8c66206f05a2ec..b9a974045bced110527e953ebffe296dccceb6b6 100644 (file)
@@ -643,6 +643,8 @@ mod $mod_desc {
             Some("one of: `address`, `leak`, `memory` or `thread`");
         pub const parse_linker_flavor: Option<&'static str> =
             Some(::rustc_back::LinkerFlavor::one_of());
+        pub const parse_optimization_fuel: Option<&'static str> =
+            Some("crate=integer");
     }
 
     #[allow(dead_code)]
@@ -787,6 +789,21 @@ fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> boo
             }
             true
         }
+
+        fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool {
+            match v {
+                None => false,
+                Some(s) => {
+                    let parts = s.split('=').collect::<Vec<_>>();
+                    if parts.len() != 2 { return false; }
+                    let crate_name = parts[0].to_string();
+                    let fuel = parts[1].parse::<u64>();
+                    if fuel.is_err() { return false; }
+                    *slot = Some((crate_name, fuel.unwrap()));
+                    true
+                }
+            }
+        }
     }
 ) }
 
@@ -991,6 +1008,10 @@ fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> boo
                                    "Use a sanitizer"),
     linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
                                            "Linker flavor"),
+    fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
+        "Set the optimization fuel quota for a crate."),
+    print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
+        "Make Rustc print the total optimization fuel used by a crate."),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1784,11 +1805,13 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
 
     impl_dep_tracking_hash_via_hash!(bool);
     impl_dep_tracking_hash_via_hash!(usize);
+    impl_dep_tracking_hash_via_hash!(u64);
     impl_dep_tracking_hash_via_hash!(String);
     impl_dep_tracking_hash_via_hash!(lint::Level);
     impl_dep_tracking_hash_via_hash!(Option<bool>);
     impl_dep_tracking_hash_via_hash!(Option<usize>);
     impl_dep_tracking_hash_via_hash!(Option<String>);
+    impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
     impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
@@ -1810,6 +1833,7 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
     impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
                                                  Option<cstore::NativeLibraryKind>));
+    impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
     impl DepTrackingHash for SearchPaths {
         fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
             let mut elems: Vec<_> = self
index 70b2809ccbed2ba0ada1744a840cb35605350101..adc9aabb8c77a1abf24a93f9807e890cb9d1b020 100644 (file)
@@ -13,7 +13,6 @@
 
 use dep_graph::DepGraph;
 use hir::def_id::{CrateNum, DefIndex};
-use hir::svh::Svh;
 use lint;
 use middle::cstore::CrateStore;
 use middle::dependency_format;
@@ -123,6 +122,20 @@ pub struct Session {
     pub code_stats: RefCell<CodeStats>,
 
     next_node_id: Cell<ast::NodeId>,
+
+    /// If -zfuel=crate=n is specified, Some(crate).
+    optimization_fuel_crate: Option<String>,
+    /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
+    optimization_fuel_limit: Cell<u64>,
+    /// We're rejecting all further optimizations.
+    out_of_fuel: Cell<bool>,
+
+    // The next two are public because the driver needs to read them.
+
+    /// If -zprint-fuel=crate, Some(crate).
+    pub print_fuel_crate: Option<String>,
+    /// Always set to zero and incremented so that we can print fuel expended by a crate.
+    pub print_fuel: Cell<u64>,
 }
 
 pub struct PerfStats {
@@ -388,15 +401,14 @@ pub fn must_not_eliminate_frame_pointers(&self) -> bool {
 
     /// Returns the symbol name for the registrar function,
     /// given the crate Svh and the function DefIndex.
-    pub fn generate_plugin_registrar_symbol(&self, svh: &Svh, index: DefIndex)
+    pub fn generate_plugin_registrar_symbol(&self, disambiguator: Symbol, index: DefIndex)
                                             -> String {
-        format!("__rustc_plugin_registrar__{}_{}", svh, index.as_usize())
+        format!("__rustc_plugin_registrar__{}_{}", disambiguator, index.as_usize())
     }
 
-    pub fn generate_derive_registrar_symbol(&self,
-                                            svh: &Svh,
-                                            index: DefIndex) -> String {
-        format!("__rustc_derive_registrar__{}_{}", svh, index.as_usize())
+    pub fn generate_derive_registrar_symbol(&self, disambiguator: Symbol, index: DefIndex)
+                                            -> String {
+        format!("__rustc_derive_registrar__{}_{}", disambiguator, index.as_usize())
     }
 
     pub fn sysroot<'a>(&'a self) -> &'a Path {
@@ -507,6 +519,32 @@ pub fn print_perf_stats(&self) {
         println!("Total time spent decoding DefPath tables:      {}",
                  duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get()));
     }
+
+    /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
+    /// This expends fuel if applicable, and records fuel if applicable.
+    pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+        let mut ret = true;
+        match self.optimization_fuel_crate {
+            Some(ref c) if c == crate_name => {
+                let fuel = self.optimization_fuel_limit.get();
+                ret = fuel != 0;
+                if fuel == 0 && !self.out_of_fuel.get() {
+                    println!("optimization-fuel-exhausted: {}", msg());
+                    self.out_of_fuel.set(true);
+                } else if fuel > 0 {
+                    self.optimization_fuel_limit.set(fuel-1);
+                }
+            }
+            _ => {}
+        }
+        match self.print_fuel_crate {
+            Some(ref c) if c == crate_name=> {
+                self.print_fuel.set(self.print_fuel.get()+1);
+            },
+            _ => {}
+        }
+        ret
+    }
 }
 
 pub fn build_session(sopts: config::Options,
@@ -602,6 +640,12 @@ pub fn build_session_(sopts: config::Options,
         }
     );
 
+    let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
+    let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref()
+        .map(|i| i.1).unwrap_or(0));
+    let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
+    let print_fuel = Cell::new(0);
+
     let sess = Session {
         dep_graph: dep_graph.clone(),
         target: target_cfg,
@@ -643,6 +687,11 @@ pub fn build_session_(sopts: config::Options,
             decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
         },
         code_stats: RefCell::new(CodeStats::new()),
+        optimization_fuel_crate: optimization_fuel_crate,
+        optimization_fuel_limit: optimization_fuel_limit,
+        print_fuel_crate: print_fuel_crate,
+        print_fuel: print_fuel,
+        out_of_fuel: Cell::new(false),
     };
 
     init_llvm(&sess);
index 931c77badad222009ee0e6da53af98e99d2b5ee1..f7a7d0e2071f210287dc4b4b6c575866146e1f21 100644 (file)
@@ -39,6 +39,7 @@
 use ty::fast_reject;
 use ty::fold::TypeFolder;
 use ty::subst::Subst;
+use ty::SubtypePredicate;
 use util::nodemap::{FxHashMap, FxHashSet};
 
 use syntax_pos::{DUMMY_SP, Span};
@@ -68,6 +69,19 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     found_pattern: Option<&'a Pat>,
 }
 
+impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
+    fn is_match(&self, ty: Ty<'tcx>) -> bool {
+        ty == *self.target_ty || match (&ty.sty, &self.target_ty.sty) {
+            (&ty::TyInfer(ty::TyVar(a_vid)), &ty::TyInfer(ty::TyVar(b_vid))) =>
+                self.infcx.type_variables
+                          .borrow_mut()
+                          .sub_unified(a_vid, b_vid),
+
+            _ => false,
+        }
+    }
+}
+
 impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
         NestedVisitorMap::None
@@ -76,7 +90,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
     fn visit_local(&mut self, local: &'a Local) {
         if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
             let ty = self.infcx.resolve_type_vars_if_possible(&ty);
-            let is_match = ty.walk().any(|t| t == *self.target_ty);
+            let is_match = ty.walk().any(|t| self.is_match(t));
 
             if is_match && self.found_pattern.is_none() {
                 self.found_pattern = Some(&*local.pat);
@@ -112,6 +126,13 @@ fn report_fulfillment_error(&self,
             FulfillmentErrorCode::CodeAmbiguity => {
                 self.maybe_report_ambiguity(&error.obligation);
             }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(&error.obligation.cause,
+                                             expected_found.expected,
+                                             expected_found.found,
+                                             err.clone())
+                    .emit();
+            }
         }
     }
 
@@ -555,6 +576,13 @@ pub fn report_selection_error(&self,
                         err
                     }
 
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
                     ty::Predicate::Equate(ref predicate) => {
                         let predicate = self.resolve_type_vars_if_possible(predicate);
                         let err = self.equality_predicate(&obligation.cause,
@@ -761,6 +789,17 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
                 }
             }
 
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                } else {
+                    let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                    // both must be type variables, or the other would've been instantiated
+                    assert!(a.is_ty_var() && b.is_ty_var());
+                    self.need_type_info(obligation, a);
+                }
+            }
+
             _ => {
                 if !self.tcx.sess.has_errors() {
                     let mut err = struct_span_err!(self.tcx.sess,
index b87d18464377f6b3f4481210de7eb09651fff63b..64453f2983b92f03b6a86ae8444f2474630a052c 100644 (file)
@@ -11,6 +11,7 @@
 use dep_graph::DepGraph;
 use infer::{InferCtxt, InferOk};
 use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
+use ty::error::ExpectedFound;
 use rustc_data_structures::obligation_forest::{ObligationForest, Error};
 use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
 use std::marker::PhantomData;
@@ -496,6 +497,26 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                 s => Ok(s)
             }
         }
+
+        ty::Predicate::Subtype(ref subtype) => {
+            match selcx.infcx().subtype_predicate(&obligation.cause, subtype) {
+                None => {
+                    // none means that both are unresolved
+                    pending_obligation.stalled_on = vec![subtype.skip_binder().a,
+                                                         subtype.skip_binder().b];
+                    Ok(None)
+                }
+                Some(Ok(ok)) => {
+                    Ok(Some(ok.obligations))
+                }
+                Some(Err(err)) => {
+                    let expected_found = ExpectedFound::new(subtype.skip_binder().a_is_expected,
+                                                            subtype.skip_binder().a,
+                                                            subtype.skip_binder().b);
+                    Err(FulfillmentErrorCode::CodeSubtypeError(expected_found, err))
+                }
+            }
+        }
     }
 }
 
index 47cbccdd2ab107ef673483a8e201cf88ead77ce4..ea243d65881ea23b2f2e0e0a2a587427839c9e70 100644 (file)
@@ -20,7 +20,8 @@
 use middle::free_region::FreeRegionMap;
 use ty::subst::Substs;
 use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
-use infer::InferCtxt;
+use ty::error::{ExpectedFound, TypeError};
+use infer::{InferCtxt};
 
 use std::rc::Rc;
 use syntax::ast;
@@ -214,6 +215,8 @@ pub struct FulfillmentError<'tcx> {
 pub enum FulfillmentErrorCode<'tcx> {
     CodeSelectionError(SelectionError<'tcx>),
     CodeProjectionError(MismatchedProjectionTypes<'tcx>),
+    CodeSubtypeError(ExpectedFound<Ty<'tcx>>,
+                     TypeError<'tcx>), // always comes from a SubtypePredicate
     CodeAmbiguity,
 }
 
index 7cd0b26940d9118284e3adcc03b35a3fda36972d..d190635bec3063ce3c0e8193fba6cde6942e0800 100644 (file)
@@ -178,6 +178,7 @@ fn predicates_reference_self(
                     ty::Predicate::TypeOutlives(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::ClosureKind(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::Equate(..) => {
                         false
                     }
@@ -209,6 +210,7 @@ fn generics_require_sized_self(self, def_id: DefId) -> bool {
                     ty::Predicate::Projection(..) |
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::WellFormed(..) |
                     ty::Predicate::ObjectSafe(..) |
index 38ea1e4a19b91f536e989da9610cc1547384e700..67d50210ba39adb94a909c475424607ba445f5d4 100644 (file)
@@ -568,6 +568,18 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                 }
             }
 
+            ty::Predicate::Subtype(ref p) => {
+                // does this code ever run?
+                match self.infcx.subtype_predicate(&obligation.cause, p) {
+                    Some(Ok(InferOk { obligations, .. })) => {
+                        self.inferred_obligations.extend(obligations);
+                        EvaluatedToOk
+                    },
+                    Some(Err(_)) => EvaluatedToErr,
+                    None => EvaluatedToAmbig,
+                }
+            }
+
             ty::Predicate::WellFormed(ty) => {
                 match ty::wf::obligations(self.infcx, obligation.cause.body_id,
                                           ty, obligation.cause.span) {
index 44ef461327ddbf868837dd5b2b00559a3af4528e..9d0b1035ade497076f6c76cb116da4dbc36317d3 100644 (file)
@@ -130,6 +130,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
             super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
+            super::CodeSubtypeError(ref a, ref b) =>
+                write!(f, "CodeSubtypeError({:?}, {:?})", a, b),
             super::CodeAmbiguity => write!(f, "Ambiguity")
         }
     }
index 602f27a64d4d8d195b14c2903e4cfe6b2ac06f78..d4245ec9b2475aa79fa033e16a1de9d874bd5ff8 100644 (file)
@@ -42,7 +42,10 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             ty::Predicate::ObjectSafe(data),
 
         ty::Predicate::ClosureKind(closure_def_id, kind) =>
-            ty::Predicate::ClosureKind(closure_def_id, kind)
+            ty::Predicate::ClosureKind(closure_def_id, kind),
+
+        ty::Predicate::Subtype(ref data) =>
+            ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data)),
     }
 }
 
@@ -160,6 +163,10 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                 // `X == Y`, though conceivably we might. For example,
                 // `&X == &Y` implies that `X == Y`.
             }
+            ty::Predicate::Subtype(..) => {
+                // Currently, we do not "elaborate" predicates like `X
+                // <: Y`, though conceivably we might.
+            }
             ty::Predicate::Projection(..) => {
                 // Nothing to elaborate in a projection predicate.
             }
index d8ca30477205c53ccfcfd0e5bc61dab9c16828ae..1d7100a7a4e445d9e3bace044c2fa3fc93ea4488 100644 (file)
@@ -33,7 +33,7 @@ pub enum Adjust<'tcx> {
     /// Go from a safe fn pointer to an unsafe fn pointer.
     UnsafeFnPointer,
 
-    // Go from a non-capturing closure to an fn pointer.
+    /// Go from a non-capturing closure to an fn pointer.
     ClosureFnPointer,
 
     /// Go from a mut raw pointer to a const raw pointer.
index da56514ea82fbf9e485c3f1f761ff9253f9b54cc..8b7438c0bfad2ed5f73efbfece42ffbbd22978d4 100644 (file)
@@ -732,6 +732,11 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             ast_ty_to_ty_cache: RefCell::new(NodeMap()),
        }, f)
     }
+
+    pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
+        let cname = self.crate_name(LOCAL_CRATE).as_str();
+        self.sess.consider_optimizing(&cname, msg)
+    }
 }
 
 impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
index 54e5de3909086d55728f54d8c35d6884b5ebda32..d7a4b3fda63bb84054d49fde393e1f2ef62e9fe3 100644 (file)
@@ -580,7 +580,6 @@ enum StructKind {
 }
 
 impl<'a, 'gcx, 'tcx> Struct {
-    // FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
     fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
                   repr: &ReprOptions, kind: StructKind,
                   scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
@@ -598,12 +597,8 @@ fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
         // Neither do  1-member and 2-member structs.
         // In addition, code in trans assume that 2-element structs can become pairs.
         // It's easier to just short-circuit here.
-        let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
-            && ! (repr.c || repr.packed);
-
-        // Disable field reordering until we can decide what to do.
-        // The odd pattern here avoids a warning about the value never being read.
-        if can_optimize { can_optimize = false; }
+        let can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
+            && !(repr.c || repr.packed || repr.linear || repr.simd);
 
         let (optimize, sort_ascending) = match kind {
             StructKind::AlwaysSizedUnivariant => (can_optimize, false),
index 823bdc9e092ac8290801a25a1b8b3e7ac83a61dd..868ccad8a3a90618078a7528c2c9488076ce8aaf 100644 (file)
@@ -429,6 +429,8 @@ fn default() -> Self {
 
     pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
 
+    pub borrowck: BorrowCheck(DefId) -> (),
+
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
     /// (Defined only for LOCAL_CRATE)
index 292e30e3d41f19403353bfdd2a055ac4c1066daf..8ff91583d0822f7ba57365e9d62b0023e1fe0b64 100644 (file)
@@ -452,6 +452,23 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TyS<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::TyS {
+            ref sty,
+
+            // The other fields just provide fast access to information that is
+            // also contained in `sty`, so no need to hash them.
+            flags: _,
+            region_depth: _,
+        } = *self;
+
+        sty.hash_stable(hcx, hasher);
+    }
+}
+
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
 impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}
@@ -755,6 +772,9 @@ pub enum Predicate<'tcx> {
     /// for some substitutions `...` and T being a closure type.
     /// Satisfied (or refuted) once we know the closure's kind.
     ClosureKind(DefId, ClosureKind),
+
+    /// `T1 <: T2`
+    Subtype(PolySubtypePredicate<'tcx>),
 }
 
 impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
@@ -833,6 +853,8 @@ pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 Predicate::Trait(ty::Binder(data.subst(tcx, substs))),
             Predicate::Equate(ty::Binder(ref data)) =>
                 Predicate::Equate(ty::Binder(data.subst(tcx, substs))),
+            Predicate::Subtype(ty::Binder(ref data)) =>
+                Predicate::Subtype(ty::Binder(data.subst(tcx, substs))),
             Predicate::RegionOutlives(ty::Binder(ref data)) =>
                 Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))),
             Predicate::TypeOutlives(ty::Binder(ref data)) =>
@@ -912,6 +934,14 @@ pub fn dep_node(&self) -> DepNode<DefId> {
                                                                    &'tcx ty::Region>;
 pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, &'tcx ty::Region>;
 
+#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct SubtypePredicate<'tcx> {
+    pub a_is_expected: bool,
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>
+}
+pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
+
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
@@ -1025,6 +1055,9 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
             ty::Predicate::Equate(ty::Binder(ref data)) => {
                 vec![data.0, data.1]
             }
+            ty::Predicate::Subtype(ty::Binder(SubtypePredicate { a, b, a_is_expected: _ })) => {
+                vec![a, b]
+            }
             ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
                 vec![data.0]
             }
@@ -1061,6 +1094,7 @@ pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
             }
             Predicate::Projection(..) |
             Predicate::Equate(..) |
+            Predicate::Subtype(..) |
             Predicate::RegionOutlives(..) |
             Predicate::WellFormed(..) |
             Predicate::ObjectSafe(..) |
@@ -1411,13 +1445,16 @@ pub struct ReprOptions {
     pub packed: bool,
     pub simd: bool,
     pub int: Option<attr::IntType>,
+    // Internal only for now. If true, don't reorder fields.
+    pub linear: bool,
 }
 
 impl_stable_hash_for!(struct ReprOptions {
     c,
     packed,
     simd,
-    int
+    int,
+    linear
 });
 
 impl ReprOptions {
@@ -1440,6 +1477,9 @@ pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
             ret.simd = true;
         }
 
+        // This is here instead of layout because the choice must make it into metadata.
+        ret.linear = !tcx.consider_optimizing(|| format!("Reorder fields of {:?}",
+            tcx.item_path_str(did)));
         ret
     }
 
@@ -2218,7 +2258,7 @@ pub fn def_key(self, id: DefId) -> hir_map::DefKey {
     /// `DefId` is really just an interned def-path).
     ///
     /// Note that if `id` is not local to this crate, the result will
-    //  be a non-local `DefPath`.
+    ///  be a non-local `DefPath`.
     pub fn def_path(self, id: DefId) -> hir_map::DefPath {
         if id.is_local() {
             self.hir.def_path(id)
index 9126600e3f65393d2eff900e06bcbd077535be8d..a4466d7d840110f450a7b4e8e959164da13402c3 100644 (file)
@@ -111,6 +111,18 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for ty::SubtypePredicate<'a> {
+    type Lifted = ty::SubtypePredicate<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
+                             -> Option<ty::SubtypePredicate<'tcx>> {
+        tcx.lift(&(self.a, self.b)).map(|(a, b)| ty::SubtypePredicate {
+            a_is_expected: self.a_is_expected,
+            a: a,
+            b: b,
+        })
+    }
+}
+
 impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for ty::OutlivesPredicate<A, B> {
     type Lifted = ty::OutlivesPredicate<A::Lifted, B::Lifted>;
     fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -167,6 +179,9 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             ty::Predicate::Equate(ref binder) => {
                 tcx.lift(binder).map(ty::Predicate::Equate)
             }
+            ty::Predicate::Subtype(ref binder) => {
+                tcx.lift(binder).map(ty::Predicate::Subtype)
+            }
             ty::Predicate::RegionOutlives(ref binder) => {
                 tcx.lift(binder).map(ty::Predicate::RegionOutlives)
             }
@@ -693,6 +708,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 ty::Predicate::Trait(a.fold_with(folder)),
             ty::Predicate::Equate(ref binder) =>
                 ty::Predicate::Equate(binder.fold_with(folder)),
+            ty::Predicate::Subtype(ref binder) =>
+                ty::Predicate::Subtype(binder.fold_with(folder)),
             ty::Predicate::RegionOutlives(ref binder) =>
                 ty::Predicate::RegionOutlives(binder.fold_with(folder)),
             ty::Predicate::TypeOutlives(ref binder) =>
@@ -712,6 +729,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
             ty::Predicate::Trait(ref a) => a.visit_with(visitor),
             ty::Predicate::Equate(ref binder) => binder.visit_with(visitor),
+            ty::Predicate::Subtype(ref binder) => binder.visit_with(visitor),
             ty::Predicate::RegionOutlives(ref binder) => binder.visit_with(visitor),
             ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),
             ty::Predicate::Projection(ref binder) => binder.visit_with(visitor),
@@ -776,8 +794,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 
 impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        ty::EquatePredicate(self.0.fold_with(folder),
-                            self.1.fold_with(folder))
+        ty::EquatePredicate(self.0.fold_with(folder), self.1.fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
@@ -785,6 +802,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        ty::SubtypePredicate {
+            a_is_expected: self.a_is_expected,
+            a: self.a.fold_with(folder),
+            b: self.b.fold_with(folder)
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.a.visit_with(visitor) || self.b.visit_with(visitor)
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         ty::TraitPredicate {
index fd8191303a9a60cb92e9f1bb9bd1340daba448f5..5334ee2835db2325f6bcbf4066069efb6ad7c1a9 100644 (file)
@@ -13,7 +13,7 @@
 use hir::def_id::{DefId, LOCAL_CRATE};
 use hir::map::DefPathData;
 use infer::InferCtxt;
-// use hir::map as hir_map;
+use ich::{StableHashingContext, NodeIdHashingMode};
 use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
 use ty::ParameterEnvironment;
@@ -25,8 +25,8 @@
 use middle::lang_items;
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
-use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult};
-
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+                                           HashStable};
 use std::cell::RefCell;
 use std::cmp;
 use std::hash::Hash;
@@ -187,6 +187,22 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+    /// Creates a hash of the type `Ty` which will be the same no matter what crate
+    /// context it's calculated within. This is used by the `type_id` intrinsic.
+    pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
+        let mut hasher = StableHasher::new();
+        let mut hcx = StableHashingContext::new(self);
+
+        hcx.while_hashing_spans(false, |hcx| {
+            hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+                ty.hash_stable(hcx, &mut hasher);
+            });
+        });
+        hasher.finish()
+    }
+}
+
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
@@ -312,6 +328,7 @@ pub fn required_region_bounds(self,
                     ty::Predicate::Projection(..) |
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::WellFormed(..) |
                     ty::Predicate::ObjectSafe(..) |
                     ty::Predicate::ClosureKind(..) |
@@ -339,14 +356,6 @@ pub fn required_region_bounds(self,
             .collect()
     }
 
-    /// Creates a hash of the type `Ty` which will be the same no matter what crate
-    /// context it's calculated within. This is used by the `type_id` intrinsic.
-    pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
-        let mut hasher = TypeIdHasher::new(self);
-        hasher.visit_ty(ty);
-        hasher.finish()
-    }
-
     /// Calculate the destructor of a given type.
     pub fn calculate_dtor(
         self,
index 8a5bd6862cf4552c099b431fa344c81142dc7876..0b0e8a180cc36800c103ed87ead051ed584c8d0b 100644 (file)
@@ -94,6 +94,10 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
         }
         ty::Predicate::ClosureKind(..) => {
         }
+        ty::Predicate::Subtype(ref data) => {
+            wf.compute(data.skip_binder().a); // (*)
+            wf.compute(data.skip_binder().b); // (*)
+        }
     }
 
     wf.normalize()
@@ -156,6 +160,7 @@ pub fn implied_bounds<'a, 'gcx, 'tcx>(
                 match obligation.predicate {
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::Projection(..) |
                     ty::Predicate::ClosureKind(..) |
                     ty::Predicate::ObjectSafe(..) =>
index 6323f1dc0d4c4a8da2f00a60797851a88b2edbe8..2daf71d95addf67c547871de9fb3e99a56475aea 100644 (file)
@@ -416,6 +416,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::Predicate::Trait(ref a) => write!(f, "{:?}", a),
             ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
+            ty::Predicate::Subtype(ref pair) => write!(f, "{:?}", pair),
             ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
             ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
             ty::Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
@@ -676,6 +677,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Display for ty::Binder<ty::SubtypePredicate<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
+    }
+}
+
 impl<'tcx> fmt::Display for ty::Binder<ty::ProjectionPredicate<'tcx>> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
@@ -897,6 +904,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Display for ty::SubtypePredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} <: {}", self.a, self.b)
+    }
+}
+
 impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "TraitPredicate({:?})",
@@ -949,6 +962,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::Predicate::Trait(ref data) => write!(f, "{}", data),
             ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
+            ty::Predicate::Subtype(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
index 713e656666271a97c32cae318612ddb3af349bdf..ca313622a3afd1928e5f2ffd1210d6a119f0fbc0 100644 (file)
@@ -307,12 +307,12 @@ fn initialization_data_at(&self, loc: Location) -> InitializationData {
         data
     }
 
-    fn create_drop_flag(&mut self, index: MovePathIndex) {
+    fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
         let tcx = self.tcx;
         let patch = &mut self.patch;
         debug!("create_drop_flag({:?})", self.mir.span);
         self.drop_flags.entry(index).or_insert_with(|| {
-            patch.new_temp(tcx.types.bool)
+            patch.new_temp(tcx.types.bool, span)
         });
     }
 
@@ -374,7 +374,7 @@ fn collect_drop_flags(&mut self)
                 debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
                        child, location, path, (maybe_live, maybe_dead));
                 if maybe_live && maybe_dead {
-                    self.create_drop_flag(child)
+                    self.create_drop_flag(child, terminator.source_info.span)
                 }
             });
         }
index 0915c57b588eb1a7c2c33b091682fd4fce4790e7..142286bd834d04d0560d17e53d4fedacf4690b0f 100644 (file)
@@ -22,7 +22,6 @@
 
 use self::InteriorKind::*;
 
-use rustc::dep_graph::DepNode;
 use rustc::hir::map as hir_map;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::cfg;
 use rustc::middle::mem_categorization::ImmutabilityBlame;
 use rustc::middle::region;
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::maps::Providers;
 
 use std::fmt;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
 use syntax::ast;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{DUMMY_SP, MultiSpan, Span};
 use errors::DiagnosticBuilder;
 
 use rustc::hir;
 pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.dep_graph.with_task(DepNode::BorrowCheckKrate, tcx, (), check_crate_task);
-
-    fn check_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
-        tcx.visit_all_bodies_in_krate(|body_owner_def_id, body_id| {
-            tcx.dep_graph.with_task(DepNode::BorrowCheck(body_owner_def_id),
-                                    tcx,
-                                    body_id,
-                                    borrowck_fn);
-        });
-    }
+    tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+        ty::queries::borrowck::get(tcx, DUMMY_SP, body_owner_def_id);
+    });
+}
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        borrowck,
+        ..*providers
+    };
 }
 
 /// Collection of conclusions determined via borrow checker analyses.
@@ -81,11 +81,11 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
     pub move_data: move_data::FlowedMoveData<'a, 'tcx>,
 }
 
-fn borrowck_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, body_id: hir::BodyId) {
-    debug!("borrowck_fn(body_id={:?})", body_id);
+fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
+    debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
 
-    let owner_id = tcx.hir.body_owner(body_id);
-    let owner_def_id = tcx.hir.local_def_id(owner_id);
+    let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap();
+    let body_id = tcx.hir.body_owned_by(owner_id);
     let attributes = tcx.get_attrs(owner_def_id);
     let tables = tcx.item_tables(owner_def_id);
 
index 2047a58f8ed85a24da6f28fd2ae7ae9d64c65d0b..5012969eef9058c4fe298e2ee0dc579bbadd0c47 100644 (file)
@@ -362,31 +362,31 @@ fn add_existing_base_paths(&self, lp: &Rc<LoanPath<'tcx>>,
 
     /// Adds a new move entry for a move of `lp` that occurs at location `id` with kind `kind`.
     pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    lp: Rc<LoanPath<'tcx>>,
+                    orig_lp: Rc<LoanPath<'tcx>>,
                     id: ast::NodeId,
                     kind: MoveKind) {
-        // Moving one union field automatically moves all its fields.
-        if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
-            if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
+        // Moving one union field automatically moves all its fields. Also move siblings of
+        // all parent union fields, moves do not propagate upwards automatically.
+        let mut lp = orig_lp.clone();
+        while let LpExtend(ref base_lp, mutbl, lp_elem) = lp.clone().kind {
+            if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
+                    = (&base_lp.ty.sty, lp_elem) {
                 if adt_def.is_union() {
                     for field in &adt_def.struct_variant().fields {
                         let field = InteriorKind::InteriorField(mc::NamedField(field.name));
-                        let field_ty = if field == interior {
-                            lp.ty
-                        } else {
-                            tcx.types.err // Doesn't matter
-                        };
-                        let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl,
-                                                    LpInterior(opt_variant_id, field));
-                        let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
-                        self.add_move_helper(tcx, sibling_lp, id, kind);
+                        if field != interior {
+                            let sibling_lp_kind =
+                                LpExtend(base_lp.clone(), mutbl, LpInterior(opt_variant_id, field));
+                            let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, tcx.types.err));
+                            self.add_move_helper(tcx, sibling_lp, id, kind);
+                        }
                     }
-                    return;
                 }
             }
+            lp = base_lp.clone();
         }
 
-        self.add_move_helper(tcx, lp.clone(), id, kind);
+        self.add_move_helper(tcx, orig_lp.clone(), id, kind);
     }
 
     fn add_move_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
index d3b22884a3d8c037e6b67c4adfc3636d121e27fc..a1d3357faf56684931ee9e2899c59e93bb665555 100644 (file)
@@ -51,4 +51,6 @@
 
 pub mod graphviz;
 
+pub use borrowck::provide;
+
 __build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS }
index 29fbcb70756ba08adeca9c87caff42d202225183..848e5a076bb9a3fee2b12dad3dbd8b61d8418962 100644 (file)
 use std::mem;
 use std::collections::range::RangeArgument;
 use std::collections::Bound::{Excluded, Included, Unbounded};
+use std::mem::ManuallyDrop;
 
 pub unsafe trait Array {
     type Element;
-    type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
+    type PartialStorage: Unsize<[ManuallyDrop<Self::Element>]>;
     const LEN: usize;
 }
 
@@ -39,6 +40,12 @@ pub unsafe trait Array {
     const LEN: usize = 8;
 }
 
+unsafe impl<T> Array for [T; 32] {
+    type Element = T;
+    type PartialStorage = [ManuallyDrop<T>; 32];
+    const LEN: usize = 32;
+}
+
 pub struct ArrayVec<A: Array> {
     count: usize,
     values: A::PartialStorage
@@ -66,7 +73,7 @@ impl<A: Array> ArrayVec<A> {
     pub fn new() -> Self {
         ArrayVec {
             count: 0,
-            values: Default::default(),
+            values: unsafe { ::std::mem::uninitialized() },
         }
     }
 
@@ -81,7 +88,7 @@ pub unsafe fn set_len(&mut self, len: usize) {
     /// Panics when the stack vector is full.
     pub fn push(&mut self, el: A::Element) {
         let arr = &mut self.values as &mut [ManuallyDrop<_>];
-        arr[self.count] = ManuallyDrop { value: el };
+        arr[self.count] = ManuallyDrop::new(el);
         self.count += 1;
     }
 
@@ -90,8 +97,8 @@ pub fn pop(&mut self) -> Option<A::Element> {
             let arr = &mut self.values as &mut [ManuallyDrop<_>];
             self.count -= 1;
             unsafe {
-                let value = ptr::read(&arr[self.count]);
-                Some(value.value)
+                let value = ptr::read(&*arr[self.count]);
+                Some(value)
             }
         } else {
             None
@@ -210,7 +217,7 @@ impl<A: Array> Iterator for Iter<A> {
     fn next(&mut self) -> Option<A::Element> {
         let arr = &self.store as &[ManuallyDrop<_>];
         unsafe {
-            self.indices.next().map(|i| ptr::read(&arr[i]).value)
+            self.indices.next().map(|i| ptr::read(&*arr[i]))
         }
     }
 
@@ -233,7 +240,7 @@ impl<'a, A: Array> Iterator for Drain<'a, A> {
 
     #[inline]
     fn next(&mut self) -> Option<A::Element> {
-        self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value })
+        self.iter.next().map(|elt| unsafe { ptr::read(&**elt) })
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
@@ -295,25 +302,3 @@ fn into_iter(self) -> Self::IntoIter {
         self.iter_mut()
     }
 }
-
-// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
-#[allow(unions_with_drop_fields)]
-pub union ManuallyDrop<T> {
-    value: T,
-    #[allow(dead_code)]
-    empty: (),
-}
-
-impl<T> ManuallyDrop<T> {
-    fn new() -> ManuallyDrop<T> {
-        ManuallyDrop {
-            empty: ()
-        }
-    }
-}
-
-impl<T> Default for ManuallyDrop<T> {
-    fn default() -> Self {
-        ManuallyDrop::new()
-    }
-}
index 9d97a83f693c32f7cb528def5b49ff3ac47f1178..bdef9fefd41e4ab07535ab83a00c466eac1c5d0f 100644 (file)
@@ -29,16 +29,23 @@ pub struct Blake2bCtx {
     t: [u64; 2],
     c: usize,
     outlen: u16,
-    finalized: bool
+    finalized: bool,
+
+    #[cfg(debug_assertions)]
+    fnv_hash: u64,
 }
 
+#[cfg(debug_assertions)]
 impl ::std::fmt::Debug for Blake2bCtx {
-    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
-        try!(write!(fmt, "hash: "));
-        for v in &self.h {
-            try!(write!(fmt, "{:x}", v));
-        }
-        Ok(())
+    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(fmt, "{:x}", self.fnv_hash)
+    }
+}
+
+#[cfg(not(debug_assertions))]
+impl ::std::fmt::Debug for Blake2bCtx {
+    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(fmt, "Enable debug_assertions() for more info.")
     }
 }
 
@@ -157,6 +164,9 @@ fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx {
         c: 0,
         outlen: outlen as u16,
         finalized: false,
+
+        #[cfg(debug_assertions)]
+        fnv_hash: 0xcbf29ce484222325,
     };
 
     ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64);
@@ -194,6 +204,16 @@ fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) {
         checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy);
         ctx.c += bytes_to_copy;
     }
+
+    #[cfg(debug_assertions)]
+    {
+        // compute additional FNV hash for simpler to read debug output
+        const MAGIC_PRIME: u64 = 0x00000100000001b3;
+
+        for &byte in data {
+            ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME);
+        }
+    }
 }
 
 fn blake2b_final(ctx: &mut Blake2bCtx)
index c1735b4a4ec9a588156757293152deb775fa1129..00c46d992bfd5a05498e6b58b5c84f40b1952a0a 100644 (file)
@@ -39,6 +39,8 @@
 #![feature(conservative_impl_trait)]
 #![feature(discriminant_value)]
 #![feature(specialization)]
+#![feature(manually_drop)]
+#![feature(struct_field_attributes)]
 
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
index a46238309bb46a87e16b16ee72ee1505cbb65b65..3515e5c5ede35a3f9c67fc4692aa33544527f787 100644 (file)
@@ -43,7 +43,16 @@ fn process_obligation(&mut self,
                           obligation: &mut Self::Obligation)
                           -> Result<Option<Vec<Self::Obligation>>, Self::Error>;
 
-    fn process_backedge<'c, I>(&mut self, cycle: I,
+    /// As we do the cycle check, we invoke this callback when we
+    /// encounter an actual cycle. `cycle` is an iterator that starts
+    /// at the start of the cycle in the stack and walks **toward the
+    /// top**.
+    ///
+    /// In other words, if we had O1 which required O2 which required
+    /// O3 which required O1, we would give an iterator yielding O1,
+    /// O2, O3 (O1 is not yielded twice).
+    fn process_backedge<'c, I>(&mut self,
+                               cycle: I,
                                _marker: PhantomData<&'c Self::Obligation>)
         where I: Clone + Iterator<Item=&'c Self::Obligation>;
 }
@@ -239,8 +248,8 @@ fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
                 }
             }
             Entry::Vacant(v) => {
-                debug!("register_obligation_at({:?}, {:?}) - ok",
-                       obligation, parent);
+                debug!("register_obligation_at({:?}, {:?}) - ok, new index is {}",
+                       obligation, parent, self.nodes.len());
                 v.insert(NodeIndex::new(self.nodes.len()));
                 self.cache_list.push(obligation.as_predicate().clone());
                 self.nodes.push(Node::new(parent, obligation));
@@ -376,6 +385,9 @@ fn process_cycles<P>(&mut self, processor: &mut P)
         where P: ObligationProcessor<Obligation=O>
     {
         let mut stack = self.scratch.take().unwrap();
+        debug_assert!(stack.is_empty());
+
+        debug!("process_cycles()");
 
         for index in 0..self.nodes.len() {
             // For rustc-benchmarks/inflate-0.1.0 this state test is extremely
@@ -389,6 +401,9 @@ fn process_cycles<P>(&mut self, processor: &mut P)
             }
         }
 
+        debug!("process_cycles: complete");
+
+        debug_assert!(stack.is_empty());
         self.scratch = Some(stack);
     }
 
@@ -402,21 +417,6 @@ fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>,
             NodeState::OnDfsStack => {
                 let index =
                     stack.iter().rposition(|n| *n == index).unwrap();
-                // I need a Clone closure
-                #[derive(Clone)]
-                struct GetObligation<'a, O: 'a>(&'a [Node<O>]);
-                impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> {
-                    type Output = &'a O;
-                    extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O {
-                        &self.0[*args.0].obligation
-                    }
-                }
-                impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> {
-                    extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O {
-                        &self.0[*args.0].obligation
-                    }
-                }
-
                 processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)),
                                            PhantomData);
             }
@@ -645,3 +645,20 @@ fn new(parent: Option<NodeIndex>, obligation: O) -> Node<O> {
         }
     }
 }
+
+// I need a Clone closure
+#[derive(Clone)]
+struct GetObligation<'a, O: 'a>(&'a [Node<O>]);
+
+impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> {
+    type Output = &'a O;
+    extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O {
+        &self.0[*args.0].obligation
+    }
+}
+
+impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> {
+    extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O {
+        &self.0[*args.0].obligation
+    }
+}
index dc412a0763ef70f196eed9134bfa930f21a40570..95f063976d491018a44cc55c149d40dec931a1ed 100644 (file)
 /// This hasher currently always uses the stable Blake2b algorithm
 /// and allows for variable output lengths through its type
 /// parameter.
-#[derive(Debug)]
 pub struct StableHasher<W> {
     state: Blake2bHasher,
     bytes_hashed: u64,
     width: PhantomData<W>,
 }
 
+impl<W: StableHasherResult> ::std::fmt::Debug for StableHasher<W> {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(f, "{:?}", self.state)
+    }
+}
+
 pub trait StableHasherResult: Sized {
     fn finish(hasher: StableHasher<Self>) -> Self;
 }
index 2bce7faf08cec45b91c9654ed4244b0d64383ef3..2631108aeb5fa3563c6f004d791927b8a2d080c5 100644 (file)
@@ -9,11 +9,14 @@
 // except according to those terms.
 
 use bitvec::BitMatrix;
+use stable_hasher::{HashStable, StableHasher, StableHasherResult};
 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
 use std::cell::RefCell;
 use std::fmt::Debug;
 use std::mem;
 
+
+
 #[derive(Clone)]
 pub struct TransitiveRelation<T: Debug + PartialEq> {
     // List of elements. This is used to map from a T to a usize.  We
@@ -334,6 +337,49 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
     }
 }
 
+impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
+    where T: HashStable<CTX> + PartialEq + Debug
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        // We are assuming here that the relation graph has been built in a
+        // deterministic way and we can just hash it the way it is.
+        let TransitiveRelation {
+            ref elements,
+            ref edges,
+            // "closure" is just a copy of the data above
+            closure: _
+        } = *self;
+
+        elements.hash_stable(hcx, hasher);
+        edges.hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX> HashStable<CTX> for Edge {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let Edge {
+            ref source,
+            ref target,
+        } = *self;
+
+        source.hash_stable(hcx, hasher);
+        target.hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX> HashStable<CTX> for Index {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let Index(idx) = *self;
+        idx.hash_stable(hcx, hasher);
+    }
+}
+
 #[test]
 fn test_one_step() {
     let mut relation = TransitiveRelation::new();
index bdb05d06b0b10646b8b75769abe776043d0d9b7e..6b136d0fa0cbbd425c198fa421f877c2d11367c0 100644 (file)
@@ -35,7 +35,7 @@
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
-use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues,
+use rustc_passes::{ast_validation, no_asm, loops, consts,
                    static_recursion, hir_stats, mir_stats};
 use rustc_const_eval::check_match;
 use super::Compilation;
@@ -891,6 +891,7 @@ macro_rules! try_with_f {
     let mut local_providers = ty::maps::Providers::default();
     mir::provide(&mut local_providers);
     rustc_privacy::provide(&mut local_providers);
+    borrowck::provide(&mut local_providers);
     typeck::provide(&mut local_providers);
     ty::provide(&mut local_providers);
     reachable::provide(&mut local_providers);
@@ -957,10 +958,6 @@ macro_rules! try_with_f {
              "liveness checking",
              || middle::liveness::check_crate(tcx));
 
-        time(time_passes,
-             "rvalue checking",
-             || rvalues::check_crate(tcx));
-
         time(time_passes,
              "MIR dump",
              || mir::mir_map::build_mir_for_crate(tcx));
@@ -976,8 +973,8 @@ macro_rules! try_with_f {
             // in stage 4 below.
             passes.push_hook(box mir::transform::dump_mir::DumpMir);
             passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial"));
-            passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
             passes.push_pass(box mir::transform::type_check::TypeckMir);
+            passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
             passes.push_pass(
                 box mir::transform::simplify_branches::SimplifyBranches::new("initial"));
             passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
@@ -1083,6 +1080,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
          "serialize dep graph",
          || rustc_incremental::save_dep_graph(tcx,
                                               &incremental_hashes_map,
+                                              &translation.metadata.hashes,
                                               translation.link.crate_hash));
     translation
 }
@@ -1142,7 +1140,7 @@ pub fn phase_6_link_output(sess: &Session,
                            outputs: &OutputFilenames) {
     time(sess.time_passes(),
          "linking",
-         || link::link_binary(sess, trans, outputs, &trans.link.crate_name.as_str()));
+         || link::link_binary(sess, trans, outputs, &trans.crate_name.as_str()));
 }
 
 fn escape_dep_filename(filename: &str) -> String {
index c90dde3a5f6e0232694ae37dec7e11e70c91b446..1a892b73aa5d771c86f6f2dd1c09796763647997 100644 (file)
@@ -517,6 +517,16 @@ fn build_controller(&mut self,
             control.make_glob_map = resolve::MakeGlobMap::Yes;
         }
 
+        if sess.print_fuel_crate.is_some() {
+            let old_callback = control.compilation_done.callback;
+            control.compilation_done.callback = box move |state| {
+                old_callback(state);
+                let sess = state.session;
+                println!("Fuel used by {}: {}",
+                    sess.print_fuel_crate.as_ref().unwrap(),
+                    sess.print_fuel.get());
+            }
+        }
         control
     }
 }
index af2416f787ea4669e693fa0162bca977c6ac7ece..44e291a44c7779e4ba1ae72b27514ee610647bfb 100644 (file)
@@ -233,6 +233,7 @@ fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<as
                 hir::ItemStatic(..) |
                 hir::ItemFn(..) |
                 hir::ItemForeignMod(..) |
+                hir::ItemGlobalAsm(..) |
                 hir::ItemTy(..) => None,
 
                 hir::ItemEnum(..) |
index 1b77ead92deb6a4084d6539c7658fa8678af9cbd..9715ace3e2e2e5a6eb43f32d725c98a68ce15c1e 100644 (file)
@@ -35,6 +35,46 @@ pub struct SubDiagnostic {
     pub render_span: Option<RenderSpan>,
 }
 
+#[derive(PartialEq, Eq)]
+pub struct DiagnosticStyledString(pub Vec<StringPart>);
+
+impl DiagnosticStyledString {
+    pub fn new() -> DiagnosticStyledString {
+        DiagnosticStyledString(vec![])
+    }
+    pub fn push_normal<S: Into<String>>(&mut self, t: S) {
+        self.0.push(StringPart::Normal(t.into()));
+    }
+    pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
+        self.0.push(StringPart::Highlighted(t.into()));
+    }
+    pub fn normal<S: Into<String>>(t: S) -> DiagnosticStyledString {
+        DiagnosticStyledString(vec![StringPart::Normal(t.into())])
+    }
+
+    pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
+        DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
+    }
+
+    pub fn content(&self) -> String {
+        self.0.iter().map(|x| x.content()).collect::<String>()
+    }
+}
+
+#[derive(PartialEq, Eq)]
+pub enum StringPart {
+    Normal(String),
+    Highlighted(String),
+}
+
+impl StringPart {
+    pub fn content(&self) -> String {
+        match self {
+            &StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s.to_owned()
+        }
+    }
+}
+
 impl Diagnostic {
     pub fn new(level: Level, message: &str) -> Self {
         Diagnostic::new_with_code(level, None, message)
@@ -81,8 +121,8 @@ pub fn span_label(&mut self, span: Span, label: &fmt::Display)
 
     pub fn note_expected_found(&mut self,
                                label: &fmt::Display,
-                               expected: &fmt::Display,
-                               found: &fmt::Display)
+                               expected: DiagnosticStyledString,
+                               found: DiagnosticStyledString)
                                -> &mut Self
     {
         self.note_expected_found_extra(label, expected, found, &"", &"")
@@ -90,21 +130,29 @@ pub fn note_expected_found(&mut self,
 
     pub fn note_expected_found_extra(&mut self,
                                      label: &fmt::Display,
-                                     expected: &fmt::Display,
-                                     found: &fmt::Display,
+                                     expected: DiagnosticStyledString,
+                                     found: DiagnosticStyledString,
                                      expected_extra: &fmt::Display,
                                      found_extra: &fmt::Display)
                                      -> &mut Self
     {
+        let mut msg: Vec<_> = vec![(format!("expected {} `", label), Style::NoStyle)];
+        msg.extend(expected.0.iter()
+                   .map(|x| match *x {
+                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
+                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
+                   }));
+        msg.push((format!("`{}\n", expected_extra), Style::NoStyle));
+        msg.push((format!("   found {} `", label), Style::NoStyle));
+        msg.extend(found.0.iter()
+                   .map(|x| match *x {
+                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
+                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
+                   }));
+        msg.push((format!("`{}", found_extra), Style::NoStyle));
+
         // For now, just attach these as notes
-        self.highlighted_note(vec![
-            (format!("expected {} `", label), Style::NoStyle),
-            (format!("{}", expected), Style::Highlight),
-            (format!("`{}\n", expected_extra), Style::NoStyle),
-            (format!("   found {} `", label), Style::NoStyle),
-            (format!("{}", found), Style::Highlight),
-            (format!("`{}", found_extra), Style::NoStyle),
-        ]);
+        self.highlighted_note(msg);
         self
     }
 
index 7dfea6b8951b05f2aebd649e338124e57af9fbf6..7b27f13951b61b5babf4bc9c32ab37c71f5d8f10 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 use Diagnostic;
+use DiagnosticStyledString;
+
 use Level;
 use Handler;
 use std::fmt::{self, Debug};
@@ -115,14 +117,14 @@ pub fn emit(&mut self) {
 
     forward!(pub fn note_expected_found(&mut self,
                                         label: &fmt::Display,
-                                        expected: &fmt::Display,
-                                        found: &fmt::Display)
+                                        expected: DiagnosticStyledString,
+                                        found: DiagnosticStyledString)
                                         -> &mut Self);
 
     forward!(pub fn note_expected_found_extra(&mut self,
                                               label: &fmt::Display,
-                                              expected: &fmt::Display,
-                                              found: &fmt::Display,
+                                              expected: DiagnosticStyledString,
+                                              found: DiagnosticStyledString,
                                               expected_extra: &fmt::Display,
                                               found_extra: &fmt::Display)
                                               -> &mut Self);
index 2efdaa57fba36bf68ad45c2f635745574a1b2791..da29e354a7014eeae31e26f438f63fac7dad4d74 100644 (file)
@@ -203,7 +203,7 @@ fn description(&self) -> &str {
     }
 }
 
-pub use diagnostic::{Diagnostic, SubDiagnostic};
+pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, StringPart};
 pub use diagnostic_builder::DiagnosticBuilder;
 
 /// A handler deals with errors; certain errors
index d900907395656d9c140df0839fe0ee52bcab30b9..8a1af5dd08d74d7dfb85dac9ff9d94e5acbbcd9b 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
 use rustc::hir::def_id::DefIndex;
 use rustc::ich::Fingerprint;
+use rustc::middle::cstore::EncodedMetadataHash;
 use std::sync::Arc;
 use rustc_data_structures::fx::FxHashMap;
 
@@ -98,7 +99,7 @@ pub struct SerializedMetadataHashes {
     /// where `X` refers to some item in this crate. That `X` will be
     /// a `DefPathIndex` that gets retracted to the current `DefId`
     /// (matching the one found in this structure).
-    pub hashes: Vec<SerializedMetadataHash>,
+    pub hashes: Vec<EncodedMetadataHash>,
 
     /// For each DefIndex (as it occurs in SerializedMetadataHash), this
     /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so
@@ -112,14 +113,3 @@ pub struct SerializedMetadataHashes {
     /// the DefIndex.
     pub index_map: FxHashMap<DefIndex, DefPathIndex>
 }
-
-/// The hash for some metadata that (when saving) will be exported
-/// from this crate, or which (when importing) was exported by an
-/// upstream crate.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
-pub struct SerializedMetadataHash {
-    pub def_index: DefIndex,
-
-    /// the hash itself, computed by `calculate_item_hash`
-    pub hash: Fingerprint,
-}
index d931f64d579e1a7f254baab3bddce755221dcc12..af5c1f05bd1fcdd82ad0393b6c93b9b46e3cf4cc 100644 (file)
@@ -215,9 +215,11 @@ fn visit_impl_item(&mut self, item: &hir::ImplItem) {
     }
 }
 
-pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  prev_metadata_hashes: &FxHashMap<DefId, Fingerprint>,
-                                  current_metadata_hashes: &FxHashMap<DefId, Fingerprint>) {
+pub fn check_dirty_clean_metadata<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    prev_metadata_hashes: &FxHashMap<DefId, Fingerprint>,
+    current_metadata_hashes: &FxHashMap<DefId, Fingerprint>)
+{
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         return;
     }
@@ -230,7 +232,7 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             current_metadata_hashes: current_metadata_hashes,
             checked_attrs: FxHashSet(),
         };
-        krate.visit_all_item_likes(&mut dirty_clean_visitor);
+        intravisit::walk_crate(&mut dirty_clean_visitor, krate);
 
         let mut all_attrs = FindAllAttrs {
             tcx: tcx,
@@ -246,30 +248,58 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     });
 }
 
-pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> {
+pub struct DirtyCleanMetadataVisitor<'a, 'tcx: 'a, 'm> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     prev_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
     current_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
     checked_attrs: FxHashSet<ast::AttrId>,
 }
 
-impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
+impl<'a, 'tcx, 'm> intravisit::Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+        intravisit::NestedVisitorMap::All(&self.tcx.hir)
+    }
+
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.check_item(item.id, item.span);
+        intravisit::walk_item(self, item);
+    }
 
-        if let hir::ItemEnum(ref def, _) = item.node {
-            for v in &def.variants {
-                self.check_item(v.node.data.id(), v.span);
-            }
+    fn visit_variant_data(&mut self,
+                          variant_data: &'tcx hir::VariantData,
+                          _: ast::Name,
+                          _: &'tcx hir::Generics,
+                          _parent_id: ast::NodeId,
+                          span: Span) {
+        if self.tcx.hir.find(variant_data.id()).is_some() {
+            // VariantData that represent structs or tuples don't have a
+            // separate entry in the HIR map and checking them would error,
+            // so only check if this is an enum or union variant.
+            self.check_item(variant_data.id(), span);
         }
+
+        intravisit::walk_struct_def(self, variant_data);
     }
 
-    fn visit_trait_item(&mut self, item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
         self.check_item(item.id, item.span);
+        intravisit::walk_trait_item(self, item);
     }
 
-    fn visit_impl_item(&mut self, item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
         self.check_item(item.id, item.span);
+        intravisit::walk_impl_item(self, item);
+    }
+
+    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) {
+        self.check_item(i.id, i.span);
+        intravisit::walk_foreign_item(self, i);
+    }
+
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+        self.check_item(s.id, s.span);
+        intravisit::walk_struct_field(self, s);
     }
 }
 
@@ -281,13 +311,15 @@ fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
         for attr in self.tcx.get_attrs(def_id).iter() {
             if attr.check_name(ATTR_DIRTY_METADATA) {
                 if check_config(self.tcx, attr) {
-                    self.checked_attrs.insert(attr.id);
-                    self.assert_state(false, def_id, item_span);
+                    if self.checked_attrs.insert(attr.id) {
+                        self.assert_state(false, def_id, item_span);
+                    }
                 }
             } else if attr.check_name(ATTR_CLEAN_METADATA) {
                 if check_config(self.tcx, attr) {
-                    self.checked_attrs.insert(attr.id);
-                    self.assert_state(true, def_id, item_span);
+                    if self.checked_attrs.insert(attr.id) {
+                        self.assert_state(true, def_id, item_span);
+                    }
                 }
             }
         }
index fe8cf72996e15d8b1359e20a4338c6746f81cc0e..e769641a4cadf2094e42e6fc14fc3004667e014d 100644 (file)
@@ -44,16 +44,18 @@ impl<'q> Predecessors<'q> {
     pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
         let tcx = hcx.tcx;
 
-        let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc ||
-            tcx.sess.opts.debugging_opts.query_dep_graph;
-
         // Find the set of "start nodes". These are nodes that we will
         // possibly query later.
         let is_output = |node: &DepNode<DefId>| -> bool {
             match *node {
                 DepNode::WorkProduct(_) => true,
-                DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(),
-
+                DepNode::MetaData(ref def_id) => {
+                    // We do *not* create dep-nodes for the current crate's
+                    // metadata anymore, just for metadata that we import/read
+                    // from other crates.
+                    debug_assert!(!def_id.is_local());
+                    false
+                }
                 // if -Z query-dep-graph is passed, save more extended data
                 // to enable better unit testing
                 DepNode::TypeckTables(_) |
@@ -75,6 +77,22 @@ pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
                   .or_insert_with(|| hcx.hash(input).unwrap());
         }
 
+        if tcx.sess.opts.debugging_opts.query_dep_graph {
+            // Not all inputs might have been reachable from an output node,
+            // but we still want their hash for our unit tests.
+            let hir_nodes = query.graph.all_nodes().iter().filter_map(|node| {
+                match node.data {
+                    DepNode::Hir(_) => Some(&node.data),
+                    _ => None,
+                }
+            });
+
+            for node in hir_nodes {
+                hashes.entry(node)
+                      .or_insert_with(|| hcx.hash(node).unwrap());
+            }
+        }
+
         let bootstrap_outputs: Vec<&'q DepNode<DefId>> =
             (0 .. graph.len_nodes())
             .map(NodeIndex)
index 1591503865e817a6180a0ea86c884a9cbe3886ed..1864009fbdf21f119b2ff80dec63f02c2118ea19 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
+use rustc::middle::cstore::EncodedMetadataHash;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::graph::{NodeIndex, INCOMING};
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::Encoder;
-use std::hash::Hash;
 use std::io::{self, Cursor, Write};
 use std::fs::{self, File};
 use std::path::PathBuf;
 use super::dirty_clean;
 use super::file_format;
 use super::work_product;
-use calculate_svh::IchHasher;
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 incremental_hashes_map: &IncrementalHashesMap,
+                                metadata_hashes: &[EncodedMetadataHash],
                                 svh: Svh) {
     debug!("save_dep_graph()");
     let _ignore = tcx.dep_graph.in_ignore();
@@ -56,16 +55,16 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let preds = Predecessors::new(&query, &mut hcx);
     let mut current_metadata_hashes = FxHashMap();
 
+    // IMPORTANT: We are saving the metadata hashes *before* the dep-graph,
+    //            since metadata-encoding might add new entries to the
+    //            DefIdDirectory (which is saved in the dep-graph file).
     if sess.opts.debugging_opts.incremental_cc ||
        sess.opts.debugging_opts.query_dep_graph {
-        // IMPORTANT: We are saving the metadata hashes *before* the dep-graph,
-        //            since metadata-encoding might add new entries to the
-        //            DefIdDirectory (which is saved in the dep-graph file).
         save_in(sess,
                 metadata_hash_export_path(sess),
                 |e| encode_metadata_hashes(tcx,
                                            svh,
-                                           &preds,
+                                           metadata_hashes,
                                            &mut builder,
                                            &mut current_metadata_hashes,
                                            e));
@@ -241,80 +240,16 @@ pub fn encode_dep_graph(preds: &Predecessors,
 
 pub fn encode_metadata_hashes(tcx: TyCtxt,
                               svh: Svh,
-                              preds: &Predecessors,
+                              metadata_hashes: &[EncodedMetadataHash],
                               builder: &mut DefIdDirectoryBuilder,
                               current_metadata_hashes: &mut FxHashMap<DefId, Fingerprint>,
                               encoder: &mut Encoder)
                               -> io::Result<()> {
-    // For each `MetaData(X)` node where `X` is local, accumulate a
-    // hash.  These are the metadata items we export. Downstream
-    // crates will want to see a hash that tells them whether we might
-    // have changed the metadata for a given item since they last
-    // compiled.
-    //
-    // (I initially wrote this with an iterator, but it seemed harder to read.)
     let mut serialized_hashes = SerializedMetadataHashes {
-        hashes: vec![],
+        hashes: metadata_hashes.to_vec(),
         index_map: FxHashMap()
     };
 
-    for (index, target) in preds.reduced_graph.all_nodes().iter().enumerate() {
-        let index = NodeIndex(index);
-        let def_id = match *target.data {
-            DepNode::MetaData(def_id) if def_id.is_local() => def_id,
-            _ => continue,
-        };
-
-        // To create the hash for each item `X`, we don't hash the raw
-        // bytes of the metadata (though in principle we
-        // could). Instead, we walk the predecessors of `MetaData(X)`
-        // from the dep-graph. This corresponds to all the inputs that
-        // were read to construct the metadata. To create the hash for
-        // the metadata, we hash (the hash of) all of those inputs.
-        debug!("save: computing metadata hash for {:?}", def_id);
-
-        // Create a vector containing a pair of (source-id, hash).
-        // The source-id is stored as a `DepNode<u64>`, where the u64
-        // is the det. hash of the def-path. This is convenient
-        // because we can sort this to get a stable ordering across
-        // compilations, even if the def-ids themselves have changed.
-        let mut hashes: Vec<(DepNode<u64>, Fingerprint)> =
-            preds.reduced_graph
-                 .depth_traverse(index, INCOMING)
-                 .map(|index| preds.reduced_graph.node_data(index))
-                 .filter(|dep_node| HashContext::is_hashable(dep_node))
-                 .map(|dep_node| {
-                     let hash_dep_node = dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id)))
-                                                 .unwrap();
-                     let hash = preds.hashes[dep_node];
-                     (hash_dep_node, hash)
-                 })
-                 .collect();
-
-        hashes.sort();
-        let mut state = IchHasher::new();
-        hashes.hash(&mut state);
-        let hash = state.finish();
-
-        debug!("save: metadata hash for {:?} is {}", def_id, hash);
-
-        if tcx.sess.opts.debugging_opts.incremental_dump_hash {
-            println!("metadata hash for {:?} is {}", def_id, hash);
-            for pred_index in preds.reduced_graph.depth_traverse(index, INCOMING) {
-                let dep_node = preds.reduced_graph.node_data(pred_index);
-                if HashContext::is_hashable(&dep_node) {
-                    println!("metadata hash for {:?} depends on {:?} with hash {}",
-                             def_id, dep_node, preds.hashes[dep_node]);
-                }
-            }
-        }
-
-        serialized_hashes.hashes.push(SerializedMetadataHash {
-            def_index: def_id.index,
-            hash: hash,
-        });
-    }
-
     if tcx.sess.opts.debugging_opts.query_dep_graph {
         for serialized_hash in &serialized_hashes.hashes {
             let def_id = DefId::local(serialized_hash.def_index);
index 32c9183ece999ff742f7d33f1dd9b0b92fddda20..402166cc13fd933853955fa504921cbc238a62ae 100644 (file)
@@ -507,6 +507,7 @@ pub enum DIBuilder_opaque {}
 
     /// See Module::setModuleInlineAsm.
     pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
+    pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
 
     /// See llvm::LLVMTypeKind::getTypeID.
     pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
index 459132eb9c61394f637b9cd210ec03281c9fbdbf..d9008ce555cc17afa48a0e4924f3dba299450dc9 100644 (file)
 
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 
-use encoder::EncodeContext;
+use index_builder::EntryBuilder;
 use schema::*;
 
 use rustc::hir;
 use rustc::ty;
 
-use rustc_serialize::Encodable;
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
     pub body: Lazy<hir::Body>,
@@ -26,7 +24,14 @@ pub struct Ast<'tcx> {
     pub rvalue_promotable_to_static: bool,
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl_stable_hash_for!(struct Ast<'tcx> {
+    body,
+    tables,
+    nested_bodies,
+    rvalue_promotable_to_static
+});
+
+impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> {
     pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let body = self.tcx.hir.body(body_id);
         let lazy_body = self.lazy(body);
@@ -34,15 +39,12 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let tables = self.tcx.body_tables(body_id);
         let lazy_tables = self.lazy(tables);
 
-        let nested_pos = self.position();
-        let nested_count = {
-            let mut visitor = NestedBodyEncodingVisitor {
-                ecx: self,
-                count: 0,
-            };
-            visitor.visit_body(body);
-            visitor.count
+        let mut visitor = NestedBodyCollector {
+            tcx: self.tcx,
+            bodies_found: Vec::new(),
         };
+        visitor.visit_body(body);
+        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];
@@ -50,27 +52,25 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         self.lazy(&Ast {
             body: lazy_body,
             tables: lazy_tables,
-            nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
+            nested_bodies: lazy_nested_bodies,
             rvalue_promotable_to_static: rvalue_promotable_to_static
         })
     }
 }
 
-struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    ecx: &'a mut EncodeContext<'b, 'tcx>,
-    count: usize,
+struct NestedBodyCollector<'a, 'tcx: 'a> {
+    tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    bodies_found: Vec<&'tcx hir::Body>,
 }
 
-impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
+impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         NestedVisitorMap::None
     }
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
-        let body = self.ecx.tcx.hir.body(body);
-        body.encode(self.ecx).unwrap();
-        self.count += 1;
-
+        let body = self.tcx.hir.body(body);
+        self.bodies_found.push(body);
         self.visit_body(body);
     }
 }
index 04a8b88f8a594a694537722cfda51677330f75f6..a8ee999505e2074e2755a593316c05d8acd591ce 100644 (file)
@@ -600,7 +600,7 @@ fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span:
             Err(err) => self.sess.span_fatal(span, &err),
         };
 
-        let sym = self.sess.generate_derive_registrar_symbol(&root.hash,
+        let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator,
                                                              root.macro_derive_registrar.unwrap());
         let registrar = unsafe {
             let sym = match lib.symbol(&sym) {
@@ -654,7 +654,7 @@ fn register_bang_proc_macro(&mut self,
     /// Look for a plugin registrar. Returns library path, crate
     /// SVH and DefIndex of the registrar function.
     pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
-                                 -> Option<(PathBuf, Svh, DefIndex)> {
+                                 -> Option<(PathBuf, Symbol, DefIndex)> {
         let ekrate = self.read_extension_crate(span, &ExternCrateInfo {
              name: Symbol::intern(name),
              ident: Symbol::intern(name),
@@ -675,7 +675,7 @@ pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
         let root = ekrate.metadata.get_root();
         match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
             (Some(dylib), Some(reg)) => {
-                Some((dylib.to_path_buf(), root.hash, reg))
+                Some((dylib.to_path_buf(), root.disambiguator, reg))
             }
             (None, Some(_)) => {
                 span_err!(self.sess, span, E0457,
index 37984e4c3718fd96231832ea22bae1f8f47e409d..3239dfb937b5e79bd170036a0d232252d159f450 100644 (file)
@@ -14,8 +14,9 @@
 use schema;
 
 use rustc::dep_graph::DepTrackingMapConfig;
-use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
-use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
+use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
+                            ExternCrate, NativeLibrary, LinkMeta,
+                            LinkagePreference, LoadedMacro, EncodedMetadata};
 use rustc::hir::def::{self, Def};
 use rustc::middle::lang_items;
 use rustc::session::Session;
@@ -498,7 +499,8 @@ fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
-                                 reachable: &NodeSet) -> Vec<u8>
+                                 reachable: &NodeSet)
+                                 -> EncodedMetadata
     {
         encoder::encode_metadata(tcx, self, link_meta, reachable)
     }
index cdbecb3ae2e428a2e8535dceafd73eef0d0db7f9..3498be9dfdf3205d9dd7b5e1583fe9c9f4077143 100644 (file)
@@ -429,6 +429,7 @@ fn to_def(&self, did: DefId) -> Option<Def> {
             EntryKind::Trait(_) => Def::Trait(did),
             EntryKind::Enum(..) => Def::Enum(did),
             EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
+            EntryKind::GlobalAsm => Def::GlobalAsm(did),
 
             EntryKind::ForeignMod |
             EntryKind::Impl(_) |
index 38d774992a55111b8d901b75a5d192730f76ba38..0e204695e8f22660ef8c05afd4105a163c7116c5 100644 (file)
@@ -12,8 +12,9 @@
 use index::Index;
 use schema::*;
 
-use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
-use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
+use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
+                            EncodedMetadata, EncodedMetadataHash};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::middle::dependency_format::Linkage;
 use rustc::middle::lang_items;
@@ -42,7 +43,7 @@
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 use rustc::hir::intravisit;
 
-use super::index_builder::{FromId, IndexBuilder, Untracked};
+use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder};
 
 pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder<'a>,
@@ -54,6 +55,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+
+    pub metadata_hashes: Vec<EncodedMetadataHash>,
 }
 
 macro_rules! encoder_methods {
@@ -172,7 +175,7 @@ pub fn lazy<T: Encodable>(&mut self, value: &T) -> Lazy<T> {
         })
     }
 
-    fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
+    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
         where I: IntoIterator<Item = T>,
               T: Encodable
     {
@@ -184,7 +187,7 @@ fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
         })
     }
 
-    fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
+    pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
         where I: IntoIterator<Item = &'b T>,
               T: 'b + Encodable
     {
@@ -233,15 +236,20 @@ fn encode_with_shorthand<T, U, M>(&mut self,
 
         Ok(())
     }
+}
 
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
+        debug!("EntryBuilder::encode_item_variances({:?})", def_id);
         let tcx = self.tcx;
-        self.lazy_seq(tcx.item_variances(def_id).iter().cloned())
+        self.lazy_seq_from_slice(&tcx.item_variances(def_id))
     }
 
     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
         let tcx = self.tcx;
-        self.lazy(&tcx.item_type(def_id))
+        let ty = tcx.item_type(def_id);
+        debug!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id, ty);
+        self.lazy(&ty)
     }
 
     /// Encode data for the given variant of the given ADT. The
@@ -256,6 +264,7 @@ fn encode_enum_variant_info(&mut self,
         let def = tcx.lookup_adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.did;
+        debug!("EntryBuilder::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -302,10 +311,13 @@ fn encode_info_for_mod(&mut self,
                            -> Entry<'tcx> {
         let tcx = self.tcx;
         let def_id = tcx.hir.local_def_id(id);
+        debug!("EntryBuilder::encode_info_for_mod({:?})", def_id);
 
         let data = ModData {
             reexports: match tcx.export_map.get(&id) {
-                Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
+                Some(exports) if *vis == hir::Public => {
+                    self.lazy_seq_from_slice(exports.as_slice())
+                }
                 _ => LazySeq::empty(),
             },
         };
@@ -339,14 +351,14 @@ fn encode_fields(&mut self, adt_def_id: DefId) {
         for (variant_index, variant) in def.variants.iter().enumerate() {
             for (field_index, field) in variant.fields.iter().enumerate() {
                 self.record(field.did,
-                            EncodeContext::encode_field,
+                            EntryBuilder::encode_field,
                             (adt_def_id, Untracked((variant_index, field_index))));
             }
         }
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     /// Encode data for the given field of the given variant of the
     /// given ADT. The indices of the variant/field are untracked:
     /// this is ok because we will have to lookup the adt-def by its
@@ -363,6 +375,8 @@ fn encode_field(&mut self,
         let field = &variant.fields[field_index];
 
         let def_id = field.did;
+        debug!("EntryBuilder::encode_field({:?})", def_id);
+
         let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap();
         let variant_data = tcx.hir.expect_variant_data(variant_id);
 
@@ -387,6 +401,7 @@ fn encode_field(&mut self,
     }
 
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
         let variant = tcx.lookup_adt_def(adt_def_id).struct_variant();
 
@@ -429,16 +444,19 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
     }
 
     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
+        debug!("EntryBuilder::encode_generics({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(tcx.item_generics(def_id))
     }
 
     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
+        debug!("EntryBuilder::encode_predicates({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.item_predicates(def_id))
     }
 
     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
         let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
@@ -521,6 +539,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_impl_item({:?})", def_id);
         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.hir.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
@@ -607,11 +626,13 @@ fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
     }
 
     fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
+        debug!("EntryBuilder::encode_mir({:?})", def_id);
         self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
     }
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
+        debug!("EntryBuilder::encode_inherent_implementations({:?})", def_id);
         match self.tcx.maps.inherent_impls.borrow().get(&def_id) {
             None => LazySeq::empty(),
             Some(implementations) => {
@@ -624,18 +645,19 @@ fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex
     }
 
     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
+        debug!("EntryBuilder::encode_stability({:?})", def_id);
         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
     }
 
     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
+        debug!("EntryBuilder::encode_deprecation({:?})", def_id);
         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
     }
 
     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("encoding info for item at {}",
-               tcx.sess.codemap().span_to_string(item.span));
+        debug!("EntryBuilder::encode_info_for_item({:?})", def_id);
 
         let kind = match item.node {
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
@@ -655,6 +677,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
             }
             hir::ItemForeignMod(_) => EntryKind::ForeignMod,
+            hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
             hir::ItemTy(..) => EntryKind::Type,
             hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
             hir::ItemStruct(ref struct_def, _) => {
@@ -895,6 +918,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
             hir::ItemFn(..) |
             hir::ItemMod(..) |
             hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
             hir::ItemExternCrate(..) |
             hir::ItemUse(..) |
             hir::ItemDefaultImpl(..) |
@@ -907,7 +931,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 let def = self.tcx.lookup_adt_def(def_id);
                 for (i, variant) in def.variants.iter().enumerate() {
                     self.record(variant.did,
-                                EncodeContext::encode_enum_variant_info,
+                                EntryBuilder::encode_enum_variant_info,
                                 (def_id, Untracked(i)));
                 }
             }
@@ -918,7 +942,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 if !struct_def.is_struct() {
                     let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
                     self.record(ctor_def_id,
-                                EncodeContext::encode_struct_ctor,
+                                EntryBuilder::encode_struct_ctor,
                                 (def_id, ctor_def_id));
                 }
             }
@@ -928,14 +952,14 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
             hir::ItemImpl(..) => {
                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(trait_item_def_id,
-                                EncodeContext::encode_info_for_impl_item,
+                                EntryBuilder::encode_info_for_impl_item,
                                 trait_item_def_id);
                 }
             }
             hir::ItemTrait(..) => {
                 for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(item_def_id,
-                                EncodeContext::encode_info_for_trait_item,
+                                EntryBuilder::encode_info_for_trait_item,
                                 item_def_id);
                 }
             }
@@ -943,13 +967,13 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     fn encode_info_for_foreign_item(&mut self,
                                     (def_id, nitem): (DefId, &hir::ForeignItem))
                                     -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("writing foreign item {}", tcx.node_path_str(nitem.id));
+        debug!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id);
 
         let kind = match nitem.node {
             hir::ForeignItemFn(_, ref names, _) => {
@@ -1002,7 +1026,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
             hir::ItemExternCrate(_) |
             hir::ItemUse(..) => (), // ignore these
-            _ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
+            _ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)),
         }
         self.index.encode_addl_info_for_item(item);
     }
@@ -1010,7 +1034,7 @@ fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
         intravisit::walk_foreign_item(self, ni);
         let def_id = self.index.tcx.hir.local_def_id(ni.id);
         self.index.record(def_id,
-                          EncodeContext::encode_info_for_foreign_item,
+                          EntryBuilder::encode_info_for_foreign_item,
                           (def_id, ni));
     }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
@@ -1023,7 +1047,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
     }
     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
         let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
-        self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
+        self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def);
     }
 }
 
@@ -1032,14 +1056,14 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
         for ty_param in &generics.ty_params {
             let def_id = self.tcx.hir.local_def_id(ty_param.id);
             let has_default = Untracked(ty_param.default.is_some());
-            self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default));
+            self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default));
         }
     }
 
     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         if let hir::TyImplTrait(_) = ty.node {
             let def_id = self.tcx.hir.local_def_id(ty.id);
-            self.record(def_id, EncodeContext::encode_info_for_anon_ty, def_id);
+            self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id);
         }
     }
 
@@ -1047,17 +1071,18 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
             hir::ExprClosure(..) => {
                 let def_id = self.tcx.hir.local_def_id(expr.id);
-                self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
+                self.record(def_id, EntryBuilder::encode_info_for_closure, def_id);
             }
             _ => {}
         }
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
     fn encode_info_for_ty_param(&mut self,
                                 (def_id, Untracked(has_default)): (DefId, Untracked<bool>))
                                 -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_ty_param({:?})", def_id);
         let tcx = self.tcx;
         Entry {
             kind: EntryKind::Type,
@@ -1084,6 +1109,7 @@ fn encode_info_for_ty_param(&mut self,
     }
 
     fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id);
         let tcx = self.tcx;
         Entry {
             kind: EntryKind::Type,
@@ -1106,6 +1132,7 @@ fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("EntryBuilder::encode_info_for_closure({:?})", def_id);
         let tcx = self.tcx;
 
         let data = ClosureData {
@@ -1133,11 +1160,20 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
         }
     }
 
+    fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
+        // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
+        //       we really on the HashStable specialization for [Attribute]
+        //       to properly filter things out.
+        self.lazy_seq_from_slice(attrs)
+    }
+}
+
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_items(&mut self) -> Index {
         let krate = self.tcx.hir.krate();
         let mut index = IndexBuilder::new(self);
         index.record(DefId::local(CRATE_DEF_INDEX),
-                     EncodeContext::encode_info_for_mod,
+                     EntryBuilder::encode_info_for_mod,
                      FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
         let mut visitor = EncodeVisitor { index: index };
         krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
@@ -1147,10 +1183,6 @@ fn encode_info_for_items(&mut self) -> Index {
         visitor.index.into_items()
     }
 
-    fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
-        self.lazy_seq_ref(attrs)
-    }
-
     fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
         fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
             // Pull the cnums and name,vers,hash out of cstore
@@ -1298,7 +1330,9 @@ fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreferenc
             None => LazySeq::empty(),
         }
     }
+}
 
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
         let mut i = self.position();
         let crate_deps = self.encode_crate_deps();
@@ -1348,7 +1382,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
         let link_meta = self.link_meta;
         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
         let root = self.lazy(&CrateRoot {
-            name: link_meta.crate_name,
+            name: tcx.crate_name(LOCAL_CRATE),
             triple: tcx.sess.opts.target_triple.clone(),
             hash: link_meta.crate_hash,
             disambiguator: tcx.sess.local_crate_disambiguator(),
@@ -1431,14 +1465,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cstore: &cstore::CStore,
                                  link_meta: &LinkMeta,
                                  exported_symbols: &NodeSet)
-                                 -> Vec<u8> {
+                                 -> EncodedMetadata
+{
     let mut cursor = Cursor::new(vec![]);
     cursor.write_all(METADATA_HEADER).unwrap();
 
     // Will be filed with the root position after encoding everything.
     cursor.write_all(&[0, 0, 0, 0]).unwrap();
 
-    let root = {
+    let (root, metadata_hashes) = {
         let mut ecx = EncodeContext {
             opaque: opaque::Encoder::new(&mut cursor),
             tcx: tcx,
@@ -1448,6 +1483,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
+            metadata_hashes: Vec::new(),
         };
 
         // Encode the rustc version string in a predictable location.
@@ -1455,7 +1491,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Encode all the entries and extra information in the crate,
         // culminating in the `CrateRoot` which points to all of it.
-        ecx.encode_crate_root()
+        let root = ecx.encode_crate_root();
+        (root, ecx.metadata_hashes)
     };
     let mut result = cursor.into_inner();
 
@@ -1467,7 +1504,10 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     result[header + 2] = (pos >> 8) as u8;
     result[header + 3] = (pos >> 0) as u8;
 
-    result
+    EncodedMetadata {
+        raw_data: result,
+        hashes: metadata_hashes,
+    }
 }
 
 pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions {
index a811f72bc956cbe1408c0ff27753d0583ce0f111..01f948866b85081b8ba42889f7bcdf3598d5c270 100644 (file)
 use index::Index;
 use schema::*;
 
-use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::ich::{StableHashingContext, Fingerprint};
+use rustc::middle::cstore::EncodedMetadataHash;
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
 use std::ops::{Deref, DerefMut};
 
+use rustc_data_structures::accumulate_vec::AccumulateVec;
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+use rustc_serialize::Encodable;
+
 /// Builder that can encode new items, adding them into the index.
 /// Item encoding cannot be nested.
 pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
@@ -112,16 +117,45 @@ pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
     /// holds, and that it is therefore not gaining "secret" access to
     /// bits of HIR or other state that would not be trackd by the
     /// content system.
-    pub fn record<DATA>(&mut self,
-                        id: DefId,
-                        op: fn(&mut EncodeContext<'b, 'tcx>, DATA) -> Entry<'tcx>,
-                        data: DATA)
+    pub fn record<'x, DATA>(&'x mut self,
+                            id: DefId,
+                            op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
+                            data: DATA)
         where DATA: DepGraphRead
     {
-        let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
-        data.read(self.tcx);
-        let entry = op(&mut self.ecx, data);
-        self.items.record(id, self.ecx.lazy(&entry));
+        assert!(id.is_local());
+        let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
+
+        // We don't track this since we are explicitly computing the incr. comp.
+        // hashes anyway. In theory we could do some tracking here and use it to
+        // avoid rehashing things (and instead cache the hashes) but it's
+        // unclear whether that would be a win since hashing is cheap enough.
+        let _task = tcx.dep_graph.in_ignore();
+
+        let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph ||
+                           tcx.sess.opts.debugging_opts.incremental_cc) &&
+                           tcx.sess.opts.build_dep_graph();
+
+        let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx;
+        let mut entry_builder = EntryBuilder {
+            tcx: tcx,
+            ecx: ecx,
+            hcx: if compute_ich {
+                Some((StableHashingContext::new(tcx), StableHasher::new()))
+            } else {
+                None
+            }
+        };
+
+        let entry = op(&mut entry_builder, data);
+
+        if let Some((ref mut hcx, ref mut hasher)) = entry_builder.hcx {
+            entry.hash_stable(hcx, hasher);
+        }
+
+        let entry = entry_builder.ecx.lazy(&entry);
+        entry_builder.finish(id);
+        self.items.record(id, entry);
     }
 
     pub fn into_items(self) -> Index {
@@ -223,3 +257,91 @@ fn read(&self, tcx: TyCtxt) {
         tcx.hir.read(self.0);
     }
 }
+
+pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> {
+    pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
+    ecx: &'a mut EncodeContext<'b, 'tcx>,
+    hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher<Fingerprint>)>,
+}
+
+impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
+
+    pub fn finish(self, def_id: DefId) {
+        if let Some((_, hasher)) = self.hcx {
+            let hash = hasher.finish();
+            self.ecx.metadata_hashes.push(EncodedMetadataHash {
+                def_index: def_id.index,
+                hash: hash,
+            });
+        }
+    }
+
+    pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            value.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy(value)
+    }
+
+    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
+        where I: IntoIterator<Item = T>,
+              T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            let iter = iter.into_iter();
+            let (lower_bound, upper_bound) = iter.size_hint();
+
+            if upper_bound == Some(lower_bound) {
+                lower_bound.hash_stable(hcx, hasher);
+                let mut num_items_hashed = 0;
+                let ret = self.ecx.lazy_seq(iter.inspect(|item| {
+                    item.hash_stable(hcx, hasher);
+                    num_items_hashed += 1;
+                }));
+
+                // Sometimes items in a sequence are filtered out without being
+                // hashed (e.g. for &[ast::Attribute]) and this code path cannot
+                // handle that correctly, so we want to make sure we didn't hit
+                // it by accident.
+                if lower_bound != num_items_hashed {
+                    bug!("Hashed a different number of items ({}) than expected ({})",
+                         num_items_hashed,
+                         lower_bound);
+                }
+                debug!("metadata-hash: {:?}", hasher);
+                ret
+            } else {
+                // Collect into a vec so we know the length of the sequence
+                let items: AccumulateVec<[T; 32]> = iter.collect();
+                items.hash_stable(hcx, hasher);
+                debug!("metadata-hash: {:?}", hasher);
+                self.ecx.lazy_seq(items)
+            }
+        } else {
+            self.ecx.lazy_seq(iter)
+        }
+    }
+
+    pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            slice.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy_seq_ref(slice.iter())
+    }
+
+    pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
+        where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
+    {
+        if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
+            slice.hash_stable(hcx, hasher);
+            debug!("metadata-hash: {:?}", hasher);
+        }
+        self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
+    }
+}
index 2fbdb8c0de676dec7f7921e3037e9c6410811c0f..b9e142ac65072e18dd2c256a4a418067700d0553 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(rustc_private)]
 #![feature(specialization)]
 #![feature(staged_api)]
+#![feature(discriminant_value)]
 
 #[macro_use]
 extern crate log;
index abb482a50ebc2621487e53fb43c3af4c5e8f7b73..6cd35f1335ed79ef423a7a25c95efcc284a47de1 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::hir;
 use rustc::hir::def::{self, CtorKind};
 use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::ich::StableHashingContext;
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
 use rustc::middle::lang_items;
 use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
+use std::mem;
+
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
+                                           StableHasherResult};
 
 pub fn rustc_version() -> String {
     format!("rustc {}",
@@ -100,6 +105,15 @@ fn clone(&self) -> Self {
 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
 
+impl<CTX, T> HashStable<CTX> for Lazy<T> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _: &mut CTX,
+                                          _: &mut StableHasher<W>) {
+        // There's nothing to do. Whatever got encoded within this Lazy<>
+        // wrapper has already been hashed.
+    }
+}
+
 /// A sequence of type T referred to by its absolute position
 /// in the metadata and length, and which can be decoded lazily.
 /// The sequence is a single node for the purposes of `Lazy`.
@@ -148,6 +162,15 @@ fn clone(&self) -> Self {
 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
 
+impl<CTX, T> HashStable<CTX> for LazySeq<T> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _: &mut CTX,
+                                          _: &mut StableHasher<W>) {
+        // There's nothing to do. Whatever got encoded within this Lazy<>
+        // wrapper has already been hashed.
+    }
+}
+
 /// Encoding / decoding state for `Lazy` and `LazySeq`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum LazyState {
@@ -219,6 +242,23 @@ pub struct Entry<'tcx> {
     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
 }
 
+impl_stable_hash_for!(struct Entry<'tcx> {
+    kind,
+    visibility,
+    span,
+    attributes,
+    children,
+    stability,
+    deprecation,
+    ty,
+    inherent_impls,
+    variances,
+    generics,
+    predicates,
+    ast,
+    mir
+});
+
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub enum EntryKind<'tcx> {
     Const(u8),
@@ -227,6 +267,7 @@ pub enum EntryKind<'tcx> {
     ForeignImmStatic,
     ForeignMutStatic,
     ForeignMod,
+    GlobalAsm,
     Type,
     Enum(ReprOptions),
     Field,
@@ -246,22 +287,92 @@ pub enum EntryKind<'tcx> {
     AssociatedConst(AssociatedContainer, u8),
 }
 
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for EntryKind<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            EntryKind::ImmStatic        |
+            EntryKind::MutStatic        |
+            EntryKind::ForeignImmStatic |
+            EntryKind::ForeignMutStatic |
+            EntryKind::ForeignMod       |
+            EntryKind::GlobalAsm        |
+            EntryKind::Field |
+            EntryKind::Type => {
+                // Nothing else to hash here.
+            }
+            EntryKind::Const(qualif) => {
+                qualif.hash_stable(hcx, hasher);
+            }
+            EntryKind::Enum(ref repr_options) => {
+                repr_options.hash_stable(hcx, hasher);
+            }
+            EntryKind::Variant(ref variant_data) => {
+                variant_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Struct(ref variant_data, ref repr_options) |
+            EntryKind::Union(ref variant_data, ref repr_options)  => {
+                variant_data.hash_stable(hcx, hasher);
+                repr_options.hash_stable(hcx, hasher);
+            }
+            EntryKind::Fn(ref fn_data) |
+            EntryKind::ForeignFn(ref fn_data) => {
+                fn_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Mod(ref mod_data) => {
+                mod_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::MacroDef(ref macro_def) => {
+                macro_def.hash_stable(hcx, hasher);
+            }
+            EntryKind::Closure(closure_data) => {
+                closure_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Trait(ref trait_data) => {
+                trait_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::DefaultImpl(ref impl_data) |
+            EntryKind::Impl(ref impl_data) => {
+                impl_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::Method(ref method_data) => {
+                method_data.hash_stable(hcx, hasher);
+            }
+            EntryKind::AssociatedType(associated_container) => {
+                associated_container.hash_stable(hcx, hasher);
+            }
+            EntryKind::AssociatedConst(associated_container, qualif) => {
+                associated_container.hash_stable(hcx, hasher);
+                qualif.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
     pub reexports: LazySeq<def::Export>,
 }
 
+impl_stable_hash_for!(struct ModData { reexports });
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct MacroDef {
     pub body: String,
 }
 
+impl_stable_hash_for!(struct MacroDef { body });
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct FnData {
     pub constness: hir::Constness,
     pub arg_names: LazySeq<ast::Name>,
 }
 
+impl_stable_hash_for!(struct FnData { constness, arg_names });
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
@@ -273,6 +384,13 @@ pub struct VariantData<'tcx> {
     pub struct_ctor: Option<DefIndex>,
 }
 
+impl_stable_hash_for!(struct VariantData<'tcx> {
+    ctor_kind,
+    discr,
+    evaluated_discr,
+    struct_ctor
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
@@ -281,6 +399,13 @@ pub struct TraitData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
+impl_stable_hash_for!(struct TraitData<'tcx> {
+    unsafety,
+    paren_sugar,
+    has_default_impl,
+    super_predicates
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
@@ -291,6 +416,14 @@ pub struct ImplData<'tcx> {
     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
 }
 
+impl_stable_hash_for!(struct ImplData<'tcx> {
+    polarity,
+    parent_impl,
+    coerce_unsized_info,
+    trait_ref
+});
+
+
 /// Describes whether the container of an associated item
 /// is a trait or an impl and whether, in a trait, it has
 /// a default, or an in impl, whether it's marked "default".
@@ -302,6 +435,13 @@ pub enum AssociatedContainer {
     ImplFinal,
 }
 
+impl_stable_hash_for!(enum ::schema::AssociatedContainer {
+    TraitRequired,
+    TraitWithDefault,
+    ImplDefault,
+    ImplFinal
+});
+
 impl AssociatedContainer {
     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
         match *self {
@@ -335,9 +475,11 @@ pub struct MethodData {
     pub container: AssociatedContainer,
     pub has_self: bool,
 }
+impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ClosureData<'tcx> {
     pub kind: ty::ClosureKind,
     pub ty: Lazy<ty::PolyFnSig<'tcx>>,
 }
+impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
index 1cd9a1b25bade8c0f1080b61480637d5e50423f2..df2841a66826980d6cd1ae96739c3ed4cba53b05 100644 (file)
@@ -62,7 +62,8 @@ fn expr_as_lvalue(&mut self,
                 let idx = unpack!(block = this.as_operand(block, None, index));
 
                 // bounds check:
-                let (len, lt) = (this.temp(usize_ty.clone()), this.temp(bool_ty));
+                let (len, lt) = (this.temp(usize_ty.clone(), expr_span),
+                                 this.temp(bool_ty, expr_span));
                 this.cfg.push_assign(block, source_info, // len = len(slice)
                                      &len, Rvalue::Len(slice.clone()));
                 this.cfg.push_assign(block, source_info, // lt = idx < len
index 6694107a8d48510bb3991ff74fcc74462e17e6e9..fb547332c5f58b79bffe08dd478bdcc26d9c4a32 100644 (file)
@@ -82,7 +82,7 @@ fn expr_as_rvalue(&mut self,
                     let bool_ty = this.hir.bool_ty();
 
                     let minval = this.minval_literal(expr_span, expr.ty);
-                    let is_min = this.temp(bool_ty);
+                    let is_min = this.temp(bool_ty, expr_span);
 
                     this.cfg.push_assign(block, source_info, &is_min,
                                          Rvalue::BinaryOp(BinOp::Eq, arg.clone(), minval));
@@ -95,7 +95,7 @@ fn expr_as_rvalue(&mut self,
             }
             ExprKind::Box { value, value_extents } => {
                 let value = this.hir.mirror(value);
-                let result = this.temp(expr.ty);
+                let result = this.temp(expr.ty, expr_span);
                 // to start, malloc some memory of suitable type (thus far, uninitialized):
                 this.cfg.push_assign(block, source_info, &result, Rvalue::Box(value.ty));
                 this.in_scope(value_extents, block, |this| {
@@ -260,7 +260,7 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
         let bool_ty = self.hir.bool_ty();
         if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() {
             let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false);
-            let result_value = self.temp(result_tup);
+            let result_value = self.temp(result_tup, span);
 
             self.cfg.push_assign(block, source_info,
                                  &result_value, Rvalue::CheckedBinaryOp(op,
@@ -301,7 +301,7 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
                 };
 
                 // Check for / 0
-                let is_zero = self.temp(bool_ty);
+                let is_zero = self.temp(bool_ty, span);
                 let zero = self.zero_literal(span, ty);
                 self.cfg.push_assign(block, source_info, &is_zero,
                                      Rvalue::BinaryOp(BinOp::Eq, rhs.clone(), zero));
@@ -315,9 +315,9 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
                     let neg_1 = self.neg_1_literal(span, ty);
                     let min = self.minval_literal(span, ty);
 
-                    let is_neg_1 = self.temp(bool_ty);
-                    let is_min   = self.temp(bool_ty);
-                    let of       = self.temp(bool_ty);
+                    let is_neg_1 = self.temp(bool_ty, span);
+                    let is_min   = self.temp(bool_ty, span);
+                    let of       = self.temp(bool_ty, span);
 
                     // this does (rhs == -1) & (lhs == MIN). It could short-circuit instead
 
index 42d9ab4d2bf274dde9f1c82b789c70b325220f0c..e4598b4143871e2bc3a6f059ab7188f61d8c2b83 100644 (file)
@@ -44,8 +44,8 @@ fn expr_as_temp(&mut self,
         }
 
         let expr_ty = expr.ty.clone();
-        let temp = this.temp(expr_ty.clone());
         let expr_span = expr.span;
+        let temp = this.temp(expr_ty.clone(), expr_span);
         let source_info = this.source_info(expr_span);
 
         if expr.temp_lifetime_was_shrunk && this.hir.needs_drop(expr_ty) {
index 7336da654c1840f550e82d5b66ffc125bd7454ac..c03432312b0ab6c4adc235e2a3036603c6f3854b 100644 (file)
@@ -138,7 +138,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
             }
             _ => {
                 let expr_ty = expr.ty;
-                let temp = this.temp(expr.ty.clone());
+                let temp = this.temp(expr.ty.clone(), expr_span);
                 unpack!(block = this.into(&temp, block, expr));
                 unpack!(block = this.build_drop(block, expr_span, temp, expr_ty));
                 block.unit()
index 705eb1f56608e49be2b7fdd1bef2458804f047a8..ddeec1fe6d0bae009c53f07e9896dd31da33f93c 100644 (file)
@@ -710,7 +710,8 @@ fn declare_binding(&mut self,
             mutability: mutability,
             ty: var_ty.clone(),
             name: Some(name),
-            source_info: Some(source_info),
+            source_info: source_info,
+            is_user_variable: true,
         });
         self.var_indices.insert(var_id, var);
 
index f4fdf8ade900a0ba7951491a80889477d00ca4f5..5fece4d6a5d2387aae043ceb46cd070b98ea66e5 100644 (file)
@@ -210,7 +210,7 @@ pub fn perform_test(&mut self,
                 debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}",
                        num_enum_variants, values, variants);
                 let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
-                let discr = self.temp(discr_ty);
+                let discr = self.temp(discr_ty, test.span);
                 self.cfg.push_assign(block, source_info, &discr,
                                      Rvalue::Discriminant(lvalue.clone()));
                 assert_eq!(values.len() + 1, targets.len());
@@ -270,7 +270,7 @@ pub fn perform_test(&mut self,
                     if let ty::TyRef(region, mt) = ty.sty {
                         if let ty::TyArray(_, _) = mt.ty.sty {
                             ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
-                            let val_slice = self.temp(ty);
+                            let val_slice = self.temp(ty, test.span);
                             self.cfg.push_assign(block, source_info, &val_slice,
                                                  Rvalue::Cast(CastKind::Unsize, val, ty));
                             val = Operand::Consume(val_slice);
@@ -285,7 +285,7 @@ pub fn perform_test(&mut self,
                         value: value.clone()
                     });
 
-                    let slice = self.temp(ty);
+                    let slice = self.temp(ty, test.span);
                     self.cfg.push_assign(block, source_info, &slice,
                                          Rvalue::Cast(CastKind::Unsize, array, ty));
                     Operand::Consume(slice)
@@ -304,7 +304,7 @@ pub fn perform_test(&mut self,
                     let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]);
 
                     let bool_ty = self.hir.bool_ty();
-                    let eq_result = self.temp(bool_ty);
+                    let eq_result = self.temp(bool_ty, test.span);
                     let eq_block = self.cfg.start_new_block();
                     let cleanup = self.diverge_cleanup();
                     self.cfg.terminate(block, source_info, TerminatorKind::Call {
@@ -349,7 +349,8 @@ pub fn perform_test(&mut self,
 
             TestKind::Len { len, op } => {
                 let (usize_ty, bool_ty) = (self.hir.usize_ty(), self.hir.bool_ty());
-                let (actual, result) = (self.temp(usize_ty), self.temp(bool_ty));
+                let (actual, result) = (self.temp(usize_ty, test.span),
+                                        self.temp(bool_ty, test.span));
 
                 // actual = len(lvalue)
                 self.cfg.push_assign(block, source_info,
@@ -383,7 +384,7 @@ fn compare(&mut self,
                left: Operand<'tcx>,
                right: Operand<'tcx>) -> BasicBlock {
         let bool_ty = self.hir.bool_ty();
-        let result = self.temp(bool_ty);
+        let result = self.temp(bool_ty, span);
 
         // result = op(left, right)
         let source_info = self.source_info(span);
index 99aa5cb0fa86eb1f5d735cd1b945f4f17d5937a2..35a8b245f2bb64203a7e19e14d8c891015e02821 100644 (file)
@@ -27,8 +27,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     ///
     /// NB: **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
-    pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> {
-        let temp = self.local_decls.push(LocalDecl::new_temp(ty));
+    pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Lvalue<'tcx> {
+        let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
         let lvalue = Lvalue::Local(temp);
         debug!("temp: created temp {:?} with type {:?}",
                lvalue, self.local_decls[temp].ty);
@@ -106,7 +106,7 @@ pub fn push_usize(&mut self,
                       value: u64)
                       -> Lvalue<'tcx> {
         let usize_ty = self.hir.usize_ty();
-        let temp = self.temp(usize_ty);
+        let temp = self.temp(usize_ty, source_info.span);
         self.cfg.push_assign_constant(
             block, source_info, &temp,
             Constant {
index db03a1c68f7156023cde3ad4c0b631b71036fb41..ef3fa23500b34395b9f79ce79fc841beac3d75ad 100644 (file)
@@ -249,7 +249,8 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>,
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
             breakable_scopes: vec![],
-            local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1),
+            local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
+                                                                             span), 1),
             var_indices: NodeMap(),
             unit_temp: None,
             cached_resume_block: None,
@@ -304,8 +305,12 @@ fn args_and_body(&mut self,
             self.local_decls.push(LocalDecl {
                 mutability: Mutability::Not,
                 ty: ty,
-                source_info: None,
+                source_info: SourceInfo {
+                    scope: ARGUMENT_VISIBILITY_SCOPE,
+                    span: pattern.map_or(self.fn_span, |pat| pat.span)
+                },
                 name: name,
+                is_user_variable: false,
             });
         }
 
@@ -341,7 +346,8 @@ fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
             Some(ref tmp) => tmp.clone(),
             None => {
                 let ty = self.hir.unit_ty();
-                let tmp = self.temp(ty);
+                let fn_span = self.fn_span;
+                let tmp = self.temp(ty, fn_span);
                 self.unit_temp = Some(tmp.clone());
                 tmp
             }
index eb16812af9b0225fa5714dcca15928b114e859a1..bb07081fe433b74dab3ccf6ae1fbce3480616218 100644 (file)
@@ -244,6 +244,39 @@ const fn foo(mut x: u8) {
 ```
 "##,
 
+E0161: r##"
+A value was moved. However, its size was not known at compile time, and only
+values of a known size can be moved.
+
+Erroneous code example:
+
+```compile_fail
+#![feature(box_syntax)]
+
+fn main() {
+    let array: &[isize] = &[1, 2, 3];
+    let _x: Box<[isize]> = box *array;
+    // error: cannot move a value of type [isize]: the size of [isize] cannot
+    //        be statically determined
+}
+```
+
+In Rust, you can only move a value when its size is known at compile time.
+
+To work around this restriction, consider "hiding" the value behind a reference:
+either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
+it around as usual. Example:
+
+```
+#![feature(box_syntax)]
+
+fn main() {
+    let array: &[isize] = &[1, 2, 3];
+    let _x: Box<&[isize]> = box array; // ok!
+}
+```
+"##,
+
 E0396: r##"
 The value behind a raw pointer can't be determined at compile-time
 (or even link-time), which means it can't be used in a constant
index 63d20be88feee70eb623fd9c9b8fe13f1e2b7538..0cec84d16a81c44740e5b0399c73351c28f01cd7 100644 (file)
@@ -137,16 +137,20 @@ enum CallKind {
     Direct(DefId),
 }
 
-fn temp_decl(mutability: Mutability, ty: Ty) -> LocalDecl {
-    LocalDecl { mutability, ty, name: None, source_info: None }
+fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
+    LocalDecl {
+        mutability, ty, name: None,
+        source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
+        is_user_variable: false
+    }
 }
 
-fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
+fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
     -> IndexVec<Local, LocalDecl<'tcx>>
 {
-    iter::once(temp_decl(Mutability::Mut, sig.output()))
+    iter::once(temp_decl(Mutability::Mut, sig.output(), span))
         .chain(sig.inputs().iter().map(
-            |ity| temp_decl(Mutability::Not, ity)))
+            |ity| temp_decl(Mutability::Not, ity, span)))
         .collect()
 }
 
@@ -188,7 +192,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
         ),
         IndexVec::new(),
         sig.output(),
-        local_decls_for_sig(&sig),
+        local_decls_for_sig(&sig, span),
         sig.inputs().len(),
         vec![],
         span
@@ -297,7 +301,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 
     debug!("build_call_shim: sig={:?}", sig);
 
-    let mut local_decls = local_decls_for_sig(&sig);
+    let mut local_decls = local_decls_for_sig(&sig, span);
     let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
 
     let rcvr_arg = Local::new(1+0);
@@ -317,7 +321,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                 tcx.mk_ref(re_erased, ty::TypeAndMut {
                     ty: sig.inputs()[0],
                     mutbl: hir::Mutability::MutMutable
-                })
+                }),
+                span
             ));
             statements.push(Statement {
                 source_info: source_info,
@@ -442,7 +447,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
 
     debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);
 
-    let local_decls = local_decls_for_sig(&sig);
+    let local_decls = local_decls_for_sig(&sig, span);
 
     let source_info = SourceInfo {
         span: span,
index 80a9c06f11b287f7ef33ee939fdbb42267fa00de..ac2bdaad24f766a397d2f5c53da0b3bc0bf877f1 100644 (file)
@@ -461,11 +461,8 @@ fn inline_call(&self, callsite: CallSite<'tcx>,
                 for loc in callee_mir.vars_and_temps_iter() {
                     let mut local = callee_mir.local_decls[loc].clone();
 
-                    if let Some(ref mut source_info) = local.source_info {
-                        source_info.scope = scope_map[source_info.scope];
-
-                        source_info.span = callsite.location.span;
-                    }
+                    local.source_info.scope = scope_map[local.source_info.scope];
+                    local.source_info.span = callsite.location.span;
 
                     let idx = caller_mir.local_decls.push(local);
                     local_map.push(idx);
@@ -506,7 +503,7 @@ fn dest_needs_borrow(lval: &Lvalue) -> bool {
 
                     let ty = dest.ty(caller_mir, self.tcx);
 
-                    let temp = LocalDecl::new_temp(ty);
+                    let temp = LocalDecl::new_temp(ty, callsite.location.span);
 
                     let tmp = caller_mir.local_decls.push(temp);
                     let tmp = Lvalue::Local(tmp);
@@ -590,7 +587,7 @@ fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
             arg.deref());
 
         let ty = arg.ty(caller_mir, self.tcx);
-        let ref_tmp = LocalDecl::new_temp(ty);
+        let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
         let ref_tmp = caller_mir.local_decls.push(ref_tmp);
         let ref_tmp = Lvalue::Local(ref_tmp);
 
@@ -611,7 +608,7 @@ fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
 
         let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Consume(ref_tmp), ptr_ty);
 
-        let cast_tmp = LocalDecl::new_temp(ptr_ty);
+        let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
         let cast_tmp = caller_mir.local_decls.push(cast_tmp);
         let cast_tmp = Lvalue::Local(cast_tmp);
 
@@ -645,7 +642,7 @@ fn make_call_args(&self, args: Vec<Operand<'tcx>>,
 
             let ty = arg.ty(caller_mir, tcx);
 
-            let arg_tmp = LocalDecl::new_temp(ty);
+            let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span);
             let arg_tmp = caller_mir.local_decls.push(arg_tmp);
             let arg_tmp = Lvalue::Local(arg_tmp);
 
index 57cf4b1e8b02bf06edaa1cb49310b8e4c5289d40..ed9a0d3809f245886e0aa6e41bee1c7f76ba3d7f 100644 (file)
@@ -208,7 +208,8 @@ fn promote_temp(&mut self, temp: Local) -> Local {
 
         let no_stmts = self.source[loc.block].statements.len();
         let new_temp = self.promoted.local_decls.push(
-            LocalDecl::new_temp(self.source.local_decls[temp].ty));
+            LocalDecl::new_temp(self.source.local_decls[temp].ty,
+                                self.source.local_decls[temp].source_info.span));
 
         debug!("promote({:?} @ {:?}/{:?}, {:?})",
                temp, loc, no_stmts, self.keep_original);
@@ -379,7 +380,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         };
 
         // Declare return pointer local
-        let initial_locals = iter::once(LocalDecl::new_return_pointer(ty)).collect();
+        let initial_locals = iter::once(LocalDecl::new_return_pointer(ty, span))
+            .collect();
 
         let mut promoter = Promoter {
             promoted: Mir::new(
index 8eabe92fb98c005a7a4beec26e456b02e9791f47..1313b24fa74f5eecc5311586c9f12e10f406b51c 100644 (file)
@@ -881,7 +881,7 @@ fn visit_assign(&mut self,
                 // Avoid a generic error for other uses of arguments.
                 if self.qualif.intersects(Qualif::FN_ARGUMENT) {
                     let decl = &self.mir.local_decls[index];
-                    span_err!(self.tcx.sess, decl.source_info.unwrap().span, E0022,
+                    span_err!(self.tcx.sess, decl.source_info.span, E0022,
                               "arguments of constant functions can only \
                                be immutable by-value bindings");
                     return;
index 3d604affbfea9ce0e24f33c5f02069dab9896e46..bfb08de56d8bb899b15509b8f4d849992851bd62 100644 (file)
@@ -24,6 +24,7 @@
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 
 fn mirbug(tcx: TyCtxt, span: Span, msg: &str) {
@@ -87,6 +88,11 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.sanitize_type(rvalue, rval_ty);
     }
 
+    fn visit_local_decl(&mut self, local_decl: &LocalDecl<'tcx>) {
+        self.super_local_decl(local_decl);
+        self.sanitize_type(local_decl, local_decl.ty);
+    }
+
     fn visit_mir(&mut self, mir: &Mir<'tcx>) {
         self.sanitize_type(&"return type", mir.return_ty);
         for local_decl in &mir.local_decls {
@@ -317,6 +323,7 @@ pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fulfillment_cx: traits::FulfillmentContext<'tcx>,
     last_span: Span,
     body_id: ast::NodeId,
+    reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
 }
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
@@ -326,6 +333,7 @@ fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, body_id: ast::NodeId) -> Self {
             fulfillment_cx: traits::FulfillmentContext::new(),
             last_span: DUMMY_SP,
             body_id: body_id,
+            reported_errors: FxHashSet(),
         }
     }
 
@@ -641,9 +649,43 @@ fn assert_iscleanup(&mut self,
         }
     }
 
-    fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
+    fn check_local(&mut self, mir: &Mir<'gcx>, local: Local, local_decl: &LocalDecl<'gcx>) {
+        match mir.local_kind(local) {
+            LocalKind::ReturnPointer | LocalKind::Arg => {
+                // return values of normal functions are required to be
+                // sized by typeck, but return values of ADT constructors are
+                // not because we don't include a `Self: Sized` bounds on them.
+                //
+                // Unbound parts of arguments were never required to be Sized
+                // - maybe we should make that a warning.
+                return
+            }
+            LocalKind::Var | LocalKind::Temp => {}
+        }
+
+        let span = local_decl.source_info.span;
+        let ty = local_decl.ty;
+        if !ty.is_sized(self.tcx().global_tcx(), self.infcx.param_env(), span) {
+            // in current MIR construction, all non-control-flow rvalue
+            // expressions evaluate through `as_temp` or `into` a return
+            // slot or local, so to find all unsized rvalues it is enough
+            // to check all temps, return slots and locals.
+            if let None = self.reported_errors.replace((ty, span)) {
+                span_err!(self.tcx().sess, span, E0161,
+                          "cannot move a value of type {0}: the size of {0} \
+                           cannot be statically determined", ty);
+            }
+        }
+    }
+
+    fn typeck_mir(&mut self, mir: &Mir<'gcx>) {
         self.last_span = mir.span;
         debug!("run_on_mir: {:?}", mir.span);
+
+        for (local, local_decl) in mir.local_decls.iter_enumerated() {
+            self.check_local(mir, local, local_decl);
+        }
+
         for block in mir.basic_blocks() {
             for stmt in &block.statements {
                 if stmt.source_info.span != DUMMY_SP {
@@ -698,16 +740,18 @@ pub fn new() -> Self {
 impl<'tcx> MirPass<'tcx> for TypeckMir {
     fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     src: MirSource, mir: &mut Mir<'tcx>) {
-        debug!("run_pass: {}", tcx.node_path_str(src.item_id()));
+        let item_id = src.item_id();
+        let def_id = tcx.hir.local_def_id(item_id);
+        debug!("run_pass: {}", tcx.item_path_str(def_id));
 
         if tcx.sess.err_count() > 0 {
             // compiling a broken program can obviously result in a
             // broken MIR, so try not to report duplicate errors.
             return;
         }
-        let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id());
+        let param_env = ty::ParameterEnvironment::for_item(tcx, item_id);
         tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
-            let mut checker = TypeChecker::new(&infcx, src.item_id());
+            let mut checker = TypeChecker::new(&infcx, item_id);
             {
                 let mut verifier = TypeVerifier::new(&mut checker, mir);
                 verifier.visit_mir(mir);
index ccbc6700d89c1bc3c314d5d3d8acf9a4434cc299..04a1fc891cf1e582e2ef50d2b4271bf8df16bd6c 100644 (file)
@@ -686,7 +686,7 @@ fn new_block<'a>(&mut self,
     }
 
     fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
-        self.elaborator.patch().new_temp(ty)
+        self.elaborator.patch().new_temp(ty, self.source_info.span)
     }
 
     fn terminator_loc(&mut self, bb: BasicBlock) -> Location {
index 19f240da73059d498b543a087c967581cc98b695..7898d93c22e3b7cec2b167b0a06afa5f30d592fd 100644 (file)
@@ -11,6 +11,7 @@
 use rustc::ty::Ty;
 use rustc::mir::*;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use syntax_pos::Span;
 
 /// This struct represents a patch to MIR, which can add
 /// new statements and basic blocks and patch over block
@@ -92,10 +93,10 @@ pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
         }
     }
 
-    pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
+    pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
         let index = self.next_local;
         self.next_local += 1;
-        self.new_locals.push(LocalDecl::new_temp(ty));
+        self.new_locals.push(LocalDecl::new_temp(ty, span));
         Local::new(index as usize)
     }
 
index ef2bf6e543420a59a962a5d59f15f428715adf5f..b202e1495104e52f82973fe2015940e2d4e8340a 100644 (file)
@@ -196,8 +196,8 @@ fn write_scope_tree(tcx: TyCtxt,
         // User variable types (including the user's name in a comment).
         for local in mir.vars_iter() {
             let var = &mir.local_decls[local];
-            let (name, source_info) = if var.source_info.unwrap().scope == child {
-                (var.name.unwrap(), var.source_info.unwrap())
+            let (name, source_info) = if var.source_info.scope == child {
+                (var.name.unwrap(), var.source_info)
             } else {
                 // Not a variable or not declared in this scope.
                 continue;
index 5f06eadb84a9248f13e6bbf3592423f79b91f68f..036a52d5a3db3491e4ff8a8f1e52bd18b5d200b6 100644 (file)
@@ -82,39 +82,6 @@ struct SomeStruct {
 ```
 "##,
 
-E0161: r##"
-A value was moved. However, its size was not known at compile time, and only
-values of a known size can be moved.
-
-Erroneous code example:
-
-```compile_fail
-#![feature(box_syntax)]
-
-fn main() {
-    let array: &[isize] = &[1, 2, 3];
-    let _x: Box<[isize]> = box *array;
-    // error: cannot move a value of type [isize]: the size of [isize] cannot
-    //        be statically determined
-}
-```
-
-In Rust, you can only move a value when its size is known at compile time.
-
-To work around this restriction, consider "hiding" the value behind a reference:
-either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
-it around as usual. Example:
-
-```
-#![feature(box_syntax)]
-
-fn main() {
-    let array: &[isize] = &[1, 2, 3];
-    let _x: Box<&[isize]> = box array; // ok!
-}
-```
-"##,
-
 E0265: r##"
 This error indicates that a static or constant references itself.
 All statics and constants need to resolve to a value in an acyclic manner.
index 7a465f0ec42392244bb038f8c62ad1dc4c6e76d1..22566c813d86ae4da36bd7ed0994e989a566277a 100644 (file)
@@ -47,5 +47,4 @@
 pub mod loops;
 pub mod mir_stats;
 pub mod no_asm;
-pub mod rvalues;
 pub mod static_recursion;
index 421181c68c4cda90eef45bf85fe12ab59a27e424..2ea235af103788b0f9de6e09b5f3a36b139ffbdd 100644 (file)
@@ -11,7 +11,6 @@
 
 use rustc::session::Session;
 
-use rustc::dep_graph::DepNode;
 use rustc::hir::map::Map;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
@@ -50,7 +49,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
 }
 
 pub fn check_crate(sess: &Session, map: &Map) {
-    let _task = map.dep_graph.in_task(DepNode::CheckLoops);
     let krate = map.krate();
     krate.visit_all_item_likes(&mut CheckLoopVisitor {
         sess: sess,
diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs
deleted file mode 100644 (file)
index c367e71..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Checks that all rvalues in a crate have statically known size. check_crate
-// is the public starting point.
-
-use rustc::dep_graph::DepNode;
-use rustc::middle::expr_use_visitor as euv;
-use rustc::middle::mem_categorization as mc;
-use rustc::ty::{self, TyCtxt};
-use rustc::traits::Reveal;
-
-use rustc::hir;
-use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
-use syntax::ast;
-use syntax_pos::Span;
-
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut rvcx = RvalueContext { tcx: tcx };
-    tcx.visit_all_item_likes_in_krate(DepNode::RvalueCheck, &mut rvcx.as_deep_visitor());
-}
-
-struct RvalueContext<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
-        let body = self.tcx.hir.body(body_id);
-        self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
-            let mut delegate = RvalueContextDelegate {
-                tcx: infcx.tcx,
-                param_env: &infcx.parameter_environment
-            };
-            euv::ExprUseVisitor::new(&mut delegate, &infcx).consume_body(body);
-        });
-        self.visit_body(body);
-    }
-}
-
-struct RvalueContextDelegate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'gcx>,
-}
-
-impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'gcx, 'tcx> {
-    fn consume(&mut self,
-               _: ast::NodeId,
-               span: Span,
-               cmt: mc::cmt<'tcx>,
-               _: euv::ConsumeMode) {
-        debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
-        let ty = self.tcx.lift_to_global(&cmt.ty).unwrap();
-        if !ty.is_sized(self.tcx.global_tcx(), self.param_env, span) {
-            span_err!(self.tcx.sess, span, E0161,
-                "cannot move a value of type {0}: the size of {0} cannot be statically determined",
-                ty);
-        }
-    }
-
-    fn matched_pat(&mut self,
-                   _matched_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::MatchMode) {}
-
-    fn consume_pat(&mut self,
-                   _consume_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::ConsumeMode) {
-    }
-
-    fn borrow(&mut self,
-              _borrow_id: ast::NodeId,
-              _borrow_span: Span,
-              _cmt: mc::cmt,
-              _loan_region: &'tcx ty::Region,
-              _bk: ty::BorrowKind,
-              _loan_cause: euv::LoanCause) {
-    }
-
-    fn decl_without_init(&mut self,
-                         _id: ast::NodeId,
-                         _span: Span) {
-    }
-
-    fn mutate(&mut self,
-              _assignment_id: ast::NodeId,
-              _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
-              _mode: euv::MutateMode) {
-    }
-}
index fc05471ead30b02040f85d148369f7b2f5169d9e..d0bf49b7b337d17fff8910c0f17a82602fdc2962 100644 (file)
@@ -11,7 +11,6 @@
 // This compiler pass detects constants that refer to themselves
 // recursively.
 
-use rustc::dep_graph::DepNode;
 use rustc::hir::map as hir_map;
 use rustc::session::{CompileResult, Session};
 use rustc::hir::def::{Def, CtorKind};
@@ -88,8 +87,6 @@ fn visit_impl_item(&mut self, ii: &'hir hir::ImplItem) {
 }
 
 pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> CompileResult {
-    let _task = hir_map.dep_graph.in_task(DepNode::CheckStaticRecursion);
-
     let mut visitor = CheckCrateVisitor {
         sess: sess,
         hir_map: hir_map,
index e884f3bdbb122f24ff546440dbb7366a84e3a81f..ed49e8a14c8c7b0097825e234b382d52e8f98967 100644 (file)
@@ -100,8 +100,8 @@ fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self {
     fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
         let registrar = self.reader.find_plugin_registrar(span, name);
 
-        if let Some((lib, svh, index)) = registrar {
-            let symbol = self.sess.generate_plugin_registrar_symbol(&svh, index);
+        if let Some((lib, disambiguator, index)) = registrar {
+            let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index);
             let fun = self.dylink_registrar(span, lib, symbol);
             self.plugins.push(PluginRegistrar {
                 fun: fun,
index 300848fe8f25e1eb58ce214863b7c51e5d127bc7..92f7e48b6be4853f23321529f98156d4be2cfe4d 100644 (file)
@@ -160,7 +160,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 self.prev_level
             }
             // Other `pub` items inherit levels from parents
-            _ => {
+            hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
+            hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
+            hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
+            hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
                 if item.vis == hir::Public { self.prev_level } else { None }
             }
         };
@@ -212,7 +215,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     }
                 }
             }
-            _ => {}
+            hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
+            hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
+            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemDefaultImpl(..) => {}
         }
 
         // Mark all items in interfaces of reachable items as reachable
@@ -225,6 +230,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemUse(..) => {}
             // The interface is empty
             hir::ItemDefaultImpl(..) => {}
+            // The interface is empty
+            hir::ItemGlobalAsm(..) => {}
             // Visit everything
             hir::ItemConst(..) | hir::ItemStatic(..) |
             hir::ItemFn(..) | hir::ItemTy(..) => {
@@ -1092,6 +1099,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemMod(..) => {}
             // Checked in resolve
             hir::ItemUse(..) => {}
+            // No subitems
+            hir::ItemGlobalAsm(..) => {}
             // Subitems of these items have inherited publicity
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
             hir::ItemTy(..) => {
index a15431afc164b66e14a5cab7e2bd1a598263e3cd..80f853778c744b50c909f011a589802c7da969fd 100644 (file)
@@ -268,6 +268,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 self.define(parent, ident, TypeNS, imported_binding);
             }
 
+            ItemKind::GlobalAsm(..) => {}
+
             ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
 
             ItemKind::Mod(..) => {
index c94f63329d1ff1ec3c104835d630fac5a8d06722..6ba214f20f98d3b15ad4d603894231f283c40dd8 100644 (file)
@@ -1709,7 +1709,7 @@ fn resolve_item(&mut self, item: &Item) {
                 }
             }
 
-            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => {
+            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_)=> {
                 // do nothing, these are just around to be encoded
             }
 
index 3fd0ce45e3610af20760a82c093a76450a1f6e9d..3e8f7e11b6b432fe9635ab655059349bbe6fbe9f 100644 (file)
@@ -341,6 +341,7 @@ fn process_def_kind(&mut self,
             Def::AssociatedTy(..) |
             Def::AssociatedConst(..) |
             Def::PrimTy(_) |
+            Def::GlobalAsm(_) |
             Def::Err => {
                span_bug!(span,
                          "process_def_kind for unexpected item: {:?}",
index 44615071a56a71eb87e495b03b3907ddb91bcc30..d822f7bea3a30e57891bb1df04f4166bbbf82d0d 100644 (file)
@@ -701,6 +701,7 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
             Def::SelfTy(..) |
             Def::Label(..) |
             Def::Macro(..) |
+            Def::GlobalAsm(..) |
             Def::Err => None,
         }
     }
index 7be80a757ca0166a300c275e96a6ca8f1320cd3b..c4fdc46d030c9e163d2b0a9d8d2f4637f8f5ef58 100644 (file)
@@ -283,7 +283,7 @@ fn homogenous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg>
 
             Layout::Vector { .. } => {
                 Some(Reg {
-                    kind: RegKind::Integer,
+                    kind: RegKind::Vector,
                     size: self.size(ccx)
                 })
             }
index 3e270b7928ebc28127af2ab9d8228ce937286fa3..92cbd004206e7c53fc066821a34cc6418f5b5c58 100644 (file)
@@ -124,3 +124,11 @@ pub fn trans_inline_asm<'a, 'tcx>(
             llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
     }
 }
+
+pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                  ga: &hir::GlobalAsm) {
+    let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
+    unsafe {
+        llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr());
+    }
+}
index 66380079a8b29038538e18324455f68bce83deb4..7468f4ace1b16d760d811f728bd94caafa444925 100644 (file)
@@ -47,7 +47,6 @@
 use flate;
 use syntax::ast;
 use syntax::attr;
-use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 /// The LLVM module name containing crate-metadata. This includes a `.` on
@@ -136,11 +135,8 @@ pub fn find_crate_name(sess: Option<&Session>,
     "rust_out".to_string()
 }
 
-pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap,
-                       name: &str)
-                       -> LinkMeta {
+pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta {
     let r = LinkMeta {
-        crate_name: Symbol::intern(name),
         crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()),
     };
     info!("{:?}", r);
@@ -443,7 +439,10 @@ fn archive_config<'a>(sess: &'a Session,
 }
 
 fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: &Path) {
-    let result = fs::File::create(out_filename).and_then(|mut f| f.write_all(&trans.metadata));
+    let result = fs::File::create(out_filename).and_then(|mut f| {
+        f.write_all(&trans.metadata.raw_data)
+    });
+
     if let Err(e) = result {
         sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
     }
index 23a67ef5046eebec0a527e24a0859eff3f359dce..5d6717272fdf3d000fdea7c56f5a14815f081cc1 100644 (file)
@@ -15,6 +15,7 @@
 use util::nodemap::FxHashMap;
 use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use rustc::session::config;
+use rustc::ty::TyCtxt;
 use syntax::attr;
 use trans_item::TransItem;
 
@@ -64,15 +65,15 @@ pub fn compute_from<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         }
 
         if let Some(id) = scx.sess().derive_registrar_fn.get() {
-            let svh = &scx.link_meta().crate_hash;
             let def_id = scx.tcx().hir.local_def_id(id);
             let idx = def_id.index;
-            let registrar = scx.sess().generate_derive_registrar_symbol(svh, idx);
+            let disambiguator = scx.sess().local_crate_disambiguator();
+            let registrar = scx.sess().generate_derive_registrar_symbol(disambiguator, idx);
             local_crate.push((registrar, SymbolExportLevel::C));
         }
 
         if scx.sess().crate_types.borrow().contains(&config::CrateTypeDylib) {
-            local_crate.push((scx.metadata_symbol_name(),
+            local_crate.push((metadata_symbol_name(scx.tcx()),
                               SymbolExportLevel::Rust));
         }
 
@@ -173,6 +174,12 @@ pub fn for_each_exported_symbol<F>(&self,
     }
 }
 
+pub fn metadata_symbol_name(tcx: TyCtxt) -> String {
+    format!("rust_metadata_{}_{}",
+            tcx.crate_name(LOCAL_CRATE),
+            tcx.crate_disambiguator(LOCAL_CRATE))
+}
+
 pub fn crate_export_threshold(crate_type: config::CrateType)
                                      -> SymbolExportLevel {
     match crate_type {
index 3568c1ba8f4c153257f60af8c860a51a207d4097..8facbd6cc278373299585b0dd64dd5904fcc62f8 100644 (file)
@@ -179,14 +179,14 @@ pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
 
     if let Some(id) = node_id {
         if scx.sess().plugin_registrar_fn.get() == Some(id) {
-            let svh = &scx.link_meta().crate_hash;
             let idx = def_id.index;
-            return scx.sess().generate_plugin_registrar_symbol(svh, idx);
+            let disambiguator = scx.sess().local_crate_disambiguator();
+            return scx.sess().generate_plugin_registrar_symbol(disambiguator, idx);
         }
         if scx.sess().derive_registrar_fn.get() == Some(id) {
-            let svh = &scx.link_meta().crate_hash;
             let idx = def_id.index;
-            return scx.sess().generate_derive_registrar_symbol(svh, idx);
+            let disambiguator = scx.sess().local_crate_disambiguator();
+            return scx.sess().generate_derive_registrar_symbol(disambiguator, idx);
         }
     }
 
index 574b345218be9def7543abb1534eb700aae1e23b..c770bbdb90f72569b46571cb3d18d769d4f395a9 100644 (file)
 use back::link;
 use back::linker::LinkerInfo;
 use back::symbol_export::{self, ExportedSymbols};
-use llvm::{Linkage, ValueRef, Vector, get_param};
+use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
 use llvm;
 use rustc::hir::def_id::LOCAL_CRATE;
 use middle::lang_items::StartFnLangItem;
+use middle::cstore::EncodedMetadata;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
+use rustc::dep_graph::{AssertDepGraphSafe, DepNode};
+use rustc::middle::cstore::LinkMeta;
 use rustc::hir::map as hir_map;
 use rustc::util::common::time;
 use session::config::{self, NoDebugInfo};
@@ -55,7 +57,7 @@
 use common::{type_is_zero_size, val_ty};
 use common;
 use consts;
-use context::{SharedCrateContext, CrateContextList};
+use context::{self, LocalCrateContext, SharedCrateContext, Stats};
 use debuginfo;
 use declare;
 use machine;
@@ -723,10 +725,16 @@ fn contains_null(s: &str) -> bool {
     s.bytes().any(|b| b == 0)
 }
 
-fn write_metadata(cx: &SharedCrateContext,
-                  exported_symbols: &NodeSet) -> Vec<u8> {
+fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                            link_meta: &LinkMeta,
+                            exported_symbols: &NodeSet)
+                            -> (ContextRef, ModuleRef, EncodedMetadata) {
     use flate;
 
+    let (metadata_llcx, metadata_llmod) = unsafe {
+        context::create_context_and_module(tcx.sess, "metadata")
+    };
+
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
     enum MetadataKind {
         None,
@@ -734,7 +742,7 @@ enum MetadataKind {
         Compressed
     }
 
-    let kind = cx.sess().crate_types.borrow().iter().map(|ty| {
+    let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
         match *ty {
             config::CrateTypeExecutable |
             config::CrateTypeStaticlib |
@@ -748,32 +756,35 @@ enum MetadataKind {
     }).max().unwrap();
 
     if kind == MetadataKind::None {
-        return Vec::new();
+        return (metadata_llcx, metadata_llmod, EncodedMetadata {
+            raw_data: vec![],
+            hashes: vec![],
+        });
     }
 
-    let cstore = &cx.tcx().sess.cstore;
-    let metadata = cstore.encode_metadata(cx.tcx(),
-                                          cx.link_meta(),
+    let cstore = &tcx.sess.cstore;
+    let metadata = cstore.encode_metadata(tcx,
+                                          &link_meta,
                                           exported_symbols);
     if kind == MetadataKind::Uncompressed {
-        return metadata;
+        return (metadata_llcx, metadata_llmod, metadata);
     }
 
     assert!(kind == MetadataKind::Compressed);
     let mut compressed = cstore.metadata_encoding_version().to_vec();
-    compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
+    compressed.extend_from_slice(&flate::deflate_bytes(&metadata.raw_data));
 
-    let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed);
-    let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
-    let name = cx.metadata_symbol_name();
+    let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
+    let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
+    let name = symbol_export::metadata_symbol_name(tcx);
     let buf = CString::new(name).unwrap();
     let llglobal = unsafe {
-        llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf.as_ptr())
+        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr())
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
         let section_name =
-            cx.tcx().sess.cstore.metadata_section_name(&cx.sess().target.target);
+            tcx.sess.cstore.metadata_section_name(&tcx.sess.target.target);
         let name = CString::new(section_name).unwrap();
         llvm::LLVMSetSection(llglobal, name.as_ptr());
 
@@ -782,15 +793,16 @@ enum MetadataKind {
         // metadata doesn't get loaded into memory.
         let directive = format!(".section {}", section_name);
         let directive = CString::new(directive).unwrap();
-        llvm::LLVMSetModuleInlineAsm(cx.metadata_llmod(), directive.as_ptr())
+        llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
     }
-    return metadata;
+    return (metadata_llcx, metadata_llmod, metadata);
 }
 
 /// Find any symbols that are defined in one compilation unit, but not declared
 /// in any other compilation unit.  Give these symbols internal linkage.
 fn internalize_symbols<'a, 'tcx>(sess: &Session,
-                                 ccxs: &CrateContextList<'a, 'tcx>,
+                                 scx: &SharedCrateContext<'a, 'tcx>,
+                                 llvm_modules: &[ModuleLlvm],
                                  symbol_map: &SymbolMap<'tcx>,
                                  exported_symbols: &ExportedSymbols) {
     let export_threshold =
@@ -805,7 +817,6 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
         .map(|&(ref name, _)| &name[..])
         .collect::<FxHashSet<&str>>();
 
-    let scx = ccxs.shared();
     let tcx = scx.tcx();
 
     let incr_comp = sess.opts.debugging_opts.incremental.is_some();
@@ -820,8 +831,8 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
         // incremental compilation, we don't need to collect. See below for more
         // information.
         if !incr_comp {
-            for ccx in ccxs.iter_need_trans() {
-                for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
+            for ll in llvm_modules {
+                for val in iter_globals(ll.llmod).chain(iter_functions(ll.llmod)) {
                     let linkage = llvm::LLVMRustGetLinkage(val);
                     // We only care about external declarations (not definitions)
                     // and available_externally definitions.
@@ -857,8 +868,8 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
         // Examine each external definition.  If the definition is not used in
         // any other compilation unit, and is not reachable from other crates,
         // then give it internal linkage.
-        for ccx in ccxs.iter_need_trans() {
-            for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
+        for ll in llvm_modules {
+            for val in iter_globals(ll.llmod).chain(iter_functions(ll.llmod)) {
                 let linkage = llvm::LLVMRustGetLinkage(val);
 
                 let is_externally_visible = (linkage == llvm::Linkage::ExternalLinkage) ||
@@ -917,19 +928,20 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
 // when using MSVC linker.  We do this only for data, as linker can fix up
 // code references on its own.
 // See #26591, #27438
-fn create_imps(cx: &CrateContextList) {
+fn create_imps(sess: &Session,
+               llvm_modules: &[ModuleLlvm]) {
     // The x86 ABI seems to require that leading underscores are added to symbol
     // names, so we need an extra underscore on 32-bit. There's also a leading
     // '\x01' here which disables LLVM's symbol mangling (e.g. no extra
     // underscores added in front).
-    let prefix = if cx.shared().sess().target.target.target_pointer_width == "32" {
+    let prefix = if sess.target.target.target_pointer_width == "32" {
         "\x01__imp__"
     } else {
         "\x01__imp_"
     };
     unsafe {
-        for ccx in cx.iter_need_trans() {
-            let exported: Vec<_> = iter_globals(ccx.llmod())
+        for ll in llvm_modules {
+            let exported: Vec<_> = iter_globals(ll.llmod)
                                        .filter(|&val| {
                                            llvm::LLVMRustGetLinkage(val) ==
                                            llvm::Linkage::ExternalLinkage &&
@@ -937,13 +949,13 @@ fn create_imps(cx: &CrateContextList) {
                                        })
                                        .collect();
 
-            let i8p_ty = Type::i8p(&ccx);
+            let i8p_ty = Type::i8p_llcx(ll.llcx);
             for val in exported {
                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
                 let mut imp_name = prefix.as_bytes().to_vec();
                 imp_name.extend(name.to_bytes());
                 let imp_name = CString::new(imp_name).unwrap();
-                let imp = llvm::LLVMAddGlobal(ccx.llmod(),
+                let imp = llvm::LLVMAddGlobal(ll.llmod,
                                               i8p_ty.to_ref(),
                                               imp_name.as_ptr() as *const _);
                 let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
@@ -1053,28 +1065,28 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // particular items that will be processed.
     let krate = tcx.hir.krate();
 
-    let ty::CrateAnalysis { reachable, name, .. } = analysis;
+    let ty::CrateAnalysis { reachable, .. } = analysis;
     let exported_symbols = find_exported_symbols(tcx, reachable);
 
     let check_overflow = tcx.sess.overflow_checks();
 
-    let link_meta = link::build_link_meta(incremental_hashes_map, &name);
+    let link_meta = link::build_link_meta(incremental_hashes_map);
 
     let shared_ccx = SharedCrateContext::new(tcx,
-                                             link_meta.clone(),
                                              exported_symbols,
                                              check_overflow);
     // Translate the metadata.
-    let metadata = time(tcx.sess.time_passes(), "write metadata", || {
-        write_metadata(&shared_ccx, shared_ccx.exported_symbols())
-    });
+    let (metadata_llcx, metadata_llmod, metadata) =
+        time(tcx.sess.time_passes(), "write metadata", || {
+            write_metadata(tcx, &link_meta, shared_ccx.exported_symbols())
+        });
 
     let metadata_module = ModuleTranslation {
         name: link::METADATA_MODULE_NAME.to_string(),
         symbol_name_hash: 0, // we always rebuild metadata, at least for now
         source: ModuleSource::Translated(ModuleLlvm {
-            llcx: shared_ccx.metadata_llcx(),
-            llmod: shared_ccx.metadata_llmod(),
+            llcx: metadata_llcx,
+            llmod: metadata_llmod,
         }),
     };
     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
@@ -1085,6 +1097,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let empty_exported_symbols = ExportedSymbols::empty();
         let linker_info = LinkerInfo::new(&shared_ccx, &empty_exported_symbols);
         return CrateTranslation {
+            crate_name: tcx.crate_name(LOCAL_CRATE),
             modules: vec![],
             metadata_module: metadata_module,
             link: link_meta,
@@ -1102,73 +1115,78 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let symbol_map = Rc::new(symbol_map);
 
-    let previous_work_products = trans_reuse_previous_work_products(&shared_ccx,
-                                                                    &codegen_units,
-                                                                    &symbol_map);
-
-    let crate_context_list = CrateContextList::new(&shared_ccx,
-                                                   codegen_units,
-                                                   previous_work_products,
-                                                   symbol_map.clone());
-    let modules: Vec<_> = crate_context_list.iter_all()
-        .map(|ccx| {
-            let source = match ccx.previous_work_product() {
-                Some(buf) => ModuleSource::Preexisting(buf.clone()),
-                None => ModuleSource::Translated(ModuleLlvm {
-                    llcx: ccx.llcx(),
-                    llmod: ccx.llmod(),
-                }),
-            };
-
-            ModuleTranslation {
-                name: String::from(ccx.codegen_unit().name()),
-                symbol_name_hash: ccx.codegen_unit()
-                                     .compute_symbol_name_hash(&shared_ccx,
-                                                               &symbol_map),
-                source: source,
-            }
+    let mut all_stats = Stats::default();
+    let modules: Vec<ModuleTranslation> = codegen_units
+        .into_iter()
+        .map(|cgu| {
+            let dep_node = cgu.work_product_dep_node();
+            let (stats, module) =
+                tcx.dep_graph.with_task(dep_node,
+                                        AssertDepGraphSafe(&shared_ccx),
+                                        AssertDepGraphSafe((cgu, symbol_map.clone())),
+                                        module_translation);
+            all_stats.extend(stats);
+            module
         })
         .collect();
 
-    assert_module_sources::assert_module_sources(tcx, &modules);
+    fn module_translation<'a, 'tcx>(
+        scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
+        args: AssertDepGraphSafe<(CodegenUnit<'tcx>, Rc<SymbolMap<'tcx>>)>)
+        -> (Stats, ModuleTranslation)
+    {
+        // FIXME(#40304): We ought to be using the id as a key and some queries, I think.
+        let AssertDepGraphSafe(scx) = scx;
+        let AssertDepGraphSafe((cgu, symbol_map)) = args;
+
+        let cgu_name = String::from(cgu.name());
+        let cgu_id = cgu.work_product_id();
+        let symbol_name_hash = cgu.compute_symbol_name_hash(scx, &symbol_map);
+
+        // Check whether there is a previous work-product we can
+        // re-use.  Not only must the file exist, and the inputs not
+        // be dirty, but the hash of the symbols we will generate must
+        // be the same.
+        let previous_work_product =
+            scx.dep_graph().previous_work_product(&cgu_id).and_then(|work_product| {
+                if work_product.input_hash == symbol_name_hash {
+                    debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
+                    Some(work_product)
+                } else {
+                    if scx.sess().opts.debugging_opts.incremental_info {
+                        println!("incremental: CGU `{}` invalidated because of \
+                                  changed partitioning hash.",
+                                 cgu.name());
+                    }
+                    debug!("trans_reuse_previous_work_products: \
+                            not reusing {:?} because hash changed to {:?}",
+                           work_product, symbol_name_hash);
+                    None
+                }
+            });
 
-    // Instantiate translation items without filling out definitions yet...
-    for ccx in crate_context_list.iter_need_trans() {
-        let dep_node = ccx.codegen_unit().work_product_dep_node();
-        tcx.dep_graph.with_task(dep_node,
-                                ccx,
-                                AssertDepGraphSafe(symbol_map.clone()),
-                                trans_decl_task);
-
-        fn trans_decl_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
-                                     symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>) {
-            // FIXME(#40304): Instead of this, the symbol-map should be an
-            // on-demand thing that we compute.
-            let AssertDepGraphSafe(symbol_map) = symbol_map;
-            let cgu = ccx.codegen_unit();
-            let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
-            for (trans_item, linkage) in trans_items {
+        if let Some(buf) = previous_work_product {
+            // Don't need to translate this module.
+            let module = ModuleTranslation {
+                name: cgu_name,
+                symbol_name_hash,
+                source: ModuleSource::Preexisting(buf.clone())
+            };
+            return (Stats::default(), module);
+        }
+
+        // Instantiate translation items without filling out definitions yet...
+        let lcx = LocalCrateContext::new(scx, cgu, symbol_map.clone());
+        let module = {
+            let ccx = CrateContext::new(scx, &lcx);
+            let trans_items = ccx.codegen_unit()
+                                 .items_in_deterministic_order(ccx.tcx(), &symbol_map);
+            for &(trans_item, linkage) in &trans_items {
                 trans_item.predefine(&ccx, linkage);
             }
-        }
-    }
 
-    // ... and now that we have everything pre-defined, fill out those definitions.
-    for ccx in crate_context_list.iter_need_trans() {
-        let dep_node = ccx.codegen_unit().work_product_dep_node();
-        tcx.dep_graph.with_task(dep_node,
-                                ccx,
-                                AssertDepGraphSafe(symbol_map.clone()),
-                                trans_def_task);
-
-        fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
-                                    symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>) {
-            // FIXME(#40304): Instead of this, the symbol-map should be an
-            // on-demand thing that we compute.
-            let AssertDepGraphSafe(symbol_map) = symbol_map;
-            let cgu = ccx.codegen_unit();
-            let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
-            for (trans_item, _) in trans_items {
+            // ... and now that we have everything pre-defined, fill out those definitions.
+            for &(trans_item, _) in &trans_items {
                 trans_item.define(&ccx);
             }
 
@@ -1206,26 +1224,38 @@ fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
             if ccx.sess().opts.debuginfo != NoDebugInfo {
                 debuginfo::finalize(&ccx);
             }
-        }
+
+            ModuleTranslation {
+                name: cgu_name,
+                symbol_name_hash,
+                source: ModuleSource::Translated(ModuleLlvm {
+                    llcx: ccx.llcx(),
+                    llmod: ccx.llmod(),
+                })
+            }
+        };
+
+        (lcx.into_stats(), module)
     }
 
+    assert_module_sources::assert_module_sources(tcx, &modules);
+
     symbol_names_test::report_symbol_names(&shared_ccx);
 
     if shared_ccx.sess().trans_stats() {
-        let stats = shared_ccx.stats();
         println!("--- trans stats ---");
-        println!("n_glues_created: {}", stats.n_glues_created.get());
-        println!("n_null_glues: {}", stats.n_null_glues.get());
-        println!("n_real_glues: {}", stats.n_real_glues.get());
+        println!("n_glues_created: {}", all_stats.n_glues_created.get());
+        println!("n_null_glues: {}", all_stats.n_null_glues.get());
+        println!("n_real_glues: {}", all_stats.n_real_glues.get());
 
-        println!("n_fns: {}", stats.n_fns.get());
-        println!("n_inlines: {}", stats.n_inlines.get());
-        println!("n_closures: {}", stats.n_closures.get());
+        println!("n_fns: {}", all_stats.n_fns.get());
+        println!("n_inlines: {}", all_stats.n_inlines.get());
+        println!("n_closures: {}", all_stats.n_closures.get());
         println!("fn stats:");
-        stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
+        all_stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
             insns_b.cmp(&insns_a)
         });
-        for tuple in stats.fn_stats.borrow().iter() {
+        for tuple in all_stats.fn_stats.borrow().iter() {
             match *tuple {
                 (ref name, insns) => {
                     println!("{} insns, {}", insns, *name);
@@ -1235,7 +1265,7 @@ fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
     }
 
     if shared_ccx.sess().count_llvm_insns() {
-        for (k, v) in shared_ccx.stats().llvm_insns.borrow().iter() {
+        for (k, v) in all_stats.llvm_insns.borrow().iter() {
             println!("{:7} {}", *v, *k);
         }
     }
@@ -1245,11 +1275,23 @@ fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
     let exported_symbols = ExportedSymbols::compute_from(&shared_ccx,
                                                          &symbol_map);
 
+    // Get the list of llvm modules we created. We'll do a few wacky
+    // transforms on them now.
+
+    let llvm_modules: Vec<_> =
+        modules.iter()
+               .filter_map(|module| match module.source {
+                   ModuleSource::Translated(llvm) => Some(llvm),
+                   _ => None,
+               })
+               .collect();
+
     // Now that we have all symbols that are exported from the CGUs of this
     // crate, we can run the `internalize_symbols` pass.
     time(shared_ccx.sess().time_passes(), "internalize symbols", || {
         internalize_symbols(sess,
-                            &crate_context_list,
+                            &shared_ccx,
+                            &llvm_modules,
                             &symbol_map,
                             &exported_symbols);
     });
@@ -1260,7 +1302,7 @@ fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
 
     if sess.target.target.options.is_like_msvc &&
        sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
-        create_imps(&crate_context_list);
+        create_imps(sess, &llvm_modules);
     }
 
     let linker_info = LinkerInfo::new(&shared_ccx, &exported_symbols);
@@ -1277,6 +1319,7 @@ fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
     });
 
     CrateTranslation {
+        crate_name: tcx.crate_name(LOCAL_CRATE),
         modules: modules,
         metadata_module: metadata_module,
         link: link_meta,
@@ -1475,43 +1518,6 @@ enum Fields<'a> {
     }
 }
 
-/// For each CGU, identify if we can reuse an existing object file (or
-/// maybe other context).
-fn trans_reuse_previous_work_products(scx: &SharedCrateContext,
-                                      codegen_units: &[CodegenUnit],
-                                      symbol_map: &SymbolMap)
-                                      -> Vec<Option<WorkProduct>> {
-    debug!("trans_reuse_previous_work_products()");
-    codegen_units
-        .iter()
-        .map(|cgu| {
-            let id = cgu.work_product_id();
-
-            let hash = cgu.compute_symbol_name_hash(scx, symbol_map);
-
-            debug!("trans_reuse_previous_work_products: id={:?} hash={}", id, hash);
-
-            if let Some(work_product) = scx.dep_graph().previous_work_product(&id) {
-                if work_product.input_hash == hash {
-                    debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
-                    return Some(work_product);
-                } else {
-                    if scx.sess().opts.debugging_opts.incremental_info {
-                        println!("incremental: CGU `{}` invalidated because of \
-                                  changed partitioning hash.",
-                                  cgu.name());
-                    }
-                    debug!("trans_reuse_previous_work_products: \
-                            not reusing {:?} because hash changed to {:?}",
-                           work_product, hash);
-                }
-            }
-
-            None
-        })
-        .collect()
-}
-
 fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
                                                      -> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
     let time_passes = scx.sess().time_passes();
index cbe170d85834cfa527dc845f877153c5dd157c89..2daebf5cf3d6b191efeca18907acf854eb359aff 100644 (file)
@@ -173,14 +173,15 @@ fn reg_component(cls: &[Class], i: &mut usize, size: u64) -> Option<Reg> {
         Class::Sse => {
             let vec_len = 1 + cls[*i+1..].iter().take_while(|&&c| c == Class::SseUp).count();
             *i += vec_len;
-            Some(match size {
-                4 => Reg::f32(),
-                8 => Reg::f64(),
-                _ => {
-                    Reg {
-                        kind: RegKind::Vector,
-                        size: Size::from_bytes(vec_len as u64 * 8)
-                    }
+            Some(if vec_len == 1 {
+                match size {
+                    4 => Reg::f32(),
+                    _ => Reg::f64()
+                }
+            } else {
+                Reg {
+                    kind: RegKind::Vector,
+                    size: Size::from_bytes(vec_len as u64 * 8)
                 }
             })
         }
index 500802a4135d009894d5a6beec787122e910c211..ba2b807d5a01c9496fc7f1967faf00644576a28f 100644 (file)
@@ -349,6 +349,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
 
             collect_neighbours(scx, instance, &mut neighbors);
         }
+        TransItem::GlobalAsm(..) => {
+            recursion_depth_reset = None;
+        }
     }
 
     record_inlining_canditates(scx.tcx(), starting_point, &neighbors[..], inlining_map);
@@ -840,6 +843,12 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                     }
                 }
             }
+            hir::ItemGlobalAsm(..) => {
+                debug!("RootCollector: ItemGlobalAsm({})",
+                       def_id_to_string(self.scx.tcx(),
+                                        self.scx.tcx().hir.local_def_id(item.id)));
+                self.output.push(TransItem::GlobalAsm(item.id));
+            }
             hir::ItemStatic(..) => {
                 debug!("RootCollector: ItemStatic({})",
                        def_id_to_string(self.scx.tcx(),
index 98fbb64fd55407b467c2bf20dbfb85744b563bfe..c3770470bfd056536d620c38affa728d11e11aa7 100644 (file)
@@ -10,9 +10,7 @@
 
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef};
-use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap,
-                       DepTrackingMapConfig, WorkProduct};
-use middle::cstore::LinkMeta;
+use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap, DepTrackingMapConfig};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::traits;
@@ -47,6 +45,7 @@
 use syntax_pos::DUMMY_SP;
 use abi::Abi;
 
+#[derive(Clone, Default)]
 pub struct Stats {
     pub n_glues_created: Cell<usize>,
     pub n_null_glues: Cell<usize>,
@@ -60,19 +59,30 @@ pub struct Stats {
     pub fn_stats: RefCell<Vec<(String, usize)> >,
 }
 
+impl Stats {
+    pub fn extend(&mut self, stats: Stats) {
+        self.n_glues_created.set(self.n_glues_created.get() + stats.n_glues_created.get());
+        self.n_null_glues.set(self.n_null_glues.get() + stats.n_null_glues.get());
+        self.n_real_glues.set(self.n_real_glues.get() + stats.n_real_glues.get());
+        self.n_fns.set(self.n_fns.get() + stats.n_fns.get());
+        self.n_inlines.set(self.n_inlines.get() + stats.n_inlines.get());
+        self.n_closures.set(self.n_closures.get() + stats.n_closures.get());
+        self.n_llvm_insns.set(self.n_llvm_insns.get() + stats.n_llvm_insns.get());
+        self.llvm_insns.borrow_mut().extend(
+            stats.llvm_insns.borrow().iter()
+                                     .map(|(key, value)| (key.clone(), value.clone())));
+        self.fn_stats.borrow_mut().append(&mut *stats.fn_stats.borrow_mut());
+    }
+}
+
 /// The shared portion of a `CrateContext`.  There is one `SharedCrateContext`
 /// per crate.  The data here is shared between all compilation units of the
 /// crate, so it must not contain references to any LLVM data structures
 /// (aside from metadata-related ones).
 pub struct SharedCrateContext<'a, 'tcx: 'a> {
-    metadata_llmod: ModuleRef,
-    metadata_llcx: ContextRef,
-
     exported_symbols: NodeSet,
-    link_meta: LinkMeta,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     empty_param_env: ty::ParameterEnvironment<'tcx>,
-    stats: Stats,
     check_overflow: bool,
 
     use_dll_storage_attrs: bool,
@@ -89,7 +99,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
 pub struct LocalCrateContext<'tcx> {
     llmod: ModuleRef,
     llcx: ContextRef,
-    previous_work_product: Option<WorkProduct>,
+    stats: Stats,
     codegen_unit: CodegenUnit<'tcx>,
     needs_unwind_cleanup_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
     /// Cache instances of monomorphic and polymorphic items
@@ -214,107 +224,23 @@ fn to_dep_node(key: &Self::Key) -> DepNode<DefId> {
     }
 }
 
-/// This list owns a number of LocalCrateContexts and binds them to their common
-/// SharedCrateContext. This type just exists as a convenience, something to
-/// pass around all LocalCrateContexts with and get an iterator over them.
-pub struct CrateContextList<'a, 'tcx: 'a> {
-    shared: &'a SharedCrateContext<'a, 'tcx>,
-    local_ccxs: Vec<LocalCrateContext<'tcx>>,
-}
-
-impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
-    pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
-               codegen_units: Vec<CodegenUnit<'tcx>>,
-               previous_work_products: Vec<Option<WorkProduct>>,
-               symbol_map: Rc<SymbolMap<'tcx>>)
-               -> CrateContextList<'a, 'tcx> {
-        CrateContextList {
-            shared: shared_ccx,
-            local_ccxs: codegen_units.into_iter().zip(previous_work_products).map(|(cgu, wp)| {
-                LocalCrateContext::new(shared_ccx, cgu, wp, symbol_map.clone())
-            }).collect()
-        }
-    }
-
-    /// Iterate over all crate contexts, whether or not they need
-    /// translation.  That is, whether or not a `.o` file is available
-    /// for re-use from a previous incr. comp.).
-    pub fn iter_all<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
-        CrateContextIterator {
-            shared: self.shared,
-            index: 0,
-            local_ccxs: &self.local_ccxs[..],
-            filter_to_previous_work_product_unavail: false,
-        }
-    }
-
-    /// Iterator over all CCX that need translation (cannot reuse results from
-    /// previous incr. comp.).
-    pub fn iter_need_trans<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
-        CrateContextIterator {
-            shared: self.shared,
-            index: 0,
-            local_ccxs: &self.local_ccxs[..],
-            filter_to_previous_work_product_unavail: true,
-        }
-    }
-
-    pub fn shared(&self) -> &'a SharedCrateContext<'a, 'tcx> {
-        self.shared
-    }
-}
-
 /// A CrateContext value binds together one LocalCrateContext with the
 /// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
 /// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
 pub struct CrateContext<'a, 'tcx: 'a> {
     shared: &'a SharedCrateContext<'a, 'tcx>,
-    local_ccxs: &'a [LocalCrateContext<'tcx>],
-    /// The index of `local` in `local_ccxs`.  This is used in
-    /// `maybe_iter(true)` to identify the original `LocalCrateContext`.
-    index: usize,
+    local_ccx: &'a LocalCrateContext<'tcx>,
 }
 
-impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
-}
-
-pub struct CrateContextIterator<'a, 'tcx: 'a> {
-    shared: &'a SharedCrateContext<'a, 'tcx>,
-    local_ccxs: &'a [LocalCrateContext<'tcx>],
-    index: usize,
-
-    /// if true, only return results where `previous_work_product` is none
-    filter_to_previous_work_product_unavail: bool,
+impl<'a, 'tcx> CrateContext<'a, 'tcx> {
+    pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
+               local_ccx: &'a LocalCrateContext<'tcx>)
+               -> Self {
+        CrateContext { shared, local_ccx }
+    }
 }
 
-impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
-    type Item = CrateContext<'a, 'tcx>;
-
-    fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> {
-        loop {
-            if self.index >= self.local_ccxs.len() {
-                return None;
-            }
-
-            let index = self.index;
-            self.index += 1;
-
-            let ccx = CrateContext {
-                shared: self.shared,
-                index: index,
-                local_ccxs: self.local_ccxs,
-            };
-
-            if
-                self.filter_to_previous_work_product_unavail &&
-                ccx.previous_work_product().is_some()
-            {
-                continue;
-            }
-
-            return Some(ccx);
-        }
-    }
+impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
 }
 
 pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
@@ -347,7 +273,7 @@ pub fn is_pie_binary(sess: &Session) -> bool {
     !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
 }
 
-unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
+pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
     let llcx = llvm::LLVMContextCreate();
     let mod_name = CString::new(mod_name).unwrap();
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
@@ -405,14 +331,9 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
 
 impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
     pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-               link_meta: LinkMeta,
                exported_symbols: NodeSet,
                check_overflow: bool)
                -> SharedCrateContext<'b, 'tcx> {
-        let (metadata_llcx, metadata_llmod) = unsafe {
-            create_context_and_module(&tcx.sess, "metadata")
-        };
-
         // An interesting part of Windows which MSVC forces our hand on (and
         // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
         // attributes in LLVM IR as well as native dependencies (in C these
@@ -459,23 +380,9 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
         let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
 
         SharedCrateContext {
-            metadata_llmod: metadata_llmod,
-            metadata_llcx: metadata_llcx,
             exported_symbols: exported_symbols,
-            link_meta: link_meta,
             empty_param_env: tcx.empty_parameter_environment(),
             tcx: tcx,
-            stats: Stats {
-                n_glues_created: Cell::new(0),
-                n_null_glues: Cell::new(0),
-                n_real_glues: Cell::new(0),
-                n_fns: Cell::new(0),
-                n_inlines: Cell::new(0),
-                n_closures: Cell::new(0),
-                n_llvm_insns: Cell::new(0),
-                llvm_insns: RefCell::new(FxHashMap()),
-                fn_stats: RefCell::new(Vec::new()),
-            },
             check_overflow: check_overflow,
             use_dll_storage_attrs: use_dll_storage_attrs,
             translation_items: RefCell::new(FxHashSet()),
@@ -492,14 +399,6 @@ pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
         ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP)
     }
 
-    pub fn metadata_llmod(&self) -> ModuleRef {
-        self.metadata_llmod
-    }
-
-    pub fn metadata_llcx(&self) -> ContextRef {
-        self.metadata_llcx
-    }
-
     pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
         &self.exported_symbols
     }
@@ -512,10 +411,6 @@ pub fn project_cache(&self) -> &RefCell<DepTrackingMap<ProjectionCache<'tcx>>> {
         &self.project_cache
     }
 
-    pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
-        &self.link_meta
-    }
-
     pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.tcx
     }
@@ -528,10 +423,6 @@ pub fn dep_graph<'a>(&'a self) -> &'a DepGraph {
         &self.tcx.dep_graph
     }
 
-    pub fn stats<'a>(&'a self) -> &'a Stats {
-        &self.stats
-    }
-
     pub fn use_dll_storage_attrs(&self) -> bool {
         self.use_dll_storage_attrs
     }
@@ -539,20 +430,13 @@ pub fn use_dll_storage_attrs(&self) -> bool {
     pub fn translation_items(&self) -> &RefCell<FxHashSet<TransItem<'tcx>>> {
         &self.translation_items
     }
-
-    pub fn metadata_symbol_name(&self) -> String {
-        format!("rust_metadata_{}_{}",
-                self.link_meta().crate_name,
-                self.link_meta().crate_hash)
-    }
 }
 
 impl<'tcx> LocalCrateContext<'tcx> {
-    fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
-               codegen_unit: CodegenUnit<'tcx>,
-               previous_work_product: Option<WorkProduct>,
-               symbol_map: Rc<SymbolMap<'tcx>>)
-           -> LocalCrateContext<'tcx> {
+    pub fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
+                   codegen_unit: CodegenUnit<'tcx>,
+                   symbol_map: Rc<SymbolMap<'tcx>>)
+                   -> LocalCrateContext<'tcx> {
         unsafe {
             // Append ".rs" to LLVM module identifier.
             //
@@ -578,7 +462,7 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
             let local_ccx = LocalCrateContext {
                 llmod: llmod,
                 llcx: llcx,
-                previous_work_product: previous_work_product,
+                stats: Stats::default(),
                 codegen_unit: codegen_unit,
                 needs_unwind_cleanup_cache: RefCell::new(FxHashMap()),
                 instances: RefCell::new(FxHashMap()),
@@ -647,10 +531,13 @@ fn dummy_ccx<'a>(shared: &'a SharedCrateContext<'a, 'tcx>,
         assert!(local_ccxs.len() == 1);
         CrateContext {
             shared: shared,
-            index: 0,
-            local_ccxs: local_ccxs
+            local_ccx: &local_ccxs[0]
         }
     }
+
+    pub fn into_stats(self) -> Stats {
+        self.stats
+    }
 }
 
 impl<'b, 'tcx> CrateContext<'b, 'tcx> {
@@ -659,7 +546,7 @@ pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> {
     }
 
     fn local(&self) -> &'b LocalCrateContext<'tcx> {
-        &self.local_ccxs[self.index]
+        self.local_ccx
     }
 
     pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
@@ -688,10 +575,6 @@ pub fn llcx(&self) -> ContextRef {
         self.local().llcx
     }
 
-    pub fn previous_work_product(&self) -> Option<&WorkProduct> {
-        self.local().previous_work_product.as_ref()
-    }
-
     pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
         &self.local().codegen_unit
     }
@@ -700,14 +583,6 @@ pub fn td(&self) -> llvm::TargetDataRef {
         unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
     }
 
-    pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
-        &self.shared.exported_symbols
-    }
-
-    pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
-        &self.shared.link_meta
-    }
-
     pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FxHashMap<Ty<'tcx>, bool>> {
         &self.local().needs_unwind_cleanup_cache
     }
@@ -777,7 +652,7 @@ pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, String>>
     }
 
     pub fn stats<'a>(&'a self) -> &'a Stats {
-        &self.shared.stats
+        &self.local().stats
     }
 
     pub fn int_type(&self) -> Type {
index c6f8ba7b6dc78d79c5fdcb2f7955e086c24c1b27..3d074c31c8a32f23c215dbb061b25330083272e3 100644 (file)
@@ -65,7 +65,7 @@ pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &Function
     let mut has_variables = BitVector::new(mir.visibility_scopes.len());
     for var in mir.vars_iter() {
         let decl = &mir.local_decls[var];
-        has_variables.insert(decl.source_info.unwrap().scope.index());
+        has_variables.insert(decl.source_info.scope.index());
     }
 
     // Instantiate all scopes.
index ccb693aa41f4c4a5e8ac78ad33b5d6a1d86e4046..1f4756a94ea33518b14740dd227ed339e2eb455c 100644 (file)
@@ -26,7 +26,7 @@
                       DICompositeType, DILexicalBlock, DIFlags};
 
 use rustc::hir::def::CtorKind;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::fold::TypeVisitor;
 use rustc::ty::subst::Substs;
 use rustc::ty::util::TypeIdHasher;
@@ -784,7 +784,8 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
     };
 
     debug!("compile_unit_metadata: {:?}", compile_unit_name);
-    let producer = format!("rustc version {}",
+    // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
+    let producer = format!("clang LLVM (rustc version {})",
                            (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
 
     let compile_unit_name = compile_unit_name.as_ptr();
@@ -809,7 +810,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
     };
 
     fn fallback_path(scc: &SharedCrateContext) -> CString {
-        CString::new(scc.link_meta().crate_name.to_string()).unwrap()
+        CString::new(scc.tcx().crate_name(LOCAL_CRATE).to_string()).unwrap()
     }
 }
 
index ceff96a39b2c982a04bc8233028aa67357506961..0a873767d935997b5601dc2495c263a41955c37e 100644 (file)
@@ -37,7 +37,7 @@ pub fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
     // visible). It might better to use the `exported_items` set from
     // `driver::CrateAnalysis` in the future, but (atm) this set is not
     // available in the translation pass.
-    !cx.exported_symbols().contains(&node_id)
+    !cx.shared().exported_symbols().contains(&node_id)
 }
 
 #[allow(non_snake_case)]
index 5e7d612d17f82e21eb12904140b5b21cabaa9b36..7077eade61182af2387119e8dd0801d8e3b48062 100644 (file)
@@ -16,7 +16,7 @@
 use llvm::{ValueRef};
 use abi::{Abi, FnType};
 use adt;
-use mir::lvalue::LvalueRef;
+use mir::lvalue::{LvalueRef, Alignment};
 use base::*;
 use common::*;
 use declare;
@@ -36,8 +36,6 @@
 use std::cmp::Ordering;
 use std::iter;
 
-use mir::lvalue::Alignment;
-
 fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
     let llvm_name = match name {
         "sqrtf32" => "llvm.sqrt.f32",
@@ -188,7 +186,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             C_nil(ccx)
         }
         // Effectively no-ops
-        "uninit" | "forget" => {
+        "uninit" => {
             C_nil(ccx)
         }
         "needs_drop" => {
@@ -622,7 +620,10 @@ fn modify_as_needed<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
 
                     for i in 0..elems.len() {
                         let val = bcx.extract_value(val, i);
-                        bcx.store(val, bcx.struct_gep(llresult, i), None);
+                        let lval = LvalueRef::new_sized_ty(llresult, ret_ty,
+                                                           Alignment::AbiAligned);
+                        let (dest, align) = lval.trans_field_ptr(bcx, i);
+                        bcx.store(val, dest, align.to_align());
                     }
                     C_nil(ccx)
                 }
index 5c3b17c889760bba085ae4ec87ce9719b991c0d3..abda358bc4f87c8d36d3c05255f3eade1e302b88 100644 (file)
@@ -40,6 +40,7 @@
 #![feature(conservative_impl_trait)]
 
 use rustc::dep_graph::WorkProduct;
+use syntax_pos::symbol::Symbol;
 
 extern crate flate;
 extern crate libc;
@@ -165,10 +166,11 @@ unsafe impl Send for ModuleTranslation { }
 unsafe impl Sync for ModuleTranslation { }
 
 pub struct CrateTranslation {
+    pub crate_name: Symbol,
     pub modules: Vec<ModuleTranslation>,
     pub metadata_module: ModuleTranslation,
     pub link: middle::cstore::LinkMeta,
-    pub metadata: Vec<u8>,
+    pub metadata: middle::cstore::EncodedMetadata,
     pub exported_symbols: back::symbol_export::ExportedSymbols,
     pub no_builtins: bool,
     pub windows_subsystem: Option<String>,
index a3968650043ba41a5b29accdf68f238e4c7dc209..889f9dc4cded5880f85a9c2171a7b24e708d350c 100644 (file)
@@ -19,7 +19,6 @@
 use rustc::mir::traversal;
 use common;
 use super::MirContext;
-use super::rvalue;
 
 pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
     let mir = mircx.mir;
@@ -93,7 +92,7 @@ fn visit_assign(&mut self,
 
         if let mir::Lvalue::Local(index) = *lvalue {
             self.mark_assigned(index);
-            if !rvalue::rvalue_creates_operand(rvalue) {
+            if !self.cx.rvalue_creates_operand(rvalue) {
                 self.mark_as_lvalue(index);
             }
         } else {
index c8d15d28708f4e3b9a8b926bc272afd174e9c778..3d8c5085462a8c55150feca10016cb3db3dccfe2 100644 (file)
 use libc::c_uint;
 use llvm::{self, ValueRef, BasicBlockRef};
 use llvm::debuginfo::DIScope;
-use rustc::ty;
+use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutTyper};
 use rustc::mir::{self, Mir};
 use rustc::mir::tcx::LvalueTy;
 use rustc::ty::subst::Substs;
 use rustc::infer::TransNormalize;
-use rustc::ty::TypeFoldable;
 use session::config::FullDebugInfo;
 use base;
 use builder::Builder;
-use common::{self, CrateContext, C_null, Funclet};
+use common::{self, CrateContext, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::{self, Instance};
 use abi::FnType;
@@ -171,23 +170,12 @@ enum LocalRef<'tcx> {
 
 impl<'tcx> LocalRef<'tcx> {
     fn new_operand<'a>(ccx: &CrateContext<'a, 'tcx>,
-                         ty: ty::Ty<'tcx>) -> LocalRef<'tcx> {
+                       ty: Ty<'tcx>) -> LocalRef<'tcx> {
         if common::type_is_zero_size(ccx, ty) {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
             // we need something in the operand.
-            let llty = type_of::type_of(ccx, ty);
-            let val = if common::type_is_imm_pair(ccx, ty) {
-                let fields = llty.field_types();
-                OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
-            } else {
-                OperandValue::Immediate(C_null(llty))
-            };
-            let op = OperandRef {
-                val: val,
-                ty: ty
-            };
-            LocalRef::Operand(Some(op))
+            LocalRef::Operand(Some(OperandRef::new_zst(ccx, ty)))
         } else {
             LocalRef::Operand(None)
         }
@@ -207,15 +195,17 @@ pub fn trans_mir<'a, 'tcx: 'a>(
     debug!("fn_ty: {:?}", fn_ty);
     let debug_context =
         debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir);
-    let bcx = Builder::new_block(ccx, llfn, "entry-block");
+    let bcx = Builder::new_block(ccx, llfn, "start");
 
     let cleanup_kinds = analyze::cleanup_kinds(&mir);
 
-    // Allocate a `Block` for every basic block
+    // Allocate a `Block` for every basic block, except
+    // the start block, if nothing loops back to it.
+    let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
     let block_bcxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
         mir.basic_blocks().indices().map(|bb| {
-            if bb == mir::START_BLOCK {
-                bcx.build_sibling_block("start").llbb()
+            if bb == mir::START_BLOCK && !reentrant_start_block {
+                bcx.llbb()
             } else {
                 bcx.build_sibling_block(&format!("{:?}", bb)).llbb()
             }
@@ -255,8 +245,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
 
             if let Some(name) = decl.name {
                 // User variable
-                let source_info = decl.source_info.unwrap();
-                let debug_scope = mircx.scopes[source_info.scope];
+                let debug_scope = mircx.scopes[decl.source_info.scope];
                 let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
 
                 if !lvalue_locals.contains(local.index()) && !dbg {
@@ -268,7 +257,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
                 assert!(!ty.has_erasable_regions());
                 let lvalue = LvalueRef::alloca(&bcx, ty, &name.as_str());
                 if dbg {
-                    let (scope, span) = mircx.debug_loc(source_info);
+                    let (scope, span) = mircx.debug_loc(decl.source_info);
                     declare_local(&bcx, &mircx.debug_context, name, ty, scope,
                         VariableAccess::DirectVariable { alloca: lvalue.llval },
                         VariableKind::LocalVariable, span);
@@ -302,9 +291,10 @@ pub fn trans_mir<'a, 'tcx: 'a>(
             .collect()
     };
 
-    // Branch to the START block
-    let start_bcx = mircx.blocks[mir::START_BLOCK];
-    bcx.br(start_bcx);
+    // Branch to the START block, if it's not the entry block.
+    if reentrant_start_block {
+        bcx.br(mircx.blocks[mir::START_BLOCK]);
+    }
 
     // Up until here, IR instructions for this function have explicitly not been annotated with
     // source code location, so we don't step into call setup code. From here on, source location
@@ -386,7 +376,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
 
             let lvalue = LvalueRef::alloca(bcx, arg_ty, &format!("arg{}", arg_index));
             for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
-                let dst = bcx.struct_gep(lvalue.llval, i);
+                let (dst, _) = lvalue.trans_field_ptr(bcx, i);
                 let arg = &mircx.fn_ty.args[idx];
                 idx += 1;
                 if common::type_is_fat_ptr(bcx.ccx, tupled_arg_ty) {
index 771a88238b2b73a66cbcdb319bebbf97e9ce5c98..c31142323c85f56f8514978e701f82d548b85ee6 100644 (file)
@@ -16,7 +16,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 
 use base;
-use common;
+use common::{self, CrateContext, C_null};
 use builder::Builder;
 use value::Value;
 use type_of;
@@ -79,6 +79,22 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl<'a, 'tcx> OperandRef<'tcx> {
+    pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
+                   ty: Ty<'tcx>) -> OperandRef<'tcx> {
+        assert!(common::type_is_zero_size(ccx, ty));
+        let llty = type_of::type_of(ccx, ty);
+        let val = if common::type_is_imm_pair(ccx, ty) {
+            let fields = llty.field_types();
+            OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
+        } else {
+            OperandValue::Immediate(C_null(llty))
+        };
+        OperandRef {
+            val: val,
+            ty: ty
+        }
+    }
+
     /// Asserts that this operand refers to a scalar and returns
     /// a reference to its value.
     pub fn immediate(self) -> ValueRef {
index 8f7cb914c47354294c7342dbe17b88e577c02eb2..aa41720d717a7268a979ccd7c8b3a955e6eae572 100644 (file)
@@ -158,7 +158,7 @@ pub fn trans_rvalue(&mut self,
             }
 
             _ => {
-                assert!(rvalue_creates_operand(rvalue));
+                assert!(self.rvalue_creates_operand(rvalue));
                 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
                 self.store_operand(&bcx, dest.llval, dest.alignment.to_align(), temp);
                 bcx
@@ -171,7 +171,7 @@ pub fn trans_rvalue_operand(&mut self,
                                 rvalue: &mir::Rvalue<'tcx>)
                                 -> (Builder<'a, 'tcx>, OperandRef<'tcx>)
     {
-        assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
+        assert!(self.rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
 
         match *rvalue {
             mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
@@ -466,8 +466,10 @@ pub fn trans_rvalue_operand(&mut self,
             }
             mir::Rvalue::Repeat(..) |
             mir::Rvalue::Aggregate(..) => {
-                bug!("cannot generate operand from rvalue {:?}", rvalue);
-
+                // According to `rvalue_creates_operand`, only ZST
+                // aggregate rvalues are allowed to be operands.
+                let ty = rvalue.ty(self.mir, self.ccx.tcx());
+                (bcx, OperandRef::new_zst(self.ccx, self.monomorphize(&ty)))
             }
         }
     }
@@ -650,26 +652,29 @@ pub fn trans_scalar_checked_binop(&mut self,
 
         OperandValue::Pair(val, of)
     }
-}
 
-pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
-    match *rvalue {
-        mir::Rvalue::Ref(..) |
-        mir::Rvalue::Len(..) |
-        mir::Rvalue::Cast(..) | // (*)
-        mir::Rvalue::BinaryOp(..) |
-        mir::Rvalue::CheckedBinaryOp(..) |
-        mir::Rvalue::UnaryOp(..) |
-        mir::Rvalue::Discriminant(..) |
-        mir::Rvalue::Box(..) |
-        mir::Rvalue::Use(..) => // (*)
-            true,
-        mir::Rvalue::Repeat(..) |
-        mir::Rvalue::Aggregate(..) =>
-            false,
-    }
+    pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
+        match *rvalue {
+            mir::Rvalue::Ref(..) |
+            mir::Rvalue::Len(..) |
+            mir::Rvalue::Cast(..) | // (*)
+            mir::Rvalue::BinaryOp(..) |
+            mir::Rvalue::CheckedBinaryOp(..) |
+            mir::Rvalue::UnaryOp(..) |
+            mir::Rvalue::Discriminant(..) |
+            mir::Rvalue::Box(..) |
+            mir::Rvalue::Use(..) => // (*)
+                true,
+            mir::Rvalue::Repeat(..) |
+            mir::Rvalue::Aggregate(..) => {
+                let ty = rvalue.ty(self.mir, self.ccx.tcx());
+                let ty = self.monomorphize(&ty);
+                common::type_is_zero_size(self.ccx, ty)
+            }
+        }
 
-    // (*) this is only true if the type is suitable
+        // (*) this is only true if the type is suitable
+    }
 }
 
 #[derive(Copy, Clone)]
index 90ce40cfbcf8fa3f27f3f33cbeb781baca05ab39..4973181202eeddcea8a787e66e53b42cecaba165 100644 (file)
@@ -185,15 +185,16 @@ pub fn compute_symbol_name_hash(&self,
             symbol_name.len().hash(&mut state);
             symbol_name.hash(&mut state);
             let exported = match item {
-               TransItem::Fn(ref instance) => {
-                   let node_id =
-                       scx.tcx().hir.as_local_node_id(instance.def_id());
+                TransItem::Fn(ref instance) => {
+                    let node_id =
+                        scx.tcx().hir.as_local_node_id(instance.def_id());
                     node_id.map(|node_id| exported_symbols.contains(&node_id))
-                           .unwrap_or(false)
-               }
-               TransItem::Static(node_id) => {
+                        .unwrap_or(false)
+                }
+                TransItem::Static(node_id) => {
                     exported_symbols.contains(&node_id)
-               }
+                }
+                TransItem::GlobalAsm(..) => true,
             };
             exported.hash(&mut state);
         }
@@ -243,7 +244,9 @@ fn local_node_id(tcx: TyCtxt, trans_item: TransItem) -> Option<NodeId> {
                 TransItem::Fn(instance) => {
                     tcx.hir.as_local_node_id(instance.def_id())
                 }
-                TransItem::Static(node_id) => Some(node_id),
+                TransItem::Static(node_id) | TransItem::GlobalAsm(node_id) => {
+                    Some(node_id)
+                }
             }
         }
     }
@@ -338,7 +341,8 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
                 None => {
                     match trans_item {
                         TransItem::Fn(..) |
-                        TransItem::Static(..) => llvm::ExternalLinkage,
+                        TransItem::Static(..) |
+                        TransItem::GlobalAsm(..) => llvm::ExternalLinkage,
                     }
                 }
             };
@@ -483,7 +487,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't
 
             Some(def_id)
         }
-        TransItem::Static(node_id) => Some(tcx.hir.local_def_id(node_id)),
+        TransItem::Static(node_id) |
+        TransItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
     }
 }
 
index 1b48e131b720a2c5e5a3b01c5e7597cbd524c235..36c3981e3a6f240c2b78538f8a8e03a4ac8ed4c4 100644 (file)
@@ -99,7 +99,10 @@ fn get_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 TransItem::Fn(Instance { def, .. }) => {
                     tcx.hir.as_local_node_id(def.def_id())
                 }
-                TransItem::Static(node_id) => Some(node_id),
+                TransItem::Static(node_id) |
+                TransItem::GlobalAsm(node_id) => {
+                    Some(node_id)
+                }
             }.map(|node_id| {
                 tcx.hir.span(node_id)
             })
index 410e3f30be731eb0622e0a659030f04215094612..f5556bb8382f6540f58bea55168ad96429475e56 100644 (file)
@@ -14,6 +14,7 @@
 //! item-path. This is used for unit testing the code that generates
 //! paths etc in all kinds of annoying scenarios.
 
+use asm;
 use attributes;
 use base;
 use consts;
@@ -38,7 +39,8 @@
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum TransItem<'tcx> {
     Fn(Instance<'tcx>),
-    Static(NodeId)
+    Static(NodeId),
+    GlobalAsm(NodeId),
 }
 
 /// Describes how a translation item will be instantiated in object files.
@@ -89,6 +91,14 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
                     span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
                 }
             }
+            TransItem::GlobalAsm(node_id) => {
+                let item = ccx.tcx().hir.expect_item(node_id);
+                if let hir::ItemGlobalAsm(ref ga) = item.node {
+                    asm::trans_global_asm(ccx, ga);
+                } else {
+                    span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
+                }
+            }
             TransItem::Fn(instance) => {
                 let _task = ccx.tcx().dep_graph.in_task(
                     DepNode::TransCrateItem(instance.def_id())); // (*)
@@ -123,6 +133,7 @@ pub fn predefine(&self,
             TransItem::Fn(instance) => {
                 TransItem::predefine_fn(ccx, instance, linkage, &symbol_name);
             }
+            TransItem::GlobalAsm(..) => {}
         }
 
         debug!("END PREDEFINING '{} ({})' in cgu {}",
@@ -185,6 +196,10 @@ pub fn compute_symbol_name(&self,
                 let def_id = scx.tcx().hir.local_def_id(node_id);
                 symbol_names::symbol_name(Instance::mono(scx.tcx(), def_id), scx)
             }
+            TransItem::GlobalAsm(node_id) => {
+                let def_id = scx.tcx().hir.local_def_id(node_id);
+                format!("global_asm_{:?}", def_id)
+            }
         }
     }
 
@@ -202,6 +217,7 @@ pub fn instantiation_mode(&self,
                 }
             }
             TransItem::Static(..) => InstantiationMode::GloballyShared,
+            TransItem::GlobalAsm(..) => InstantiationMode::GloballyShared,
         }
     }
 
@@ -210,7 +226,8 @@ pub fn is_generic_fn(&self) -> bool {
             TransItem::Fn(ref instance) => {
                 instance.substs.types().next().is_some()
             }
-            TransItem::Static(..)   => false,
+            TransItem::Static(..) |
+            TransItem::GlobalAsm(..) => false,
         }
     }
 
@@ -218,6 +235,7 @@ pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Link
         let def_id = match *self {
             TransItem::Fn(ref instance) => instance.def_id(),
             TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
+            TransItem::GlobalAsm(..) => return None,
         };
 
         let attributes = tcx.get_attrs(def_id);
@@ -249,6 +267,9 @@ pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
                 let instance = Instance::new(def_id, tcx.intern_substs(&[]));
                 to_string_internal(tcx, "static ", instance)
             },
+            TransItem::GlobalAsm(..) => {
+                "global_asm".to_string()
+            }
         };
 
         fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -273,6 +294,9 @@ pub fn to_raw_string(&self) -> String {
             TransItem::Static(id) => {
                 format!("Static({:?})", id)
             }
+            TransItem::GlobalAsm(id) => {
+                format!("GlobalAsm({:?})", id)
+            }
         }
     }
 }
index f68acab911317c5935920cc32f7f13cb823b9297..d70afc0cce5a3cbebfa7ff9bc997b53b0b5137c2 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use llvm;
-use llvm::{TypeRef, Bool, False, True, TypeKind};
+use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
 use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 
 use context::CrateContext;
@@ -82,6 +82,10 @@ pub fn i8(ccx: &CrateContext) -> Type {
         ty!(llvm::LLVMInt8TypeInContext(ccx.llcx()))
     }
 
+    pub fn i8_llcx(llcx: ContextRef) -> Type {
+        ty!(llvm::LLVMInt8TypeInContext(llcx))
+    }
+
     pub fn i16(ccx: &CrateContext) -> Type {
         ty!(llvm::LLVMInt16TypeInContext(ccx.llcx()))
     }
@@ -123,6 +127,10 @@ pub fn i8p(ccx: &CrateContext) -> Type {
         Type::i8(ccx).ptr_to()
     }
 
+    pub fn i8p_llcx(llcx: ContextRef) -> Type {
+        Type::i8_llcx(llcx).ptr_to()
+    }
+
     pub fn int(ccx: &CrateContext) -> Type {
         match &ccx.tcx().sess.target.target.target_pointer_width[..] {
             "16" => Type::i16(ccx),
index f9bc947a973584a270acb9e82cc3ea7c9be60447..9c5870c12aad450d5da70494c16e8ecb573d8fca 100644 (file)
@@ -100,7 +100,7 @@ fn try_overloaded_call_step(&self,
         // If the callee is a bare function or a closure, then we're all set.
         match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty {
             ty::TyFnDef(..) | ty::TyFnPtr(_) => {
-                self.write_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty);
+                self.apply_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty);
                 return Some(CallStep::Builtin);
             }
 
index 51fbc5aab6cd1510a87654b0f349967df668e050..78176b155691cef23cbc783376890d8837101c99 100644 (file)
@@ -169,6 +169,7 @@ fn deduce_expectations_from_obligations
                     ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()),
                     ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
                     ty::Predicate::Equate(..) => None,
+                    ty::Predicate::Subtype(..) => None,
                     ty::Predicate::RegionOutlives(..) => None,
                     ty::Predicate::TypeOutlives(..) => None,
                     ty::Predicate::WellFormed(..) => None,
index a5acd0c7e530047368f0d2abdd4ce89e59532ee7..2e9057800a54a3583033e5457f7689ca890b51a1 100644 (file)
@@ -195,8 +195,10 @@ fn coerce<E>(&self,
         // Consider coercing the subtype to a DST
         let unsize = self.coerce_unsized(a, b);
         if unsize.is_ok() {
+            debug!("coerce: unsize successful");
             return unsize;
         }
+        debug!("coerce: unsize failed");
 
         // Examine the supertype and consider auto-borrowing.
         //
@@ -712,13 +714,7 @@ pub fn try_coerce(&self,
         self.commit_if_ok(|_| {
             let ok = coerce.coerce(&[expr], source, target)?;
             let adjustment = self.register_infer_ok_obligations(ok);
-            if !adjustment.is_identity() {
-                debug!("Success, coerced with {:?}", adjustment);
-                if self.tables.borrow().adjustments.get(&expr.id).is_some() {
-                    bug!("expr already has an adjustment on it!");
-                }
-                self.write_adjustment(expr.id, adjustment);
-            }
+            self.apply_adjustment(expr.id, adjustment);
 
             // We should now have added sufficient adjustments etc to
             // ensure that the type of expression, post-adjustment, is
@@ -745,7 +741,7 @@ fn try_find_coercion_lub<E>(&self,
     {
         let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
         let new_ty = self.resolve_type_vars_with_obligations(new_ty);
-        debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
+        debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty);
 
         // Special-ish case: we can coerce any type `T` into the `!`
         // type, but only if the source expression diverges.
@@ -780,9 +776,9 @@ fn try_find_coercion_lub<E>(&self,
                 // Reify both sides and return the reified fn pointer type.
                 let fn_ptr = self.tcx.mk_fn_ptr(fty);
                 for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
-                    // No adjustments can produce a fn item, so this should never trip.
-                    assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
-                    self.write_adjustment(expr.id, Adjustment {
+                    // The only adjustment that can produce an fn item is
+                    // `NeverToAny`, so this should always be valid.
+                    self.apply_adjustment(expr.id, Adjustment {
                         kind: Adjust::ReifyFnPointer,
                         target: fn_ptr
                     });
@@ -803,9 +799,7 @@ fn try_find_coercion_lub<E>(&self,
             match result {
                 Ok(ok) => {
                     let adjustment = self.register_infer_ok_obligations(ok);
-                    if !adjustment.is_identity() {
-                        self.write_adjustment(new.id, adjustment);
-                    }
+                    self.apply_adjustment(new.id, adjustment);
                     return Ok(adjustment.target);
                 }
                 Err(e) => first_error = Some(e),
@@ -825,7 +819,9 @@ fn try_find_coercion_lub<E>(&self,
                 }) => {
                     match self.node_ty(expr.id).sty {
                         ty::TyRef(_, mt_orig) => {
-                            // Reborrow that we can safely ignore.
+                            // Reborrow that we can safely ignore, because
+                            // the next adjustment can only be a DerefRef
+                            // which will be merged into it.
                             mutbl_adj == mt_orig.mutbl
                         }
                         _ => false,
@@ -858,19 +854,9 @@ fn try_find_coercion_lub<E>(&self,
             }
             Ok(ok) => {
                 let adjustment = self.register_infer_ok_obligations(ok);
-                if !adjustment.is_identity() {
-                    let mut tables = self.tables.borrow_mut();
-                    for expr in exprs {
-                        let expr = expr.as_coercion_site();
-                        if let Some(&mut Adjustment {
-                            kind: Adjust::NeverToAny,
-                            ref mut target
-                        }) = tables.adjustments.get_mut(&expr.id) {
-                            *target = adjustment.target;
-                            continue;
-                        }
-                        tables.adjustments.insert(expr.id, adjustment);
-                    }
+                for expr in exprs {
+                    let expr = expr.as_coercion_site();
+                    self.apply_adjustment(expr.id, adjustment);
                 }
                 Ok(adjustment.target)
             }
index 2861fd288326b001f639e03bbf4fd7bb7f61a140..cd58fcd4806da62d104e61679c7a9527ae71bad6 100644 (file)
@@ -124,7 +124,6 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "rustc_peek" => (1, vec![param(0)], param(0)),
             "init" => (1, Vec::new(), param(0)),
             "uninit" => (1, Vec::new(), param(0)),
-            "forget" => (1, vec![ param(0) ], tcx.mk_nil()),
             "transmute" => (2, vec![ param(0) ], param(1)),
             "move_val_init" => {
                 (1,
index 73f6cd76290aa0a82fb9f835a16ece2d778dbaf7..28ac335cf195a12a29da60f5f62baefafd6513a9 100644 (file)
@@ -143,7 +143,7 @@ fn adjust_self_ty(&mut self,
         let target = target.adjust_for_autoref(self.tcx, autoref);
 
         // Write out the final adjustment.
-        self.write_adjustment(self.self_expr.id, Adjustment {
+        self.apply_adjustment(self.self_expr.id, Adjustment {
             kind: Adjust::DerefRef {
                 autoderefs: pick.autoderefs,
                 autoref: autoref,
@@ -433,7 +433,8 @@ fn convert_lvalue_derefs_to_mutable(&self) {
         for (i, &expr) in exprs.iter().rev().enumerate() {
             debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
 
-            // Count autoderefs.
+            // Count autoderefs. We don't need to fix up the autoref - the parent
+            // expression will fix them up for us.
             let adjustment = self.tables.borrow().adjustments.get(&expr.id).cloned();
             match adjustment {
                 Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => {
@@ -464,7 +465,7 @@ fn convert_lvalue_derefs_to_mutable(&self) {
                     // expects. This is annoying and horrible. We
                     // ought to recode this routine so it doesn't
                     // (ab)use the normal type checking paths.
-                    let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned();
+                    let adj = self.tables.borrow_mut().adjustments.remove(&base_expr.id);
                     let (autoderefs, unsize, adjusted_base_ty) = match adj {
                         Some(Adjustment {
                             kind: Adjust::DerefRef { autoderefs, autoref, unsize },
@@ -537,6 +538,7 @@ fn convert_lvalue_derefs_to_mutable(&self) {
                     // a preference for mut
                     let method_call = ty::MethodCall::expr(expr.id);
                     if self.tables.borrow().method_map.contains_key(&method_call) {
+                        self.tables.borrow_mut().adjustments.remove(&base_expr.id);
                         let method = self.try_overloaded_deref(expr.span,
                                                                Some(&base_expr),
                                                                self.node_ty(base_expr.id),
index 4085a171bbef53801977e1efa5a026c107968e5f..9ecf0ffa71ebd65500ff8a3dc70744b6214efddc 100644 (file)
@@ -299,7 +299,7 @@ pub fn lookup_method_in_trait_adjusted(&self,
                 }
             };
 
-            self.write_adjustment(self_expr.id, Adjustment {
+            self.apply_adjustment(self_expr.id, Adjustment {
                 kind: Adjust::DerefRef {
                     autoderefs: autoderefs,
                     autoref: autoref,
index 5b0418921563a2dea56b4fa4bbf47897b57f3fc8..59dbbfe49f0a99848f3a712f02cd7fd808bf7eb5 100644 (file)
@@ -576,6 +576,7 @@ fn assemble_inherent_candidates_from_param(&mut self,
                         }
                     }
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::Projection(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::WellFormed(..) |
@@ -1148,19 +1149,16 @@ fn consider_probe(&self,
 
         self.probe(|_| {
             // First check that the self type can be related.
-            match self.sub_types(false,
-                                 &ObligationCause::dummy(),
-                                 self_ty,
-                                 probe.xform_self_ty) {
-                Ok(InferOk { obligations, value: () }) => {
-                    // FIXME(#32730) propagate obligations
-                    assert!(obligations.is_empty())
-                }
+            let sub_obligations = match self.sub_types(false,
+                                                       &ObligationCause::dummy(),
+                                                       self_ty,
+                                                       probe.xform_self_ty) {
+                Ok(InferOk { obligations, value: () }) => obligations,
                 Err(_) => {
                     debug!("--> cannot relate self-types");
                     return false;
                 }
-            }
+            };
 
             // If so, impls may carry other conditions (e.g., where
             // clauses) that must be considered. Make sure that those
@@ -1199,6 +1197,7 @@ fn consider_probe(&self,
             // Evaluate those obligations to see if they might possibly hold.
             let mut all_true = true;
             for o in obligations.iter()
+                .chain(sub_obligations.iter())
                 .chain(norm_obligations.iter())
                 .chain(ref_obligations.iter()) {
                 if !selcx.evaluate_obligation(o) {
index c995b7e92843dd1707b5639e77144e02fa8b1c60..5e7325275b8199c17fdecc0daa07c00d9141cf35 100644 (file)
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_back::slice::ref_slice;
 use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
-use rustc::infer::type_variable::{self, TypeVariableOrigin};
+use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::ty::subst::{Kind, Subst, Substs};
-use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
+use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::{ParamTy, ParameterEnvironment};
 use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
 use rustc::ty::{self, Ty, TyCtxt, Visibility};
 use rustc::ty::{MethodCall, MethodCallee};
-use rustc::ty::adjustment;
+use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
 use TypeAndSubsts;
 use lint;
 use util::common::{ErrorReported, indenter};
-use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap};
+use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
 
 use std::cell::{Cell, RefCell};
+use std::collections::hash_map::Entry;
 use std::cmp;
 use std::mem::replace;
 use std::ops::{self, Deref};
@@ -1637,12 +1638,12 @@ pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
         }
     }
 
-    pub fn write_autoderef_adjustment(&self,
+    pub fn apply_autoderef_adjustment(&self,
                                       node_id: ast::NodeId,
                                       derefs: usize,
                                       adjusted_ty: Ty<'tcx>) {
-        self.write_adjustment(node_id, adjustment::Adjustment {
-            kind: adjustment::Adjust::DerefRef {
+        self.apply_adjustment(node_id, Adjustment {
+            kind: Adjust::DerefRef {
                 autoderefs: derefs,
                 autoref: None,
                 unsize: false
@@ -1651,16 +1652,42 @@ pub fn write_autoderef_adjustment(&self,
         });
     }
 
-    pub fn write_adjustment(&self,
-                            node_id: ast::NodeId,
-                            adj: adjustment::Adjustment<'tcx>) {
-        debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
+    pub fn apply_adjustment(&self, node_id: ast::NodeId, adj: Adjustment<'tcx>) {
+        debug!("apply_adjustment(node_id={}, adj={:?})", node_id, adj);
 
         if adj.is_identity() {
             return;
         }
 
-        self.tables.borrow_mut().adjustments.insert(node_id, adj);
+        match self.tables.borrow_mut().adjustments.entry(node_id) {
+            Entry::Vacant(entry) => { entry.insert(adj); },
+            Entry::Occupied(mut entry) => {
+                debug!(" - composing on top of {:?}", entry.get());
+                let composed_kind = match (entry.get().kind, adj.kind) {
+                    // Applying any adjustment on top of a NeverToAny
+                    // is a valid NeverToAny adjustment, because it can't
+                    // be reached.
+                    (Adjust::NeverToAny, _) => Adjust::NeverToAny,
+                    (Adjust::DerefRef {
+                        autoderefs: 1,
+                        autoref: Some(AutoBorrow::Ref(..)),
+                        unsize: false
+                    }, Adjust::DerefRef { autoderefs, .. }) if autoderefs > 0 => {
+                        // A reborrow has no effect before a dereference.
+                        adj.kind
+                    }
+                    // FIXME: currently we never try to compose autoderefs
+                    // and ReifyFnPointer/UnsafeFnPointer, but we could.
+                    _ =>
+                        bug!("while adjusting {}, can't compose {:?} and {:?}",
+                             node_id, entry.get(), adj)
+                };
+                *entry.get_mut() = Adjustment {
+                    kind: composed_kind,
+                    target: adj.target
+                };
+            }
+        }
     }
 
     /// Basically whenever we are converting from a type scheme into
@@ -1978,218 +2005,13 @@ fn default_type_parameters(&self) {
         }
     }
 
+    // Implements type inference fallback algorithm
     fn select_all_obligations_and_apply_defaults(&self) {
-        if self.tcx.sess.features.borrow().default_type_parameter_fallback {
-            self.new_select_all_obligations_and_apply_defaults();
-        } else {
-            self.old_select_all_obligations_and_apply_defaults();
-        }
-    }
-
-    // Implements old type inference fallback algorithm
-    fn old_select_all_obligations_and_apply_defaults(&self) {
         self.select_obligations_where_possible();
         self.default_type_parameters();
         self.select_obligations_where_possible();
     }
 
-    fn new_select_all_obligations_and_apply_defaults(&self) {
-        use rustc::ty::error::UnconstrainedNumeric::Neither;
-        use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
-
-        // For the time being this errs on the side of being memory wasteful but provides better
-        // error reporting.
-        // let type_variables = self.type_variables.clone();
-
-        // There is a possibility that this algorithm will have to run an arbitrary number of times
-        // to terminate so we bound it by the compiler's recursion limit.
-        for _ in 0..self.tcx.sess.recursion_limit.get() {
-            // First we try to solve all obligations, it is possible that the last iteration
-            // has made it possible to make more progress.
-            self.select_obligations_where_possible();
-
-            let mut conflicts = Vec::new();
-
-            // Collect all unsolved type, integral and floating point variables.
-            let unsolved_variables = self.unsolved_variables();
-
-            // We must collect the defaults *before* we do any unification. Because we have
-            // directly attached defaults to the type variables any unification that occurs
-            // will erase defaults causing conflicting defaults to be completely ignored.
-            let default_map: FxHashMap<Ty<'tcx>, _> =
-                unsolved_variables
-                    .iter()
-                    .filter_map(|t| self.default(t).map(|d| (*t, d)))
-                    .collect();
-
-            let mut unbound_tyvars = FxHashSet();
-
-            debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);
-
-            // We loop over the unsolved variables, resolving them and if they are
-            // and unconstrainted numeric type we add them to the set of unbound
-            // variables. We do this so we only apply literal fallback to type
-            // variables without defaults.
-            for ty in &unsolved_variables {
-                let resolved = self.resolve_type_vars_if_possible(ty);
-                if self.type_var_diverges(resolved) {
-                    self.demand_eqtype(syntax_pos::DUMMY_SP, *ty,
-                                       self.tcx.mk_diverging_default());
-                } else {
-                    match self.type_is_unconstrained_numeric(resolved) {
-                        UnconstrainedInt | UnconstrainedFloat => {
-                            unbound_tyvars.insert(resolved);
-                        },
-                        Neither => {}
-                    }
-                }
-            }
-
-            // We now remove any numeric types that also have defaults, and instead insert
-            // the type variable with a defined fallback.
-            for ty in &unsolved_variables {
-                if let Some(_default) = default_map.get(ty) {
-                    let resolved = self.resolve_type_vars_if_possible(ty);
-
-                    debug!("select_all_obligations_and_apply_defaults: \
-                            ty: {:?} with default: {:?}",
-                             ty, _default);
-
-                    match resolved.sty {
-                        ty::TyInfer(ty::TyVar(_)) => {
-                            unbound_tyvars.insert(ty);
-                        }
-
-                        ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
-                            unbound_tyvars.insert(ty);
-                            if unbound_tyvars.contains(resolved) {
-                                unbound_tyvars.remove(resolved);
-                            }
-                        }
-
-                        _ => {}
-                    }
-                }
-            }
-
-            // If there are no more fallbacks to apply at this point we have applied all possible
-            // defaults and type inference will proceed as normal.
-            if unbound_tyvars.is_empty() {
-                break;
-            }
-
-            // Finally we go through each of the unbound type variables and unify them with
-            // the proper fallback, reporting a conflicting default error if any of the
-            // unifications fail. We know it must be a conflicting default because the
-            // variable would only be in `unbound_tyvars` and have a concrete value if
-            // it had been solved by previously applying a default.
-
-            // We wrap this in a transaction for error reporting, if we detect a conflict
-            // we will rollback the inference context to its prior state so we can probe
-            // for conflicts and correctly report them.
-
-            let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
-                conflicts.extend(
-                    self.apply_defaults_and_return_conflicts(&unbound_tyvars, &default_map, None)
-                );
-
-                // If there are conflicts we rollback, otherwise commit
-                if conflicts.len() > 0 {
-                    Err(())
-                } else {
-                    Ok(())
-                }
-            });
-
-            // Loop through each conflicting default, figuring out the default that caused
-            // a unification failure and then report an error for each.
-            for (conflict, default) in conflicts {
-                let conflicting_default =
-                    self.apply_defaults_and_return_conflicts(
-                            &unbound_tyvars,
-                            &default_map,
-                            Some(conflict)
-                        )
-                        .last()
-                        .map(|(_, tv)| tv)
-                        .unwrap_or(type_variable::Default {
-                            ty: self.next_ty_var(
-                                TypeVariableOrigin::MiscVariable(syntax_pos::DUMMY_SP)),
-                            origin_span: syntax_pos::DUMMY_SP,
-                            // what do I put here?
-                            def_id: self.tcx.hir.local_def_id(ast::CRATE_NODE_ID)
-                        });
-
-                // This is to ensure that we elimnate any non-determinism from the error
-                // reporting by fixing an order, it doesn't matter what order we choose
-                // just that it is consistent.
-                let (first_default, second_default) =
-                    if default.def_id < conflicting_default.def_id {
-                        (default, conflicting_default)
-                    } else {
-                        (conflicting_default, default)
-                    };
-
-
-                self.report_conflicting_default_types(
-                    first_default.origin_span,
-                    self.body_id,
-                    first_default,
-                    second_default)
-            }
-        }
-
-        self.select_obligations_where_possible();
-    }
-
-    // For use in error handling related to default type parameter fallback. We explicitly
-    // apply the default that caused conflict first to a local version of the type variable
-    // table then apply defaults until we find a conflict. That default must be the one
-    // that caused conflict earlier.
-    fn apply_defaults_and_return_conflicts<'b>(
-        &'b self,
-        unbound_vars: &'b FxHashSet<Ty<'tcx>>,
-        default_map: &'b FxHashMap<Ty<'tcx>, type_variable::Default<'tcx>>,
-        conflict: Option<Ty<'tcx>>,
-    ) -> impl Iterator<Item=(Ty<'tcx>, type_variable::Default<'tcx>)> + 'b {
-        use rustc::ty::error::UnconstrainedNumeric::Neither;
-        use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
-
-        conflict.into_iter().chain(unbound_vars.iter().cloned()).flat_map(move |ty| {
-            if self.type_var_diverges(ty) {
-                self.demand_eqtype(syntax_pos::DUMMY_SP, ty,
-                                   self.tcx.mk_diverging_default());
-            } else {
-                match self.type_is_unconstrained_numeric(ty) {
-                    UnconstrainedInt => {
-                        self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.types.i32)
-                    },
-                    UnconstrainedFloat => {
-                        self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.types.f64)
-                    },
-                    Neither => {
-                        if let Some(default) = default_map.get(ty) {
-                            let default = default.clone();
-                            let default_ty = self.normalize_associated_types_in(
-                                default.origin_span, &default.ty);
-                            match self.eq_types(false,
-                                                &self.misc(default.origin_span),
-                                                ty,
-                                                default_ty) {
-                                Ok(ok) => self.register_infer_ok_obligations(ok),
-                                Err(_) => {
-                                    return Some((ty, default));
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            None
-        })
-    }
-
     fn select_all_obligations_or_error(&self) {
         debug!("select_all_obligations_or_error");
 
@@ -2302,7 +2124,7 @@ fn try_index_step(&self,
                 debug!("try_index_step: success, using built-in indexing");
                 // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
                 assert!(!unsize);
-                self.write_autoderef_adjustment(base_expr.id, autoderefs, adjusted_ty);
+                self.apply_autoderef_adjustment(base_expr.id, autoderefs, adjusted_ty);
                 return Some((tcx.types.usize, ty));
             }
             _ => {}
@@ -2685,8 +2507,8 @@ pub fn check_expr_has_type(&self,
                     "expression with never type wound up being adjusted");
             let adj_ty = self.next_diverging_ty_var(
                 TypeVariableOrigin::AdjustmentType(expr.span));
-            self.write_adjustment(expr.id, adjustment::Adjustment {
-                kind: adjustment::Adjust::NeverToAny,
+            self.apply_adjustment(expr.id, Adjustment {
+                kind: Adjust::NeverToAny,
                 target: adj_ty
             });
             ty = adj_ty;
@@ -2757,11 +2579,30 @@ fn expected_inputs_for_expected_output(&self,
                 // No argument expectations are produced if unification fails.
                 let origin = self.misc(call_span);
                 let ures = self.sub_types(false, &origin, formal_ret, ret_ty);
+
                 // FIXME(#15760) can't use try! here, FromError doesn't default
                 // to identity so the resulting type is not constrained.
                 match ures {
-                    Ok(ok) => self.register_infer_ok_obligations(ok),
-                    Err(e) => return Err(e),
+                    Ok(ok) => {
+                        // Process any obligations locally as much as
+                        // we can.  We don't care if some things turn
+                        // out unconstrained or ambiguous, as we're
+                        // just trying to get hints here.
+                        let result = self.save_and_restore_obligations_in_snapshot_flag(|_| {
+                            let mut fulfill = FulfillmentContext::new();
+                            let ok = ok; // FIXME(#30046)
+                            for obligation in ok.obligations {
+                                fulfill.register_predicate_obligation(self, obligation);
+                            }
+                            fulfill.select_where_possible(self)
+                        });
+
+                        match result {
+                            Ok(()) => { }
+                            Err(_) => return Err(()),
+                        }
+                    }
+                    Err(_) => return Err(()),
                 }
 
                 // Record all the argument types, with the substitutions
@@ -2917,7 +2758,7 @@ fn check_field(&self,
                         let field_ty = self.field_ty(expr.span, field, substs);
                         if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
                             autoderef.finalize(lvalue_pref, &[base]);
-                            self.write_autoderef_adjustment(base.id, autoderefs, base_t);
+                            self.apply_autoderef_adjustment(base.id, autoderefs, base_t);
 
                             self.tcx.check_stability(field.did, expr.id, expr.span);
 
@@ -3041,7 +2882,7 @@ fn check_tup_field(&self,
 
             if let Some(field_ty) = field {
                 autoderef.finalize(lvalue_pref, &[base]);
-                self.write_autoderef_adjustment(base.id, autoderefs, base_t);
+                self.apply_autoderef_adjustment(base.id, autoderefs, base_t);
                 return field_ty;
             }
         }
index 77ab076eba38604f89bc5dc3775ea204ead4ecc3..649353d52f6aaf29052d3b783a52d38c4c1682f1 100644 (file)
@@ -490,8 +490,10 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
     let def_id = tcx.hir.local_def_id(item_id);
     match it.node {
         // These don't define types.
-        hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => {
-        }
+        hir::ItemExternCrate(_) |
+        hir::ItemUse(..) |
+        hir::ItemMod(_) |
+        hir::ItemGlobalAsm(_) => {}
         hir::ItemForeignMod(ref foreign_mod) => {
             for item in &foreign_mod.items {
                 let def_id = tcx.hir.local_def_id(item.id);
@@ -543,12 +545,12 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.item_generics(def_id);
             tcx.item_type(def_id);
             tcx.item_predicates(def_id);
-        },
-        _ => {
+        }
+        hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => {
             tcx.item_generics(def_id);
             tcx.item_type(def_id);
             tcx.item_predicates(def_id);
-        },
+        }
     }
 }
 
@@ -1074,6 +1076,7 @@ fn ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemTrait(..) |
                 ItemMod(..) |
                 ItemForeignMod(..) |
+                ItemGlobalAsm(..) |
                 ItemExternCrate(..) |
                 ItemUse(..) => {
                     span_bug!(
index fb951fd20e564cbd3490f105994b03b10564a92d..2d72052f1e5ad6b4bf4e807671c74c64fcd9e36e 100644 (file)
@@ -1378,7 +1378,7 @@ fn main() {
 You hit this error because the compiler lacks the information to
 determine the type of this variable. Erroneous code example:
 
-```compile_fail,E0102
+```compile_fail,E0282
 // could be an array of anything
 let x = []; // error: cannot determine a type for this local variable
 ```
index f0f543fa6f23b7af8b774a5e5e8bbe72e0fd069d..1bde1eea37c39a0b16c7032a1a16b6fcabb3c628 100644 (file)
@@ -113,6 +113,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             hir::ItemFn(..) |
             hir::ItemMod(..) |
             hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
             hir::ItemTy(..) |
             hir::ItemImpl(..) |
             hir::ItemDefaultImpl(..) => {}
index 36352f50e4406237115aa36abf42d55a53438c38..890414e317c62f3bc522d7660cfef818a6ef4478 100644 (file)
@@ -251,6 +251,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             hir::ItemFn(..) |
             hir::ItemMod(..) |
             hir::ItemForeignMod(..) |
+            hir::ItemGlobalAsm(..) |
             hir::ItemTy(..) => {}
         }
     }
index 2511560e8726188efaeaf7400d62e2bbfc22f0c1..3d233463bba3a0fda17570add29d2ec081ff3789 100644 (file)
@@ -838,7 +838,7 @@ fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
 pub enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
-    EqPredicate { lhs: Type, rhs: Type }
+    EqPredicate { lhs: Type, rhs: Type },
 }
 
 impl Clean<WherePredicate> for hir::WherePredicate {
@@ -875,6 +875,7 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
         match *self {
             Predicate::Trait(ref pred) => pred.clean(cx),
             Predicate::Equate(ref pred) => pred.clean(cx),
+            Predicate::Subtype(ref pred) => pred.clean(cx),
             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
             Predicate::Projection(ref pred) => pred.clean(cx),
@@ -904,6 +905,13 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
     }
 }
 
+impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
+    fn clean(&self, _cx: &DocContext) -> WherePredicate {
+        panic!("subtype predicates are an internal rustc artifact \
+                and should not be seen by rustdoc")
+    }
+}
+
 impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<&'tcx ty::Region, &'tcx ty::Region> {
     fn clean(&self, cx: &DocContext) -> WherePredicate {
         let ty::OutlivesPredicate(ref a, ref b) = *self;
index 1e687d63f58755d732d1e71878c4ca45262d90df..c59101cc779968eea9f7f7f3e772f3359ac6e401 100644 (file)
@@ -469,22 +469,28 @@ fn parse(string: &str) -> LangString {
         );
 
         for token in tokens {
-            match token {
+            match token.trim() {
                 "" => {},
-                "should_panic" => { data.should_panic = true; seen_rust_tags = true; },
-                "no_run" => { data.no_run = true; seen_rust_tags = true; },
-                "ignore" => { data.ignore = true; seen_rust_tags = true; },
-                "rust" => { data.rust = true; seen_rust_tags = true; },
-                "test_harness" => { data.test_harness = true; seen_rust_tags = true; },
+                "should_panic" => {
+                    data.should_panic = true;
+                    seen_rust_tags = seen_other_tags == false;
+                }
+                "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
+                "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+                "rust" => { data.rust = true; seen_rust_tags = true; }
+                "test_harness" => {
+                    data.test_harness = true;
+                    seen_rust_tags = !seen_other_tags || seen_rust_tags;
+                }
                 "compile_fail" if allow_compile_fail => {
                     data.compile_fail = true;
-                    seen_rust_tags = true;
+                    seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     data.no_run = true;
                 }
                 x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => {
                     if let Ok(_) = x[1..].parse::<u32>() {
                         data.error_codes.push(x.to_owned());
-                        seen_rust_tags = true;
+                        seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     } else {
                         seen_other_tags = true;
                     }
@@ -670,9 +676,11 @@ fn t(s: &str,
         t("test_harness",          false,        false,  false,  true,  true,  false, Vec::new());
         t("compile_fail",          false,        true,   false,  true,  false, true,  Vec::new());
         t("{.no_run .example}",    false,        true,   false,  true,  false, false, Vec::new());
-        t("{.sh .should_panic}",   true,         false,  false,  true,  false, false, Vec::new());
+        t("{.sh .should_panic}",   true,         false,  false,  false, false, false, Vec::new());
         t("{.example .rust}",      false,        false,  false,  true,  false, false, Vec::new());
         t("{.test_harness .rust}", false,        false,  false,  true,  true,  false, Vec::new());
+        t("text, no_run",          false,        true,   false,  false, false, false, Vec::new());
+        t("text,no_run",           false,        true,   false,  false, false, false, Vec::new());
     }
 
     #[test]
index c89ec5bbe15bd36a0b14a8fcfc13139c69c2937f..4252f2981ed6193e1ba5d59166c7c7eea0b037ab 100644 (file)
@@ -373,6 +373,7 @@ pub fn visit_item(&mut self, item: &hir::Item,
             }
             // If we're inlining, skip private items.
             _ if self.inlining && item.vis != hir::Public => {}
+            hir::ItemGlobalAsm(..) => {}
             hir::ItemExternCrate(ref p) => {
                 let cstore = &self.cx.sess().cstore;
                 om.extern_crates.push(ExternCrate {
index 852c98eb2fd52fcfb37e4cab0131f3aa415b6338..40a6ffe9505fd1f834d2fce524e9171cdef07110 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::ty::Visibility;
+use rustc::util::nodemap::FxHashSet;
 
 use std::cell::RefMut;
 
@@ -29,6 +30,8 @@ pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> {
     access_levels: RefMut<'a, AccessLevels<DefId>>,
     // Previous accessibility level, None means unreachable
     prev_level: Option<AccessLevel>,
+    // Keeps track of already visited modules, in case a module re-exports its parent
+    visited_mods: FxHashSet<DefId>,
 }
 
 impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
@@ -38,6 +41,7 @@ pub fn new(cx: &'a ::core::DocContext<'b, 'tcx>) -> LibEmbargoVisitor<'a, 'b, 't
             cstore: &*cx.sess().cstore,
             access_levels: cx.access_levels.borrow_mut(),
             prev_level: Some(AccessLevel::Public),
+            visited_mods: FxHashSet()
         }
     }
 
@@ -62,6 +66,10 @@ fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLev
     }
 
     pub fn visit_mod(&mut self, def_id: DefId) {
+        if !self.visited_mods.insert(def_id) {
+            return;
+        }
+
         for item in self.cstore.item_children(def_id) {
             self.visit_item(item.def);
         }
index 544f4f9ddbed3dc9b14c015bdea4a31a1355f443..dd8318006835f65cdf590cead33197a2e256106f 100644 (file)
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! The 32-bit floating point type.
+//! This module provides constants which are specific to the implementation
+//! of the `f32` floating point data type. Mathematically significant
+//! numbers are provided in the `consts` sub-module.
 //!
 //! *[See also the `f32` primitive type](../primitive.f32.html).*
 
index dd4bc253bed4b769fecc3abf0ca2c3a836e1db37..2f02e01935a4951438476c21db8939496eafbf85 100644 (file)
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! The 64-bit floating point type.
+//! This module provides constants which are specific to the implementation
+//! of the `f64` floating point data type. Mathematically significant
+//! numbers are provided in the `consts` sub-module.
 //!
 //! *[See also the `f64` primitive type](../primitive.f64.html).*
 
index 6299a9070ae03bd22bc9f1e34e50fe6d70887288..4f6d170560c1da65d190ef738e2006ed4d3f4435 100644 (file)
 //! compiler - but they are documented here the same). Like the prelude, the
 //! standard macros are imported by default into all crates.
 //!
+//! # Contributing changes to the documentation
+//!
+//! Check out the rust contribution guidelines [here](
+//! https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md).
+//! The source for this documentation can be found on [Github](https://github.com/rust-lang).
+//! To contribute changes, make sure you read the guidelines first, then submit
+//! pull-requests for your suggested changes.
+//!
+//! Contributions are appreciated! If you see a part of the docs that can be
+//! improved, submit a PR, or chat with us first on irc.mozilla.org #rust-docs.
+//!
 //! # A Tour of The Rust Standard Library
 //!
 //! The rest of this crate documentation is dedicated to pointing out notable
index 5b2053e929a10317d645126fcbd16e163dd0cc10..61ff8daddf0a67fbd3e4661ef3f063bf97002eec 100644 (file)
@@ -277,7 +277,7 @@ 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]`)
+/// - [`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]
@@ -406,7 +406,7 @@ mod prim_slice { }
 ///
 /// This documentation describes a number of methods and trait implementations
 /// on the `str` type. For technical reasons, there is additional, separate
-/// documentation in [the `std::str` module](str/index.html) as well.
+/// documentation in the [`std::str`](str/index.html) module as well.
 ///
 /// # Examples
 ///
@@ -425,7 +425,7 @@ mod prim_slice { }
 /// # Representation
 ///
 /// A `&str` is made up of two components: a pointer to some bytes, and a
-/// length. You can look at these with the [`.as_ptr`] and [`len`] methods:
+/// length. You can look at these with the [`as_ptr`] and [`len`] methods:
 ///
 /// ```
 /// use std::slice;
@@ -452,11 +452,11 @@ mod prim_slice { }
 /// assert_eq!(s, Ok(story));
 /// ```
 ///
-/// [`.as_ptr`]: #method.as_ptr
+/// [`as_ptr`]: #method.as_ptr
 /// [`len`]: #method.len
 ///
 /// Note: This example shows the internals of `&str`. `unsafe` should not be
-/// used to get a string slice under normal circumstances. Use `.as_slice()`
+/// used to get a string slice under normal circumstances. Use `as_slice`
 /// instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_str { }
index 7ab6b82ada3445f6ca739fcd4439cc6a538c58c0..e37cc7e963e10bc5eae668929a4fe8db4747e851 100644 (file)
@@ -652,8 +652,8 @@ pub fn park_timeout(dur: Duration) {
 /// A unique identifier for a running thread.
 ///
 /// A `ThreadId` is an opaque object that has a unique value for each thread
-/// that creates one. `ThreadId`s do not correspond to a thread's system-
-/// designated identifier.
+/// that creates one. `ThreadId`s are not guaranteed to correspond to a thread's
+/// system-designated identifier.
 ///
 /// # Examples
 ///
@@ -662,17 +662,15 @@ pub fn park_timeout(dur: Duration) {
 ///
 /// use std::thread;
 ///
-/// let handler = thread::Builder::new()
-///     .spawn(|| {
-///         let thread = thread::current();
-///         let thread_id = thread.id();
-///     })
-///     .unwrap();
+/// let other_thread = thread::spawn(|| {
+///     thread::current().id()
+/// });
 ///
-/// handler.join().unwrap();
+/// let other_thread_id = other_thread.join().unwrap();
+/// assert!(thread::current().id() != other_thread_id);
 /// ```
 #[unstable(feature = "thread_id", issue = "21507")]
-#[derive(Eq, PartialEq, Copy, Clone)]
+#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
 pub struct ThreadId(u64);
 
 impl ThreadId {
@@ -701,13 +699,6 @@ fn new() -> ThreadId {
     }
 }
 
-#[unstable(feature = "thread_id", issue = "21507")]
-impl fmt::Debug for ThreadId {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("ThreadId { .. }")
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Thread
 ////////////////////////////////////////////////////////////////////////////////
@@ -795,14 +786,12 @@ pub fn unpark(&self) {
     ///
     /// use std::thread;
     ///
-    /// let handler = thread::Builder::new()
-    ///     .spawn(|| {
-    ///         let thread = thread::current();
-    ///         println!("thread id: {:?}", thread.id());
-    ///     })
-    ///     .unwrap();
+    /// let other_thread = thread::spawn(|| {
+    ///     thread::current().id()
+    /// });
     ///
-    /// handler.join().unwrap();
+    /// let other_thread_id = other_thread.join().unwrap();
+    /// assert!(thread::current().id() != other_thread_id);
     /// ```
     #[unstable(feature = "thread_id", issue = "21507")]
     pub fn id(&self) -> ThreadId {
index c6a3e8a2dedc4653985b20276673a99c3fa658b9..131adfe47afdac6646dbd31819235deb53b20e02 100644 (file)
@@ -1585,6 +1585,15 @@ pub struct ForeignMod {
     pub items: Vec<ForeignItem>,
 }
 
+/// Global inline assembly
+///
+/// aka module-level assembly or file-scoped assembly
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub struct GlobalAsm {
+    pub asm: Symbol,
+    pub ctxt: SyntaxContext,
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct EnumDef {
     pub variants: Vec<Variant>,
@@ -1812,6 +1821,8 @@ pub enum ItemKind {
     ///
     /// E.g. `extern {}` or `extern "C" {}`
     ForeignMod(ForeignMod),
+    /// Module-level inline assembly (from `global_asm!()`)
+    GlobalAsm(P<GlobalAsm>),
     /// A type alias (`type` or `pub type`).
     ///
     /// E.g. `type Foo = Bar<u8>;`
@@ -1864,6 +1875,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Fn(..) => "function",
             ItemKind::Mod(..) => "module",
             ItemKind::ForeignMod(..) => "foreign module",
+            ItemKind::GlobalAsm(..) => "global asm",
             ItemKind::Ty(..) => "type alias",
             ItemKind::Enum(..) => "enum",
             ItemKind::Struct(..) => "struct",
index 1b3352f73ade794e9ee9da45730a72f5df9475b8..48bfc050223ab82ab60fe6581280c16fe70410a0 100644 (file)
@@ -1039,6 +1039,7 @@ pub fn default(crate_name: String) -> ExpansionConfig<'static> {
     feature_tests! {
         fn enable_quotes = quote,
         fn enable_asm = asm,
+        fn enable_global_asm = global_asm,
         fn enable_log_syntax = log_syntax,
         fn enable_concat_idents = concat_idents,
         fn enable_trace_macros = trace_macros,
index 08762ccf04bde8d0dbaaf6a638402384cbe10262..8b62416dcbdbd6e541f68b055ac8f8933dfc3a95 100644 (file)
@@ -346,6 +346,9 @@ pub fn new() -> Features {
 
     // Hack to document `-Z linker-flavor` in The Unstable Book
     (active, linker_flavor, "1.18.0", Some(41142)),
+
+    // Allows module-level inline assembly by way of global_asm!()
+    (active, global_asm, "1.18.0", Some(35119)),
 );
 
 declare_features! (
@@ -982,6 +985,9 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
 pub const EXPLAIN_ASM: &'static str =
     "inline assembly is not stable enough for use and is subject to change";
 
+pub const EXPLAIN_GLOBAL_ASM: &'static str =
+    "`global_asm!` is not stable enough for use and is subject to change";
+
 pub const EXPLAIN_LOG_SYNTAX: &'static str =
     "`log_syntax!` is not stable enough for use and is subject to change";
 
index 92e25b00e0ac108cfd41d90b06e1773f45b21d38..a6ab8e10d9f91aef1cff7fe1944be51965869e5c 100644 (file)
@@ -140,6 +140,10 @@ fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod {
         noop_fold_foreign_mod(nm, self)
     }
 
+    fn fold_global_asm(&mut self, ga: P<GlobalAsm>) -> P<GlobalAsm> {
+        noop_fold_global_asm(ga, self)
+    }
+
     fn fold_variant(&mut self, v: Variant) -> Variant {
         noop_fold_variant(v, self)
     }
@@ -412,6 +416,11 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
     }
 }
 
+pub fn noop_fold_global_asm<T: Folder>(ga: P<GlobalAsm>,
+                                       _: &mut T) -> P<GlobalAsm> {
+    ga
+}
+
 pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
     Spanned {
         node: Variant_ {
@@ -867,6 +876,7 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
         }
         ItemKind::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
         ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
+        ItemKind::GlobalAsm(ga) => ItemKind::GlobalAsm(folder.fold_global_asm(ga)),
         ItemKind::Ty(t, generics) => {
             ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
         }
index 58be43526fd9d7e6da9ddc0572ec177c63ea482c..3b928ea93c78aef2fe8bdfff94f208bcd3d0b1d0 100644 (file)
@@ -2552,10 +2552,10 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
                   }
                   token::Literal(token::Float(n), _suf) => {
                     self.bump();
-                    let prev_span = self.prev_span;
                     let fstr = n.as_str();
-                    let mut err = self.diagnostic().struct_span_err(prev_span,
+                    let mut err = self.diagnostic().struct_span_err(self.prev_span,
                         &format!("unexpected token: `{}`", n));
+                    err.span_label(self.prev_span, &"unexpected token");
                     if fstr.chars().all(|x| "0123456789.".contains(x)) {
                         let float = match fstr.parse::<f64>().ok() {
                             Some(f) => f,
@@ -2573,7 +2573,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
                             word(&mut s.s, fstr.splitn(2, ".").last().unwrap())
                         });
                         err.span_suggestion(
-                            prev_span,
+                            lo.to(self.prev_span),
                             "try parenthesizing the first index",
                             sugg);
                     }
index e7feff2b79fceb9936a665f90923ee0f9fa490b1..433ba3d3693f1a396565ec486d2b2d4e53a5d1e5 100644 (file)
@@ -1267,6 +1267,11 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.print_foreign_mod(nmod, &item.attrs)?;
                 self.bclose(item.span)?;
             }
+            ast::ItemKind::GlobalAsm(ref ga) => {
+                self.head(&visibility_qualified(&item.vis, "global_asm!"))?;
+                word(&mut self.s, &ga.asm.as_str())?;
+                self.end()?;
+            }
             ast::ItemKind::Ty(ref ty, ref params) => {
                 self.ibox(INDENT_UNIT)?;
                 self.ibox(0)?;
index b5e9a1892acc9927446c1cfffcd394cbbcd93094..bae1c56db007c66d137cca850179820e91b77eaa 100644 (file)
@@ -58,6 +58,7 @@ fn visit_ident(&mut self, span: Span, ident: Ident) {
     }
     fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
+    fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
     fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
     fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
     fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
@@ -253,6 +254,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
         ItemKind::ForeignMod(ref foreign_module) => {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
+        ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
         ItemKind::Ty(ref typ, ref type_parameters) => {
             visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
@@ -464,6 +466,10 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a
     walk_list!(visitor, visit_attribute, &foreign_item.attrs);
 }
 
+pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
+    // Empty!
+}
+
 pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) {
     match *bound {
         TraitTyParamBound(ref typ, ref modifier) => {
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
new file mode 100644 (file)
index 0000000..dc67e1c
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2012-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.
+
+/// Module-level assembly support.
+///
+/// The macro defined here allows you to specify "top-level",
+/// "file-scoped", or "module-level" assembly. These synonyms
+/// all correspond to LLVM's module-level inline assembly instruction.
+///
+/// For example, `global_asm!("some assembly here")` translates to
+/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
+/// therefore apply.
+
+use syntax::ast;
+use syntax::ext::base;
+use syntax::ext::base::*;
+use syntax::feature_gate;
+use syntax::ptr::P;
+use syntax::symbol::Symbol;
+use syntax_pos::Span;
+use syntax::tokenstream;
+
+use syntax::util::small_vector::SmallVector;
+
+pub const MACRO: &'static str = "global_asm";
+
+pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
+                              sp: Span,
+                              tts: &[tokenstream::TokenTree]) -> Box<base::MacResult + 'cx> {
+    if !cx.ecfg.enable_global_asm() {
+        feature_gate::emit_feature_err(&cx.parse_sess,
+                                       MACRO,
+                                       sp,
+                                       feature_gate::GateIssue::Language,
+                                       feature_gate::EXPLAIN_GLOBAL_ASM);
+        return DummyResult::any(sp);
+    }
+
+    let mut p = cx.new_parser_from_tts(tts);
+    let (asm, _) = match expr_to_string(cx,
+                                        panictry!(p.parse_expr()),
+                                        "inline assembly must be a string literal") {
+        Some((s, st)) => (s, st),
+        None => return DummyResult::any(sp),
+    };
+
+    MacEager::items(SmallVector::one(P(ast::Item {
+        ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
+        attrs: Vec::new(),
+        id: ast::DUMMY_NODE_ID,
+        node: ast::ItemKind::GlobalAsm(P(ast::GlobalAsm {
+            asm: asm,
+            ctxt: cx.backtrace(),
+        })),
+        vis: ast::Visibility::Inherited,
+        span: sp,
+    })))
+}
index 1e9b112b6df564263738be5f058d2e4c1a54bed6..e35e79df5852066cea8c85a228e3c89b9a40aa65 100644 (file)
@@ -38,6 +38,7 @@
 mod env;
 mod format;
 mod format_foreign;
+mod global_asm;
 mod log_syntax;
 mod trace_macros;
 
@@ -99,6 +100,7 @@ macro_rules! register {
         module_path: expand_mod,
 
         asm: asm::expand_asm,
+        global_asm: global_asm::expand_global_asm,
         cfg: cfg::expand_cfg,
         concat: concat::expand_syntax_ext,
         concat_idents: concat_idents::expand_syntax_ext,
index 5ab786f40b9335aca5b7a36d5e0af99c8869e995..c24867224ea864cd94733550001037fe7dee83fa 100644 (file)
@@ -312,6 +312,10 @@ extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString,
                              HasSideEffects, IsAlignStack, fromRust(Dialect)));
 }
 
+extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
+  unwrap(M)->appendModuleInlineAsm(StringRef(Asm));
+}
+
 typedef DIBuilder *LLVMRustDIBuilderRef;
 
 typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
diff --git a/src/test/codegen/foo.s b/src/test/codegen/foo.s
new file mode 100644 (file)
index 0000000..304d82a
--- /dev/null
@@ -0,0 +1,3 @@
+.global foo
+foo:
+    jmp baz
diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs
new file mode 100644 (file)
index 0000000..5bd0c1b
--- /dev/null
@@ -0,0 +1,73 @@
+// 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.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(global_asm)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// this regex will capture the correct unconditional branch inst.
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+global_asm!(r#"
+    .global foo
+foo:
+    jmp baz
+"#);
+
+extern "C" {
+    fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs
new file mode 100644 (file)
index 0000000..401b1fa
--- /dev/null
@@ -0,0 +1,68 @@
+// 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.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(global_asm)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+global_asm!(include_str!("foo.s"));
+
+extern "C" {
+    fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs
new file mode 100644 (file)
index 0000000..8b59165
--- /dev/null
@@ -0,0 +1,90 @@
+// 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.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(global_asm)]
+#![crate_type = "lib"]
+#[no_std]
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+// any other global_asm will be appended to this first block, so:
+// CHECK-LABEL: bar
+// CHECK: module asm "{{[[:space:]]+}}jmp quux"
+global_asm!(r#"
+    .global foo
+foo:
+    jmp baz
+"#);
+
+extern "C" {
+    fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
+
+// no checks here; this has been appended to the first occurrence
+global_asm!(r#"
+    .global bar
+bar:
+    jmp quux
+"#);
+
+extern "C" {
+    fn bar();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn quux() {}
index 9de74f72005e359a20f35cf2d8a5fcbaa2532cbd..9883ca6b35d0497b297afff0da37e0f73582dd10 100644 (file)
@@ -20,7 +20,8 @@
 #[no_mangle]
 #[naked]
 fn naked_empty() {
-    // CHECK: ret void
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: ret void
 }
 
 // CHECK: Function Attrs: naked uwtable
@@ -28,9 +29,10 @@ fn naked_empty() {
 #[naked]
 // CHECK-NEXT: define internal void @naked_with_args(i{{[0-9]+}})
 fn naked_with_args(a: isize) {
-    // CHECK: %a = alloca i{{[0-9]+}}
-    // CHECK: ret void
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
+    // CHECK: ret void
 }
 
 // CHECK: Function Attrs: naked uwtable
@@ -38,7 +40,8 @@ fn naked_with_args(a: isize) {
 #[no_mangle]
 #[naked]
 fn naked_with_return() -> isize {
-    // CHECK: ret i{{[0-9]+}} 0
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: ret i{{[0-9]+}} 0
     0
 }
 
@@ -47,9 +50,10 @@ fn naked_with_return() -> isize {
 #[no_mangle]
 #[naked]
 fn naked_with_args_and_return(a: isize) -> isize {
-    // CHECK: %a = alloca i{{[0-9]+}}
-    // CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
+    // CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
     a
 }
 
@@ -58,14 +62,37 @@ fn naked_with_args_and_return(a: isize) -> isize {
 #[no_mangle]
 #[naked]
 fn naked_recursive() {
-    // CHECK: call void @naked_empty()
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: call void @naked_empty()
+
+    // FIXME(#39685) Avoid one block per call.
+    // CHECK-NEXT: br label %bb1
+    // CHECK: bb1:
+
     naked_empty();
-    // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
+
+    // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
+
+    // FIXME(#39685) Avoid one block per call.
+    // CHECK-NEXT: br label %bb2
+    // CHECK: bb2:
+
+    // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
+
+    // FIXME(#39685) Avoid one block per call.
+    // CHECK-NEXT: br label %bb3
+    // CHECK: bb3:
+
+    // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
+
+    // FIXME(#39685) Avoid one block per call.
+    // CHECK-NEXT: br label %bb4
+    // CHECK: bb4:
+
     naked_with_args(
-        // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
         naked_with_args_and_return(
-            // CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
             naked_with_return()
         )
     );
+    // CHECK-NEXT: ret void
 }
index 1d64798bb838202e6f1696addb1f96adaab34a7a..6a17ddebd1dc17f89c7755ea980ef65f8f280f4d 100644 (file)
@@ -10,6 +10,7 @@
 
 fn main() {
     let x = [];
-    //~^ ERROR E0102
-    //~| NOTE cannot resolve type of variable
+    //~^ ERROR type annotations needed
+    //~| NOTE consider giving `x` a type
+    //~| NOTE cannot infer type for `_`
 }
index 0cc6ea3e984d95c9f2c4e365608b0917c9ad5755..cff0064497aff34ac814b8be55d4a1b9c4e64b9d 100644 (file)
@@ -62,7 +62,6 @@ fn mut_plus_immut() {
     &mut f
     +
     &f;  //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
-    //~^ cannot borrow `f` as immutable because it is also borrowed as mutable
 }
 
 fn immut_plus_mut() {
@@ -71,7 +70,6 @@ fn immut_plus_mut() {
     &f
     +
     &mut f;  //~ ERROR: cannot borrow `f` as mutable because it is also borrowed as immutable
-    //~^ cannot borrow `f` as mutable because it is also borrowed as immutable
 }
 
 fn main() {}
index 56cbe0b1878675314087ea02137e368721b1448a..f09e7ffd7e4b791c4b51472ca9db8013b79e0659 100644 (file)
@@ -109,7 +109,6 @@ fn while_aliased_mut_cond(cond: bool, cond2: bool) {
         borrow(&*v); //~ ERROR cannot borrow
         if cond2 {
             x = &mut v; //~ ERROR cannot borrow
-            //~^ ERROR cannot borrow
         }
     }
 }
index f789d44016eb177850ec2dd3cf35b6ae421c3b11..38e0e27a7b98e792e828f44bb7ad64ec83f426a0 100644 (file)
@@ -19,7 +19,6 @@ fn main() {
         match 1 {
             1 => { addr = &mut x; }
             //~^ ERROR cannot borrow `x` as mutable more than once at a time
-            //~| ERROR cannot borrow `x` as mutable more than once at a time
             2 => { addr = &mut x; }
             //~^ ERROR cannot borrow `x` as mutable more than once at a time
             _ => { addr = &mut x; }
diff --git a/src/test/compile-fail/default_ty_param_conflict.rs b/src/test/compile-fail/default_ty_param_conflict.rs
deleted file mode 100644 (file)
index 8cde239..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-use std::fmt::Debug;
-
-// Example from the RFC
-fn foo<F:Default=usize>() -> F { F::default() }
-//~^ NOTE: a default was defined here...
-
-fn bar<B:Debug=isize>(b: B) { println!("{:?}", b); }
-//~^ NOTE: a second default was defined here...
-
-fn main() {
-    // Here, F is instantiated with $0=uint
-    let x = foo();
-    //~^ ERROR: mismatched types
-    //~| NOTE: conflicting type parameter defaults `usize` and `isize`
-    //~| NOTE: conflicting type parameter defaults `usize` and `isize`
-    //~| NOTE: ...that was applied to an unconstrained type variable here
-
-    // Here, B is instantiated with $1=uint, and constraint $0 <: $1 is added.
-    bar(x);
-    //~^ NOTE: ...that also applies to the same type variable here
-}
diff --git a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs b/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs
deleted file mode 100644 (file)
index e5b035e..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-//aux-build:default_ty_param_cross_crate_crate.rs
-
-#![feature(default_type_parameter_fallback)]
-
-extern crate default_param_test;
-
-use default_param_test::{Foo, bleh};
-
-fn meh<X, B=bool>(x: Foo<X, B>) {}
-//~^ NOTE: a default was defined here...
-
-fn main() {
-    let foo = bleh();
-    //~^ NOTE: ...that also applies to the same type variable here
-
-    meh(foo);
-    //~^ ERROR: mismatched types
-    //~| NOTE: conflicting type parameter defaults `bool` and `char`
-    //~| NOTE: conflicting type parameter defaults `bool` and `char`
-    //~| a second default is defined on `default_param_test::bleh`
-    //~| NOTE:  ...that was applied to an unconstrained type variable here
-}
index 835ec8e4a5e7e2060328e2a32e36eb948a056d2c..09bd3a2fc57d97a4f02744a84621c97622f16baa 100644 (file)
@@ -35,7 +35,7 @@ fn main() {
     // n == m
     let &x = &1isize as &T;      //~ ERROR type `&T` cannot be dereferenced
     let &&x = &(&1isize as &T);  //~ ERROR type `&T` cannot be dereferenced
-    let box x = box 1isize as Box<T>; //~ ERROR `T: std::marker::Sized` is not satisfied
+    let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<T>` cannot be dereferenced
 
     // n > m
     let &&x = &1isize as &T;
diff --git a/src/test/compile-fail/feature-gate-global_asm.rs b/src/test/compile-fail/feature-gate-global_asm.rs
new file mode 100644 (file)
index 0000000..0560abb
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// gate-test-global_asm
+
+global_asm!(""); //~ ERROR `global_asm!` is not stable
+
+fn main() {}
index 521f122f8af0b57eec342d14cadd72fee2904610..48c9fda31e8c80707674537252d6a2fe4306d0a9 100644 (file)
 
 #![feature(core_intrinsics)]
 
-use std::intrinsics::{init, forget};
+use std::intrinsics::{init};
 
 // Test that the `forget` and `init` intrinsics are really unsafe
 pub fn main() {
     let stuff = init::<isize>(); //~ ERROR call to unsafe function requires unsafe
-    forget(stuff);             //~ ERROR call to unsafe function requires unsafe
 }
index 346fae11070e15b91e8ef1c8317bda7cf3287292..6aeb9442c40ed9ebb637ac2cbf66e66490d610ac 100644 (file)
@@ -16,4 +16,5 @@ fn main() {
     let &v = new();
     //~^ ERROR type annotations needed [E0282]
     //~| NOTE cannot infer type for `_`
+    //~| NOTE consider giving a type to pattern
 }
index 848174d6fe1e057e1670c5e4d6e4e3161416e038..d52ed06c4085d7d57b4522fac267c709d4f94f22 100644 (file)
@@ -16,4 +16,5 @@ fn main() {
     let &v = new();
     //~^ ERROR type annotations needed [E0282]
     //~| NOTE cannot infer type for `_`
+    //~| NOTE consider giving a type to pattern
 }
index 849c9aa18c905a2ca39d4f44c8aca1537943e894..323ce3b0adf33d89f9166ffd2c2b60182a2120cb 100644 (file)
@@ -17,7 +17,6 @@ fn causes_ice(mut l: &mut Sexpression) {
     loop { match l {
         &mut Sexpression::Num(ref mut n) => {},
         &mut Sexpression::Cons(ref mut expr) => { //~ ERROR cannot borrow `l.0`
-            //~| ERROR cannot borrow `l.0`
             l = &mut **expr; //~ ERROR cannot assign to `l`
         }
     }}
diff --git a/src/test/compile-fail/issue-30225.rs b/src/test/compile-fail/issue-30225.rs
new file mode 100644 (file)
index 0000000..7acbbfb
--- /dev/null
@@ -0,0 +1,48 @@
+// 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.
+
+// Regression test for #30225, which was an ICE that would trigger as
+// a result of a poor interaction between trait result caching and
+// type inference. Specifically, at that time, unification could cause
+// unrelated type variables to become instantiated, if subtyping
+// relationships existed. These relationships are now propagated
+// through obligations and hence everything works out fine.
+
+trait Foo<U,V> : Sized {
+    fn foo(self, u: Option<U>, v: Option<V>) {}
+}
+
+struct A;
+struct B;
+
+impl Foo<A, B> for () {}      // impl A
+impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
+
+fn toxic() {
+    // cache the resolution <() as Foo<$0,$1>> = impl A
+    let u = None;
+    let v = None;
+    Foo::foo((), u, v);
+}
+
+fn bomb() {
+    let mut u = None; // type is Option<$0>
+    let mut v = None; // type is Option<$1>
+    let mut x = None; // type is Option<$2>
+
+    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
+    u = v; // mark $0 and $1 in a subtype relationship
+    //~^ ERROR mismatched types
+    x = Some(()); // set $2 = (), allowing impl selection
+                  // to proceed for <() as Foo<$0, $1>> = impl A.
+                  // kaboom, this *used* to trigge an ICE
+}
+
+fn main() {}
index 3b62aaf2ab8e9450789eca11ffa54610af1bc333..b4feadbacf7404cc61d1b9cc91f54224eaa19ffd 100644 (file)
@@ -11,7 +11,6 @@
 fn main() {
     let Box(a) = loop { };
     //~^ ERROR expected tuple struct/variant, found struct `Box`
-    //~| ERROR expected tuple struct/variant, found struct `Box`
 
     // (The below is a trick to allow compiler to infer a type for
     // variable `a` without attempting to ascribe a type to the
diff --git a/src/test/compile-fail/issue-41139.rs b/src/test/compile-fail/issue-41139.rs
new file mode 100644 (file)
index 0000000..15ca151
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+trait Trait {}
+
+fn get_function<'a>() -> &'a Fn() -> Trait { panic!("") }
+
+fn main() {
+    let t : &Trait = &get_function()();
+    //~^ ERROR cannot move a value of type Trait + 'static
+}
index fdd89058fd3973498140ded97fe2f7b3d1c2d43c..a5f001b785cc9481b9ceef9a31e6b0bf767b7600 100644 (file)
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 fn main() {
-    let v = &[];
-    let it = v.iter(); //~ ERROR type annotations needed [E0282]
-                       //~| NOTE cannot infer type for `T`
-                       //~| NOTE consider giving `it` a type
+    let v = &[]; //~ ERROR type annotations needed
+    //~| NOTE consider giving `v` a type
+    //~| NOTE cannot infer type for `_`
+    let it = v.iter();
 }
index f6f7c210f466a0712d6dca5d2269e4289ca8ec12..5bb2ab75c53fd42a8fadd9b43920b94e87e0d216 100644 (file)
@@ -21,7 +21,6 @@
 // Should get errors for both 'Some' and 'None'
 use std::option::Option::{Some, None};
 //~^ ERROR unused imports: `None`, `Some`
-//~| ERROR unused imports: `None`, `Some`
 
 use test::A;       //~ ERROR unused import: `test::A`
 // Be sure that if we just bring some methods into scope that they're also
diff --git a/src/test/compile-fail/union/union-borrow-move-parent-sibling.rs b/src/test/compile-fail/union/union-borrow-move-parent-sibling.rs
new file mode 100644 (file)
index 0000000..5f504fe
--- /dev/null
@@ -0,0 +1,57 @@
+// 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(untagged_unions)]
+#![allow(unused)]
+
+#[allow(unions_with_drop_fields)]
+union U {
+    x: ((Vec<u8>, Vec<u8>), Vec<u8>),
+    y: Box<Vec<u8>>,
+}
+
+unsafe fn parent_sibling_borrow() {
+    let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = &mut u.x.0;
+    let a = &u.y; //~ ERROR cannot borrow `u.y`
+}
+
+unsafe fn parent_sibling_move() {
+    let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = u.x.0;
+    let a = u.y; //~ ERROR use of moved value: `u.y`
+}
+
+unsafe fn grandparent_sibling_borrow() {
+    let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = &mut (u.x.0).0;
+    let a = &u.y; //~ ERROR cannot borrow `u.y`
+}
+
+unsafe fn grandparent_sibling_move() {
+    let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = (u.x.0).0;
+    let a = u.y; //~ ERROR use of moved value: `u.y`
+}
+
+unsafe fn deref_sibling_borrow() {
+    let mut u = U { y: Box::default() };
+    let a = &mut *u.y;
+    let a = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
+}
+
+unsafe fn deref_sibling_move() {
+    let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+    let a = *u.y;
+    let a = u.x; //~ ERROR use of moved value: `u.x`
+}
+
+
+fn main() {}
index 048ccb529a24fc9a516eaeea9667189c55c454fd..37c6ef58f5e56bf680c07ca33d956b044f7917ac 100644 (file)
@@ -38,8 +38,13 @@ enum EnumVisibility { A }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-pub enum EnumVisibility { A }
+pub enum EnumVisibility {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    A
+}
 
 
 
@@ -56,7 +61,10 @@ enum EnumChangeNameCStyleVariant {
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeNameCStyleVariant {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     Variant1,
+    #[rustc_metadata_clean(cfg="cfail3")]
     Variant2Changed,
 }
 
@@ -259,10 +267,13 @@ enum EnumChangeFieldTypeTupleStyleVariant {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeTupleStyleVariant {
-    Variant1(u32, u64),
+    Variant1(u32,
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        u64),
 }
 
 
@@ -277,11 +288,16 @@ enum EnumChangeFieldTypeStructStyleVariant {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
-    Variant2 { a: u32, b: u64 },
+    Variant2 {
+        a: u32,
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        b: u64
+    },
 }
 
 
@@ -312,10 +328,16 @@ enum EnumChangeOrderTupleStyleVariant {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeOrderTupleStyleVariant {
-    Variant1(u64, u32),
+    Variant1(
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        u64,
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        u32),
 }
 
 
@@ -611,11 +633,23 @@ enum EnumSwapUsageTypeParameters<A, B> {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumSwapUsageTypeParameters<A, B> {
-    Variant1 { a: B },
-    Variant2 { a: A },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant1 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        a: B
+    },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant2 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        a: A
+    },
 }
 
 
@@ -630,11 +664,23 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
-    Variant1 { a: &'b u32 },
-    Variant2 { b: &'a u32 },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant1 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        a: &'b u32
+    },
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    Variant2 {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        b: &'a u32
+    },
 }
 
 
@@ -653,10 +699,16 @@ mod change_field_type_indirectly_tuple_style {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     enum TupleStyle {
-        Variant1(FieldType)
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        Variant1(
+            #[rustc_metadata_dirty(cfg="cfail2")]
+            #[rustc_metadata_clean(cfg="cfail3")]
+            FieldType
+        )
     }
 }
 
@@ -671,10 +723,16 @@ mod change_field_type_indirectly_struct_style {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     enum StructStyle {
-        Variant1 { a: FieldType }
+        #[rustc_metadata_clean(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        Variant1 {
+            #[rustc_metadata_dirty(cfg="cfail2")]
+            #[rustc_metadata_clean(cfg="cfail3")]
+            a: FieldType
+        }
     }
 }
 
index 03e621fedbeb4d49bc3dd5a5af34c874f7dd0874..1d26e6c07d15bc9ab081d7f57a33053dfd7f5800 100644 (file)
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_parameter_name(d: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_parameter_type(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_return_type(c: i32) -> i8;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_parameter(c: i32, d: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_return_type(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn make_function_variadic(c: i32, ...);
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern "rust-call" {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_calling_convention(c: i32);
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 extern {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     pub fn make_function_public(c: i32);
 }
 
@@ -246,9 +262,11 @@ mod indirectly_change_parameter_type {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     extern {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         pub fn indirectly_change_parameter_type(c: c_int);
     }
 }
@@ -264,9 +282,11 @@ mod indirectly_change_return_type {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     extern {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         pub fn indirectly_change_return_type() -> c_int;
     }
 }
index 93d94cd1a19c4b83e20c16bfef8dc6c9921e4139..2fe3f0d5d1fe03911aaa08cd7e87874665c89ffc 100644 (file)
@@ -50,7 +50,7 @@ fn add_return_type() {}
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")] // The type doesn't change, so metadata is the same
 #[rustc_metadata_clean(cfg="cfail3")]
 fn add_return_type() -> () {}
 
@@ -154,7 +154,7 @@ fn lifetime_parameter() {}
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+// #[rustc_metadata_dirty(cfg="cfail2")] -- Unused lifetime params don't show up in the type?
 #[rustc_metadata_clean(cfg="cfail3")]
 fn lifetime_parameter<'a>() {}
 
@@ -315,16 +315,16 @@ fn return_impl_trait() -> impl Clone {
 
 #[cfg(cfail1)]
 fn change_return_impl_trait() -> impl Clone {
-    0
+    0u32
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")] // The actual type is the same, so: clean
 #[rustc_metadata_clean(cfg="cfail3")]
 fn change_return_impl_trait() -> impl Copy {
-    0
+    0u32
 }
 
 
index fd9ac61046e3a978add0ffde467dc65a420c9d60..899aefa24a033b0e3d4eeeb666b96c7e3b9c86d2 100644 (file)
@@ -107,7 +107,7 @@ pub fn method_privacy() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -126,7 +126,7 @@ pub fn method_selfness() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -171,7 +171,7 @@ pub fn add_method_to_impl1(&self) { }
 impl Foo {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_method_to_impl1(&self) { }
 
@@ -219,9 +219,7 @@ impl Foo {
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    // At the moment we explicitly ignore argument names in metadata, since they
-    // are not used in downstream crates (except in rustdoc)
-    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
@@ -287,9 +285,7 @@ impl Foo {
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
     #[rustc_clean(label="HirBody", cfg="cfail3")]
-    // At the moment we explicitly ignore argument names in metadata, since they
-    // are not used in downstream crates (except in rustdoc)
-    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
@@ -373,7 +369,7 @@ pub fn add_lifetime_parameter_to_method(&self) { }
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")] // Apparently unused lifetimes don't show up in the type.
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
@@ -544,7 +540,7 @@ pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 impl<T: 'static> Bar<T> {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
@@ -565,7 +561,7 @@ pub fn add_trait_bound_to_impl_parameter(&self) { }
 impl<T: Clone> Bar<T> {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
index 2d79987823f2036c1c944fdd412c6e22b9a39b13..17a5dc16783678fe8326ade18b0d643f035d08e3 100644 (file)
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct TupleStructFieldType(u32);
+struct TupleStructFieldType(
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    u32
+);
 
 
 // Tuple Struct Add Field ------------------------------------------------------
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct TupleStructAddField(i32, u32);
+struct TupleStructAddField(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    i32,
+    #[rustc_metadata_clean(cfg="cfail3")]
+    u32
+);
 
 
 // Tuple Struct Field Visibility -----------------------------------------------
@@ -101,9 +111,13 @@ struct RecordStructFieldType { x: f32 }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct RecordStructFieldType { x: u64 }
+struct RecordStructFieldType {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    x: u64
+}
 
 
 // Record Struct Field Name ----------------------------------------------------
@@ -129,7 +143,12 @@ struct RecordStructAddField { x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct RecordStructAddField { x: f32, y: () }
+struct RecordStructAddField {
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    x: f32,
+    #[rustc_metadata_clean(cfg="cfail3")]
+    y: () }
 
 
 // Record Struct Field Visibility ----------------------------------------------
@@ -142,7 +161,11 @@ struct RecordStructFieldVisibility { x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct RecordStructFieldVisibility { pub x: f32 }
+struct RecordStructFieldVisibility {
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    pub x: f32
+}
 
 
 // Add Lifetime Parameter ------------------------------------------------------
@@ -168,7 +191,14 @@ struct RecordStructFieldVisibility { pub x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddLifetimeParameterBound<'a, 'b: 'a>(&'a f32, &'b f64);
+struct AddLifetimeParameterBound<'a, 'b: 'a>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'a f32,
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'b f64
+);
 
 #[cfg(cfail1)]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
@@ -178,7 +208,13 @@ struct RecordStructFieldVisibility { pub x: f32 }
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
+struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'a f32,
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    &'b f64)
     where 'b: 'a;
 
 
@@ -192,7 +228,16 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddTypeParameter<T1, T2>(T1, T2);
+struct AddTypeParameter<T1, T2>(
+     // The field contains the parent's Generics, so it's dirty even though its
+     // type hasn't changed.
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T1,
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T2
+);
 
 
 // Add Type Parameter Bound ----------------------------------------------------
@@ -205,7 +250,11 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddTypeParameterBound<T: Send>(T);
+struct AddTypeParameterBound<T: Send>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T
+);
 
 
 #[cfg(cfail1)]
@@ -216,7 +265,11 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-struct AddTypeParameterBoundWhereClause<T>(T) where T: Sync;
+struct AddTypeParameterBoundWhereClause<T>(
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    T
+) where T: Sync;
 
 
 // Empty struct ----------------------------------------------------------------
@@ -234,6 +287,7 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64)
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub struct Visibility;
 
@@ -252,9 +306,13 @@ mod tuple_struct_change_field_type_indirectly {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    struct TupleStruct(FieldType);
+    struct TupleStruct(
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
+        FieldType
+    );
 }
 
 
@@ -267,9 +325,11 @@ mod record_struct_change_field_type_indirectly {
 
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     struct RecordStruct {
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         _x: FieldType
     }
 }
index 94698506ec53fd6df782c9fcb32fe7775a6a177e..61a2be054a51a61e8758f837d3d67a3344b235b9 100644 (file)
@@ -100,7 +100,7 @@ trait TraitAddReturnType {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddReturnType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -121,7 +121,7 @@ trait TraitChangeReturnType {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeReturnType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -142,7 +142,7 @@ trait TraitAddParameterToMethod {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -164,7 +164,7 @@ fn with_default(x: i32) {}
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
@@ -194,7 +194,7 @@ trait TraitChangeMethodParameterType {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -215,7 +215,7 @@ trait TraitChangeMethodParameterTypeRef {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -236,7 +236,7 @@ trait TraitChangeMethodParametersOrder {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -257,9 +257,13 @@ trait TraitAddMethodDefaultImplementation {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddMethodDefaultImplementation {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method() { }
 }
 
@@ -293,7 +297,7 @@ trait TraitChangeModeSelfRefToMut {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -335,7 +339,7 @@ trait TraitChangeModeSelfOwnToRef {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -356,7 +360,7 @@ trait TraitAddUnsafeModifier {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddUnsafeModifier {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -377,7 +381,7 @@ trait TraitAddExternModifier {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddExternModifier {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -398,7 +402,7 @@ trait TraitChangeExternCToRustIntrinsic {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -419,7 +423,7 @@ trait TraitAddTypeParameterToMethod {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -440,12 +444,12 @@ trait TraitAddLifetimeParameterToMethod {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")] // Unused lifetimes don't seem to show up in type?
     #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a>();
 }
@@ -465,7 +469,7 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -486,7 +490,7 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -507,7 +511,7 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -528,7 +532,7 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -549,7 +553,7 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -570,7 +574,7 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -585,7 +589,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 // Add associated type ------------------------------------------------------------
 #[cfg(cfail1)]
 trait TraitAddAssociatedType {
-    fn mathod();
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn method();
 }
 
 #[cfg(not(cfail1))]
@@ -596,7 +605,7 @@ trait TraitAddAssociatedType {
 trait TraitAddAssociatedType {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -606,9 +615,12 @@ trait TraitAddAssociatedType {
 trait TraitAddTraitBoundToAssociatedType {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
+
+// Apparently the type bound contributes to the predicates of the trait, but
+// does not change the associated item itself.
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
@@ -617,11 +629,11 @@ trait TraitAddTraitBoundToAssociatedType {
 trait TraitAddTraitBoundToAssociatedType {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -631,7 +643,7 @@ trait TraitAddTraitBoundToAssociatedType {
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
@@ -642,11 +654,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: 'a;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -656,18 +668,22 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 trait TraitAddDefaultToAssociatedType {
     type Associated;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddDefaultToAssociatedType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     type Associated = ReferenceType0;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -675,7 +691,7 @@ trait TraitAddDefaultToAssociatedType {
 // Add associated constant --------------------------------------------------------
 #[cfg(cfail1)]
 trait TraitAddAssociatedConstant {
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
@@ -686,7 +702,7 @@ trait TraitAddAssociatedConstant {
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
-    fn mathod();
+    fn method();
 }
 
 
@@ -696,18 +712,26 @@ trait TraitAddAssociatedConstant {
 trait TraitAddInitializerToAssociatedConstant {
     const Value: u32;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddInitializerToAssociatedConstant {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     const Value: u32 = 1;
 
-    fn mathod();
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn method();
 }
 
 
@@ -717,13 +741,13 @@ trait TraitAddInitializerToAssociatedConstant {
 trait TraitChangeTypeOfAssociatedConstant {
     const Value: u32;
 
-    fn mathod();
+    fn method();
 }
 
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -732,7 +756,11 @@ trait TraitChangeTypeOfAssociatedConstant {
     #[rustc_metadata_clean(cfg="cfail3")]
     const Value: f64;
 
-    fn mathod();
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_clean(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn method();
 }
 
 
@@ -1111,9 +1139,6 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
-
-// EDIT: Some more cases ----------------------------------------------------------
-
 // Change return type of method indirectly by modifying a use statement------------
 mod change_return_type_of_method_indirectly_use {
     #[cfg(cfail1)]
@@ -1123,7 +1148,7 @@ mod change_return_type_of_method_indirectly_use {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeReturnType {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -1145,7 +1170,7 @@ mod change_method_parameter_type_indirectly_by_use {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeArgType {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -1167,7 +1192,7 @@ mod change_method_parameter_type_bound_indirectly_by_use {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -1190,7 +1215,7 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
         #[rustc_dirty(label="Hir", cfg="cfail2")]
index 30e376f04fb87ff78b0a4fa7d4f4db82306c4516..06c8eb6a878f06e96a88451a87cbb9ad69a9f8de 100644 (file)
@@ -120,7 +120,7 @@ impl ChangeMethodBodyTraitInlined for Foo {
     #[rustc_metadata_clean(cfg="cfail3")]
     #[inline]
     fn method_name() {
-        ()
+        panic!()
     }
 }
 
@@ -144,7 +144,7 @@ pub trait ChangeMethodSelfnessTrait {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeMethodSelfnessTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -176,16 +176,14 @@ pub trait RemoveMethodSelfnessTrait {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl RemoveMethodSelfnessTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn method_name() {
-        ()
-    }
+    fn method_name() {}
 }
 
 // Change Method Selfmutness -----------------------------------------------------------
@@ -208,16 +206,14 @@ pub trait ChangeMethodSelfmutnessTrait {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeMethodSelfmutnessTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn method_name(&mut self) {
-        ()
-    }
+    fn method_name(&mut self) {}
 }
 
 // Change item kind -----------------------------------------------------------
@@ -317,16 +313,20 @@ fn method_name() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub trait ChangeHasValueTrait {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
@@ -346,32 +346,16 @@ fn method_name() { }
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl AddDefaultTrait for Foo {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     default fn method_name() { }
 }
 
-// Remove default
-
-pub trait RemoveDefaultTrait {
-    fn method_name();
-}
-
-#[cfg(cfail1)]
-impl RemoveDefaultTrait for Foo {
-    default fn method_name() { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
-#[rustc_metadata_clean(cfg="cfail3")]
-impl RemoveDefaultTrait for Foo {
-    fn method_name() { }
-}
-
 // Add arguments
 
 #[cfg(cfail1)]
@@ -392,7 +376,7 @@ pub trait AddArgumentTrait {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl AddArgumentTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -422,7 +406,7 @@ pub trait ChangeArgumentTypeTrait {
 #[cfg(not(cfail1))]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 impl ChangeArgumentTypeTrait for Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
@@ -504,7 +488,7 @@ fn id(self) -> Self { self }
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
@@ -529,7 +513,7 @@ fn id(self) -> Self { self }
 impl<T: Clone> AddTraitBoundToImplParameter for T {
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
index 4017b4d4ba9aee6085c31b165248d9bae6133e40..917c2c9dbce4f10434ebb49e6b7984d7414785f9 100644 (file)
@@ -33,13 +33,3 @@ fn main() {
     }
 }
 
-struct _Struct {
-    #[rustc_metadata_dirty(cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
-    _field1: i32,
-
-    #[rustc_metadata_clean(cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
-    _field2: i32,
-}
-
diff --git a/src/test/parse-fail/tuple-float-index.rs b/src/test/parse-fail/tuple-float-index.rs
deleted file mode 100644 (file)
index 57ad89a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-fn main () {
-    (1, (2, 3)).1.1; //~ ERROR unexpected token
-                     //~^ HELP try parenthesizing the first index
-                     //~| SUGGESTION ((1, (2, 3)).1).1
-}
index 4253767ee76a962ee0604693fe6d9e97e2b3da3b..4e09928edc6d1c7972fd6629f69b1a4fd982b159 100644 (file)
@@ -38,6 +38,11 @@ struct Huge {
     int32_t e;
 };
 
+struct FloatPoint {
+    double x;
+    double y;
+};
+
 // System V x86_64 ABI:
 // a, b, c, d, e should be in registers
 // s should be byval pointer
@@ -258,3 +263,17 @@ struct Huge huge_struct(struct Huge s) {
 
     return s;
 }
+
+// System V x86_64 ABI:
+// p should be in registers
+// return should be in registers
+//
+// Win64 ABI:
+// p should be a byval pointer
+// return should be in a hidden sret pointer
+struct FloatPoint float_point(struct FloatPoint p) {
+    assert(p.x == 5.);
+    assert(p.y == -3.);
+
+    return p;
+}
index b91362b8edccb0849a4030ee4802849d09d307c9..ff845a644b11441beedabbac2666a078d891385b 100644 (file)
@@ -46,6 +46,13 @@ struct Huge {
     e: i32
 }
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(C)]
+struct FloatPoint {
+    x: f64,
+    y: f64
+}
+
 #[link(name = "test", kind = "static")]
 extern {
     fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect);
@@ -72,6 +79,8 @@ fn byval_rect_floats(a: f32, b: f32, c: f64, d: f32, e: f32,
     fn sret_split_struct(a: i32, b: i32, s: Rect) -> BiggerRect;
 
     fn huge_struct(s: Huge) -> Huge;
+
+    fn float_point(p: FloatPoint) -> FloatPoint;
 }
 
 fn main() {
@@ -79,6 +88,7 @@ fn main() {
     let t = BiggerRect { s: s, a: 27834, b: 7657 };
     let u = FloatRect { a: 3489, b: 3490, c: 8. };
     let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 };
+    let p = FloatPoint { x: 5., y: -3. };
 
     unsafe {
         byval_rect(1, 2, 3, 4, 5, s);
@@ -94,5 +104,6 @@ fn main() {
         assert_eq!(split_ret_byval_struct(1, 2, s), s);
         assert_eq!(sret_byval_struct(1, 2, 3, 4, s), t);
         assert_eq!(sret_split_struct(1, 2, s), t);
+        assert_eq!(float_point(p), p);
     }
 }
diff --git a/src/test/run-pass/default_ty_param_default_dependent_associated_type.rs b/src/test/run-pass/default_ty_param_default_dependent_associated_type.rs
deleted file mode 100644 (file)
index 8fc2c2e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![feature(default_type_parameter_fallback)]
-
-use std::marker::PhantomData;
-
-trait Id {
-    type This;
-}
-
-impl<A> Id for A {
-    type This = A;
-}
-
-struct Foo<X: Default = usize, Y = <X as Id>::This> {
-    data: PhantomData<(X, Y)>
-}
-
-impl<X: Default, Y> Foo<X, Y> {
-    fn new() -> Foo<X, Y> {
-        Foo { data: PhantomData }
-    }
-}
-
-fn main() {
-    let foo = Foo::new();
-}
diff --git a/src/test/run-pass/default_ty_param_dependent_defaults.rs b/src/test/run-pass/default_ty_param_dependent_defaults.rs
deleted file mode 100644 (file)
index ac833d0..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![feature(default_type_parameter_fallback)]
-use std::marker::PhantomData;
-
-struct Foo<T,U=T> { t: T, data: PhantomData<U> }
-
-fn main() {
-    let foo = Foo { t: 'a', data: PhantomData };
-}
diff --git a/src/test/run-pass/default_ty_param_method_call_test.rs b/src/test/run-pass/default_ty_param_method_call_test.rs
deleted file mode 100644 (file)
index e8d9309..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-struct Foo;
-
-impl Foo {
-    fn method<A:Default=String>(&self) -> A {
-        A::default()
-    }
-}
-
-fn main() {
-    let f = Foo.method();
-    println!("{}", f);
-}
diff --git a/src/test/run-pass/default_ty_param_struct.rs b/src/test/run-pass/default_ty_param_struct.rs
deleted file mode 100644 (file)
index d9ac51f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-struct Foo<A>(A);
-
-impl<A:Default=i32> Foo<A> {
-    fn new() -> Foo<A> {
-        Foo(A::default())
-    }
-}
-
-fn main() {
-    let foo = Foo::new();
-}
diff --git a/src/test/run-pass/default_ty_param_struct_and_type_alias.rs b/src/test/run-pass/default_ty_param_struct_and_type_alias.rs
deleted file mode 100644 (file)
index d3bdab9..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![feature(default_type_parameter_fallback)]
-
-use std::marker::PhantomData;
-
-pub struct DeterministicHasher;
-pub struct RandomHasher;
-
-
-pub struct MyHashMap<K, V, H=DeterministicHasher> {
-    data: PhantomData<(K, V, H)>
-}
-
-impl<K, V, H> MyHashMap<K, V, H> {
-    fn new() -> MyHashMap<K, V, H> {
-        MyHashMap { data: PhantomData }
-    }
-}
-
-mod mystd {
-    use super::{MyHashMap, RandomHasher};
-    pub type HashMap<K, V, H=RandomHasher> = MyHashMap<K, V, H>;
-}
-
-fn try_me<H>(hash_map: mystd::HashMap<i32, i32, H>) {}
-
-fn main() {
-    let hash_map = mystd::HashMap::new();
-    try_me(hash_map);
-}
diff --git a/src/test/run-pass/default_ty_param_trait_impl.rs b/src/test/run-pass/default_ty_param_trait_impl.rs
deleted file mode 100644 (file)
index c67d3a4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-// Another example from the RFC
-trait Foo { }
-trait Bar { }
-
-impl<T:Bar=usize> Foo for Vec<T> {}
-impl Bar for usize {}
-
-fn takes_foo<F:Foo>(f: F) {}
-
-fn main() {
-    let x = Vec::new(); // x: Vec<$0>
-    takes_foo(x); // adds oblig Vec<$0> : Foo
-}
diff --git a/src/test/run-pass/default_ty_param_trait_impl_simple.rs b/src/test/run-pass/default_ty_param_trait_impl_simple.rs
deleted file mode 100644 (file)
index 067ad52..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-// An example from the RFC
-trait Foo { fn takes_foo(&self); }
-trait Bar { }
-
-impl<T:Bar=usize> Foo for Vec<T> {
-    fn takes_foo(&self) {}
-}
-
-impl Bar for usize {}
-
-fn main() {
-    let x = Vec::new(); // x: Vec<$0>
-    x.takes_foo(); // adds oblig Vec<$0> : Foo
-}
diff --git a/src/test/run-pass/default_ty_param_type_alias.rs b/src/test/run-pass/default_ty_param_type_alias.rs
deleted file mode 100644 (file)
index 1b47474..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-use std::collections::HashMap;
-
-type IntMap<K=usize> = HashMap<K, usize>;
-
-fn main() {
-    let x = IntMap::new();
-}
diff --git a/src/test/run-pass/empty_global_asm.rs b/src/test/run-pass/empty_global_asm.rs
new file mode 100644 (file)
index 0000000..db73da2
--- /dev/null
@@ -0,0 +1,28 @@
+// 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(global_asm)]
+
+#[cfg(target_arch = "x86")]
+global_asm!("");
+
+#[cfg(target_arch = "x86_64")]
+global_asm!("");
+
+#[cfg(target_arch = "arm")]
+global_asm!("");
+
+#[cfg(target_arch = "aarch64")]
+global_asm!("");
+
+#[cfg(target_arch = "mips")]
+global_asm!("");
+
+fn main() {}
index dc4f0774b9771e87e35557a4759585888a6c8bf1..c5057f70c065ae1dc784b4c6fe36f57e3835d023 100644 (file)
@@ -104,4 +104,9 @@ fn main() {
     assert_eq!(l.checked_sub(l), Some(0));
     assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127));
     assert_eq!(o.checked_shl(b(128)), None);
+
+    // https://github.com/rust-lang/rust/issues/41228
+    assert_eq!(b(-87559967289969187895646876466835277875_i128) /
+               b(84285771033834995895337664386045050880_i128),
+               -1i128);
 }
diff --git a/src/test/run-pass/issue-40951.rs b/src/test/run-pass/issue-40951.rs
new file mode 100644 (file)
index 0000000..adc7101
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+// Regression test for #40951.
+
+const FOO: [&'static str; 1] = ["foo"];
+
+fn find<T: PartialEq>(t: &[T], element: &T) { }
+
+fn main() {
+    let x = format!("hi");
+    find(&FOO, &&*x);
+}
diff --git a/src/test/run-pass/issue-41213.rs b/src/test/run-pass/issue-41213.rs
new file mode 100644 (file)
index 0000000..d475502
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+enum A {
+    A1,
+    A2,
+    A3,
+}
+
+enum B {
+    B1(String, String),
+    B2(String, String),
+}
+
+fn main() {
+    let a = A::A1;
+    loop {
+        let _ctor = match a {
+            A::A3 => break,
+            A::A1 => B::B1,
+            A::A2 => B::B2,
+        };
+        break;
+    }
+}
diff --git a/src/test/run-pass/optimization-fuel-0.rs b/src/test/run-pass/optimization-fuel-0.rs
new file mode 100644 (file)
index 0000000..3832c04
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="foo"]
+
+use std::mem::size_of;
+
+// compile-flags: -Z fuel=foo=0
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+
+fn main() {
+    assert_eq!(size_of::<S1>(), 6);
+    assert_eq!(size_of::<S2>(), 6);
+}
+
diff --git a/src/test/run-pass/optimization-fuel-1.rs b/src/test/run-pass/optimization-fuel-1.rs
new file mode 100644 (file)
index 0000000..5f294e2
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="foo"]
+
+use std::mem::size_of;
+
+// compile-flags: -Z fuel=foo=1
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+
+fn main() {
+    let optimized = (size_of::<S1>() == 4) as usize
+        +(size_of::<S2>() == 4) as usize;
+    assert_eq!(optimized, 1);
+}
+
+
diff --git a/src/test/run-pass/simple_global_asm.rs b/src/test/run-pass/simple_global_asm.rs
new file mode 100644 (file)
index 0000000..cd8273c
--- /dev/null
@@ -0,0 +1,31 @@
+// 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(global_asm)]
+#![feature(naked_functions)]
+
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
+global_asm!(r#"
+    .global foo
+    .global _foo
+foo:
+_foo:
+    ret
+"#);
+
+extern {
+    fn foo();
+}
+
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
+fn main() { unsafe { foo(); } }
+
+#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
+fn main() {}
diff --git a/src/test/run-pass/type-infer-generalize-ty-var.rs b/src/test/run-pass/type-infer-generalize-ty-var.rs
new file mode 100644 (file)
index 0000000..d7fb85c
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a scenario where we generate a constraint like `?1 <: &?2`.
+// In such a case, it is important that we instantiate `?1` with `&?3`
+// where `?3 <: ?2`, and not with `&?2`. This is a regression test for
+// #18653. The important thing is that we build.
+
+use std::cell::RefCell;
+
+enum Wrap<A> {
+    WrapSome(A),
+    WrapNone
+}
+
+use Wrap::*;
+
+struct T;
+struct U;
+
+trait Get<T: ?Sized> {
+    fn get(&self) -> &T;
+}
+
+impl Get<MyShow + 'static> for Wrap<T> {
+    fn get(&self) -> &(MyShow + 'static) {
+        static x: usize = 42;
+        &x
+    }
+}
+
+impl Get<usize> for Wrap<U> {
+    fn get(&self) -> &usize {
+        static x: usize = 55;
+        &x
+    }
+}
+
+trait MyShow { fn dummy(&self) { } }
+impl<'a> MyShow for &'a (MyShow + 'a) { }
+impl MyShow for usize { }
+fn constrain<'a>(rc: RefCell<&'a (MyShow + 'a)>) { }
+
+fn main() {
+    let mut collection: Wrap<_> = WrapNone;
+
+    {
+        let __arg0 = Get::get(&collection);
+        let __args_cell = RefCell::new(__arg0);
+        constrain(__args_cell);
+    }
+    collection = WrapSome(T);
+}
index bbb01eaaf46b9b43afbdbf4bdbf4c7ebfbf4aa61..2f50e63153ea4bf8722b3bec2458aaa40d6168be 100644 (file)
@@ -31,6 +31,17 @@ enum e3 {
     a([u16; 0], u8), b
 }
 
+struct ReorderedStruct {
+    a: u8,
+    b: u16,
+    c: u8
+}
+
+enum ReorderedEnum {
+    A(u8, u16, u8),
+    B(u8, u16, u8),
+}
+
 pub fn main() {
     assert_eq!(size_of::<u8>(), 1 as usize);
     assert_eq!(size_of::<u32>(), 4 as usize);
@@ -54,4 +65,6 @@ pub fn main() {
     assert_eq!(size_of::<e1>(), 8 as usize);
     assert_eq!(size_of::<e2>(), 8 as usize);
     assert_eq!(size_of::<e3>(), 4 as usize);
+    assert_eq!(size_of::<ReorderedStruct>(), 4);
+    assert_eq!(size_of::<ReorderedEnum>(), 6);
 }
index ac3dfcdfde155cd79aca32d0c6b71e937303d93c..cfd616c56b4f02ed18e42a4170d8207d0586a9fe 100644 (file)
@@ -77,4 +77,49 @@ fn main() {
     assert_eq!(o.checked_sub(b(18)), None);
     assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127));
     assert_eq!(o.checked_shl(b(128)), None);
+
+    // Test cases for all udivmodti4 branches.
+    // case "0X/0X"
+    assert_eq!(b(0x69545bd57727c050_u128) /
+               b(0x3283527a3350d88c_u128),
+               2u128);
+    // case "0X/KX"
+    assert_eq!(b(0x0_8003c9c50b473ae6_u128) /
+               b(0x1_283e8838c30fa8f4_u128),
+               0u128);
+    // case "K0/K0"
+    assert_eq!(b(0xc43f42a207978720_u128 << 64) /
+               b(0x098e62b74c23cf1a_u128 << 64),
+               20u128);
+    // case "KK/K0" for power-of-two D.
+    assert_eq!(b(0xa9008fb6c9d81e42_0e25730562a601c8_u128) /
+               b(1u128 << 120),
+               169u128);
+    // case "KK/K0" with N >= D (https://github.com/rust-lang/rust/issues/41228).
+    assert_eq!(b(0xe4d26e59f0640328_06da5b06efe83a41_u128) /
+               b(0x330fcb030ea4447c_u128 << 64),
+               4u128);
+    assert_eq!(b(3u128 << 64 | 1) /
+               b(3u128 << 64),
+               1u128);
+    // case "KK/K0" with N < D.
+    assert_eq!(b(0x6655c9fb66ca2884_e2d1dfd470158c62_u128) /
+               b(0xb35b667cab7e355b_u128 << 64),
+               0u128);
+    // case "KX/0K" for power-of-two D.
+    assert_eq!(b(0x3e49dd84feb2df59_7b2f97d93a253969_u128) /
+               b(1u128 << 4),
+               0x03e49dd84feb2df5_97b2f97d93a25396_u128);
+    // case "KX/0K" in general.
+    assert_eq!(b(0x299692b3a1dae5bd_6162e6f489d2620e_u128) /
+               b(0x900b6f027571d6f7_u128),
+               0x49e95f54b0442578_u128);
+    // case "KX/KK" with N >= D.
+    assert_eq!(b(0xc7b889180b67b07d_bc1a3c88783d35b5_u128) /
+               b(0x1d7e69f53160b9e2_60074771e852f244_u128),
+               6u128);
+    // case "KX/KK" with N < D.
+    assert_eq!(b(0x679289ac23bb334f_36144401cf882172_u128) /
+               b(0x7b0b271b64865f05_f54a7b72746c062f_u128),
+               0u128);
 }
diff --git a/src/test/rustdoc/auxiliary/issue-40936.rs b/src/test/rustdoc/auxiliary/issue-40936.rs
new file mode 100644 (file)
index 0000000..54cc18c
--- /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.
+
+pub mod outermod {
+    pub mod innermod {
+        pub use super::*;
+    }
+}
diff --git a/src/test/rustdoc/issue-40936.rs b/src/test/rustdoc/issue-40936.rs
new file mode 100644 (file)
index 0000000..3e02eec
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+// aux-build:issue-40936.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+
+extern crate issue_40936;
index 6f42a9f679a6a51225746d8d0f386139afc0f8f4..6956a043cc694a4a8ee04375b23c0e658948e10c 100644 (file)
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 16 |     x.push(y);
    |            ^ lifetime mismatch
    |
-   = note: expected type `Ref<'a, i32>`
-              found type `Ref<'_, i32>`
+   = note: expected type `Ref<'a, _>`
+              found type `Ref<'_, _>`
 note: the anonymous lifetime #2 defined on the body at 15:51...
   --> $DIR/ex2a-push-one-existing-name.rs:15:52
    |
index edc1c2362de57c597c75e923f1d8d81cca6dee04..990ae65ba9854193bfcf0f0d3918b60bcae13000 100644 (file)
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 16 |     x.push(y);
    |            ^ lifetime mismatch
    |
-   = note: expected type `Ref<'_, i32>`
-              found type `Ref<'_, i32>`
+   = note: expected type `Ref<'_, _>`
+              found type `Ref<'_, _>`
 note: the anonymous lifetime #3 defined on the body at 15:43...
   --> $DIR/ex2b-push-no-existing-names.rs:15:44
    |
index 755b71d4a1d9e9eabb90fbfaacda6d517096d634..82f6c71ec1c2eb36314a56c70547593c393920d6 100644 (file)
@@ -27,7 +27,7 @@ note: but, the lifetime must be valid for the lifetime 'b as defined on the body
 17 | |     x.push(z);
 18 | | }
    | |_^ ...ending here
-note: ...so that expression is assignable (expected Ref<'b, i32>, found Ref<'_, i32>)
+note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _>)
   --> $DIR/ex2c-push-inference-variable.rs:17:12
    |
 17 |     x.push(z);
diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs
new file mode 100644 (file)
index 0000000..c448ad9
--- /dev/null
@@ -0,0 +1,61 @@
+// 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.
+
+enum Bar {
+    Qux,
+    Zar,
+}
+
+struct Foo {
+    bar: usize,
+}
+
+struct X<T1, T2> {
+    x: T1,
+    y: T2,
+}
+
+fn a() -> Foo {
+    Some(Foo { bar: 1 })
+}
+
+fn a2() -> Foo {
+    Ok(Foo { bar: 1})
+}
+
+fn b() -> Option<Foo> {
+    Foo { bar: 1 }
+}
+
+fn c() -> Result<Foo, Bar> {
+    Foo { bar: 1 }
+}
+
+fn d() -> X<X<String, String>, String> {
+    X {
+        x: X {
+            x: "".to_string(),
+            y: 2,
+        },
+        y: 3,
+    }
+}
+
+fn e() -> X<X<String, String>, String> {
+    X {
+        x: X {
+            x: "".to_string(),
+            y: 2,
+        },
+        y: "".to_string(),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
new file mode 100644 (file)
index 0000000..c67c611
--- /dev/null
@@ -0,0 +1,70 @@
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:26:5
+   |
+26 |     Some(Foo { bar: 1 })
+   |     ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option`
+   |
+   = note: expected type `Foo`
+              found type `std::option::Option<Foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:30:5
+   |
+30 |     Ok(Foo { bar: 1})
+   |     ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result`
+   |
+   = note: expected type `Foo`
+              found type `std::result::Result<Foo, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:34:5
+   |
+34 |     Foo { bar: 1 }
+   |     ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
+   |
+   = note: expected type `std::option::Option<Foo>`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:38:5
+   |
+38 |     Foo { bar: 1 }
+   |     ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
+   |
+   = note: expected type `std::result::Result<Foo, Bar>`
+              found type `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:42:5
+   |
+42 |       X {
+   |  _____^ starting here...
+43 | |         x: X {
+44 | |             x: "".to_string(),
+45 | |             y: 2,
+46 | |         },
+47 | |         y: 3,
+48 | |     }
+   | |_____^ ...ending here: expected struct `std::string::String`, found integral variable
+   |
+   = note: expected type `X<X<_, std::string::String>, std::string::String>`
+              found type `X<X<_, {integer}>, {integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/abridged.rs:52:5
+   |
+52 |       X {
+   |  _____^ starting here...
+53 | |         x: X {
+54 | |             x: "".to_string(),
+55 | |             y: 2,
+56 | |         },
+57 | |         y: "".to_string(),
+58 | |     }
+   | |_____^ ...ending here: expected struct `std::string::String`, found integral variable
+   |
+   = note: expected type `X<X<_, std::string::String>, _>`
+              found type `X<X<_, {integer}>, _>`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs
new file mode 100644 (file)
index 0000000..0d9e243
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="foo"]
+#![allow(dead_code)]
+
+// compile-flags: -Z print-fuel=foo
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+struct S3(u8, u16, u8);
+
+fn main() {
+}
diff --git a/src/test/ui/print-fuel/print-fuel.stdout b/src/test/ui/print-fuel/print-fuel.stdout
new file mode 100644 (file)
index 0000000..cc88cc0
--- /dev/null
@@ -0,0 +1 @@
+Fuel used by foo: 3
index dd999c4a5e4c779d1e30f105926d4a4ef4e07eda..830678f174f88cf38e0d76836bac2cc7c9a9ee96 100644 (file)
@@ -1,25 +1,22 @@
-print-type-size type: `IndirectNonZero<u32>`: 20 bytes, alignment: 4 bytes
-print-type-size     field `.pre`: 1 bytes
-print-type-size     padding: 3 bytes
-print-type-size     field `.nested`: 12 bytes, alignment: 4 bytes
+print-type-size type: `IndirectNonZero<u32>`: 12 bytes, alignment: 4 bytes
+print-type-size     field `.nested`: 8 bytes
 print-type-size     field `.post`: 2 bytes
-print-type-size     end padding: 2 bytes
-print-type-size type: `MyOption<IndirectNonZero<u32>>`: 20 bytes, alignment: 4 bytes
-print-type-size     variant `Some`: 20 bytes
-print-type-size         field `.0`: 20 bytes
-print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes
-print-type-size     variant `Record`: 10 bytes
-print-type-size         field `.pre`: 1 bytes
-print-type-size         padding: 3 bytes
-print-type-size         field `.val`: 4 bytes, alignment: 4 bytes
-print-type-size         field `.post`: 2 bytes
-print-type-size     end padding: 2 bytes
-print-type-size type: `NestedNonZero<u32>`: 12 bytes, alignment: 4 bytes
 print-type-size     field `.pre`: 1 bytes
-print-type-size     padding: 3 bytes
-print-type-size     field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
+print-type-size     variant `Some`: 12 bytes
+print-type-size         field `.0`: 12 bytes
+print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
+print-type-size     variant `Record`: 7 bytes
+print-type-size         field `.val`: 4 bytes
+print-type-size         field `.post`: 2 bytes
+print-type-size         field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
+print-type-size type: `NestedNonZero<u32>`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.val`: 4 bytes
 print-type-size     field `.post`: 2 bytes
-print-type-size     end padding: 2 bytes
+print-type-size     field `.pre`: 1 bytes
+print-type-size     end padding: 1 bytes
 print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
index 1278a7d7c92c67836d9e74db7eefd791ef4b3b23..83fd333c9c7fc45dba547de22add55c477521ef9 100644 (file)
@@ -1,13 +1,11 @@
-print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes
+print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.h`: 2 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
-print-type-size     padding: 2 bytes
-print-type-size     field `.g`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.c`: 1 bytes
-print-type-size     padding: 1 bytes
-print-type-size     field `.h`: 2 bytes, alignment: 2 bytes
 print-type-size     field `.d`: 1 bytes
-print-type-size     end padding: 3 bytes
+print-type-size     end padding: 2 bytes
 print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
index bb95f790bd9e471bdd740e5f9817faf8af8d4f54..0eaff7118b35c38a528dab7052d2cd498acb15aa 100644 (file)
@@ -1,10 +1,12 @@
 print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
-print-type-size     discriminant: 4 bytes
-print-type-size     variant `A`: 5 bytes
-print-type-size         field `.0`: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 7 bytes
 print-type-size         field `.1`: 1 bytes
-print-type-size     variant `B`: 8 bytes
-print-type-size         field `.0`: 8 bytes
+print-type-size         padding: 2 bytes
+print-type-size         field `.0`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `B`: 11 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `A`: 7 bytes
@@ -15,7 +17,7 @@ print-type-size     variant `B`: 11 bytes
 print-type-size         padding: 3 bytes
 print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size type: `S`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.g`: 4 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
-print-type-size     padding: 2 bytes
-print-type-size     field `.g`: 4 bytes, alignment: 4 bytes
+print-type-size     end padding: 2 bytes
diff --git a/src/test/ui/suggestions/tuple-float-index.rs b/src/test/ui/suggestions/tuple-float-index.rs
new file mode 100644 (file)
index 0000000..8bfbd0e
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+fn main () {
+    (1, (2, 3)).1.1;
+}
diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr
new file mode 100644 (file)
index 0000000..abe04dc
--- /dev/null
@@ -0,0 +1,11 @@
+error: unexpected token: `1.1`
+  --> $DIR/tuple-float-index.rs:14:17
+   |
+14 |     (1, (2, 3)).1.1;
+   |                 ^^^ unexpected token
+   |
+help: try parenthesizing the first index
+   |     ((1, (2, 3)).1).1;
+
+error: aborting due to previous error
+
index adddd7b7e89b047030eeb63a0b32cb2aa18c017d..28c8d22707325f82eb80172e1dc297468511c96d 100644 (file)
@@ -11,7 +11,7 @@
 extern crate toml;
 extern crate rustc_serialize;
 
-use std::collections::{BTreeMap, HashMap};
+use std::collections::BTreeMap;
 use std::env;
 use std::fs::File;
 use std::io::{self, Read, Write};
 struct Manifest {
     manifest_version: String,
     date: String,
-    pkg: HashMap<String, Package>,
+    pkg: BTreeMap<String, Package>,
 }
 
 #[derive(RustcEncodable)]
 struct Package {
     version: String,
-    target: HashMap<String, Target>,
+    target: BTreeMap<String, Target>,
 }
 
 #[derive(RustcEncodable)]
@@ -135,14 +135,16 @@ macro_rules! t {
 struct Builder {
     rust_release: String,
     cargo_release: String,
+    rls_release: String,
     input: PathBuf,
     output: PathBuf,
     gpg_passphrase: String,
-    digests: HashMap<String, String>,
+    digests: BTreeMap<String, String>,
     s3_address: String,
     date: String,
     rust_version: String,
     cargo_version: String,
+    rls_version: String,
 }
 
 fn main() {
@@ -152,6 +154,7 @@ fn main() {
     let date = args.next().unwrap();
     let rust_release = args.next().unwrap();
     let cargo_release = args.next().unwrap();
+    let rls_release = args.next().unwrap();
     let s3_address = args.next().unwrap();
     let mut passphrase = String::new();
     t!(io::stdin().read_to_string(&mut passphrase));
@@ -159,14 +162,16 @@ fn main() {
     Builder {
         rust_release: rust_release,
         cargo_release: cargo_release,
+        rls_release: rls_release,
         input: input,
         output: output,
         gpg_passphrase: passphrase,
-        digests: HashMap::new(),
+        digests: BTreeMap::new(),
         s3_address: s3_address,
         date: date,
         rust_version: String::new(),
         cargo_version: String::new(),
+        rls_version: String::new(),
     }.build();
 }
 
@@ -174,6 +179,7 @@ impl Builder {
     fn build(&mut self) {
         self.rust_version = self.version("rust", "x86_64-unknown-linux-gnu");
         self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu");
+        self.rls_version = self.version("rls", "x86_64-unknown-linux-gnu");
 
         self.digest_and_sign();
         let Manifest { manifest_version, date, pkg } = self.build_manifest();
@@ -214,7 +220,7 @@ fn build_manifest(&mut self) -> Manifest {
         let mut manifest = Manifest {
             manifest_version: "2".to_string(),
             date: self.date.to_string(),
-            pkg: HashMap::new(),
+            pkg: BTreeMap::new(),
         };
 
         self.package("rustc", &mut manifest.pkg, HOSTS);
@@ -223,14 +229,12 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("rust-std", &mut manifest.pkg, TARGETS);
         self.package("rust-docs", &mut manifest.pkg, TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
-
-        if self.rust_release == "nightly" {
-            self.package("rust-analysis", &mut manifest.pkg, TARGETS);
-        }
+        self.package("rls", &mut manifest.pkg, HOSTS);
+        self.package("rust-analysis", &mut manifest.pkg, TARGETS);
 
         let mut pkg = Package {
             version: self.cached_version("rust").to_string(),
-            target: HashMap::new(),
+            target: BTreeMap::new(),
         };
         for host in HOSTS {
             let filename = self.filename("rust", host);
@@ -265,6 +269,14 @@ fn build_manifest(&mut self) -> Manifest {
                 });
             }
 
+            extensions.push(Component {
+                pkg: "rls".to_string(),
+                target: host.to_string(),
+            });
+            extensions.push(Component {
+                pkg: "rust-analysis".to_string(),
+                target: host.to_string(),
+            });
             for target in TARGETS {
                 if target != host {
                     extensions.push(Component {
@@ -272,12 +284,6 @@ fn build_manifest(&mut self) -> Manifest {
                         target: target.to_string(),
                     });
                 }
-                if self.rust_release == "nightly" {
-                    extensions.push(Component {
-                        pkg: "rust-analysis".to_string(),
-                        target: target.to_string(),
-                    });
-                }
             }
             extensions.push(Component {
                 pkg: "rust-src".to_string(),
@@ -299,7 +305,7 @@ fn build_manifest(&mut self) -> Manifest {
 
     fn package(&mut self,
                pkgname: &str,
-               dst: &mut HashMap<String, Package>,
+               dst: &mut BTreeMap<String, Package>,
                targets: &[&str]) {
         let targets = targets.iter().map(|name| {
             let filename = self.filename(pkgname, name);
@@ -343,6 +349,8 @@ fn filename(&self, component: &str, target: &str) -> String {
             format!("rust-src-{}.tar.gz", self.rust_release)
         } else if component == "cargo" {
             format!("cargo-{}-{}.tar.gz", self.cargo_release, target)
+        } else if component == "rls" {
+            format!("rls-{}-{}.tar.gz", self.rls_release, target)
         } else {
             format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
         }
@@ -351,6 +359,8 @@ fn filename(&self, component: &str, target: &str) -> String {
     fn cached_version(&self, component: &str) -> &str {
         if component == "cargo" {
             &self.cargo_version
+        } else if component == "rls" {
+            &self.rls_version
         } else {
             &self.rust_version
         }
index d9da1bdc3485837d8024036f23ff5be81f5e7c71..06cbd9a3df41686b464dee0f15dda74cb91ab8fc 100644 (file)
@@ -97,6 +97,7 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
     let primary_spans: Vec<_> = spans_in_this_file.iter()
         .cloned()
         .filter(|span| span.is_primary)
+        .take(1) // sometimes we have more than one showing up in the json; pick first
         .collect();
     let primary_spans = if primary_spans.is_empty() {
         // subdiagnostics often don't have a span of their own;
index 2865fa6a79253862af85e76ee76bba779a30c8c0..7fb296c19f6ed9183e758e21f6c5b0e28c0c592c 100644 (file)
@@ -1589,8 +1589,14 @@ fn lib_path_cmd_prefix(path: &str) -> String {
     }
 
     fn dump_output(&self, out: &str, err: &str) {
-        self.dump_output_file(out, "out");
-        self.dump_output_file(err, "err");
+        let revision = if let Some(r) = self.revision {
+            format!("{}.", r)
+        } else {
+            String::new()
+        };
+
+        self.dump_output_file(out, &format!("{}out", revision));
+        self.dump_output_file(err, &format!("{}err", revision));
         self.maybe_dump_to_stdout(out, err);
     }
 
index dee37341051ed2f0227a09f8878c248f0984a488..17f8b62117ad4faebbd58d5dde54d5d32cf64a46 100644 (file)
@@ -82,11 +82,9 @@ fn filter_dirs(path: &Path) -> bool {
         "src/llvm",
         "src/libbacktrace",
         "src/compiler-rt",
-        "src/rt/hoedown",
         "src/rustllvm",
         "src/rust-installer",
         "src/liblibc",
-        "src/tools/cargo",
         "src/vendor",
     ];
     skip.iter().any(|p| path.ends_with(p))