]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #38559 - japaric:ptx2, r=alexcrichton
authorAlex Crichton <alex@alexcrichton.com>
Fri, 30 Dec 2016 01:26:15 +0000 (17:26 -0800)
committerGitHub <noreply@github.com>
Fri, 30 Dec 2016 01:26:15 +0000 (17:26 -0800)
PTX support, take 2

- You can generate PTX using `--emit=asm` and the right (custom) target. Which
  then you can run on a NVIDIA GPU.

- You can compile `core` to PTX. [Xargo] also works and it can compile some
  other crates like `collections` (but I doubt all of those make sense on a GPU)

[Xargo]: https://github.com/japaric/xargo

- You can create "global" functions, which can be "called" by the host, using
  the `"ptx-kernel"` ABI, e.g. `extern "ptx-kernel" fn kernel() { .. }`. Every
  other function is a "device" function and can only be called by the GPU.

- Intrinsics like `__syncthreads()` and `blockIdx.x` are available as
  `"platform-intrinsics"`. These intrinsics are *not* in the `core` crate but
  any Rust user can create "bindings" to them using an `extern
  "platform-intrinsics"` block. See example at the end.

- Trying to emit PTX with `-g` (debuginfo); you get an LLVM error. But I don't
  think PTX can contain debuginfo anyway so `-g` should be ignored and a warning
  should be printed ("`-g` doesn't work with this target" or something).

- "Single source" support. You *can't* write a single source file that contains
  both host and device code. I think that should be possible to implement that
  outside the compiler using compiler plugins / build scripts.

- The equivalent to CUDA `__shared__` which it's used to declare memory that's
  shared between the threads of the same block. This could be implemented using
  attributes: `#[shared] static mut SCRATCH_MEMORY: [f32; 64]` but hasn't been
  implemented yet.

- Built-in targets. This PR doesn't add targets to the compiler just yet but one
  can create custom targets to be able to emit PTX code (see the example at the
  end). The idea is to have people experiment with this feature before
  committing to it (built-in targets are "insta-stable")

- All functions must be "inlined". IOW, the `.rlib` must always contain the LLVM
  bitcode of all the functions of the crate it was produced from. Otherwise, you
  end with "undefined references" in the final PTX code but you won't get *any*
  linker error because no linker is involved. IOW, you'll hit a runtime error
  when loading the PTX into the GPU. The workaround is to use `#[inline]` on
  non-generic functions and to never use `#[inline(never)]` but this may not
  always be possible because e.g. you could be relying on third party code.

- Should `--emit=asm` generate a `.ptx` file instead of a `.s` file?

TL;DR Use Xargo to turn a crate into a PTX module (a `.s` file). Then pass that
PTX module, as a string, to the GPU and run it.

The full code is in [this repository]. This section gives an overview of how to
run Rust code on a NVIDIA GPU.

[this repository]: https://github.com/japaric/cuda

- Create a custom target. Here's the 64-bit NVPTX target (NOTE: the comments
  are not valid because this is supposed to be a JSON file; remove them before
  you use this file):

``` js
// nvptx64-nvidia-cuda.json
{
  "arch": "nvptx64",  // matches LLVM
  "cpu": "sm_20",  // "oldest" compute capability supported by LLVM
  "data-layout": "e-i64:64-v16:16-v32:32-n16:32:64",
  "llvm-target": "nvptx64-nvidia-cuda",
  "max-atomic-width": 0,  // LLVM errors with any other value :-(
  "os": "cuda",  // matches LLVM
  "panic-strategy": "abort",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-vendor": "nvidia",  // matches LLVM -- not required
}
```

(There's a 32-bit target specification in the linked repository)

- Write a kernel

``` rust

extern "platform-intrinsic" {
    fn nvptx_block_dim_x() -> i32;
    fn nvptx_block_idx_x() -> i32;
    fn nvptx_thread_idx_x() -> i32;
}

/// Copies an array of `n` floating point numbers from `src` to `dst`
pub unsafe extern "ptx-kernel" fn memcpy(dst: *mut f32,
                                         src: *const f32,
                                         n: usize) {
    let i = (nvptx_block_dim_x() as isize)
        .wrapping_mul(nvptx_block_idx_x() as isize)
        .wrapping_add(nvptx_thread_idx_x() as isize);

    if (i as usize) < n {
        *dst.offset(i) = *src.offset(i);
    }
}
```

- Emit PTX code

```
$ xargo rustc --target nvptx64-nvidia-cuda --release -- --emit=asm
   Compiling core v0.0.0 (file://..)
   (..)
   Compiling nvptx-builtins v0.1.0 (https://github.com/japaric/nvptx-builtins)
   Compiling kernel v0.1.0

$ cat target/nvptx64-nvidia-cuda/release/deps/kernel-*.s
//
// Generated by LLVM NVPTX Back-End
//

.version 3.2
.target sm_20
.address_size 64

        // .globl       memcpy

.visible .entry memcpy(
        .param .u64 memcpy_param_0,
        .param .u64 memcpy_param_1,
        .param .u64 memcpy_param_2
)
{
        .reg .pred      %p<2>;
        .reg .s32       %r<5>;
        .reg .s64       %rd<12>;

        ld.param.u64    %rd7, [memcpy_param_2];
        mov.u32 %r1, %ntid.x;
        mov.u32 %r2, %ctaid.x;
        mul.wide.s32    %rd8, %r2, %r1;
        mov.u32 %r3, %tid.x;
        cvt.s64.s32     %rd9, %r3;
        add.s64         %rd10, %rd9, %rd8;
        setp.ge.u64     %p1, %rd10, %rd7;
        @%p1 bra        LBB0_2;
        ld.param.u64    %rd3, [memcpy_param_0];
        ld.param.u64    %rd4, [memcpy_param_1];
        cvta.to.global.u64      %rd5, %rd4;
        cvta.to.global.u64      %rd6, %rd3;
        shl.b64         %rd11, %rd10, 2;
        add.s64         %rd1, %rd6, %rd11;
        add.s64         %rd2, %rd5, %rd11;
        ld.global.u32   %r4, [%rd2];
        st.global.u32   [%rd1], %r4;
LBB0_2:
        ret;
}
```

- Run it on the GPU

``` rust
// `kernel.ptx` is the `*.s` file we got in the previous step
const KERNEL: &'static str = include_str!("kernel.ptx");

driver::initialize()?;

let device = Device(0)?;
let ctx = device.create_context()?;
let module = ctx.load_module(KERNEL)?;
let kernel = module.function("memcpy")?;

let h_a: Vec<f32> = /* create some random data */;
let h_b = vec![0.; N];

let d_a = driver::allocate(bytes)?;
let d_b = driver::allocate(bytes)?;

// Copy from host to GPU
driver::copy(h_a, d_a)?;

// Run `memcpy` on the GPU
kernel.launch(d_b, d_a, N)?;

// Copy from GPU to host
driver::copy(d_b, h_b)?;

// Verify
assert_eq!(h_a, h_b);

// `d_a`, `d_b`, `h_a`, `h_b` are dropped/freed here
```

---

cc @alexcrichton @brson @rkruppe

> What has changed since #34195?

- `core` now can be compiled into PTX. Which makes it very easy to turn `no_std`
  crates into "kernels" with the help of Xargo.

- There's now a way, the `"ptx-kernel"` ABI, to generate "global" functions. The
  old PR required a manual step (it was hack) to "convert" "device" functions
  into "global" functions. (Only "global" functions can be launched by the host)

- Everything is unstable. There are not "insta stable" built-in targets this
  time (\*). The users have to use a custom target to experiment with this
  feature. Also, PTX instrinsics, like `__syncthreads` and `blockIdx.x`, are now
  implemented as `"platform-intrinsics"` so they no longer live in the `core`
  crate.

(\*) I'd actually like to have in-tree targets because that makes this target
more discoverable, removes the need to lug around .json files, etc.

However, bundling a target with the compiler immediately puts it in the path
towards stabilization. Which gives us just two cycles to find and fix any
problem with the target specification. Afterwards, it becomes hard to tweak
the specification because that could be a breaking change.

A possible solution could be "unstable built-in targets". Basically, to use an
unstable target, you'll have to also pass `-Z unstable-options` to the compiler.
And unstable targets, being unstable, wouldn't be available on stable.

> Why should this be merged?

- To let people experiment with the feature out of tree. Having easy access to
  the feature (in every nightly) allows this. I also think that, as it is, it
  should be possible to start prototyping type-safe single source support using
  build scripts, macros and/or plugins.

- It's a straightforward implementation. No different that adding support for
  any other architecture.

186 files changed:
.travis.yml
README.md
src/bootstrap/bin/rustc.rs
src/bootstrap/bin/rustdoc.rs
src/bootstrap/sanity.rs
src/bootstrap/step.rs
src/ci/docker/arm-android/start-emulator.sh
src/liballoc/heap.rs
src/libcollections/Cargo.toml
src/libcore/Cargo.toml
src/libproc_macro_tokens/Cargo.toml
src/librustc/cfg/construct.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/visit.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/itemlikevisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/blocks.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/infer/error_reporting.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/const_qualif.rs [deleted file]
src/librustc/middle/cstore.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/dead.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/transform.rs
src/librustc/session/config.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc/util/common.rs
src/librustc_back/target/mod.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/diagnostics.rs
src/librustc_const_eval/eval.rs
src/librustc_driver/derive_registrar.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_llvm/ffi.rs
src/librustc_llvm/lib.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/lib.rs
src/librustc_mir/mir_map.rs
src/librustc_passes/consts.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/loops.rs
src/librustc_passes/rvalues.rs
src/librustc_passes/static_recursion.rs
src/librustc_plugin/Cargo.toml
src/librustc_plugin/build.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/collector.rs
src/librustc_trans/context.rs
src/librustc_trans/glue.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/monomorphize.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/rscope.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libstd/sys/redox/args.rs
src/libstd/sys/redox/fs.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/stdio.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/stage0.txt
src/test/compile-fail/E0513.rs [deleted file]
src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
src/test/compile-fail/associated-const-type-parameter-arrays.rs
src/test/compile-fail/auxiliary/rmeta_meta.rs
src/test/compile-fail/dep-graph-struct-signature.rs
src/test/compile-fail/dep-graph-type-alias.rs
src/test/compile-fail/explicit-self-lifetime-mismatch.rs
src/test/compile-fail/issue-27008.rs
src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs
src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
src/test/compile-fail/repeat_count.rs
src/test/compile-fail/rmeta-lib-pass.rs
src/test/compile-fail/rmeta-pass.rs
src/test/compile-fail/rmeta-priv-warn.rs [new file with mode: 0644]
src/test/compile-fail/rmeta.rs
src/test/compile-fail/rmeta_meta_main.rs
src/test/debuginfo/union-smoke.rs
src/test/incremental/hashes/consts.rs
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/extern_mods.rs [new file with mode: 0644]
src/test/incremental/hashes/statics.rs
src/test/incremental/hashes/trait_defs.rs
src/test/incremental/string_constant.rs
src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot
src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot
src/test/run-make/issue-38237/Makefile [new file with mode: 0644]
src/test/run-make/issue-38237/bar.rs [new file with mode: 0644]
src/test/run-make/issue-38237/baz.rs [new file with mode: 0644]
src/test/run-make/issue-38237/foo.rs [new file with mode: 0644]
src/test/run-make/pretty-print-path-suffix/foo_method.pp
src/test/run-pass-fulldeps/issue-37290/auxiliary/lint.rs
src/test/run-pass/auxiliary/rmeta_rmeta.rs
src/test/run-pass/issue-38437.rs [new file with mode: 0644]
src/test/ui/span/mut-arg-hint.stderr
src/tools/cargotest/main.rs
src/tools/rustbook/Cargo.toml

index ea8c94af80b72337e40447c63076401a0dd8153a..3a9635a86180addce75221b1465c2667ec48f92f 100644 (file)
@@ -8,6 +8,8 @@ git:
   depth: 1
   submodules: false
 
+osx_image: xcode8.2
+
 matrix:
   include:
     # Linux builders, all docker images
index 2133b17de0fbbe214a26807b540b9804520afb56..c1218e9c600ce772e82b053083393e84ad44f47c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -82,8 +82,9 @@ build.
    # Install build tools needed for Rust. If you're building a 32-bit compiler,
    # then replace "x86_64" below with "i686". If you've already got git, python,
    # or CMake installed and in PATH you can remove them from this list. Note
-   # that it is important that the `python2` and `cmake` packages **not** used.
-   # The build has historically been known to fail with these packages.
+   # that it is important that you do **not** use the 'python2' and 'cmake'
+   # packages from the 'msys2' subsystem. The build has historically been known
+   # to fail with these packages.
    $ pacman -S git \
                make \
                diffutils \
index 9cab6c423f5f98d1df57071a9d2019ea72a0db43..129798836e03b7d1012f27de6866fe78020a0044 100644 (file)
@@ -67,6 +67,7 @@ fn main() {
         ("RUSTC_REAL", "RUSTC_LIBDIR")
     };
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
+    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
 
     let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
     let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -83,7 +84,7 @@ fn main() {
     if let Some(target) = target {
         // The stage0 compiler has a special sysroot distinct from what we
         // actually downloaded, so we just always pass the `--sysroot` option.
-        cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"));
+        cmd.arg("--sysroot").arg(sysroot);
 
         // When we build Rust dylibs they're all intended for intermediate
         // usage, so make sure we pass the -Cprefer-dynamic flag instead of
index a53bbe22eb94cbd9a2c5adfe2cdb20dec667d0dc..e9ca430f1582b4723529255bb17cfb7309fc4d36 100644 (file)
@@ -25,6 +25,7 @@ fn main() {
     let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
     let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
+    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
 
     let mut dylib_path = bootstrap::util::dylib_path();
     dylib_path.insert(0, PathBuf::from(libdir));
@@ -35,6 +36,8 @@ fn main() {
         .arg(format!("stage{}", stage))
         .arg("--cfg")
         .arg("dox")
+        .arg("--sysroot")
+        .arg(sysroot)
         .env(bootstrap::util::dylib_path_var(),
              env::join_paths(&dylib_path).unwrap());
     std::process::exit(match cmd.status() {
index 5d543419fc9b6a78b8331728caf46d2f02e31aa3..66bdd5e00f43da5f6776aa8662ca7e7589f9d0a8 100644 (file)
@@ -78,7 +78,11 @@ pub fn check(build: &mut Build) {
         }
         need_cmd("cmake".as_ref());
         if build.config.ninja {
-            need_cmd("ninja".as_ref())
+            // Some Linux distros rename `ninja` to `ninja-build`.
+            // CMake can work with either binary name.
+            if have_cmd("ninja-build".as_ref()).is_none() {
+                need_cmd("ninja".as_ref());
+            }
         }
         break
     }
index c5898c1119a670d31ae710f31afb78152aca780c..52caa3f0958a348a428d374d20d6a6a5e5b7254f 100644 (file)
@@ -838,14 +838,21 @@ fn plan(&self) -> Vec<Step<'a>> {
             } else {
                 &self.build.config.target
             };
-            // If --target was specified but --host wasn't specified, don't run
-            // any host-only tests
+            // Determine the actual targets participating in this rule.
+            // NOTE: We should keep the full projection from build triple to
+            // the hosts for the dist steps, now that the hosts array above is
+            // truncated to avoid duplication of work in that case. Therefore
+            // the original non-shadowed hosts array is used below.
             let arr = if rule.host {
-                if self.build.flags.target.len() > 0 &&
-                   self.build.flags.host.len() == 0 {
-                    &hosts[..0]
+                // If --target was specified but --host wasn't specified,
+                // don't run any host-only tests. Also, respect any `--host`
+                // overrides as done for `hosts`.
+                if self.build.flags.host.len() > 0 {
+                    &self.build.flags.host[..]
+                } else if self.build.flags.target.len() > 0 {
+                    &[]
                 } else {
-                    hosts
+                    &self.build.config.host[..]
                 }
             } else {
                 targets
index 93f20b28b8689e4d37ce95bc648f174f8558353d..fcf42c1819ee72bdf3fa332158cf42f769b7cc7a 100755 (executable)
@@ -11,5 +11,7 @@
 
 set -ex
 ANDROID_EMULATOR_FORCE_32BIT=true \
-  emulator @arm-18 -no-window -partition-size 2047 &
+  nohup nohup emulator @arm-18 -no-window -partition-size 2047 \
+  0<&- &>/dev/null &
+adb wait-for-device
 exec "$@"
index a1e32636980812b8ba7cd802ee5936cd71d3e0eb..81ed4be7763e945d1c9338fb3f105696f98abe57 100644 (file)
@@ -144,6 +144,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
 }
 
 #[cfg(not(test))]
+#[cfg(stage0)]
 #[lang = "exchange_free"]
 #[inline]
 unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
index ab882fde9c2775683f0b63f48f3cc843232a319e..186ba6e8f211243512c1814c6598a36f1b75dc48 100644 (file)
@@ -16,6 +16,7 @@ std_unicode = { path = "../libstd_unicode" }
 name = "collectionstest"
 path = "../libcollectionstest/lib.rs"
 
-[[bench]]
-name = "collectionstest"
-path = "../libcollectionstest/lib.rs"
+# FIXME: need to extract benchmarks to separate crate
+#[[bench]]
+#name = "collectionstest"
+#path = "../libcollectionstest/lib.rs"
index a72c712ad1733c4d29ae1f5f688092acf69b5526..e0dbc096cd0d97f567da3f17d42b4f167dace0e0 100644 (file)
@@ -13,6 +13,7 @@ bench = false
 name = "coretest"
 path = "../libcoretest/lib.rs"
 
-[[bench]]
-name = "coretest"
-path = "../libcoretest/lib.rs"
+# FIXME: need to extract benchmarks to a separate crate
+#[[bench]]
+#name = "coretest"
+#path = "../libcoretest/lib.rs"
index 2b66d56759f35b220debeab20ea604f5f51f07bb..b4365e4fb265a5bc159c244b960204c2f5ece639 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "proc_macro_tokens"
 version = "0.0.0"
+build = false
 
 [lib]
 path = "lib.rs"
index f21d98a0fc7f97a5eedbb2f9fc3d6b353b375517..4d66bba9f07ee6b135b33b57e63f08ec59cb6aa3 100644 (file)
@@ -327,10 +327,6 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
                 self.opt_expr(base, field_cfg)
             }
 
-            hir::ExprRepeat(ref elem, ref count) => {
-                self.straightline(expr, pred, [elem, count].iter().map(|&e| &**e))
-            }
-
             hir::ExprAssign(ref l, ref r) |
             hir::ExprAssignOp(_, ref l, ref r) => {
                 self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
@@ -347,7 +343,8 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
             hir::ExprType(ref e, _) |
             hir::ExprUnary(_, ref e) |
             hir::ExprField(ref e, _) |
-            hir::ExprTupField(ref e, _) => {
+            hir::ExprTupField(ref e, _) |
+            hir::ExprRepeat(ref e, _) => {
                 self.straightline(expr, pred, Some(&**e).into_iter())
             }
 
index 2637d34c5c56e569d91a3e1bcff2ad47310efa50..26e1dc7e0490c21f826b4657e67d13c04c4c8e81 100644 (file)
@@ -51,6 +51,12 @@ pub fn new(enabled: bool) -> DepGraph {
         }
     }
 
+    /// True if we are actually building the full dep-graph.
+    #[inline]
+    pub fn is_fully_enabled(&self) -> bool {
+        self.data.thread.is_fully_enabled()
+    }
+
     pub fn query(&self) -> DepGraphQuery<DefId> {
         self.data.thread.query()
     }
index f6a22e47cf21278051fd3f11fc5ab474cab25303..1990574ca9a831d3232c95b282cb854e97333f59 100644 (file)
@@ -45,6 +45,16 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
             debug!("Ended task {:?}", task_id);
         }
 
+        fn visit_trait_item(&mut self, i: &'tcx hir::TraitItem) {
+            let trait_item_def_id = self.tcx.map.local_def_id(i.id);
+            let task_id = (self.dep_node_fn)(trait_item_def_id);
+            let _task = self.tcx.dep_graph.in_task(task_id.clone());
+            debug!("Started task {:?}", task_id);
+            self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id));
+            self.visitor.visit_trait_item(i);
+            debug!("Ended task {:?}", task_id);
+        }
+
         fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
             let impl_item_def_id = self.tcx.map.local_def_id(i.id);
             let task_id = (self.dep_node_fn)(impl_item_def_id);
index 186d6f626509fd0b0daf5f37ddeefa42d516ab1a..4b171193b4af17f54dddbd2807f06a561daf1175 100644 (file)
@@ -177,6 +177,17 @@ fn visit_nested_item(&mut self, id: ItemId) {
         }
     }
 
+    /// Like `visit_nested_item()`, but for trait items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    #[allow(unused_variables)]
+    fn visit_nested_trait_item(&mut self, id: TraitItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
+        if let Some(item) = opt_item {
+            self.visit_trait_item(item);
+        }
+    }
+
     /// Like `visit_nested_item()`, but for impl items. See
     /// `visit_nested_item()` for advice on when to override this
     /// method.
@@ -192,10 +203,10 @@ fn visit_nested_impl_item(&mut self, id: ImplItemId) {
     /// visit_nested_item, does nothing by default unless you override
     /// `nested_visit_map` to return `Some(_)`, in which case it will walk the
     /// body.
-    fn visit_body(&mut self, id: ExprId) {
-        let opt_expr = self.nested_visit_map().intra().map(|map| map.expr(id));
-        if let Some(expr) = opt_expr {
-            self.visit_expr(expr);
+    fn visit_nested_body(&mut self, id: BodyId) {
+        let opt_body = self.nested_visit_map().intra().map(|map| map.body(id));
+        if let Some(body) = opt_body {
+            self.visit_body(body);
         }
     }
 
@@ -205,6 +216,10 @@ fn visit_item(&mut self, i: &'v Item) {
         walk_item(self, i)
     }
 
+    fn visit_body(&mut self, b: &'v Body) {
+        walk_body(self, b);
+    }
+
     /// When invoking `visit_all_item_likes()`, you need to supply an
     /// item-like visitor.  This method converts a "intra-visit"
     /// visitor into an item-like visitor that walks the entire tree.
@@ -253,8 +268,6 @@ fn visit_decl(&mut self, d: &'v Decl) {
     fn visit_expr(&mut self, ex: &'v Expr) {
         walk_expr(self, ex)
     }
-    fn visit_expr_post(&mut self, _ex: &'v Expr) {
-    }
     fn visit_ty(&mut self, t: &'v Ty) {
         walk_ty(self, t)
     }
@@ -264,12 +277,18 @@ fn visit_generics(&mut self, g: &'v Generics) {
     fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) {
         walk_where_predicate(self, predicate)
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: ExprId, s: Span, id: NodeId) {
+    fn visit_fn_decl(&mut self, fd: &'v FnDecl) {
+        walk_fn_decl(self, fd)
+    }
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) {
         walk_fn(self, fk, fd, b, s, id)
     }
     fn visit_trait_item(&mut self, ti: &'v TraitItem) {
         walk_trait_item(self, ti)
     }
+    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
+        walk_trait_item_ref(self, ii)
+    }
     fn visit_impl_item(&mut self, ii: &'v ImplItem) {
         walk_impl_item(self, ii)
     }
@@ -375,6 +394,14 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_i
     }
 }
 
+pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
+    for argument in &body.arguments {
+        visitor.visit_id(argument.id);
+        visitor.visit_pat(&argument.pat);
+    }
+    visitor.visit_expr(&body.value);
+}
+
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
     visitor.visit_id(local.id);
     visitor.visit_pat(&local.pat);
@@ -420,11 +447,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_path(path, item.id);
         }
-        ItemStatic(ref typ, _, ref expr) |
-        ItemConst(ref typ, ref expr) => {
+        ItemStatic(ref typ, _, body) |
+        ItemConst(ref typ, body) => {
             visitor.visit_id(item.id);
             visitor.visit_ty(typ);
-            visitor.visit_expr(expr);
+            visitor.visit_nested_body(body);
         }
         ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => {
             visitor.visit_fn(FnKind::ItemFn(item.name,
@@ -466,9 +493,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
             visitor.visit_ty(typ);
-            for impl_item_ref in impl_item_refs {
-                visitor.visit_impl_item_ref(impl_item_ref);
-            }
+            walk_list!(visitor, visit_impl_item_ref, impl_item_refs);
         }
         ItemStruct(ref struct_definition, ref generics) |
         ItemUnion(ref struct_definition, ref generics) => {
@@ -476,11 +501,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
-        ItemTrait(_, ref generics, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
-            walk_list!(visitor, visit_trait_item, methods);
+            walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
         }
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -508,7 +533,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                generics,
                                parent_item_id,
                                variant.span);
-    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
+    walk_list!(visitor, visit_nested_body, variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
@@ -531,7 +556,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
         TyBareFn(ref function_declaration) => {
-            walk_fn_decl(visitor, &function_declaration.decl);
+            visitor.visit_fn_decl(&function_declaration.decl);
             walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
         }
         TyPath(ref qpath) => {
@@ -541,9 +566,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
-        TyArray(ref ty, ref expression) => {
+        TyArray(ref ty, length) => {
             visitor.visit_ty(ty);
-            visitor.visit_expr(expression)
+            visitor.visit_nested_body(length)
         }
         TyPolyTraitRef(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
@@ -551,8 +576,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
-        TyTypeof(ref expression) => {
-            visitor.visit_expr(expression)
+        TyTypeof(expression) => {
+            visitor.visit_nested_body(expression)
         }
         TyInfer => {}
     }
@@ -659,9 +684,12 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
     visitor.visit_name(foreign_item.span, foreign_item.name);
 
     match foreign_item.node {
-        ForeignItemFn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, function_declaration);
-            visitor.visit_generics(generics)
+        ForeignItemFn(ref function_declaration, ref names, ref generics) => {
+            visitor.visit_generics(generics);
+            visitor.visit_fn_decl(function_declaration);
+            for name in names {
+                visitor.visit_name(name.span, name.node);
+            }
         }
         ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
     }
@@ -729,18 +757,8 @@ pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionR
 }
 
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
-    for argument in &function_declaration.inputs {
-        visitor.visit_id(argument.id);
-        visitor.visit_pat(&argument.pat);
-        visitor.visit_ty(&argument.ty)
-    }
-    walk_fn_ret_ty(visitor, &function_declaration.output)
-}
-
-pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
-    for argument in &function_declaration.inputs {
-        visitor.visit_id(argument.id);
-        visitor.visit_ty(&argument.ty)
+    for ty in &function_declaration.inputs {
+        visitor.visit_ty(ty)
     }
     walk_fn_ret_ty(visitor, &function_declaration.output)
 }
@@ -760,42 +778,33 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
 pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
                                    function_kind: FnKind<'v>,
                                    function_declaration: &'v FnDecl,
-                                   body_id: ExprId,
+                                   body_id: BodyId,
                                    _span: Span,
                                    id: NodeId) {
     visitor.visit_id(id);
-    walk_fn_decl(visitor, function_declaration);
-    walk_fn_kind(visitor, function_kind);
-    visitor.visit_body(body_id)
-}
-
-pub fn walk_fn_with_body<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             function_kind: FnKind<'v>,
-                                             function_declaration: &'v FnDecl,
-                                             body: &'v Expr,
-                                             _span: Span,
-                                             id: NodeId) {
-    visitor.visit_id(id);
-    walk_fn_decl(visitor, function_declaration);
+    visitor.visit_fn_decl(function_declaration);
     walk_fn_kind(visitor, function_kind);
-    visitor.visit_expr(body)
+    visitor.visit_nested_body(body_id)
 }
 
 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
     visitor.visit_name(trait_item.span, trait_item.name);
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
-        ConstTraitItem(ref ty, ref default) => {
+        TraitItemKind::Const(ref ty, default) => {
             visitor.visit_id(trait_item.id);
             visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, default);
+            walk_list!(visitor, visit_nested_body, default);
         }
-        MethodTraitItem(ref sig, None) => {
+        TraitItemKind::Method(ref sig, TraitMethod::Required(ref names)) => {
             visitor.visit_id(trait_item.id);
             visitor.visit_generics(&sig.generics);
-            walk_fn_decl(visitor, &sig.decl);
+            visitor.visit_fn_decl(&sig.decl);
+            for name in names {
+                visitor.visit_name(name.span, name.node);
+            }
         }
-        MethodTraitItem(ref sig, Some(body_id)) => {
+        TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => {
             visitor.visit_fn(FnKind::Method(trait_item.name,
                                             sig,
                                             None,
@@ -805,7 +814,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
                              trait_item.span,
                              trait_item.id);
         }
-        TypeTraitItem(ref bounds, ref default) => {
+        TraitItemKind::Type(ref bounds, ref default) => {
             visitor.visit_id(trait_item.id);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
@@ -813,6 +822,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
     }
 }
 
+pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) {
+    // NB: Deliberately force a compilation error if/when new fields are added.
+    let TraitItemRef { id, name, ref kind, span, ref defaultness } = *trait_item_ref;
+    visitor.visit_nested_trait_item(id);
+    visitor.visit_name(span, name);
+    visitor.visit_associated_item_kind(kind);
+    visitor.visit_defaultness(defaultness);
+}
+
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     // NB: Deliberately force a compilation error if/when new fields are added.
     let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
@@ -822,10 +840,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     visitor.visit_defaultness(defaultness);
     walk_list!(visitor, visit_attribute, attrs);
     match *node {
-        ImplItemKind::Const(ref ty, ref expr) => {
+        ImplItemKind::Const(ref ty, body) => {
             visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
+            visitor.visit_nested_body(body);
         }
         ImplItemKind::Method(ref sig, body_id) => {
             visitor.visit_fn(FnKind::Method(impl_item.name,
@@ -904,9 +922,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprArray(ref subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprRepeat(ref element, ref count) => {
+        ExprRepeat(ref element, count) => {
             visitor.visit_expr(element);
-            visitor.visit_expr(count)
+            visitor.visit_nested_body(count)
         }
         ExprStruct(ref qpath, ref fields, ref optional_base) => {
             visitor.visit_qpath(qpath, expression.id, expression.span);
@@ -1013,8 +1031,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             }
         }
     }
-
-    visitor.visit_expr_post(expression)
 }
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
@@ -1097,16 +1113,3 @@ fn visit_id(&mut self, id: NodeId) {
         self.result.add(id);
     }
 }
-
-/// Computes the id range for a single fn body, ignoring nested items.
-pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>,
-                                        decl: &'v FnDecl,
-                                        body: &'v Expr,
-                                        sp: Span,
-                                        id: NodeId,
-                                        map: &map::Map<'v>)
-                                        -> IdRange {
-    let mut visitor = IdRangeComputingVisitor::new(map);
-    walk_fn_with_body(&mut visitor, fk, decl, body, sp, id);
-    visitor.result()
-}
index 71ef7131440b80393fa90c3e3880437befd77909..f359ca2016359ef85cf04f58d9ee2c1e7d67f3b4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Item, ImplItem};
+use super::{Item, ImplItem, TraitItem};
 use super::intravisit::Visitor;
 
 /// The "item-like visitor" visitor defines only the top-level methods
@@ -58,6 +58,7 @@
 /// needed.
 pub trait ItemLikeVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir Item);
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem);
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem);
 }
 
@@ -80,6 +81,10 @@ fn visit_item(&mut self, item: &'hir Item) {
         self.visitor.visit_item(item);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) {
+        self.visitor.visit_trait_item(trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) {
         self.visitor.visit_impl_item(impl_item);
     }
index 1cf5e35a0957fa4341a1f148bf101cef36d9e584..9a2658f48f3d91f2cf7236120cd9b072c7febc3c 100644 (file)
 use hir::def_id::{DefIndex, DefId};
 use hir::def::{Def, PathResolution};
 use session::Session;
-use util::nodemap::NodeMap;
-use rustc_data_structures::fnv::FnvHashMap;
+use util::nodemap::{NodeMap, FxHashMap};
 
 use std::collections::BTreeMap;
 use std::iter;
-use std::mem;
 
 use syntax::ast::*;
 use syntax::errors;
@@ -71,13 +69,14 @@ pub struct LoweringContext<'a> {
     // the form of a DefIndex) so that if we create a new node which introduces
     // a definition, then we can properly create the def id.
     parent_def: Option<DefIndex>,
-    exprs: FnvHashMap<hir::ExprId, hir::Expr>,
     resolver: &'a mut Resolver,
 
     /// The items being lowered are collected here.
     items: BTreeMap<NodeId, hir::Item>,
 
+    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
+    bodies: FxHashMap<hir::BodyId, hir::Body>,
 }
 
 pub trait Resolver {
@@ -105,10 +104,11 @@ pub fn lower_crate(sess: &Session,
         crate_root: std_inject::injected_crate_name(krate),
         sess: sess,
         parent_def: None,
-        exprs: FnvHashMap(),
         resolver: resolver,
         items: BTreeMap::new(),
+        trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
+        bodies: FxHashMap(),
     }.lower_crate(krate)
 }
 
@@ -133,8 +133,9 @@ fn lower_crate(mut self, c: &Crate) -> hir::Crate {
             span: c.span,
             exported_macros: exported_macros,
             items: self.items,
+            trait_items: self.trait_items,
             impl_items: self.impl_items,
-            exprs: mem::replace(&mut self.exprs, FnvHashMap()),
+            bodies: self.bodies,
         }
     }
 
@@ -150,8 +151,15 @@ fn visit_item(&mut self, item: &'lcx Item) {
                 visit::walk_item(self, item);
             }
 
+            fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
+                let id = hir::TraitItemId { node_id: item.id };
+                let hir_item = self.lctx.lower_trait_item(item);
+                self.lctx.trait_items.insert(id, hir_item);
+                visit::walk_trait_item(self, item);
+            }
+
             fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
-                let id = self.lctx.lower_impl_item_ref(item).id;
+                let id = hir::ImplItemId { node_id: item.id };
                 let hir_item = self.lctx.lower_impl_item(item);
                 self.lctx.impl_items.insert(id, hir_item);
                 visit::walk_impl_item(self, item);
@@ -162,9 +170,16 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
         visit::walk_crate(&mut item_lowerer, c);
     }
 
-    fn record_expr(&mut self, expr: hir::Expr) -> hir::ExprId {
-        let id = hir::ExprId(expr.id);
-        self.exprs.insert(id, expr);
+    fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>)
+                   -> hir::BodyId {
+        let body = hir::Body {
+            arguments: decl.map_or(hir_vec![], |decl| {
+                decl.inputs.iter().map(|x| self.lower_arg(x)).collect()
+            }),
+            value: value
+        };
+        let id = body.id();
+        self.bodies.insert(id, body);
         id
     }
 
@@ -259,7 +274,7 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
         P(hir::Ty {
             id: t.id,
             node: match t.node {
-                TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer,
+                TyKind::Infer => hir::TyInfer,
                 TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
                 TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
                 TyKind::Rptr(ref region, ref mt) => {
@@ -283,14 +298,27 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                 TyKind::Path(ref qself, ref path) => {
                     hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
                 }
+                TyKind::ImplicitSelf => {
+                    hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
+                        def: self.expect_full_def(t.id),
+                        segments: hir_vec![hir::PathSegment {
+                            name: keywords::SelfType.name(),
+                            parameters: hir::PathParameters::none()
+                        }],
+                        span: t.span,
+                    })))
+                }
                 TyKind::ObjectSum(ref ty, ref bounds) => {
                     hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
                 }
-                TyKind::Array(ref ty, ref e) => {
-                    hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e)))
+                TyKind::Array(ref ty, ref length) => {
+                    let length = self.lower_expr(length);
+                    hir::TyArray(self.lower_ty(ty),
+                                 self.record_body(length, None))
                 }
                 TyKind::Typeof(ref expr) => {
-                    hir::TyTypeof(P(self.lower_expr(expr)))
+                    let expr = self.lower_expr(expr);
+                    hir::TyTypeof(self.record_body(expr, None))
                 }
                 TyKind::PolyTraitRef(ref bounds) => {
                     hir::TyPolyTraitRef(self.lower_bounds(bounds))
@@ -317,7 +345,10 @@ fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
                 name: v.node.name.name,
                 attrs: self.lower_attrs(&v.node.attrs),
                 data: self.lower_variant_data(&v.node.data),
-                disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))),
+                disr_expr: v.node.disr_expr.as_ref().map(|e| {
+                    let e = self.lower_expr(e);
+                    self.record_body(e, None)
+                }),
             },
             span: v.span,
         }
@@ -505,13 +536,24 @@ fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
         hir::Arg {
             id: arg.id,
             pat: self.lower_pat(&arg.pat),
-            ty: self.lower_ty(&arg.ty),
         }
     }
 
+    fn lower_fn_args_to_names(&mut self, decl: &FnDecl)
+                              -> hir::HirVec<Spanned<Name>> {
+        decl.inputs.iter().map(|arg| {
+            match arg.pat.node {
+                PatKind::Ident(_, ident, None) => {
+                    respan(ident.span, ident.node.name)
+                }
+                _ => respan(arg.pat.span, keywords::Invalid.name()),
+            }
+        }).collect()
+    }
+
     fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
         P(hir::FnDecl {
-            inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(),
+            inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(),
             output: match decl.output {
                 FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
@@ -839,17 +881,20 @@ fn lower_item_kind(&mut self,
                 hir::ItemUse(path, kind)
             }
             ItemKind::Static(ref t, m, ref e) => {
+                let value = self.lower_expr(e);
                 hir::ItemStatic(self.lower_ty(t),
                                 self.lower_mutability(m),
-                                P(self.lower_expr(e)))
+                                self.record_body(value, None))
             }
             ItemKind::Const(ref t, ref e) => {
-                hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e)))
+                let value = self.lower_expr(e);
+                hir::ItemConst(self.lower_ty(t),
+                               self.record_body(value, None))
             }
             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
                 let body = self.lower_block(body);
                 let body = self.expr_block(body, ThinVec::new());
-                let body_id = self.record_expr(body);
+                let body_id = self.record_body(body, Some(decl));
                 hir::ItemFn(self.lower_fn_decl(decl),
                             self.lower_unsafety(unsafety),
                             self.lower_constness(constness),
@@ -897,7 +942,7 @@ fn lower_item_kind(&mut self,
             }
             ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_bounds(bounds);
-                let items = items.iter().map(|item| self.lower_trait_item(item)).collect();
+                let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
                 hir::ItemTrait(self.lower_unsafety(unsafety),
                                self.lower_generics(generics),
                                bounds,
@@ -915,20 +960,27 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
                     TraitItemKind::Const(ref ty, ref default) => {
-                        hir::ConstTraitItem(this.lower_ty(ty),
-                                            default.as_ref().map(|x| P(this.lower_expr(x))))
-                    }
-                    TraitItemKind::Method(ref sig, ref body) => {
-                        hir::MethodTraitItem(this.lower_method_sig(sig),
-                                             body.as_ref().map(|x| {
-                            let body = this.lower_block(x);
-                            let expr = this.expr_block(body, ThinVec::new());
-                            this.record_expr(expr)
+                        hir::TraitItemKind::Const(this.lower_ty(ty),
+                                                  default.as_ref().map(|x| {
+                            let value = this.lower_expr(x);
+                            this.record_body(value, None)
                         }))
                     }
+                    TraitItemKind::Method(ref sig, None) => {
+                        let names = this.lower_fn_args_to_names(&sig.decl);
+                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
+                                                   hir::TraitMethod::Required(names))
+                    }
+                    TraitItemKind::Method(ref sig, Some(ref body)) => {
+                        let body = this.lower_block(body);
+                        let expr = this.expr_block(body, ThinVec::new());
+                        let body_id = this.record_body(expr, Some(&sig.decl));
+                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
+                                                   hir::TraitMethod::Provided(body_id))
+                    }
                     TraitItemKind::Type(ref bounds, ref default) => {
-                        hir::TypeTraitItem(this.lower_bounds(bounds),
-                                           default.as_ref().map(|x| this.lower_ty(x)))
+                        hir::TraitItemKind::Type(this.lower_bounds(bounds),
+                                                 default.as_ref().map(|x| this.lower_ty(x)))
                     }
                     TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
                 },
@@ -937,6 +989,30 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
         })
     }
 
+    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
+        let (kind, has_default) = match i.node {
+            TraitItemKind::Const(_, ref default) => {
+                (hir::AssociatedItemKind::Const, default.is_some())
+            }
+            TraitItemKind::Type(_, ref default) => {
+                (hir::AssociatedItemKind::Type, default.is_some())
+            }
+            TraitItemKind::Method(ref sig, ref default) => {
+                (hir::AssociatedItemKind::Method {
+                    has_self: sig.decl.has_self(),
+                 }, default.is_some())
+            }
+            TraitItemKind::Macro(..) => unimplemented!(),
+        };
+        hir::TraitItemRef {
+            id: hir::TraitItemId { node_id: i.id },
+            name: i.ident.name,
+            span: i.span,
+            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
+            kind: kind,
+        }
+    }
+
     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
         self.with_parent_def(i.id, |this| {
             hir::ImplItem {
@@ -947,13 +1023,15 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                 defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
                 node: match i.node {
                     ImplItemKind::Const(ref ty, ref expr) => {
-                        hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr)))
+                        let value = this.lower_expr(expr);
+                        let body_id = this.record_body(value, None);
+                        hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
                     }
                     ImplItemKind::Method(ref sig, ref body) => {
                         let body = this.lower_block(body);
                         let expr = this.expr_block(body, ThinVec::new());
-                        let expr_id = this.record_expr(expr);
-                        hir::ImplItemKind::Method(this.lower_method_sig(sig), expr_id)
+                        let body_id = this.record_body(expr, Some(&sig.decl));
+                        hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
                     }
                     ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
                     ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
@@ -976,7 +1054,7 @@ fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
                 ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
                 ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
                 ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
-                    has_self: sig.decl.get_self().is_some(),
+                    has_self: sig.decl.has_self(),
                 },
                 ImplItemKind::Macro(..) => unimplemented!(),
             },
@@ -1038,7 +1116,9 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
                     ForeignItemKind::Fn(ref fdec, ref generics) => {
-                        hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics))
+                        hir::ForeignItemFn(this.lower_fn_decl(fdec),
+                                           this.lower_fn_args_to_names(fdec),
+                                           this.lower_generics(generics))
                     }
                     ForeignItemKind::Static(ref t, m) => {
                         hir::ForeignItemStatic(this.lower_ty(t), m)
@@ -1051,24 +1131,13 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
     }
 
     fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
-        let hir_sig = hir::MethodSig {
+        hir::MethodSig {
             generics: self.lower_generics(&sig.generics),
             abi: sig.abi,
             unsafety: self.lower_unsafety(sig.unsafety),
             constness: self.lower_constness(sig.constness),
             decl: self.lower_fn_decl(&sig.decl),
-        };
-        // Check for `self: _` and `self: &_`
-        if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
-            match hir_sig.decl.get_self().map(|eself| eself.node) {
-                Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
-                    self.diagnostic().span_err(sig.decl.inputs[0].ty.span,
-                        "the type placeholder `_` is not allowed within types on item signatures");
-                }
-                _ => {}
-            }
         }
-        hir_sig
     }
 
     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
@@ -1318,8 +1387,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 }
                 ExprKind::Repeat(ref expr, ref count) => {
                     let expr = P(self.lower_expr(expr));
-                    let count = P(self.lower_expr(count));
-                    hir::ExprRepeat(expr, count)
+                    let count = self.lower_expr(count);
+                    hir::ExprRepeat(expr, self.record_body(count, None))
                 }
                 ExprKind::Tup(ref elts) => {
                     hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
@@ -1402,7 +1471,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                         let expr = this.lower_expr(body);
                         hir::ExprClosure(this.lower_capture_clause(capture_clause),
                                          this.lower_fn_decl(decl),
-                                         this.record_expr(expr),
+                                         this.record_body(expr, Some(decl)),
                                          fn_decl_span)
                     })
                 }
@@ -1686,13 +1755,7 @@ fn make_struct(this: &mut LoweringContext,
                     // `::std::option::Option::Some(<pat>) => <body>`
                     let pat_arm = {
                         let body_block = self.lower_block(body);
-                        let body_span = body_block.span;
-                        let body_expr = P(hir::Expr {
-                            id: self.next_id(),
-                            node: hir::ExprBlock(body_block),
-                            span: body_span,
-                            attrs: ThinVec::new(),
-                        });
+                        let body_expr = P(self.expr_block(body_block, ThinVec::new()));
                         let pat = self.lower_pat(pat);
                         let some_pat = self.pat_some(e.span, pat);
 
index 068e7ed8624ed77300f10252a13fa392639634ee..6e08b52f9a2490bf1b8c0a8471723f8c9bc7f0cf 100644 (file)
@@ -48,7 +48,7 @@ pub struct FnLikeNode<'a> { node: map::Node<'a> }
 /// Components shared by fn-like things (fn items, methods, closures).
 pub struct FnParts<'a> {
     pub decl: &'a FnDecl,
-    pub body: ast::ExprId,
+    pub body: ast::BodyId,
     pub kind: FnKind<'a>,
     pub span: Span,
     pub id:   NodeId,
@@ -62,7 +62,10 @@ fn is_fn_like(&self) -> bool {
 
 impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
-        match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, }
+        match self.node {
+            ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
+            _ => false,
+        }
     }
 }
 
@@ -115,7 +118,7 @@ struct ItemFnParts<'a> {
     abi:      abi::Abi,
     vis:      &'a ast::Visibility,
     generics: &'a ast::Generics,
-    body:     ast::ExprId,
+    body:     ast::BodyId,
     id:       NodeId,
     span:     Span,
     attrs:    &'a [Attribute],
@@ -125,14 +128,14 @@ struct ItemFnParts<'a> {
 /// for use when implementing FnLikeNode operations.
 struct ClosureParts<'a> {
     decl: &'a FnDecl,
-    body: ast::ExprId,
+    body: ast::BodyId,
     id: NodeId,
     span: Span,
     attrs: &'a [Attribute],
 }
 
 impl<'a> ClosureParts<'a> {
-    fn new(d: &'a FnDecl, b: ast::ExprId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
+    fn new(d: &'a FnDecl, b: ast::BodyId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
         ClosureParts {
             decl: d,
             body: b,
@@ -172,9 +175,9 @@ pub fn to_fn_parts(self) -> FnParts<'a> {
         }
     }
 
-    pub fn body(self) -> ast::ExprId {
+    pub fn body(self) -> ast::BodyId {
         self.handle(|i: ItemFnParts<'a>|  i.body,
-                    |_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _|  body,
+                    |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _|  body,
                     |c: ClosureParts<'a>| c.body)
     }
 
@@ -227,7 +230,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                   Name,
                   &'a ast::MethodSig,
                   Option<&'a ast::Visibility>,
-                  ast::ExprId,
+                  ast::BodyId,
                   Span,
                   &'a [Attribute])
                   -> A,
@@ -252,7 +255,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
             map::NodeTraitItem(ti) => match ti.node {
-                ast::MethodTraitItem(ref sig, Some(body)) => {
+                ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
                     method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
index 45988886a608a30ff7ede1d35d39ca5096d63270..a6ffe7cea5592e752ce7b66b09a8c6e80b700c08 100644 (file)
@@ -11,7 +11,6 @@
 use super::*;
 
 use hir::intravisit::{Visitor, NestedVisitorMap};
-use middle::cstore::InlinedItem;
 use std::iter::repeat;
 use syntax::ast::{NodeId, CRATE_NODE_ID};
 use syntax_pos::Span;
@@ -21,7 +20,7 @@ pub struct NodeCollector<'ast> {
     /// The crate
     pub krate: &'ast Crate,
     /// The node map
-    pub map: Vec<MapEntry<'ast>>,
+    pub(super) map: Vec<MapEntry<'ast>>,
     /// The parent of this node
     pub parent_node: NodeId,
     /// If true, completely ignore nested items. We set this when loading
@@ -43,11 +42,11 @@ pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
         collector
     }
 
-    pub fn extend(krate: &'ast Crate,
-                  parent: &'ast InlinedItem,
-                  parent_node: NodeId,
-                  map: Vec<MapEntry<'ast>>)
-                  -> NodeCollector<'ast> {
+    pub(super) fn extend(krate: &'ast Crate,
+                         parent: &'ast InlinedItem,
+                         parent_node: NodeId,
+                         map: Vec<MapEntry<'ast>>)
+                         -> NodeCollector<'ast> {
         let mut collector = NodeCollector {
             krate: krate,
             map: map,
@@ -98,12 +97,22 @@ fn visit_nested_item(&mut self, item: ItemId) {
         }
     }
 
+    fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
+        if !self.ignore_nested_items {
+            self.visit_trait_item(self.krate.trait_item(item_id))
+        }
+    }
+
     fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
-        self.visit_impl_item(self.krate.impl_item(item_id))
+        if !self.ignore_nested_items {
+            self.visit_impl_item(self.krate.impl_item(item_id))
+        }
     }
 
-    fn visit_body(&mut self, id: ExprId) {
-        self.visit_expr(self.krate.expr(id))
+    fn visit_nested_body(&mut self, id: BodyId) {
+        if !self.ignore_nested_items {
+            self.visit_body(self.krate.body(id))
+        }
     }
 
     fn visit_item(&mut self, i: &'ast Item) {
@@ -113,11 +122,6 @@ fn visit_item(&mut self, i: &'ast Item) {
 
         self.with_parent(i.id, |this| {
             match i.node {
-                ItemEnum(ref enum_definition, _) => {
-                    for v in &enum_definition.variants {
-                        this.insert(v.node.data.id(), NodeVariant(v));
-                    }
-                }
                 ItemStruct(ref struct_def, _) => {
                     // If this is a tuple-like struct, register the constructor.
                     if !struct_def.is_struct() {
@@ -209,7 +213,7 @@ fn visit_trait_ref(&mut self, tr: &'ast TraitRef) {
     }
 
     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: ExprId, s: Span, id: NodeId) {
+                b: BodyId, s: Span, id: NodeId) {
         assert_eq!(self.parent_node, id);
         intravisit::walk_fn(self, fk, fd, b, s, id);
     }
@@ -243,6 +247,14 @@ fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
         self.insert_entry(macro_def.id, NotPresent);
     }
 
+    fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
+        let id = v.node.data.id();
+        self.insert(id, NodeVariant(v));
+        self.with_parent(id, |this| {
+            intravisit::walk_variant(this, v, g, item_id);
+        });
+    }
+
     fn visit_struct_field(&mut self, field: &'ast StructField) {
         self.insert(field.id, NodeField(field));
         self.with_parent(field.id, |this| {
index 256aee342a3fc448f83637f02a78d7401df22c3f..be8780f39b10429d6aea31bbc28cc36c69e8cdc0 100644 (file)
@@ -16,7 +16,7 @@
 use syntax::visit;
 use syntax::symbol::{Symbol, keywords};
 
-/// Creates def ids for nodes in the HIR.
+/// Creates def ids for nodes in the AST.
 pub struct DefCollector<'a> {
     definitions: &'a mut Definitions,
     parent_def: Option<DefIndex>,
index 4f64670f482796bde55b37dda9a0d31df0bf0817..b28c5e80ea3c35bc4ddf41263ac89e4d272ce9fa 100644 (file)
@@ -220,7 +220,6 @@ pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
     }
 }
 
-
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
@@ -339,7 +338,7 @@ pub fn create_def_with_parent(&mut self,
                 data,
                 self.table.def_key(self.node_to_def_index[&node_id]));
 
-        assert!(parent.is_some() ^ (data == DefPathData::CrateRoot));
+        assert_eq!(parent.is_some(), data != DefPathData::CrateRoot);
 
         // Find a unique DefKey. This basically means incrementing the disambiguator
         // until we get no match.
index 4546f6d8c27e6b64674c9fd166d8498de791c3db..27ebeea9ad91db21f18d477684a6288f5a699365 100644 (file)
@@ -17,7 +17,6 @@
 
 use dep_graph::{DepGraph, DepNode};
 
-use middle::cstore::InlinedItem;
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
 
 use syntax::abi::Abi;
@@ -26,7 +25,8 @@
 use syntax_pos::Span;
 
 use hir::*;
-use hir::print as pprust;
+use hir::intravisit::Visitor;
+use hir::print::Nested;
 
 use arena::TypedArena;
 use std::cell::RefCell;
 mod def_collector;
 pub mod definitions;
 
+/// The data we save and restore about an inlined item or method.  This is not
+/// part of the AST that we parse from a file, but it becomes part of the tree
+/// that we trans.
+#[derive(Debug)]
+struct InlinedItem {
+    def_id: DefId,
+    body: Body,
+}
+
 #[derive(Copy, Clone, Debug)]
 pub enum Node<'ast> {
     NodeItem(&'ast Item),
@@ -60,14 +69,12 @@ pub enum Node<'ast> {
     NodeLifetime(&'ast Lifetime),
     NodeTyParam(&'ast TyParam),
     NodeVisibility(&'ast Visibility),
-
-    NodeInlinedItem(&'ast InlinedItem),
 }
 
 /// Represents an entry and its parent NodeID.
 /// The odd layout is to bring down the total size.
 #[derive(Copy, Debug)]
-pub enum MapEntry<'ast> {
+enum MapEntry<'ast> {
     /// Placeholder for holes in the map.
     NotPresent,
 
@@ -121,8 +128,6 @@ fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
             NodeLifetime(n) => EntryLifetime(p, n),
             NodeTyParam(n) => EntryTyParam(p, n),
             NodeVisibility(n) => EntryVisibility(p, n),
-
-            NodeInlinedItem(n) => RootInlinedParent(n),
         }
     }
 
@@ -171,10 +176,49 @@ fn to_node(self) -> Option<Node<'ast>> {
             EntryLifetime(_, n) => NodeLifetime(n),
             EntryTyParam(_, n) => NodeTyParam(n),
             EntryVisibility(_, n) => NodeVisibility(n),
-            RootInlinedParent(n) => NodeInlinedItem(n),
             _ => return None
         })
     }
+
+    fn is_body_owner(self, node_id: NodeId) -> bool {
+        match self {
+            EntryItem(_, item) => {
+                match item.node {
+                    ItemConst(_, body) |
+                    ItemStatic(.., body) |
+                    ItemFn(_, _, _, _, _, body) => body.node_id == node_id,
+                    _ => false
+                }
+            }
+
+            EntryTraitItem(_, item) => {
+                match item.node {
+                    TraitItemKind::Const(_, Some(body)) |
+                    TraitItemKind::Method(_, TraitMethod::Provided(body)) => {
+                        body.node_id == node_id
+                    }
+                    _ => false
+                }
+            }
+
+            EntryImplItem(_, item) => {
+                match item.node {
+                    ImplItemKind::Const(_, body) |
+                    ImplItemKind::Method(_, body) => body.node_id == node_id,
+                    _ => false
+                }
+            }
+
+            EntryExpr(_, expr) => {
+                match expr.node {
+                    ExprClosure(.., body, _) => body.node_id == node_id,
+                    _ => false
+                }
+            }
+
+            _ => false
+        }
+    }
 }
 
 /// Stores a crate and any number of inlined items from other crates.
@@ -250,38 +294,34 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         if !self.is_inlined_node_id(id) {
             let mut last_expr = None;
             loop {
-                match map[id.as_usize()] {
-                    EntryItem(_, item) => {
-                        assert_eq!(id, item.id);
-                        let def_id = self.local_def_id(id);
-
+                let entry = map[id.as_usize()];
+                match entry {
+                    EntryItem(..) |
+                    EntryTraitItem(..) |
+                    EntryImplItem(..) => {
                         if let Some(last_id) = last_expr {
-                            // The body of the item may have a separate dep node
-                            // (Note that trait items don't currently have
-                            // their own dep node, so there's also just one
-                            // HirBody node for all the items)
-                            if self.is_body(last_id, item) {
+                            // The body may have a separate dep node
+                            if entry.is_body_owner(last_id) {
+                                let def_id = self.local_def_id(id);
                                 return DepNode::HirBody(def_id);
                             }
                         }
-                        return DepNode::Hir(def_id);
+                        return DepNode::Hir(self.local_def_id(id));
                     }
 
-                    EntryImplItem(_, item) => {
-                        let def_id = self.local_def_id(id);
+                    EntryVariant(p, v) => {
+                        id = p;
 
-                        if let Some(last_id) = last_expr {
-                            // The body of the item may have a separate dep node
-                            if self.is_impl_item_body(last_id, item) {
+                        if last_expr.is_some() {
+                            if v.node.disr_expr.map(|e| e.node_id) == last_expr {
+                                // The enum parent holds both Hir and HirBody nodes.
+                                let def_id = self.local_def_id(id);
                                 return DepNode::HirBody(def_id);
                             }
                         }
-                        return DepNode::Hir(def_id);
                     }
 
                     EntryForeignItem(p, _) |
-                    EntryTraitItem(p, _) |
-                    EntryVariant(p, _) |
                     EntryField(p, _) |
                     EntryStmt(p, _) |
                     EntryTy(p, _) |
@@ -308,7 +348,7 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
                         bug!("node {} has inlined ancestor but is not inlined", id0),
 
                     NotPresent =>
-                        // Some nodes, notably struct fields, are not
+                        // Some nodes, notably macro definitions, are not
                         // present in the map for whatever reason, but
                         // they *do* have def-ids. So if we encounter an
                         // empty hole, check for that case.
@@ -358,29 +398,6 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         }
     }
 
-    fn is_body(&self, node_id: NodeId, item: &Item) -> bool {
-        match item.node {
-            ItemFn(_, _, _, _, _, body) => body.node_id() == node_id,
-            // Since trait items currently don't get their own dep nodes,
-            // we check here whether node_id is the body of any of the items.
-            // If they get their own dep nodes, this can go away
-            ItemTrait(_, _, _, ref trait_items) => {
-                trait_items.iter().any(|trait_item| { match trait_item.node {
-                    MethodTraitItem(_, Some(body)) => body.node_id() == node_id,
-                    _ => false
-                }})
-            }
-            _ => false
-        }
-    }
-
-    fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool {
-        match item.node {
-            ImplItemKind::Method(_, body) => body.node_id() == node_id,
-            _ => false
-        }
-    }
-
     pub fn num_local_def_ids(&self) -> usize {
         self.definitions.len()
     }
@@ -436,6 +453,14 @@ pub fn krate(&self) -> &'ast Crate {
         self.forest.krate()
     }
 
+    pub fn trait_item(&self, id: TraitItemId) -> &'ast TraitItem {
+        self.read(id.node_id);
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.trait_item(id)
+    }
+
     pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
         self.read(id.node_id);
 
@@ -444,6 +469,31 @@ pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
         self.forest.krate.impl_item(id)
     }
 
+    pub fn body(&self, id: BodyId) -> &'ast Body {
+        self.read(id.node_id);
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.body(id)
+    }
+
+    /// Returns the `NodeId` that corresponds to the definition of
+    /// which this is the body of, i.e. a `fn`, `const` or `static`
+    /// item (possibly associated), or a closure, or the body itself
+    /// for embedded constant expressions (e.g. `N` in `[T; N]`).
+    pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
+        let parent = self.get_parent_node(node_id);
+        if self.map.borrow()[parent.as_usize()].is_body_owner(node_id) {
+            parent
+        } else {
+            node_id
+        }
+    }
+
+    pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
+        self.local_def_id(self.body_owner(id))
+    }
+
     /// Get the attributes on the krate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
@@ -687,17 +737,13 @@ pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
         }
     }
 
-    pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
+    pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body {
         match self.find_entry(id) {
-            Some(RootInlinedParent(inlined_item)) => inlined_item,
+            Some(RootInlinedParent(inlined_item)) => &inlined_item.body,
             _ => bug!("expected inlined item, found {}", self.node_to_string(id)),
         }
     }
 
-    pub fn expr(&self, id: ExprId) -> &'ast Expr {
-        self.expect_expr(id.node_id())
-    }
-
     /// Returns the name associated with the given NodeId's AST.
     pub fn name(&self, id: NodeId) -> Name {
         match self.get(id) {
@@ -778,7 +824,7 @@ pub fn span(&self, id: NodeId) -> Span {
             Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
 
             Some(RootCrate) => self.forest.krate.span,
-            Some(RootInlinedParent(parent)) => parent.body.span,
+            Some(RootInlinedParent(parent)) => parent.body.value.span,
             Some(NotPresent) | None => {
                 bug!("hir::map::Map::span: id not in map: {:?}", id)
             }
@@ -796,6 +842,10 @@ pub fn node_to_string(&self, id: NodeId) -> String {
     pub fn node_to_user_string(&self, id: NodeId) -> String {
         node_id_to_string(self, id, false)
     }
+
+    pub fn node_to_pretty_string(&self, id: NodeId) -> String {
+        print::to_string(self, |s| s.print_node(self.get(id)))
+    }
 }
 
 pub struct NodesMatchingSuffix<'a, 'ast:'a> {
@@ -934,33 +984,47 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
     }
 }
 
-/// Used for items loaded from external crate that are being inlined into this
+/// Used for bodies loaded from external crate that are being inlined into this
 /// crate.
-pub fn map_decoded_item<'ast>(map: &Map<'ast>,
-                              ii: InlinedItem,
-                              ii_parent_id: NodeId)
-                              -> &'ast InlinedItem {
+pub fn map_decoded_body<'ast>(map: &Map<'ast>,
+                              def_id: DefId,
+                              body: Body,
+                              parent_id: NodeId)
+                              -> &'ast Body {
     let _ignore = map.forest.dep_graph.in_ignore();
 
-    let ii = map.forest.inlined_items.alloc(ii);
+    let ii = map.forest.inlined_items.alloc(InlinedItem {
+        def_id: def_id,
+        body: body
+    });
 
     let mut collector = NodeCollector::extend(map.krate(),
                                               ii,
-                                              ii_parent_id,
+                                              parent_id,
                                               mem::replace(&mut *map.map.borrow_mut(), vec![]));
-    ii.visit(&mut collector);
+    collector.visit_body(&ii.body);
     *map.map.borrow_mut() = collector.map;
 
-    ii
+    &ii.body
 }
 
-pub trait NodePrinter {
-    fn print_node(&mut self, node: &Node) -> io::Result<()>;
+/// Identical to the `PpAnn` implementation for `hir::Crate`,
+/// except it avoids creating a dependency on the whole crate.
+impl<'ast> print::PpAnn for Map<'ast> {
+    fn nested(&self, state: &mut print::State, nested: print::Nested) -> io::Result<()> {
+        match nested {
+            Nested::Item(id) => state.print_item(self.expect_item(id.id)),
+            Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
+            Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::Body(id) => state.print_expr(&self.body(id).value),
+            Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat)
+        }
+    }
 }
 
-impl<'a> NodePrinter for pprust::State<'a> {
-    fn print_node(&mut self, node: &Node) -> io::Result<()> {
-        match *node {
+impl<'a> print::State<'a> {
+    pub fn print_node(&mut self, node: Node) -> io::Result<()> {
+        match node {
             NodeItem(a)        => self.print_item(&a),
             NodeForeignItem(a) => self.print_foreign_item(&a),
             NodeTraitItem(a)   => self.print_trait_item(a),
@@ -970,8 +1034,17 @@ fn print_node(&mut self, node: &Node) -> io::Result<()> {
             NodeStmt(a)        => self.print_stmt(&a),
             NodeTy(a)          => self.print_type(&a),
             NodeTraitRef(a)    => self.print_trait_ref(&a),
+            NodeLocal(a)       |
             NodePat(a)         => self.print_pat(&a),
-            NodeBlock(a)       => self.print_block(&a),
+            NodeBlock(a)       => {
+                use syntax::print::pprust::PrintState;
+
+                // containing cbox, will be closed by print-block at }
+                self.cbox(print::indent_unit)?;
+                // head-ibox, will be closed by print-block after {
+                self.ibox(0)?;
+                self.print_block(&a)
+            }
             NodeLifetime(a)    => self.print_lifetime(&a),
             NodeVisibility(a)  => self.print_visibility(&a),
             NodeTyParam(_)     => bug!("cannot print TyParam"),
@@ -979,10 +1052,7 @@ fn print_node(&mut self, node: &Node) -> io::Result<()> {
             // these cases do not carry enough information in the
             // ast_map to reconstruct their full structure for pretty
             // printing.
-            NodeLocal(_)       => bug!("cannot print isolated Local"),
             NodeStructCtor(_)  => bug!("cannot print isolated StructCtor"),
-
-            NodeInlinedItem(_) => bug!("cannot print inlined item"),
         }
     }
 }
@@ -1045,9 +1115,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
         Some(NodeTraitItem(ti)) => {
             let kind = match ti.node {
-                ConstTraitItem(..) => "assoc constant",
-                MethodTraitItem(..) => "trait method",
-                TypeTraitItem(..) => "assoc type",
+                TraitItemKind::Const(..) => "assoc constant",
+                TraitItemKind::Method(..) => "trait method",
+                TraitItemKind::Type(..) => "assoc type",
             };
 
             format!("{} {} in {}{}", kind, ti.name, path_str(), id_str)
@@ -1062,33 +1132,32 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                     field.name,
                     path_str(), id_str)
         }
-        Some(NodeExpr(ref expr)) => {
-            format!("expr {}{}", pprust::expr_to_string(&expr), id_str)
+        Some(NodeExpr(_)) => {
+            format!("expr {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeStmt(ref stmt)) => {
-            format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str)
+        Some(NodeStmt(_)) => {
+            format!("stmt {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeTy(ref ty)) => {
-            format!("type {}{}", pprust::ty_to_string(&ty), id_str)
+        Some(NodeTy(_)) => {
+            format!("type {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeTraitRef(ref tr)) => {
-            format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str)
+        Some(NodeTraitRef(_)) => {
+            format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeLocal(ref pat)) => {
-            format!("local {}{}", pprust::pat_to_string(&pat), id_str)
+        Some(NodeLocal(_)) => {
+            format!("local {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodePat(ref pat)) => {
-            format!("pat {}{}", pprust::pat_to_string(&pat), id_str)
+        Some(NodePat(_)) => {
+            format!("pat {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeBlock(ref block)) => {
-            format!("block {}{}", pprust::block_to_string(&block), id_str)
+        Some(NodeBlock(_)) => {
+            format!("block {}{}", map.node_to_pretty_string(id), id_str)
         }
         Some(NodeStructCtor(_)) => {
             format!("struct_ctor {}{}", path_str(), id_str)
         }
-        Some(NodeLifetime(ref l)) => {
-            format!("lifetime {}{}",
-                    pprust::lifetime_to_string(&l), id_str)
+        Some(NodeLifetime(_)) => {
+            format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
         }
         Some(NodeTyParam(ref ty_param)) => {
             format!("typaram {:?}{}", ty_param, id_str)
@@ -1096,9 +1165,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeVisibility(ref vis)) => {
             format!("visibility {:?}{}", vis, id_str)
         }
-        Some(NodeInlinedItem(_)) => {
-            format!("inlined item {}", id_str)
-        }
         None => {
             format!("unknown node{}", id_str)
         }
index 4eee76d466ac1a67adbb49df190e03a22ac59fed..9149da459c26e85127ca50ed0bca90877fd42d7b 100644 (file)
@@ -22,7 +22,6 @@
 pub use self::Mutability::*;
 pub use self::PrimTy::*;
 pub use self::Stmt_::*;
-pub use self::TraitItem_::*;
 pub use self::Ty_::*;
 pub use self::TyParamBound::*;
 pub use self::UnOp::*;
 
 use hir::def::Def;
 use hir::def_id::DefId;
-use util::nodemap::{NodeMap, FxHashSet};
-use rustc_data_structures::fnv::FnvHashMap;
+use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
 
-use syntax_pos::{mk_sp, Span, ExpnId, DUMMY_SP};
-use syntax::codemap::{self, respan, Spanned};
+use syntax_pos::{Span, ExpnId, DUMMY_SP};
+use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
 use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
@@ -87,7 +85,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "lifetime({}: {})",
                self.id,
-               print::lifetime_to_string(self))
+               print::to_string(print::NO_ANN, |s| s.print_lifetime(self)))
     }
 }
 
@@ -119,13 +117,8 @@ pub fn is_global(&self) -> bool {
 
 impl fmt::Debug for Path {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "path({})", print::path_to_string(self))
-    }
-}
-
-impl fmt::Display for Path {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", print::path_to_string(self))
+        write!(f, "path({})",
+               print::to_string(print::NO_ANN, |s| s.print_path(self, false)))
     }
 }
 
@@ -431,8 +424,9 @@ pub struct Crate {
     // slightly different results.
     pub items: BTreeMap<NodeId, Item>,
 
+    pub trait_items: BTreeMap<TraitItemId, TraitItem>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem>,
-    pub exprs: FnvHashMap<ExprId, Expr>,
+    pub bodies: FxHashMap<BodyId, Body>,
 }
 
 impl Crate {
@@ -440,6 +434,10 @@ pub fn item(&self, id: NodeId) -> &Item {
         &self.items[&id]
     }
 
+    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem {
+        &self.trait_items[&id]
+    }
+
     pub fn impl_item(&self, id: ImplItemId) -> &ImplItem {
         &self.impl_items[&id]
     }
@@ -459,13 +457,17 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
             visitor.visit_item(item);
         }
 
+        for (_, trait_item) in &self.trait_items {
+            visitor.visit_trait_item(trait_item);
+        }
+
         for (_, impl_item) in &self.impl_items {
             visitor.visit_impl_item(impl_item);
         }
     }
 
-    pub fn expr(&self, id: ExprId) -> &Expr {
-        &self.exprs[&id]
+    pub fn body(&self, id: BodyId) -> &Body {
+        &self.bodies[&id]
     }
 }
 
@@ -503,7 +505,8 @@ pub struct Pat {
 
 impl fmt::Debug for Pat {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "pat({}: {})", self.id, print::pat_to_string(self))
+        write!(f, "pat({}: {})", self.id,
+               print::to_string(print::NO_ANN, |s| s.print_pat(self)))
     }
 }
 
@@ -755,7 +758,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "stmt({}: {})",
                spanned.node.id(),
-               print::stmt_to_string(&spanned))
+               print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned)))
     }
 }
 
@@ -853,12 +856,23 @@ pub enum UnsafeSource {
     UserProvided,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ExprId(NodeId);
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct BodyId {
+    pub node_id: NodeId,
+}
 
-impl ExprId {
-    pub fn node_id(self) -> NodeId {
-        self.0
+/// The body of a function or constant value.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Body {
+    pub arguments: HirVec<Arg>,
+    pub value: Expr
+}
+
+impl Body {
+    pub fn id(&self) -> BodyId {
+        BodyId {
+            node_id: self.value.id
+        }
     }
 }
 
@@ -871,15 +885,10 @@ pub struct Expr {
     pub attrs: ThinVec<Attribute>,
 }
 
-impl Expr {
-    pub fn expr_id(&self) -> ExprId {
-        ExprId(self.id)
-    }
-}
-
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "expr({}: {})", self.id, print::expr_to_string(self))
+        write!(f, "expr({}: {})", self.id,
+               print::to_string(print::NO_ANN, |s| s.print_expr(self)))
     }
 }
 
@@ -936,7 +945,7 @@ pub enum Expr_ {
     /// A closure (for example, `move |a, b, c| {a + b + c}`).
     ///
     /// The final span is the span of the argument block `|...|`
-    ExprClosure(CaptureClause, P<FnDecl>, ExprId, Span),
+    ExprClosure(CaptureClause, P<FnDecl>, BodyId, Span),
     /// A block (`{ ... }`)
     ExprBlock(P<Block>),
 
@@ -980,7 +989,7 @@ pub enum Expr_ {
     ///
     /// For example, `[1; 5]`. The first expression is the element
     /// to be repeated; the second is the number of times to repeat it.
-    ExprRepeat(P<Expr>, P<Expr>),
+    ExprRepeat(P<Expr>, BodyId),
 }
 
 /// Optionally `Self`-qualified value/type path or associated extension.
@@ -1003,12 +1012,6 @@ pub enum QPath {
     TypeRelative(P<Ty>, P<PathSegment>)
 }
 
-impl fmt::Display for QPath {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", print::qpath_to_string(self))
-    }
-}
-
 /// Hints at the original code for a `match _ { .. }`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum MatchSource {
@@ -1070,6 +1073,14 @@ pub struct MethodSig {
     pub generics: Generics,
 }
 
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItemId {
+    pub node_id: NodeId,
+}
+
 /// Represents an item declaration within a trait declaration,
 /// possibly including a default implementation. A trait item is
 /// either required (meaning it doesn't have an implementation, just a
@@ -1079,21 +1090,31 @@ pub struct TraitItem {
     pub id: NodeId,
     pub name: Name,
     pub attrs: HirVec<Attribute>,
-    pub node: TraitItem_,
+    pub node: TraitItemKind,
     pub span: Span,
 }
 
+/// A trait method's body (or just argument names).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitMethod {
+    /// No default body in the trait, just a signature.
+    Required(HirVec<Spanned<Name>>),
+
+    /// Both signature and body are provided in the trait.
+    Provided(BodyId),
+}
+
 /// Represents a trait method or associated constant or type
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TraitItem_ {
+pub enum TraitItemKind {
     /// An associated constant with an optional value (otherwise `impl`s
     /// must contain a value)
-    ConstTraitItem(P<Ty>, Option<P<Expr>>),
+    Const(P<Ty>, Option<BodyId>),
     /// A method with an optional body
-    MethodTraitItem(MethodSig, Option<ExprId>),
+    Method(MethodSig, TraitMethod),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type
-    TypeTraitItem(TyParamBounds, Option<P<Ty>>),
+    Type(TyParamBounds, Option<P<Ty>>),
 }
 
 // The bodies for items are stored "out of line", in a separate
@@ -1121,9 +1142,9 @@ pub struct ImplItem {
 pub enum ImplItemKind {
     /// An associated constant of the given type, set to the constant result
     /// of the expression
-    Const(P<Ty>, P<Expr>),
+    Const(P<Ty>, BodyId),
     /// A method implementation with the given signature and body
-    Method(MethodSig, ExprId),
+    Method(MethodSig, BodyId),
     /// An associated type
     Type(P<Ty>),
 }
@@ -1147,7 +1168,8 @@ pub struct Ty {
 
 impl fmt::Debug for Ty {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "type({})", print::ty_to_string(self))
+        write!(f, "type({})",
+               print::to_string(print::NO_ANN, |s| s.print_type(self)))
     }
 }
 
@@ -1176,7 +1198,7 @@ pub enum Ty_ {
     /// A variable length slice (`[T]`)
     TySlice(P<Ty>),
     /// A fixed length array (`[T; n]`)
-    TyArray(P<Ty>, P<Expr>),
+    TyArray(P<Ty>, BodyId),
     /// A raw pointer (`*const T` or `*mut T`)
     TyPtr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`)
@@ -1200,7 +1222,7 @@ pub enum Ty_ {
     /// An `impl TraitA+TraitB` type.
     TyImplTrait(TyParamBounds),
     /// Unused for now
-    TyTypeof(P<Expr>),
+    TyTypeof(BodyId),
     /// TyInfer means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     TyInfer,
@@ -1229,67 +1251,18 @@ pub struct InlineAsm {
 /// represents an argument in a function header
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Arg {
-    pub ty: P<Ty>,
     pub pat: P<Pat>,
     pub id: NodeId,
 }
 
-/// Alternative representation for `Arg`s describing `self` parameter of methods.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum SelfKind {
-    /// `self`, `mut self`
-    Value(Mutability),
-    /// `&'lt self`, `&'lt mut self`
-    Region(Option<Lifetime>, Mutability),
-    /// `self: TYPE`, `mut self: TYPE`
-    Explicit(P<Ty>, Mutability),
-}
-
-pub type ExplicitSelf = Spanned<SelfKind>;
-
-impl Arg {
-    pub fn to_self(&self) -> Option<ExplicitSelf> {
-        if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node {
-            if name.node == keywords::SelfValue.name() {
-                return match self.ty.node {
-                    TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
-                    TyRptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyInfer => {
-                        Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
-                    }
-                    _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi),
-                                     SelfKind::Explicit(self.ty.clone(), mutbl)))
-                }
-            }
-        }
-        None
-    }
-
-    pub fn is_self(&self) -> bool {
-        if let PatKind::Binding(_, _, name, _) = self.pat.node {
-            name.node == keywords::SelfValue.name()
-        } else {
-            false
-        }
-    }
-}
-
 /// Represents the header (not the body) of a function declaration
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct FnDecl {
-    pub inputs: HirVec<Arg>,
+    pub inputs: HirVec<P<Ty>>,
     pub output: FunctionRetTy,
     pub variadic: bool,
 }
 
-impl FnDecl {
-    pub fn get_self(&self) -> Option<ExplicitSelf> {
-        self.inputs.get(0).and_then(Arg::to_self)
-    }
-    pub fn has_self(&self) -> bool {
-        self.inputs.get(0).map(Arg::is_self).unwrap_or(false)
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1403,7 +1376,7 @@ pub struct Variant_ {
     pub attrs: HirVec<Attribute>,
     pub data: VariantData,
     /// Explicit discriminant, eg `Foo = 1`
-    pub disr_expr: Option<P<Expr>>,
+    pub disr_expr: Option<BodyId>,
 }
 
 pub type Variant = Spanned<Variant_>;
@@ -1562,11 +1535,11 @@ pub enum Item_ {
     ItemUse(P<Path>, UseKind),
 
     /// A `static` item
-    ItemStatic(P<Ty>, Mutability, P<Expr>),
+    ItemStatic(P<Ty>, Mutability, BodyId),
     /// A `const` item
-    ItemConst(P<Ty>, P<Expr>),
+    ItemConst(P<Ty>, BodyId),
     /// A function declaration
-    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, ExprId),
+    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, BodyId),
     /// A module
     ItemMod(Mod),
     /// An external module
@@ -1580,7 +1553,7 @@ pub enum Item_ {
     /// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
     ItemUnion(VariantData, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItem>),
+    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
 
     // Default trait implementations
     ///
@@ -1616,6 +1589,21 @@ pub fn descriptive_variant(&self) -> &str {
     }
 }
 
+/// A reference from an trait to one of its associated items. This
+/// contains the item's id, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the id (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItemRef {
+    pub id: TraitItemId,
+    pub name: Name,
+    pub kind: AssociatedItemKind,
+    pub span: Span,
+    pub defaultness: Defaultness,
+}
+
 /// A reference from an impl to one of its associated items. This
 /// contains the item's id, naturally, but also the item's name and
 /// some other high-level details (like whether it is an associated
@@ -1653,7 +1641,7 @@ pub struct ForeignItem {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ForeignItem_ {
     /// A foreign function
-    ForeignItemFn(P<FnDecl>, Generics),
+    ForeignItemFn(P<FnDecl>, HirVec<Spanned<Name>>, Generics),
     /// A foreign static item (`static ext: u8`), with optional mutability
     /// (the boolean is true when mutable)
     ForeignItemStatic(P<Ty>, bool),
index 100e344d9418036af1b7790a2a2b9bbc8ba5d285..18fa6836b510827bfeb4e1c43d5e949bd09af7d7 100644 (file)
@@ -13,7 +13,6 @@
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax::codemap::{CodeMap, Spanned};
-use syntax::parse::token::{self, BinOpToken};
 use syntax::parse::lexer::comments;
 use syntax::print::pp::{self, break_offset, word, space, hardbreak};
 use syntax::print::pp::{Breaks, eof};
@@ -25,7 +24,7 @@
 use errors;
 
 use hir;
-use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier};
+use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 
 use std::io::{self, Write, Read};
 
@@ -38,7 +37,18 @@ pub enum AnnNode<'a> {
     NodePat(&'a hir::Pat),
 }
 
+pub enum Nested {
+    Item(hir::ItemId),
+    TraitItem(hir::TraitItemId),
+    ImplItem(hir::ImplItemId),
+    Body(hir::BodyId),
+    BodyArgPat(hir::BodyId, usize)
+}
+
 pub trait PpAnn {
+    fn nested(&self, _state: &mut State, _nested: Nested) -> io::Result<()> {
+        Ok(())
+    }
     fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
         Ok(())
     }
@@ -47,14 +57,23 @@ fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
     }
 }
 
-#[derive(Copy, Clone)]
 pub struct NoAnn;
-
 impl PpAnn for NoAnn {}
+pub const NO_ANN: &'static PpAnn = &NoAnn;
 
+impl PpAnn for hir::Crate {
+    fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> {
+        match nested {
+            Nested::Item(id) => state.print_item(self.item(id.id)),
+            Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
+            Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::Body(id) => state.print_expr(&self.body(id).value),
+            Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat)
+        }
+    }
+}
 
 pub struct State<'a> {
-    krate: Option<&'a Crate>,
     pub s: pp::Printer<'a>,
     cm: Option<&'a CodeMap>,
     comments: Option<Vec<comments::Comment>>,
@@ -86,30 +105,6 @@ fn literals(&self) -> &Option<Vec<comments::Literal>> {
     }
 }
 
-pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> {
-    static NO_ANN: NoAnn = NoAnn;
-    rust_printer_annotated(writer, &NO_ANN, krate)
-}
-
-pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>,
-                                  ann: &'a PpAnn,
-                                  krate: Option<&'a Crate>)
-                                  -> State<'a> {
-    State {
-        krate: krate,
-        s: pp::mk_printer(writer, default_columns),
-        cm: None,
-        comments: None,
-        literals: None,
-        cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
-            cur_cmnt: 0,
-            cur_lit: 0,
-        },
-        boxes: Vec::new(),
-        ann: ann,
-    }
-}
-
 #[allow(non_upper_case_globals)]
 pub const indent_unit: usize = 4;
 
@@ -130,7 +125,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        is_expanded: bool)
                        -> io::Result<()> {
     let mut s = State::new_from_input(cm, span_diagnostic, filename, input,
-                                      out, ann, is_expanded, Some(krate));
+                                      out, ann, is_expanded);
 
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
@@ -147,8 +142,7 @@ pub fn new_from_input(cm: &'a CodeMap,
                           input: &mut Read,
                           out: Box<Write + 'a>,
                           ann: &'a PpAnn,
-                          is_expanded: bool,
-                          krate: Option<&'a Crate>)
+                          is_expanded: bool)
                           -> State<'a> {
         let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic,
                                                                    filename,
@@ -165,19 +159,16 @@ pub fn new_from_input(cm: &'a CodeMap,
                        None
                    } else {
                        Some(lits)
-                   },
-                   krate)
+                   })
     }
 
     pub fn new(cm: &'a CodeMap,
                out: Box<Write + 'a>,
                ann: &'a PpAnn,
                comments: Option<Vec<comments::Comment>>,
-               literals: Option<Vec<comments::Literal>>,
-               krate: Option<&'a Crate>)
+               literals: Option<Vec<comments::Literal>>)
                -> State<'a> {
         State {
-            krate: krate,
             s: pp::mk_printer(out, default_columns),
             cm: Some(cm),
             comments: comments.clone(),
@@ -192,144 +183,36 @@ pub fn new(cm: &'a CodeMap,
     }
 }
 
-pub fn to_string<F>(f: F) -> String
+pub fn to_string<F>(ann: &PpAnn, f: F) -> String
     where F: FnOnce(&mut State) -> io::Result<()>
 {
     let mut wr = Vec::new();
     {
-        let mut printer = rust_printer(Box::new(&mut wr), None);
+        let mut printer = State {
+            s: pp::mk_printer(Box::new(&mut wr), default_columns),
+            cm: None,
+            comments: None,
+            literals: None,
+            cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
+                cur_cmnt: 0,
+                cur_lit: 0,
+            },
+            boxes: Vec::new(),
+            ann: ann,
+        };
         f(&mut printer).unwrap();
         eof(&mut printer.s).unwrap();
     }
     String::from_utf8(wr).unwrap()
 }
 
-pub fn binop_to_string(op: BinOpToken) -> &'static str {
-    match op {
-        token::Plus => "+",
-        token::Minus => "-",
-        token::Star => "*",
-        token::Slash => "/",
-        token::Percent => "%",
-        token::Caret => "^",
-        token::And => "&",
-        token::Or => "|",
-        token::Shl => "<<",
-        token::Shr => ">>",
-    }
-}
-
-pub fn ty_to_string(ty: &hir::Ty) -> String {
-    to_string(|s| s.print_type(ty))
-}
-
-pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String {
-    to_string(|s| s.print_bounds("", bounds))
-}
-
-pub fn pat_to_string(pat: &hir::Pat) -> String {
-    to_string(|s| s.print_pat(pat))
-}
-
-pub fn arm_to_string(arm: &hir::Arm) -> String {
-    to_string(|s| s.print_arm(arm))
-}
-
-pub fn expr_to_string(e: &hir::Expr) -> String {
-    to_string(|s| s.print_expr(e))
-}
-
-pub fn lifetime_to_string(e: &hir::Lifetime) -> String {
-    to_string(|s| s.print_lifetime(e))
-}
-
-pub fn stmt_to_string(stmt: &hir::Stmt) -> String {
-    to_string(|s| s.print_stmt(stmt))
-}
-
-pub fn item_to_string(i: &hir::Item) -> String {
-    to_string(|s| s.print_item(i))
-}
-
-pub fn impl_item_to_string(i: &hir::ImplItem) -> String {
-    to_string(|s| s.print_impl_item(i))
-}
-
-pub fn trait_item_to_string(i: &hir::TraitItem) -> String {
-    to_string(|s| s.print_trait_item(i))
-}
-
-pub fn generics_to_string(generics: &hir::Generics) -> String {
-    to_string(|s| s.print_generics(generics))
-}
-
-pub fn where_clause_to_string(i: &hir::WhereClause) -> String {
-    to_string(|s| s.print_where_clause(i))
-}
-
-pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
-    to_string(|s| s.print_fn_block_args(p))
-}
-
-pub fn path_to_string(p: &hir::Path) -> String {
-    to_string(|s| s.print_path(p, false))
-}
-
-pub fn qpath_to_string(p: &hir::QPath) -> String {
-    to_string(|s| s.print_qpath(p, false))
-}
-
-pub fn name_to_string(name: ast::Name) -> String {
-    to_string(|s| s.print_name(name))
-}
-
-pub fn fun_to_string(decl: &hir::FnDecl,
-                     unsafety: hir::Unsafety,
-                     constness: hir::Constness,
-                     name: ast::Name,
-                     generics: &hir::Generics)
-                     -> String {
-    to_string(|s| {
-        s.head("")?;
-        s.print_fn(decl,
-                   unsafety,
-                   constness,
-                   Abi::Rust,
-                   Some(name),
-                   generics,
-                   &hir::Inherited)?;
-        s.end()?; // Close the head box
-        s.end() // Close the outer box
+pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String {
+    to_string(NO_ANN, |s| {
+        s.print_visibility(vis)?;
+        word(&mut s.s, w)
     })
 }
 
-pub fn block_to_string(blk: &hir::Block) -> String {
-    to_string(|s| {
-        // containing cbox, will be closed by print-block at }
-        s.cbox(indent_unit)?;
-        // head-ibox, will be closed by print-block after {
-        s.ibox(0)?;
-        s.print_block(blk)
-    })
-}
-
-pub fn variant_to_string(var: &hir::Variant) -> String {
-    to_string(|s| s.print_variant(var))
-}
-
-pub fn arg_to_string(arg: &hir::Arg) -> String {
-    to_string(|s| s.print_arg(arg, false))
-}
-
-pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
-    match *vis {
-        hir::Public => format!("pub {}", s),
-        hir::Visibility::Crate => format!("pub(crate) {}", s),
-        hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
-        hir::Inherited => s.to_string(),
-    }
-}
-
 fn needs_parentheses(expr: &hir::Expr) -> bool {
     match expr.node {
         hir::ExprAssign(..) |
@@ -462,8 +345,8 @@ pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr]) -> io::Result<(
 
     pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
         self.print_inner_attributes(attrs)?;
-        for item_id in &_mod.item_ids {
-            self.print_item_id(item_id)?;
+        for &item_id in &_mod.item_ids {
+            self.ann.nested(self, Nested::Item(item_id))?;
         }
         Ok(())
     }
@@ -545,16 +428,16 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
             hir::TyImplTrait(ref bounds) => {
                 self.print_bounds("impl ", &bounds[..])?;
             }
-            hir::TyArray(ref ty, ref v) => {
+            hir::TyArray(ref ty, v) => {
                 word(&mut self.s, "[")?;
                 self.print_type(&ty)?;
                 word(&mut self.s, "; ")?;
-                self.print_expr(&v)?;
+                self.ann.nested(self, Nested::Body(v))?;
                 word(&mut self.s, "]")?;
             }
-            hir::TyTypeof(ref e) => {
+            hir::TyTypeof(e) => {
                 word(&mut self.s, "typeof(")?;
-                self.print_expr(&e)?;
+                self.ann.nested(self, Nested::Body(e))?;
                 word(&mut self.s, ")")?;
             }
             hir::TyInfer => {
@@ -569,7 +452,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()>
         self.maybe_print_comment(item.span.lo)?;
         self.print_outer_attributes(&item.attrs)?;
         match item.node {
-            hir::ForeignItemFn(ref decl, ref generics) => {
+            hir::ForeignItemFn(ref decl, ref arg_names, ref generics) => {
                 self.head("")?;
                 self.print_fn(decl,
                               hir::Unsafety::Normal,
@@ -577,7 +460,9 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()>
                               Abi::Rust,
                               Some(item.name),
                               generics,
-                              &item.vis)?;
+                              &item.vis,
+                              arg_names,
+                              None)?;
                 self.end()?; // end head-ibox
                 word(&mut self.s, ";")?;
                 self.end() // end the outer fn box
@@ -600,7 +485,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()>
     fn print_associated_const(&mut self,
                               name: ast::Name,
                               ty: &hir::Ty,
-                              default: Option<&hir::Expr>,
+                              default: Option<hir::BodyId>,
                               vis: &hir::Visibility)
                               -> io::Result<()> {
         word(&mut self.s, &visibility_qualified(vis, ""))?;
@@ -611,7 +496,7 @@ fn print_associated_const(&mut self,
         if let Some(expr) = default {
             space(&mut self.s)?;
             self.word_space("=")?;
-            self.print_expr(expr)?;
+            self.ann.nested(self, Nested::Body(expr))?;
         }
         word(&mut self.s, ";")
     }
@@ -634,25 +519,6 @@ fn print_associated_type(&mut self,
         word(&mut self.s, ";")
     }
 
-    pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> {
-        if let Some(krate) = self.krate {
-            // skip nested items if krate context was not provided
-            let item = &krate.items[&item_id.id];
-            self.print_item(item)
-        } else {
-            Ok(())
-        }
-    }
-
-    pub fn print_expr_id(&mut self, expr_id: &hir::ExprId) -> io::Result<()> {
-        if let Some(krate) = self.krate {
-            let expr = &krate.exprs[expr_id];
-            self.print_expr(expr)
-        } else {
-            Ok(())
-        }
-    }
-
     /// Pretty-print an item
     pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
         self.hardbreak_if_not_bol()?;
@@ -697,7 +563,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end inner head-block
                 self.end()?; // end outer head-block
             }
-            hir::ItemStatic(ref ty, m, ref expr) => {
+            hir::ItemStatic(ref ty, m, expr) => {
                 self.head(&visibility_qualified(&item.vis, "static"))?;
                 if m == hir::MutMutable {
                     self.word_space("mut")?;
@@ -709,11 +575,11 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end the head-ibox
 
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.ann.nested(self, Nested::Body(expr))?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer cbox
             }
-            hir::ItemConst(ref ty, ref expr) => {
+            hir::ItemConst(ref ty, expr) => {
                 self.head(&visibility_qualified(&item.vis, "const"))?;
                 self.print_name(item.name)?;
                 self.word_space(":")?;
@@ -722,11 +588,11 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end the head-ibox
 
                 self.word_space("=")?;
-                self.print_expr(&expr)?;
+                self.ann.nested(self, Nested::Body(expr))?;
                 word(&mut self.s, ";")?;
                 self.end()?; // end the outer cbox
             }
-            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
+            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => {
                 self.head("")?;
                 self.print_fn(decl,
                               unsafety,
@@ -734,11 +600,13 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                               abi,
                               Some(item.name),
                               typarams,
-                              &item.vis)?;
+                              &item.vis,
+                              &[],
+                              Some(body))?;
                 word(&mut self.s, " ")?;
                 self.end()?; // need to close a box
                 self.end()?; // need to close a box
-                self.print_expr_id(body)?;
+                self.ann.nested(self, Nested::Body(body))?;
             }
             hir::ItemMod(ref _mod) => {
                 self.head(&visibility_qualified(&item.vis, "mod"))?;
@@ -832,7 +700,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.bopen()?;
                 self.print_inner_attributes(&item.attrs)?;
                 for impl_item in impl_items {
-                    self.print_impl_item_ref(impl_item)?;
+                    self.ann.nested(self, Nested::ImplItem(impl_item.id))?;
                 }
                 self.bclose(item.span)?;
             }
@@ -858,7 +726,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 word(&mut self.s, " ")?;
                 self.bopen()?;
                 for trait_item in trait_items {
-                    self.print_trait_item(trait_item)?;
+                    self.ann.nested(self, Nested::TraitItem(trait_item.id))?;
                 }
                 self.bclose(item.span)?;
             }
@@ -928,8 +796,11 @@ pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
         match *vis {
             hir::Public => self.word_nbsp("pub"),
             hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
-            hir::Visibility::Restricted { ref path, .. } =>
-                self.word_nbsp(&format!("pub({})", path)),
+            hir::Visibility::Restricted { ref path, .. } => {
+                word(&mut self.s, "pub(")?;
+                self.print_path(path, false)?;
+                self.word_nbsp(")")
+            }
             hir::Inherited => Ok(()),
         }
     }
@@ -985,19 +856,19 @@ pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
         self.head("")?;
         let generics = hir::Generics::empty();
         self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
-        match v.node.disr_expr {
-            Some(ref d) => {
-                space(&mut self.s)?;
-                self.word_space("=")?;
-                self.print_expr(&d)
-            }
-            _ => Ok(()),
+        if let Some(d) = v.node.disr_expr {
+            space(&mut self.s)?;
+            self.word_space("=")?;
+            self.ann.nested(self, Nested::Body(d))?;
         }
+        Ok(())
     }
     pub fn print_method_sig(&mut self,
                             name: ast::Name,
                             m: &hir::MethodSig,
-                            vis: &hir::Visibility)
+                            vis: &hir::Visibility,
+                            arg_names: &[Spanned<ast::Name>],
+                            body_id: Option<hir::BodyId>)
                             -> io::Result<()> {
         self.print_fn(&m.decl,
                       m.unsafety,
@@ -1005,7 +876,9 @@ pub fn print_method_sig(&mut self,
                       m.abi,
                       Some(name),
                       &m.generics,
-                      vis)
+                      vis,
+                      arg_names,
+                      body_id)
     }
 
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
@@ -1014,27 +887,22 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
         self.maybe_print_comment(ti.span.lo)?;
         self.print_outer_attributes(&ti.attrs)?;
         match ti.node {
-            hir::ConstTraitItem(ref ty, ref default) => {
-                self.print_associated_const(ti.name,
-                                            &ty,
-                                            default.as_ref().map(|expr| &**expr),
-                                            &hir::Inherited)?;
-            }
-            hir::MethodTraitItem(ref sig, ref body) => {
-                if body.is_some() {
-                    self.head("")?;
-                }
-                self.print_method_sig(ti.name, sig, &hir::Inherited)?;
-                if let Some(ref body) = *body {
-                    self.nbsp()?;
-                    self.end()?; // need to close a box
-                    self.end()?; // need to close a box
-                    self.print_expr_id(body)?;
-                } else {
-                    word(&mut self.s, ";")?;
-                }
+            hir::TraitItemKind::Const(ref ty, default) => {
+                self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?;
             }
-            hir::TypeTraitItem(ref bounds, ref default) => {
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
+                self.print_method_sig(ti.name, sig, &hir::Inherited, arg_names, None)?;
+                word(&mut self.s, ";")?;
+            }
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+                self.head("")?;
+                self.print_method_sig(ti.name, sig, &hir::Inherited, &[], Some(body))?;
+                self.nbsp()?;
+                self.end()?; // need to close a box
+                self.end()?; // need to close a box
+                self.ann.nested(self, Nested::Body(body))?;
+            }
+            hir::TraitItemKind::Type(ref bounds, ref default) => {
                 self.print_associated_type(ti.name,
                                            Some(bounds),
                                            default.as_ref().map(|ty| &**ty))?;
@@ -1043,16 +911,6 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
         self.ann.post(self, NodeSubItem(ti.id))
     }
 
-    pub fn print_impl_item_ref(&mut self, item_ref: &hir::ImplItemRef) -> io::Result<()> {
-        if let Some(krate) = self.krate {
-            // skip nested items if krate context was not provided
-            let item = &krate.impl_item(item_ref.id);
-            self.print_impl_item(item)
-        } else {
-            Ok(())
-        }
-    }
-
     pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
         self.ann.pre(self, NodeSubItem(ii.id))?;
         self.hardbreak_if_not_bol()?;
@@ -1065,16 +923,16 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
         }
 
         match ii.node {
-            hir::ImplItemKind::Const(ref ty, ref expr) => {
-                self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?;
+            hir::ImplItemKind::Const(ref ty, expr) => {
+                self.print_associated_const(ii.name, &ty, Some(expr), &ii.vis)?;
             }
-            hir::ImplItemKind::Method(ref sig, ref body) => {
+            hir::ImplItemKind::Method(ref sig, body) => {
                 self.head("")?;
-                self.print_method_sig(ii.name, sig, &ii.vis)?;
+                self.print_method_sig(ii.name, sig, &ii.vis, &[], Some(body))?;
                 self.nbsp()?;
                 self.end()?; // need to close a box
                 self.end()?; // need to close a box
-                self.print_expr_id(body)?;
+                self.ann.nested(self, Nested::Body(body))?;
             }
             hir::ImplItemKind::Type(ref ty) => {
                 self.print_associated_type(ii.name, None, Some(ty))?;
@@ -1246,12 +1104,12 @@ fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> {
         self.end()
     }
 
-    fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> {
+    fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> {
         self.ibox(indent_unit)?;
         word(&mut self.s, "[")?;
         self.print_expr(element)?;
         self.word_space(";")?;
-        self.print_expr(count)?;
+        self.ann.nested(self, Nested::Body(count))?;
         word(&mut self.s, "]")?;
         self.end()
     }
@@ -1362,8 +1220,8 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
             hir::ExprArray(ref exprs) => {
                 self.print_expr_vec(exprs)?;
             }
-            hir::ExprRepeat(ref element, ref count) => {
-                self.print_expr_repeat(&element, &count)?;
+            hir::ExprRepeat(ref element, count) => {
+                self.print_expr_repeat(&element, count)?;
             }
             hir::ExprStruct(ref qpath, ref fields, ref wth) => {
                 self.print_expr_struct(qpath, &fields[..], wth)?;
@@ -1434,14 +1292,14 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 }
                 self.bclose_(expr.span, indent_unit)?;
             }
-            hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => {
+            hir::ExprClosure(capture_clause, ref decl, body, _fn_decl_span) => {
                 self.print_capture_clause(capture_clause)?;
 
-                self.print_fn_block_args(&decl)?;
+                self.print_closure_args(&decl, body)?;
                 space(&mut self.s)?;
 
                 // this is a bare expression
-                self.print_expr_id(body)?;
+                self.ann.nested(self, Nested::Body(body))?;
                 self.end()?; // need to close a box
 
                 // a box will be closed by print_expr, but we didn't want an overall
@@ -1615,8 +1473,8 @@ pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
                 }
                 self.end()
             }
-            hir::DeclItem(ref item) => {
-                self.print_item_id(item)
+            hir::DeclItem(item) => {
+                self.ann.nested(self, Nested::Item(item))
             }
         }
     }
@@ -1637,10 +1495,10 @@ pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Resu
         self.print_expr(coll)
     }
 
-    fn print_path(&mut self,
-                  path: &hir::Path,
-                  colons_before_params: bool)
-                  -> io::Result<()> {
+    pub fn print_path(&mut self,
+                      path: &hir::Path,
+                      colons_before_params: bool)
+                      -> io::Result<()> {
         self.maybe_print_comment(path.span.lo)?;
 
         for (i, segment) in path.segments.iter().enumerate() {
@@ -1656,10 +1514,10 @@ fn print_path(&mut self,
         Ok(())
     }
 
-    fn print_qpath(&mut self,
-                   qpath: &hir::QPath,
-                   colons_before_params: bool)
-                   -> io::Result<()> {
+    pub fn print_qpath(&mut self,
+                       qpath: &hir::QPath,
+                       colons_before_params: bool)
+                       -> io::Result<()> {
         match *qpath {
             hir::QPath::Resolved(None, ref path) => {
                 self.print_path(path, colons_before_params)
@@ -1954,27 +1812,6 @@ fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
         self.end() // close enclosing cbox
     }
 
-    fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> {
-        match explicit_self.node {
-            SelfKind::Value(m) => {
-                self.print_mutability(m)?;
-                word(&mut self.s, "self")
-            }
-            SelfKind::Region(ref lt, m) => {
-                word(&mut self.s, "&")?;
-                self.print_opt_lifetime(lt)?;
-                self.print_mutability(m)?;
-                word(&mut self.s, "self")
-            }
-            SelfKind::Explicit(ref typ, m) => {
-                self.print_mutability(m)?;
-                word(&mut self.s, "self")?;
-                self.word_space(":")?;
-                self.print_type(&typ)
-            }
-        }
-    }
-
     pub fn print_fn(&mut self,
                     decl: &hir::FnDecl,
                     unsafety: hir::Unsafety,
@@ -1982,7 +1819,9 @@ pub fn print_fn(&mut self,
                     abi: Abi,
                     name: Option<ast::Name>,
                     generics: &hir::Generics,
-                    vis: &hir::Visibility)
+                    vis: &hir::Visibility,
+                    arg_names: &[Spanned<ast::Name>],
+                    body_id: Option<hir::BodyId>)
                     -> io::Result<()> {
         self.print_fn_header_info(unsafety, constness, abi, vis)?;
 
@@ -1991,24 +1830,51 @@ pub fn print_fn(&mut self,
             self.print_name(name)?;
         }
         self.print_generics(generics)?;
-        self.print_fn_args_and_ret(decl)?;
-        self.print_where_clause(&generics.where_clause)
-    }
 
-    pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
         self.popen()?;
-        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
+        let mut i = 0;
+        // Make sure we aren't supplied *both* `arg_names` and `body_id`.
+        assert!(arg_names.is_empty() || body_id.is_none());
+        self.commasep(Inconsistent, &decl.inputs, |s, ty| {
+            s.ibox(indent_unit)?;
+            if let Some(name) = arg_names.get(i) {
+                word(&mut s.s, &name.node.as_str())?;
+                word(&mut s.s, ":")?;
+                space(&mut s.s)?;
+            } else if let Some(body_id) = body_id {
+                s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
+                word(&mut s.s, ":")?;
+                space(&mut s.s)?;
+            }
+            i += 1;
+            s.print_type(ty)?;
+            s.end()
+        })?;
         if decl.variadic {
             word(&mut self.s, ", ...")?;
         }
         self.pclose()?;
 
-        self.print_fn_output(decl)
+        self.print_fn_output(decl)?;
+        self.print_where_clause(&generics.where_clause)
     }
 
-    pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
+    fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> {
         word(&mut self.s, "|")?;
-        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
+        let mut i = 0;
+        self.commasep(Inconsistent, &decl.inputs, |s, ty| {
+            s.ibox(indent_unit)?;
+
+            s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
+            i += 1;
+
+            if ty.node != hir::TyInfer {
+                word(&mut s.s, ":")?;
+                space(&mut s.s)?;
+                s.print_type(ty)?;
+            }
+            s.end()
+        })?;
         word(&mut self.s, "|")?;
 
         if let hir::DefaultReturn(..) = decl.output {
@@ -2180,31 +2046,6 @@ pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
         self.print_type(&mt.ty)
     }
 
-    pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> {
-        self.ibox(indent_unit)?;
-        match input.ty.node {
-            hir::TyInfer if is_closure => self.print_pat(&input.pat)?,
-            _ => {
-                if let Some(eself) = input.to_self() {
-                    self.print_explicit_self(&eself)?;
-                } else {
-                    let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node {
-                        name.node == keywords::Invalid.name()
-                    } else {
-                        false
-                    };
-                    if !invalid {
-                        self.print_pat(&input.pat)?;
-                        word(&mut self.s, ":")?;
-                        space(&mut self.s)?;
-                    }
-                    self.print_type(&input.ty)?;
-                }
-            }
-        }
-        self.end()
-    }
-
     pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
         if let hir::DefaultReturn(..) = decl.output {
             return Ok(());
@@ -2252,7 +2093,9 @@ pub fn print_ty_fn(&mut self,
                       abi,
                       name,
                       &generics,
-                      &hir::Inherited)?;
+                      &hir::Inherited,
+                      &[],
+                      None)?;
         self.end()
     }
 
index 9d48fbca53edd9ddf11c8af56286e87fd8bc9ed1..9ff7dcc7d58835beaface33b9cf59205fda0a0b6 100644 (file)
@@ -75,7 +75,6 @@
 
 use hir::map as ast_map;
 use hir;
-use hir::print as pprust;
 
 use lint;
 use hir::def::Def;
@@ -1051,8 +1050,8 @@ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegio
             Some(ref node) => match *node {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
-                        hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
-                            Some((fn_decl, gen, unsafety, constness, item.name, item.span))
+                        hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, body) => {
+                            Some((fn_decl, gen, unsafety, constness, item.name, item.span, body))
                         }
                         _ => None,
                     }
@@ -1066,26 +1065,28 @@ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegio
                             return;
                         }
                     }
-                    if let hir::ImplItemKind::Method(ref sig, _) = item.node {
+                    if let hir::ImplItemKind::Method(ref sig, body) = item.node {
                         Some((&sig.decl,
                               &sig.generics,
                               sig.unsafety,
                               sig.constness,
                               item.name,
-                              item.span))
+                              item.span,
+                              body))
                     } else {
                         None
                     }
                 },
                 ast_map::NodeTraitItem(item) => {
                     match item.node {
-                        hir::MethodTraitItem(ref sig, Some(_)) => {
+                        hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
                                   sig.constness,
                                   item.name,
-                                  item.span))
+                                  item.span,
+                                  body))
                         }
                         _ => None,
                     }
@@ -1094,12 +1095,12 @@ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegio
             },
             None => None,
         };
-        let (fn_decl, generics, unsafety, constness, name, span)
+        let (fn_decl, generics, unsafety, constness, name, span, body)
                                     = node_inner.expect("expect item fn");
         let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver);
         let (fn_decl, generics) = rebuilder.rebuild();
         self.give_expl_lifetime_param(
-            err, &fn_decl, unsafety, constness, name, &generics, span);
+            err, &fn_decl, unsafety, constness, name, &generics, span, body);
     }
 
     pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {
@@ -1375,23 +1376,14 @@ fn rebuild_generics(&self,
     }
 
     fn rebuild_args_ty(&self,
-                       inputs: &[hir::Arg],
+                       inputs: &[P<hir::Ty>],
                        lifetime: hir::Lifetime,
                        anon_nums: &HashSet<u32>,
                        region_names: &HashSet<ast::Name>)
-                       -> hir::HirVec<hir::Arg> {
-        let mut new_inputs = Vec::new();
-        for arg in inputs {
-            let new_ty = self.rebuild_arg_ty_or_output(&arg.ty, lifetime,
-                                                       anon_nums, region_names);
-            let possibly_new_arg = hir::Arg {
-                ty: new_ty,
-                pat: arg.pat.clone(),
-                id: arg.id
-            };
-            new_inputs.push(possibly_new_arg);
-        }
-        new_inputs.into()
+                       -> hir::HirVec<P<hir::Ty>> {
+        inputs.iter().map(|arg_ty| {
+            self.rebuild_arg_ty_or_output(arg_ty, lifetime, anon_nums, region_names)
+        }).collect()
     }
 
     fn rebuild_output(&self, ty: &hir::FunctionRetTy,
@@ -1634,10 +1626,26 @@ fn give_expl_lifetime_param(&self,
                                 constness: hir::Constness,
                                 name: ast::Name,
                                 generics: &hir::Generics,
-                                span: Span) {
-        let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name, generics);
-        let msg = format!("consider using an explicit lifetime \
-                           parameter as shown: {}", suggested_fn);
+                                span: Span,
+                                body: hir::BodyId) {
+        let s = hir::print::to_string(&self.tcx.map, |s| {
+            use syntax::abi::Abi;
+            use syntax::print::pprust::PrintState;
+
+            s.head("")?;
+            s.print_fn(decl,
+                       unsafety,
+                       constness,
+                       Abi::Rust,
+                       Some(name),
+                       generics,
+                       &hir::Inherited,
+                       &[],
+                       Some(body))?;
+            s.end()?; // Close the head box
+            s.end()   // Close the outer box
+        });
+        let msg = format!("consider using an explicit lifetime parameter as shown: {}", s);
         err.span_help(span, &msg[..]);
     }
 
index 17cc34fcd839414b36e8445bbf91d2dac34515c1..efe855f0a39e9c84af006a7ed2e4a7b7115abf0f 100644 (file)
@@ -30,9 +30,9 @@
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
-#![cfg_attr(stage0, feature(item_like_imports))]
 #![feature(libc)]
 #![feature(nonzero)]
+#![feature(pub_restricted)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
@@ -80,9 +80,8 @@
 
 pub mod middle {
     pub mod astconv_util;
-    pub mod expr_use_visitor; // STAGE0: increase glitch immunity
+    pub mod expr_use_visitor;
     pub mod const_val;
-    pub mod const_qualif;
     pub mod cstore;
     pub mod dataflow;
     pub mod dead;
index 3ff2abac277b580fc14e66990ff1338a6fc45d53..cce79820ca8da5bea21811b57aca1cb4e50004e7 100644 (file)
@@ -821,6 +821,7 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr) {
         self.with_lint_attrs(&e.attrs, |cx| {
             run_lints!(cx, check_expr, late_passes, e);
             hir_visit::walk_expr(cx, e);
+            run_lints!(cx, check_expr_post, late_passes, e);
         })
     }
 
@@ -835,8 +836,8 @@ fn visit_stmt(&mut self, s: &'tcx hir::Stmt) {
     }
 
     fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl,
-                body_id: hir::ExprId, span: Span, id: ast::NodeId) {
-        let body = self.tcx.map.expr(body_id);
+                body_id: hir::BodyId, span: Span, id: ast::NodeId) {
+        let body = self.tcx.map.body(body_id);
         run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
         hir_visit::walk_fn(self, fk, decl, body_id, span, id);
         run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
@@ -909,10 +910,6 @@ fn visit_decl(&mut self, d: &'tcx hir::Decl) {
         hir_visit::walk_decl(self, d);
     }
 
-    fn visit_expr_post(&mut self, e: &'tcx hir::Expr) {
-        run_lints!(self, check_expr_post, late_passes, e);
-    }
-
     fn visit_generics(&mut self, g: &'tcx hir::Generics) {
         run_lints!(self, check_generics, late_passes, g);
         hir_visit::walk_generics(self, g);
index ccf53f01cd5323112bfe2b3e9d21bde83ef65e58..7e0da00694c4a4280aa5722d0122f6f9fe8286ea 100644 (file)
@@ -162,14 +162,14 @@ fn check_fn(&mut self,
                 _: &LateContext<'a, 'tcx>,
                 _: FnKind<'tcx>,
                 _: &'tcx hir::FnDecl,
-                _: &'tcx hir::Expr,
+                _: &'tcx hir::Body,
                 _: Span,
                 _: ast::NodeId) { }
     fn check_fn_post(&mut self,
                      _: &LateContext<'a, 'tcx>,
                      _: FnKind<'tcx>,
                      _: &'tcx hir::FnDecl,
-                     _: &'tcx hir::Expr,
+                     _: &'tcx hir::Body,
                      _: Span,
                      _: ast::NodeId) { }
     fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { }
diff --git a/src/librustc/middle/const_qualif.rs b/src/librustc/middle/const_qualif.rs
deleted file mode 100644 (file)
index ec98637..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Const qualification, from partial to completely promotable.
-bitflags! {
-    #[derive(RustcEncodable, RustcDecodable)]
-    flags ConstQualif: u8 {
-        // Inner mutability (can not be placed behind a reference) or behind
-        // &mut in a non-global expression. Can be copied from static memory.
-        const MUTABLE_MEM        = 1 << 0,
-        // Constant value with a type that implements Drop. Can be copied
-        // from static memory, similar to MUTABLE_MEM.
-        const NEEDS_DROP         = 1 << 1,
-        // Even if the value can be placed in static memory, copying it from
-        // there is more expensive than in-place instantiation, and/or it may
-        // be too large. This applies to [T; N] and everything containing it.
-        // N.B.: references need to clear this flag to not end up on the stack.
-        const PREFER_IN_PLACE    = 1 << 2,
-        // May use more than 0 bytes of memory, doesn't impact the constness
-        // directly, but is not allowed to be borrowed mutably in a constant.
-        const NON_ZERO_SIZED     = 1 << 3,
-        // Actually borrowed, has to always be in static memory. Does not
-        // propagate, and requires the expression to behave like a 'static
-        // lvalue. The set of expressions with this flag is the minimum
-        // that have to be promoted.
-        const HAS_STATIC_BORROWS = 1 << 4,
-        // Invalid const for miscellaneous reasons (e.g. not implemented).
-        const NOT_CONST          = 1 << 5,
-
-        // Borrowing the expression won't produce &'static T if any of these
-        // bits are set, though the value could be copied from static memory
-        // if `NOT_CONST` isn't set.
-        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
-                                   ConstQualif::NEEDS_DROP.bits |
-                                   ConstQualif::NOT_CONST.bits
-    }
-}
index d0003693eefe34e78b071150593427bfa13443e3..7151e5226cab0cb3f365d3b8a63d07af06706403 100644 (file)
 use session::Session;
 use session::search_paths::PathKind;
 use util::nodemap::{NodeSet, DefIdMap};
+
+use std::collections::BTreeMap;
 use std::path::PathBuf;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::attr;
 use syntax::ext::base::SyntaxExtension;
-use syntax::ptr::P;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_back::target::Target;
 use hir;
-use hir::intravisit::Visitor;
 use rustc_back::PanicStrategy;
 
 pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
@@ -134,102 +134,6 @@ pub struct NativeLibrary {
     pub foreign_items: Vec<DefIndex>,
 }
 
-/// The data we save and restore about an inlined item or method.  This is not
-/// part of the AST that we parse from a file, but it becomes part of the tree
-/// that we trans.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct InlinedItem {
-    pub def_id: DefId,
-    pub body: P<hir::Expr>,
-    pub const_fn_args: Vec<Option<DefId>>,
-}
-
-/// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving
-/// a crate; it then gets read as an InlinedItem.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)]
-pub struct InlinedItemRef<'a> {
-    pub def_id: DefId,
-    pub body: &'a hir::Expr,
-    pub const_fn_args: Vec<Option<DefId>>,
-}
-
-fn get_fn_args(decl: &hir::FnDecl) -> Vec<Option<DefId>> {
-    decl.inputs.iter().map(|arg| match arg.pat.node {
-        hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
-        _ => None
-    }).collect()
-}
-
-impl<'a> InlinedItemRef<'a> {
-    pub fn from_item<'b, 'tcx>(def_id: DefId,
-                               item: &'a hir::Item,
-                               tcx: TyCtxt<'b, 'a, 'tcx>)
-                               -> InlinedItemRef<'a> {
-        let (body, args) = match item.node {
-            hir::ItemFn(ref decl, _, _, _, _, body_id) =>
-                (tcx.map.expr(body_id), get_fn_args(decl)),
-            hir::ItemConst(_, ref body) => (&**body, Vec::new()),
-            _ => bug!("InlinedItemRef::from_item wrong kind")
-        };
-        InlinedItemRef {
-            def_id: def_id,
-            body: body,
-            const_fn_args: args
-        }
-    }
-
-    pub fn from_trait_item(def_id: DefId,
-                           item: &'a hir::TraitItem,
-                           _tcx: TyCtxt)
-                           -> InlinedItemRef<'a> {
-        let (body, args) = match item.node {
-            hir::ConstTraitItem(_, Some(ref body)) =>
-                (&**body, Vec::new()),
-            hir::ConstTraitItem(_, None) => {
-                bug!("InlinedItemRef::from_trait_item called for const without body")
-            },
-            _ => bug!("InlinedItemRef::from_trait_item wrong kind")
-        };
-        InlinedItemRef {
-            def_id: def_id,
-            body: body,
-            const_fn_args: args
-        }
-    }
-
-    pub fn from_impl_item<'b, 'tcx>(def_id: DefId,
-                                    item: &'a hir::ImplItem,
-                                    tcx: TyCtxt<'b, 'a, 'tcx>)
-                                    -> InlinedItemRef<'a> {
-        let (body, args) = match item.node {
-            hir::ImplItemKind::Method(ref sig, body_id) =>
-                (tcx.map.expr(body_id), get_fn_args(&sig.decl)),
-            hir::ImplItemKind::Const(_, ref body) =>
-                (&**body, Vec::new()),
-            _ => bug!("InlinedItemRef::from_impl_item wrong kind")
-        };
-        InlinedItemRef {
-            def_id: def_id,
-            body: body,
-            const_fn_args: args
-        }
-    }
-
-    pub fn visit<V>(&self, visitor: &mut V)
-        where V: Visitor<'a>
-    {
-        visitor.visit_expr(&self.body);
-    }
-}
-
-impl InlinedItem {
-    pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
-        where V: Visitor<'ast>
-    {
-        visitor.visit_expr(&self.body);
-    }
-}
-
 pub enum LoadedMacro {
     MacroRules(ast::MacroDef),
     ProcMacro(Rc<SyntaxExtension>),
@@ -346,10 +250,10 @@ fn retrace_path(&self,
     fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
 
     // misc. metadata
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> Option<(&'tcx InlinedItem, ast::NodeId)>;
-    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
-    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
+    fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+                               -> Option<&'tcx hir::Body>;
+    fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body>;
+    fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool;
 
     fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>;
     fn is_item_mir_available(&self, def: DefId) -> bool;
@@ -516,15 +420,15 @@ fn item_children(&self, did: DefId) -> Vec<def::Export> { bug!("item_children")
     fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
 
     // misc. metadata
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                              -> Option<(&'tcx InlinedItem, ast::NodeId)> {
-        bug!("maybe_get_item_ast")
+    fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+                               -> Option<&'tcx hir::Body> {
+        bug!("maybe_get_item_body")
     }
-    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
-        bug!("local_node_for_inlined_defid")
+    fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
+        bug!("item_body_nested_bodies")
     }
-    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
-        bug!("defid_for_inlined_node")
+    fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool {
+        bug!("const_is_rvalue_promotable_to_static")
     }
 
     fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
index f7a34c43cccbd8335afcbd0dfd85a655e16cd5f4..dfcb5cb7b79fee81b4c21224ba1c0ed9c77f7c8d 100644 (file)
@@ -108,6 +108,9 @@ fn has_bitset_for_nodeid(&self, n: ast::NodeId) -> bool {
 }
 
 impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> {
+    fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> {
+        pprust::PpAnn::nested(&self.tcx.map, state, nested)
+    }
     fn pre(&self,
            ps: &mut pprust::State,
            node: pprust::AnnNode) -> io::Result<()> {
@@ -160,7 +163,7 @@ fn pre(&self,
     }
 }
 
-fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
+fn build_nodeid_to_index(body: Option<&hir::Body>,
                          cfg: &cfg::CFG) -> NodeMap<Vec<CFGIndex>> {
     let mut index = NodeMap();
 
@@ -168,8 +171,8 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
     // into cfg itself?  i.e. introduce a fn-based flow-graph in
     // addition to the current block-based flow-graph, rather than
     // have to put traversals like this here?
-    if let Some(decl) = decl {
-        add_entries_from_fn_decl(&mut index, decl, cfg.entry);
+    if let Some(body) = body {
+        add_entries_from_fn_body(&mut index, body, cfg.entry);
     }
 
     cfg.graph.each_node(|node_idx, node| {
@@ -181,20 +184,24 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
 
     return index;
 
-    fn add_entries_from_fn_decl(index: &mut NodeMap<Vec<CFGIndex>>,
-                                decl: &hir::FnDecl,
+    /// Add mappings from the ast nodes for the formal bindings to
+    /// the entry-node in the graph.
+    fn add_entries_from_fn_body(index: &mut NodeMap<Vec<CFGIndex>>,
+                                body: &hir::Body,
                                 entry: CFGIndex) {
-        //! add mappings from the ast nodes for the formal bindings to
-        //! the entry-node in the graph.
+        use hir::intravisit::Visitor;
+
         struct Formals<'a> {
             entry: CFGIndex,
             index: &'a mut NodeMap<Vec<CFGIndex>>,
         }
         let mut formals = Formals { entry: entry, index: index };
-        intravisit::walk_fn_decl(&mut formals, decl);
-        impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> {
+        for arg in &body.arguments {
+            formals.visit_pat(&arg.pat);
+        }
+        impl<'a, 'v> Visitor<'v> for Formals<'a> {
             fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
-                panic!("should not encounter fn bodies or items")
+                intravisit::NestedVisitorMap::None
             }
 
             fn visit_pat(&mut self, p: &hir::Pat) {
@@ -227,7 +234,7 @@ pub enum KillFrom {
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                analysis_name: &'static str,
-               decl: Option<&hir::FnDecl>,
+               body: Option<&hir::Body>,
                cfg: &cfg::CFG,
                oper: O,
                id_range: IdRange,
@@ -250,7 +257,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let kills2 = zeroes;
         let on_entry = vec![entry; num_nodes * words_per_id];
 
-        let nodeid_to_index = build_nodeid_to_index(decl, cfg);
+        let nodeid_to_index = build_nodeid_to_index(body, cfg);
 
         DataFlowContext {
             tcx: tcx,
@@ -502,7 +509,7 @@ pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) {
 
 impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
 //                                ^^^^^^^^^^^^^ only needed for pretty printing
-    pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) {
+    pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Body) {
         //! Performs the data flow analysis.
 
         if self.bits_per_id == 0 {
@@ -526,20 +533,11 @@ pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) {
         }
 
         debug!("Dataflow result for {}:", self.analysis_name);
-        debug!("{}", {
-            let mut v = Vec::new();
-            self.pretty_print_to(box &mut v, body).unwrap();
-            String::from_utf8(v).unwrap()
-        });
-    }
-
-    fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>,
-                           body: &hir::Expr) -> io::Result<()> {
-        let mut ps = pprust::rust_printer_annotated(wr, self, None);
-        ps.cbox(pprust::indent_unit)?;
-        ps.ibox(0)?;
-        ps.print_expr(body)?;
-        pp::eof(&mut ps.s)
+        debug!("{}", pprust::to_string(self, |s| {
+            s.cbox(pprust::indent_unit)?;
+            s.ibox(0)?;
+            s.print_expr(&body.value)
+        }));
     }
 }
 
index 1c5dd97b74bd332c2b5854116df34f5910c34649..76adee4e00c15684ec411deddddf5daa2232cb45 100644 (file)
@@ -328,11 +328,12 @@ fn visit_item(&mut self, item: &hir::Item) {
                 self.worklist.extend(enum_def.variants.iter()
                                                       .map(|variant| variant.node.data.id()));
             }
-            hir::ItemTrait(.., ref trait_items) => {
-                for trait_item in trait_items {
+            hir::ItemTrait(.., ref trait_item_refs) => {
+                for trait_item_ref in trait_item_refs {
+                    let trait_item = self.krate.trait_item(trait_item_ref.id);
                     match trait_item.node {
-                        hir::ConstTraitItem(_, Some(_)) |
-                        hir::MethodTraitItem(_, Some(_)) => {
+                        hir::TraitItemKind::Const(_, Some(_)) |
+                        hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
                             if has_allow_dead_code_or_lang_attr(&trait_item.attrs) {
                                 self.worklist.push(trait_item.id);
                             }
@@ -354,6 +355,10 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _item: &hir::TraitItem) {
+        // ignore: we are handling this in `visit_item` above
+    }
+
     fn visit_impl_item(&mut self, _item: &hir::ImplItem) {
         // ignore: we are handling this in `visit_item` above
     }
@@ -546,19 +551,19 @@ fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         match impl_item.node {
-            hir::ImplItemKind::Const(_, ref expr) => {
+            hir::ImplItemKind::Const(_, body_id) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
                                         impl_item.name, "associated const");
                 }
-                intravisit::walk_expr(self, expr)
+                self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Method(_, body_id) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
                                         impl_item.name, "method");
                 }
-                self.visit_body(body_id)
+                self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Type(..) => {}
         }
@@ -567,15 +572,13 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
     // Overwrite so that we don't warn the trait item itself.
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         match trait_item.node {
-            hir::ConstTraitItem(_, Some(ref body)) => {
-                intravisit::walk_expr(self, body)
-            }
-            hir::MethodTraitItem(_, Some(body_id)) => {
-                self.visit_body(body_id)
+            hir::TraitItemKind::Const(_, Some(body_id)) |
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+                self.visit_nested_body(body_id)
             }
-            hir::ConstTraitItem(_, None) |
-            hir::MethodTraitItem(_, None) |
-            hir::TypeTraitItem(..) => {}
+            hir::TraitItemKind::Const(_, None) |
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+            hir::TraitItemKind::Type(..) => {}
         }
     }
 }
index 075b3d7a8e90c9e2588bac8f87a5d7dc0f175e75..e60d0533c9f8166be71f6991e22e84c36a43ab71 100644 (file)
@@ -103,6 +103,10 @@ pub fn calculate(sess: &session::Session) {
 
 fn calculate_type(sess: &session::Session,
                   ty: config::CrateType) -> DependencyList {
+    if !sess.opts.output_types.should_trans() {
+        return Vec::new();
+    }
+
     match ty {
         // If the global prefer_dynamic switch is turned off, first attempt
         // static linkage (this can fail).
@@ -114,7 +118,7 @@ fn calculate_type(sess: &session::Session,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        config::CrateTypeRlib | config::CrateTypeMetadata => return Vec::new(),
+        config::CrateTypeRlib => return Vec::new(),
 
         // Staticlibs and cdylibs must have all static dependencies. If any fail
         // to be found, we generate some nice pretty errors.
index 2ec7aa4c4d9031c316c0ac37d3557008203de98f..38b0b18b0129af7b7c6263505c85740c9d131eb3 100644 (file)
@@ -98,7 +98,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl,
-                body_id: hir::ExprId, span: Span, id: ast::NodeId) {
+                body_id: hir::BodyId, span: Span, id: ast::NodeId) {
 
         let (is_item_fn, is_unsafe_fn) = match fn_kind {
             FnKind::ItemFn(_, _, unsafety, ..) =>
index e927843a984b8c351a307ca2e625d4ba69f831bf..f2e46d4cbc96ba6c0831179db41b23e66e51fd29 100644 (file)
@@ -17,7 +17,7 @@
 use syntax::attr;
 use syntax::entry::EntryPointType;
 use syntax_pos::Span;
-use hir::{Item, ItemFn, ImplItem};
+use hir::{Item, ItemFn, ImplItem, TraitItem};
 use hir::itemlikevisit::ItemLikeVisitor;
 
 struct EntryContext<'a, 'tcx: 'a> {
@@ -47,6 +47,9 @@ fn visit_item(&mut self, item: &'tcx Item) {
         find_item(item, self, at_root);
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) {
+        // entry fn is never a trait item
+    }
 
     fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) {
         // entry fn is never an impl item
index b3e61f1e5706772c1eeffc77f0c19c3d9fa6c399..a3a49c916338e544a047bcd6b14f5fb819e2d066 100644 (file)
@@ -287,20 +287,11 @@ pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
         }
     }
 
-    pub fn walk_fn(&mut self,
-                   decl: &hir::FnDecl,
-                   body: &hir::Expr) {
-        self.walk_arg_patterns(decl, body);
-        self.consume_expr(body);
-    }
-
-    fn walk_arg_patterns(&mut self,
-                         decl: &hir::FnDecl,
-                         body: &hir::Expr) {
-        for arg in &decl.inputs {
+    pub fn consume_body(&mut self, body: &hir::Body) {
+        for arg in &body.arguments {
             let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
 
-            let fn_body_scope_r = self.tcx().node_scope_region(body.id);
+            let fn_body_scope_r = self.tcx().node_scope_region(body.value.id);
             let arg_cmt = self.mc.cat_rvalue(
                 arg.id,
                 arg.pat.span,
@@ -309,6 +300,8 @@ fn walk_arg_patterns(&mut self,
 
             self.walk_irrefutable_pat(arg_cmt, &arg.pat);
         }
+
+        self.consume_expr(&body.value);
     }
 
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -537,9 +530,8 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 }
             }
 
-            hir::ExprRepeat(ref base, ref count) => {
+            hir::ExprRepeat(ref base, _) => {
                 self.consume_expr(&base);
-                self.consume_expr(&count);
             }
 
             hir::ExprClosure(.., fn_decl_span) => {
index 2357549c82e081fedfaea3737221985ebe01a904..d932061d42d3db4984f56ee62c9373873398416d 100644 (file)
@@ -34,13 +34,13 @@ struct ItemVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
-    fn visit_const(&mut self, item_id: ast::NodeId, expr: &'tcx hir::Expr) {
+    fn visit_const(&mut self, item_id: ast::NodeId, body: hir::BodyId) {
         let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
         self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
-            visitor.visit_expr(expr);
+            visitor.visit_nested_body(body);
         });
     }
 }
@@ -122,33 +122,33 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     // const, static and N in [T; N].
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
+    fn visit_body(&mut self, body: &'tcx hir::Body) {
         self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
-            visitor.visit_expr(expr);
+            visitor.visit_body(body);
         });
     }
 
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
-            self.visit_const(item.id, expr);
+        if let hir::TraitItemKind::Const(_, Some(body)) = item.node {
+            self.visit_const(item.id, body);
         } else {
             intravisit::walk_trait_item(self, item);
         }
     }
 
     fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(_, ref expr) = item.node {
-            self.visit_const(item.id, expr);
+        if let hir::ImplItemKind::Const(_, body) = item.node {
+            self.visit_const(item.id, body);
         } else {
             intravisit::walk_impl_item(self, item);
         }
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: ast::NodeId) {
+                b: hir::BodyId, s: Span, id: ast::NodeId) {
         if let FnKind::Closure(..) = fk {
             span_bug!(s, "intrinsicck: closure outside of function")
         }
index 1efc211b8c35be608b29cfd05cf2b103c67607bc..4cae5b370eb7eb77ee603a62c373ccf456dafe60 100644 (file)
@@ -140,6 +140,10 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+        // at present, lang items are always items, not trait items
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
         // at present, lang items are always items, not impl items
     }
@@ -328,7 +332,6 @@ pub fn collect_language_items(session: &Session,
     PanicFmtLangItem,                "panic_fmt",               panic_fmt;
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
-    ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
     StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
 
index 445aed8f97d600fe3eeb547b24d2ca96e008d3ee..745a94a5ddba31cd6cafc49f1d240872ef5d9511 100644 (file)
 
 use hir::Expr;
 use hir;
-use hir::print::{expr_to_string, block_to_string};
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 
 /// For use with `propagate_through_loop`.
@@ -188,7 +187,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: NodeId) {
+                b: hir::BodyId, s: Span, id: NodeId) {
         visit_fn(self, fk, fd, b, s, id);
     }
     fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); }
@@ -354,13 +353,9 @@ fn lnk(&self, ln: LiveNode) -> LiveNodeKind {
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.ir.tcx.map)
+        NestedVisitorMap::None
     }
 
-    fn visit_fn(&mut self, _: FnKind<'tcx>, _: &'tcx hir::FnDecl,
-                _: hir::ExprId, _: Span, _: NodeId) {
-        // do not check contents of nested fns
-    }
     fn visit_local(&mut self, l: &'tcx hir::Local) {
         check_local(self, l);
     }
@@ -375,7 +370,7 @@ fn visit_arm(&mut self, a: &'tcx hir::Arm) {
 fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
                           fk: FnKind<'tcx>,
                           decl: &'tcx hir::FnDecl,
-                          body_id: hir::ExprId,
+                          body_id: hir::BodyId,
                           sp: Span,
                           id: ast::NodeId) {
     debug!("visit_fn");
@@ -385,7 +380,9 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
 
     debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps);
 
-    for arg in &decl.inputs {
+    let body = ir.tcx.map.body(body_id);
+
+    for arg in &body.arguments {
         arg.pat.each_binding(|_bm, arg_id, _x, path1| {
             debug!("adding argument {}", arg_id);
             let name = path1.node;
@@ -408,16 +405,14 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
         clean_exit_var: fn_maps.add_variable(CleanExit)
     };
 
-    let body = ir.tcx.map.expr(body_id);
-
     // compute liveness
     let mut lsets = Liveness::new(&mut fn_maps, specials);
-    let entry_ln = lsets.compute(body);
+    let entry_ln = lsets.compute(&body.value);
 
     // check for various error conditions
-    lsets.visit_expr(body);
+    lsets.visit_body(body);
     lsets.check_ret(id, sp, fk, entry_ln, body);
-    lsets.warn_about_unused_args(decl, entry_ln);
+    lsets.warn_about_unused_args(body, entry_ln);
 }
 
 fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
@@ -823,7 +818,7 @@ fn compute(&mut self, body: &hir::Expr) -> LiveNode {
         // effectively a return---this only occurs in `for` loops,
         // where the body is really a closure.
 
-        debug!("compute: using id for body, {}", expr_to_string(body));
+        debug!("compute: using id for body, {}", self.ir.tcx.map.node_to_pretty_string(body.id));
 
         let exit_ln = self.s.exit_ln;
         let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| {
@@ -916,7 +911,7 @@ fn propagate_through_opt_expr(&mut self,
 
     fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
                               -> LiveNode {
-        debug!("propagate_through_expr: {}", expr_to_string(expr));
+        debug!("propagate_through_expr: {}", self.ir.tcx.map.node_to_pretty_string(expr.id));
 
         match expr.node {
           // Interesting cases with control flow or which gen/kill
@@ -935,14 +930,14 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
 
           hir::ExprClosure(.., blk_id, _) => {
               debug!("{} is an ExprClosure",
-                     expr_to_string(expr));
+                     self.ir.tcx.map.node_to_pretty_string(expr.id));
 
               /*
               The next-node for a break is the successor of the entire
               loop. The next-node for a continue is the top of this loop.
               */
               let node = self.live_node(expr.id, expr.span);
-              self.with_loop_nodes(blk_id.node_id(), succ, node, |this| {
+              self.with_loop_nodes(blk_id.node_id, succ, node, |this| {
 
                  // the construction of a closure itself is not important,
                  // but we have to consider the closed over variables.
@@ -1088,11 +1083,6 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_exprs(exprs, succ)
           }
 
-          hir::ExprRepeat(ref element, ref count) => {
-            let succ = self.propagate_through_expr(&count, succ);
-            self.propagate_through_expr(&element, succ)
-          }
-
           hir::ExprStruct(_, ref fields, ref with_expr) => {
             let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
             fields.iter().rev().fold(succ, |succ, field| {
@@ -1149,7 +1139,8 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
           hir::ExprAddrOf(_, ref e) |
           hir::ExprCast(ref e, _) |
           hir::ExprType(ref e, _) |
-          hir::ExprUnary(_, ref e) => {
+          hir::ExprUnary(_, ref e) |
+          hir::ExprRepeat(ref e, _) => {
             self.propagate_through_expr(&e, succ)
           }
 
@@ -1315,7 +1306,7 @@ fn propagate_through_loop(&mut self,
             }
         }
         debug!("propagate_through_loop: using id for loop body {} {}",
-               expr.id, block_to_string(body));
+               expr.id, self.ir.tcx.map.node_to_pretty_string(body.id));
 
         let cond_ln = match kind {
             LoopLoop => ln,
@@ -1443,7 +1434,7 @@ fn check_ret(&self,
                  sp: Span,
                  fk: FnKind,
                  entry_ln: LiveNode,
-                 body: &hir::Expr)
+                 body: &hir::Body)
     {
         let fn_ty = if let FnKind::Closure(_) = fk {
             self.ir.tcx.tables().node_id_to_type(id)
@@ -1460,7 +1451,7 @@ fn check_ret(&self,
         // and must outlive the *call-site* of the function.
         let fn_ret =
             self.ir.tcx.liberate_late_bound_regions(
-                self.ir.tcx.region_maps.call_site_extent(id, body.id),
+                self.ir.tcx.region_maps.call_site_extent(id, body.value.id),
                 &fn_ret);
 
         if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
@@ -1510,8 +1501,8 @@ fn should_warn(&self, var: Variable) -> Option<String> {
         }
     }
 
-    fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) {
-        for arg in &decl.inputs {
+    fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
+        for arg in &body.arguments {
             arg.pat.each_binding(|_bm, p_id, sp, path1| {
                 let var = self.variable(p_id, sp);
                 // Ignore unused self.
index 4c3b102e540399f1c38d2f3b1b5841617a541ecd..2d88567b8b873228d292229d057aa087a6ff872f 100644 (file)
@@ -73,7 +73,6 @@
 use hir::def_id::DefId;
 use hir::map as ast_map;
 use infer::InferCtxt;
-use middle::const_qualif::ConstQualif;
 use hir::def::{Def, CtorKind};
 use ty::adjustment;
 use ty::{self, Ty, TyCtxt};
@@ -705,7 +704,7 @@ fn env_deref(&self,
             };
 
             match fn_expr.node {
-                hir::ExprClosure(.., body_id, _) => body_id.node_id(),
+                hir::ExprClosure(.., body_id, _) => body_id.node_id,
                 _ => bug!()
             }
         };
@@ -773,23 +772,23 @@ pub fn cat_rvalue_node(&self,
                            span: Span,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
-        let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned()
-                               .unwrap_or(ConstQualif::NOT_CONST);
+        let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned()
+                                   .unwrap_or(false);
 
         // Only promote `[T; 0]` before an RFC for rvalue promotions
         // is accepted.
-        let qualif = match expr_ty.sty {
-            ty::TyArray(_, 0) => qualif,
-            _ => ConstQualif::NOT_CONST
+        let promotable = match expr_ty.sty {
+            ty::TyArray(_, 0) => true,
+            _ => promotable & false
         };
 
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
         // lifetime.
-        let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-            self.temporary_scope(id)
-        } else {
+        let re = if promotable {
             self.tcx().mk_region(ty::ReStatic)
+        } else {
+            self.temporary_scope(id)
         };
         let ret = self.cat_rvalue(id, span, re, expr_ty);
         debug!("cat_rvalue_node ret {:?}", ret);
index 2c4710f1e452b6559c2709bfc55df0eb538b928e..765d93742d8fbc4f521b629bfb5f29094bd8b2cb 100644 (file)
@@ -139,7 +139,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> {
         let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
             *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib ||
-            *ty == config::CrateTypeProcMacro || *ty == config::CrateTypeMetadata
+            *ty == config::CrateTypeProcMacro
         });
         ReachableContext {
             tcx: tcx,
@@ -166,9 +166,10 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
                 match trait_method.node {
-                    hir::ConstTraitItem(_, ref default) => default.is_some(),
-                    hir::MethodTraitItem(_, ref body) => body.is_some(),
-                    hir::TypeTraitItem(..) => false,
+                    hir::TraitItemKind::Const(_, ref default) => default.is_some(),
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+                    hir::TraitItemKind::Type(..) => false,
                 }
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
@@ -250,15 +251,15 @@ fn propagate_node(&mut self, node: &ast_map::Node<'tcx>,
                 match item.node {
                     hir::ItemFn(.., body) => {
                         if item_might_be_inlined(&item) {
-                            self.visit_body(body);
+                            self.visit_nested_body(body);
                         }
                     }
 
                     // Reachable constants will be inlined into other crates
                     // unconditionally, so we need to make sure that their
                     // contents are also reachable.
-                    hir::ItemConst(_, ref init) => {
-                        self.visit_expr(&init);
+                    hir::ItemConst(_, init) => {
+                        self.visit_nested_body(init);
                     }
 
                     // These are normal, nothing reachable about these
@@ -274,28 +275,26 @@ fn propagate_node(&mut self, node: &ast_map::Node<'tcx>,
             }
             ast_map::NodeTraitItem(trait_method) => {
                 match trait_method.node {
-                    hir::ConstTraitItem(_, None) |
-                    hir::MethodTraitItem(_, None) => {
+                    hir::TraitItemKind::Const(_, None) |
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
                         // Keep going, nothing to get exported
                     }
-                    hir::ConstTraitItem(_, Some(ref body)) => {
-                        self.visit_expr(body);
+                    hir::TraitItemKind::Const(_, Some(body_id)) |
+                    hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+                        self.visit_nested_body(body_id);
                     }
-                    hir::MethodTraitItem(_, Some(body_id)) => {
-                        self.visit_body(body_id);
-                    }
-                    hir::TypeTraitItem(..) => {}
+                    hir::TraitItemKind::Type(..) => {}
                 }
             }
             ast_map::NodeImplItem(impl_item) => {
                 match impl_item.node {
-                    hir::ImplItemKind::Const(_, ref expr) => {
-                        self.visit_expr(&expr);
+                    hir::ImplItemKind::Const(_, body) => {
+                        self.visit_nested_body(body);
                     }
                     hir::ImplItemKind::Method(ref sig, body) => {
                         let did = self.tcx.map.get_parent_did(search_item);
                         if method_might_be_inlined(self.tcx, sig, impl_item, did) {
-                            self.visit_body(body)
+                            self.visit_nested_body(body)
                         }
                     }
                     hir::ImplItemKind::Type(_) => {}
@@ -358,6 +357,8 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
         // processed in visit_item above
     }
index b1e35e54eb9bb8c89a8c9a8e6bab0d257f74d0d8..faf4a448b7a84e5b20ea8d0ba53384044bc74a78 100644 (file)
@@ -1088,7 +1088,7 @@ fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'tcx, 'a
 fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
                         kind: FnKind<'tcx>,
                         decl: &'tcx hir::FnDecl,
-                        body_id: hir::ExprId,
+                        body_id: hir::BodyId,
                         sp: Span,
                         id: ast::NodeId) {
     debug!("region::resolve_fn(id={:?}, \
@@ -1101,22 +1101,22 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
            visitor.cx.parent);
 
     visitor.cx.parent = visitor.new_code_extent(
-        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() });
+        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
 
     let fn_decl_scope = visitor.new_code_extent(
-        CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id() });
+        CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id });
 
     if let Some(root_id) = visitor.cx.root_id {
-        visitor.region_maps.record_fn_parent(body_id.node_id(), root_id);
+        visitor.region_maps.record_fn_parent(body_id.node_id, root_id);
     }
 
     let outer_cx = visitor.cx;
     let outer_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet());
-    visitor.terminating_scopes.insert(body_id.node_id());
+    visitor.terminating_scopes.insert(body_id.node_id);
 
     // The arguments and `self` are parented to the fn.
     visitor.cx = Context {
-        root_id: Some(body_id.node_id()),
+        root_id: Some(body_id.node_id),
         parent: ROOT_CODE_EXTENT,
         var_parent: fn_decl_scope,
     };
@@ -1126,11 +1126,11 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
 
     // The body of the every fn is a root scope.
     visitor.cx = Context {
-        root_id: Some(body_id.node_id()),
+        root_id: Some(body_id.node_id),
         parent: fn_decl_scope,
         var_parent: fn_decl_scope
     };
-    visitor.visit_body(body_id);
+    visitor.visit_nested_body(body_id);
 
     // Restore context we had at the start.
     visitor.cx = outer_cx;
@@ -1195,7 +1195,7 @@ fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl,
-                b: hir::ExprId, s: Span, n: NodeId) {
+                b: hir::BodyId, s: Span, n: NodeId) {
         resolve_fn(self, fk, fd, b, s, n);
     }
     fn visit_arm(&mut self, a: &'ast Arm) {
index c5b03a4a32add5b64a3a0309b6d3979cf39e4edb..c491af972acbce6120f926b2f66b13166d06fd69 100644 (file)
@@ -33,7 +33,6 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use hir;
-use hir::print::lifetime_to_string;
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
@@ -190,7 +189,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
         // Items always introduce a new root scope
         self.with(RootScope, |_, this| {
             match item.node {
-                hir::ForeignItemFn(ref decl, ref generics) => {
+                hir::ForeignItemFn(ref decl, _, ref generics) => {
                     this.visit_early_late(item.id, decl, generics, |this| {
                         intravisit::walk_foreign_item(this, item);
                     })
@@ -206,7 +205,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, fn_id: ast::NodeId) {
+                b: hir::BodyId, s: Span, fn_id: ast::NodeId) {
         match fk {
             FnKind::ItemFn(_, generics, ..) => {
                 self.visit_early_late(fn_id,decl, generics, |this| {
@@ -266,7 +265,8 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         // methods in an impl can reuse label names.
         let saved = replace(&mut self.labels_in_fn, vec![]);
 
-        if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
+        if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) =
+                trait_item.node {
             self.visit_early_late(
                 trait_item.id,
                 &sig.decl, &sig.generics,
@@ -407,7 +407,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
 
 // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
 // if one of the label shadows a lifetime or another label.
-fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) {
+fn extract_labels(ctxt: &mut LifetimeContext, b: hir::BodyId) {
     struct GatherLabels<'a> {
         sess: &'a Session,
         scope: Scope<'a>,
@@ -419,7 +419,7 @@ struct GatherLabels<'a> {
         scope: ctxt.scope,
         labels_in_fn: &mut ctxt.labels_in_fn,
     };
-    gather.visit_expr(ctxt.hir_map.expr(b));
+    gather.visit_body(ctxt.hir_map.body(b));
     return;
 
     impl<'v, 'a> Visitor<'v> for GatherLabels<'a> {
@@ -501,7 +501,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     fn add_scope_and_walk_fn(&mut self,
                              fk: FnKind<'tcx>,
                              fd: &'tcx hir::FnDecl,
-                             fb: hir::ExprId,
+                             fb: hir::BodyId,
                              _span: Span,
                              fn_id: ast::NodeId) {
         match fk {
@@ -522,8 +522,8 @@ fn add_scope_and_walk_fn(&mut self,
         // `self.labels_in_fn`.
         extract_labels(self, fb);
 
-        self.with(FnScope { fn_id: fn_id, body_id: fb.node_id(), s: self.scope },
-                  |_old_scope, this| this.visit_body(fb))
+        self.with(FnScope { fn_id: fn_id, body_id: fb.node_id, s: self.scope },
+                  |_old_scope, this| this.visit_nested_body(fb))
     }
 
     // FIXME(#37666) this works around a limitation in the region inferencer
@@ -821,9 +821,8 @@ fn insert_lifetime(&mut self,
                        probably a bug in syntax::fold");
         }
 
-        debug!("lifetime_ref={:?} id={:?} resolved to {:?} span={:?}",
-               lifetime_to_string(lifetime_ref),
-               lifetime_ref.id,
+        debug!("{} resolved to {:?} span={:?}",
+               self.hir_map.node_to_string(lifetime_ref.id),
                def,
                self.sess.codemap().span_to_string(lifetime_ref.span));
         self.map.defs.insert(lifetime_ref.id, def);
@@ -860,8 +859,8 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
     debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics);
 
     let mut constrained_by_input = ConstrainedCollector { regions: FxHashSet() };
-    for arg in &decl.inputs {
-        constrained_by_input.visit_ty(&arg.ty);
+    for arg_ty in &decl.inputs {
+        constrained_by_input.visit_ty(arg_ty);
     }
 
     let mut appears_in_output = AllCollector {
index c6df1497e681dd3ac3c4587d0c7d45e772ff3c29..acb506878e6b65eb94f45d772dab26fe388ec647 100644 (file)
@@ -75,8 +75,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) {
             config::CrateTypeCdylib |
             config::CrateTypeExecutable |
             config::CrateTypeStaticlib => true,
-            config::CrateTypeRlib |
-            config::CrateTypeMetadata => false,
+            config::CrateTypeRlib => false,
         }
     });
     if !needs_check {
index 3576ae662a005033e1a5f200327b9d03228dfa75..3c5a91f4ff04c8dae35599a94bbf7d9964032d2e 100644 (file)
@@ -48,7 +48,7 @@ pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
 
         match tcx.map.get(id) {
             map::NodeItem(&Item { node: ItemConst(..), .. }) |
-            map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) |
+            map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
             map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
                 MirSource::Const(id)
             }
index ecc8042e9404f20d1fd777d51fbfc1b2fe76bd87..b3cb5ace45bc04e702d8b16a506f48f1b9277cea 100644 (file)
@@ -73,6 +73,7 @@ pub enum OutputType {
     Bitcode,
     Assembly,
     LlvmAssembly,
+    Metadata,
     Object,
     Exe,
     DepInfo,
@@ -86,7 +87,8 @@ fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
             OutputType::Bitcode |
             OutputType::Assembly |
             OutputType::LlvmAssembly |
-            OutputType::Object => false,
+            OutputType::Object |
+            OutputType::Metadata => false,
         }
     }
 
@@ -96,6 +98,7 @@ fn shorthand(&self) -> &'static str {
             OutputType::Assembly => "asm",
             OutputType::LlvmAssembly => "llvm-ir",
             OutputType::Object => "obj",
+            OutputType::Metadata => "metadata",
             OutputType::Exe => "link",
             OutputType::DepInfo => "dep-info",
         }
@@ -107,6 +110,7 @@ pub fn extension(&self) -> &'static str {
             OutputType::Assembly => "s",
             OutputType::LlvmAssembly => "ll",
             OutputType::Object => "o",
+            OutputType::Metadata => "rmeta",
             OutputType::DepInfo => "d",
             OutputType::Exe => "",
         }
@@ -152,6 +156,19 @@ pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
     pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
         self.0.values()
     }
+
+    // True if any of the output types require codegen or linking.
+    pub fn should_trans(&self) -> bool {
+        self.0.keys().any(|k| match *k {
+            OutputType::Bitcode |
+            OutputType::Assembly |
+            OutputType::LlvmAssembly |
+            OutputType::Object |
+            OutputType::Exe => true,
+            OutputType::Metadata |
+            OutputType::DepInfo => false,
+        })
+    }
 }
 
 
@@ -482,7 +499,6 @@ pub enum CrateType {
     CrateTypeStaticlib,
     CrateTypeCdylib,
     CrateTypeProcMacro,
-    CrateTypeMetadata,
 }
 
 #[derive(Clone, Hash)]
@@ -943,6 +959,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let os = &sess.target.target.target_os;
     let env = &sess.target.target.target_env;
     let vendor = &sess.target.target.target_vendor;
+    let min_atomic_width = sess.target.target.min_atomic_width();
     let max_atomic_width = sess.target.target.max_atomic_width();
 
     let mut ret = HashSet::new();
@@ -963,7 +980,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
         ret.insert((Symbol::intern("target_thread_local"), None));
     }
     for &i in &[8, 16, 32, 64, 128] {
-        if i <= max_atomic_width {
+        if i >= min_atomic_width && i <= max_atomic_width {
             let s = i.to_string();
             ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern(&s))));
             if &s == wordsz {
@@ -1158,12 +1175,12 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                              assumed.", "[KIND=]NAME"),
         opt::multi_s("", "crate-type", "Comma separated list of types of crates
                                     for the compiler to emit",
-                   "[bin|lib|rlib|dylib|cdylib|staticlib|metadata]"),
+                   "[bin|lib|rlib|dylib|cdylib|staticlib]"),
         opt::opt_s("", "crate-name", "Specify the name of the crate being built",
                "NAME"),
         opt::multi_s("", "emit", "Comma separated list of types of output for \
                               the compiler to emit",
-                 "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
+                 "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info]"),
         opt::multi_s("", "print", "Comma separated list of compiler information to \
                                print on stdout", &print_opts.join("|")),
         opt::flagmulti_s("g",  "",  "Equivalent to -C debuginfo=2"),
@@ -1292,7 +1309,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     };
 
     let unparsed_crate_types = matches.opt_strs("crate-type");
-    let crate_types = parse_crate_types_from_list(unparsed_crate_types)
+    let (crate_types, emit_metadata) = parse_crate_types_from_list(unparsed_crate_types)
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
     let mut lint_opts = vec![];
@@ -1326,6 +1343,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
                     "llvm-ir" => OutputType::LlvmAssembly,
                     "llvm-bc" => OutputType::Bitcode,
                     "obj" => OutputType::Object,
+                    "metadata" => OutputType::Metadata,
                     "link" => OutputType::Exe,
                     "dep-info" => OutputType::DepInfo,
                     part => {
@@ -1338,7 +1356,9 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
             }
         }
     };
-    if output_types.is_empty() {
+    if emit_metadata {
+        output_types.insert(OutputType::Metadata, None);
+    } else if output_types.is_empty() {
         output_types.insert(OutputType::Exe, None);
     }
 
@@ -1540,8 +1560,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     cfg)
 }
 
-pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
+pub fn parse_crate_types_from_list(list_list: Vec<String>)
+                                   -> Result<(Vec<CrateType>, bool), String> {
     let mut crate_types: Vec<CrateType> = Vec::new();
+    let mut emit_metadata = false;
     for unparsed_crate_type in &list_list {
         for part in unparsed_crate_type.split(',') {
             let new_part = match part {
@@ -1552,7 +1574,13 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
                 "cdylib"    => CrateTypeCdylib,
                 "bin"       => CrateTypeExecutable,
                 "proc-macro" => CrateTypeProcMacro,
-                "metadata"  => CrateTypeMetadata,
+                // FIXME(#38640) remove this when Cargo is fixed.
+                "metadata"  => {
+                    early_warn(ErrorOutputType::default(), "--crate-type=metadata is deprecated, \
+                                                            prefer --emit=metadata");
+                    emit_metadata = true;
+                    CrateTypeRlib
+                }
                 _ => {
                     return Err(format!("unknown crate type: `{}`",
                                        part));
@@ -1564,7 +1592,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
         }
     }
 
-    return Ok(crate_types);
+    return Ok((crate_types, emit_metadata));
 }
 
 pub mod nightly_options {
@@ -1637,7 +1665,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             CrateTypeStaticlib => "staticlib".fmt(f),
             CrateTypeCdylib => "cdylib".fmt(f),
             CrateTypeProcMacro => "proc-macro".fmt(f),
-            CrateTypeMetadata => "metadata".fmt(f),
         }
     }
 }
index f24ff98035532222905e7e32733d8f3d1f5b498a..cb1fc15c5f68210c704352863b87a7f6a73229ad 100644 (file)
@@ -508,14 +508,6 @@ pub struct GlobalCtxt<'tcx> {
     /// FIXME(arielb1): why is this separate from populated_external_types?
     pub populated_external_primitive_impls: RefCell<DefIdSet>,
 
-    /// Cache used by const_eval when decoding external constants.
-    /// Contains `None` when the constant has been fetched but doesn't exist.
-    /// Constains `Some(expr_id, type)` otherwise.
-    /// `type` is `None` in case it's not a primitive type
-    pub extern_const_statics: RefCell<DefIdMap<Option<(NodeId, Option<Ty<'tcx>>)>>>,
-    /// Cache used by const_eval when decoding extern const fns
-    pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
-
     /// Maps any item's def-id to its stability index.
     pub stability: RefCell<stability::Index<'tcx>>,
 
@@ -537,8 +529,8 @@ pub struct GlobalCtxt<'tcx> {
     /// Caches the representation hints for struct definitions.
     repr_hint_cache: RefCell<DepTrackingMap<maps::ReprHints<'tcx>>>,
 
-    /// Maps Expr NodeId's to their constant qualification.
-    pub const_qualif_map: RefCell<NodeMap<middle::const_qualif::ConstQualif>>,
+    /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
+    pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
@@ -787,13 +779,11 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             used_trait_imports: RefCell::new(NodeSet()),
             populated_external_types: RefCell::new(DefIdSet()),
             populated_external_primitive_impls: RefCell::new(DefIdSet()),
-            extern_const_statics: RefCell::new(DefIdMap()),
-            extern_const_fns: RefCell::new(DefIdMap()),
             stability: RefCell::new(stability),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
-            const_qualif_map: RefCell::new(NodeMap()),
+            rvalue_promotable_to_static: RefCell::new(NodeMap()),
             custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
             cast_kinds: RefCell::new(NodeMap()),
             fragment_infos: RefCell::new(DefIdMap()),
index 2ab10d0446b2a11f22749cc6044a9ec07bee14d2..b03a432de413107a4c4a25f69c552ba3a1db7679 100644 (file)
@@ -1206,13 +1206,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         tcx.construct_parameter_environment(
                             impl_item.span,
                             tcx.map.local_def_id(id),
-                            tcx.region_maps.call_site_extent(id, body.node_id()))
+                            tcx.region_maps.call_site_extent(id, body.node_id))
                     }
                 }
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
-                    hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => {
+                    hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the trait
                         let trait_id = tcx.map.get_parent(id);
@@ -1221,13 +1221,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                                                             trait_def_id,
                                                             tcx.region_maps.item_extent(id))
                     }
-                    hir::MethodTraitItem(_, ref body) => {
+                    hir::TraitItemKind::Method(_, ref body) => {
                         // Use call-site for extent (unless this is a
                         // trait method with no default; then fallback
                         // to the method id).
-                        let extent = if let Some(body_id) = *body {
+                        let extent = if let hir::TraitMethod::Provided(body_id) = *body {
                             // default impl: use call_site extent as free_id_outlive bound.
-                            tcx.region_maps.call_site_extent(id, body_id.node_id())
+                            tcx.region_maps.call_site_extent(id, body_id.node_id)
                         } else {
                             // no default impl: use item extent as free_id_outlive bound.
                             tcx.region_maps.item_extent(id)
@@ -1248,7 +1248,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         tcx.construct_parameter_environment(
                             item.span,
                             fn_def_id,
-                            tcx.region_maps.call_site_extent(id, body_id.node_id()))
+                            tcx.region_maps.call_site_extent(id, body_id.node_id))
                     }
                     hir::ItemEnum(..) |
                     hir::ItemStruct(..) |
@@ -1284,7 +1284,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     tcx.construct_parameter_environment(
                         expr.span,
                         base_def_id,
-                        tcx.region_maps.call_site_extent(id, body.node_id()))
+                        tcx.region_maps.call_site_extent(id, body.node_id))
                 } else {
                     tcx.empty_parameter_environment()
                 }
@@ -2100,10 +2100,10 @@ pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
                     }
                 }
 
-                hir::ItemTrait(.., ref trait_items) => {
-                    for trait_item in trait_items {
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    for trait_item_ref in trait_item_refs {
                         let assoc_item =
-                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item);
+                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
                         self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item);
                     }
                 }
@@ -2121,28 +2121,22 @@ pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
 
     fn associated_item_from_trait_item_ref(self,
                                            parent_def_id: DefId,
-                                           trait_item: &hir::TraitItem)
+                                           trait_item_ref: &hir::TraitItemRef)
                                            -> AssociatedItem {
-        let def_id = self.map.local_def_id(trait_item.id);
-
-        let (kind, has_self, has_value) = match trait_item.node {
-            hir::MethodTraitItem(ref sig, ref body) => {
-                (AssociatedKind::Method, sig.decl.get_self().is_some(),
-                 body.is_some())
-            }
-            hir::ConstTraitItem(_, ref value) => {
-                (AssociatedKind::Const, false, value.is_some())
-            }
-            hir::TypeTraitItem(_, ref ty) => {
-                (AssociatedKind::Type, false, ty.is_some())
+        let def_id = self.map.local_def_id(trait_item_ref.id.node_id);
+        let (kind, has_self) = match trait_item_ref.kind {
+            hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+            hir::AssociatedItemKind::Method { has_self } => {
+                (ty::AssociatedKind::Method, has_self)
             }
+            hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
         };
 
         AssociatedItem {
-            name: trait_item.name,
+            name: trait_item_ref.name,
             kind: kind,
-            vis: Visibility::from_hir(&hir::Inherited, trait_item.id, self),
-            defaultness: hir::Defaultness::Default { has_value: has_value },
+            vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self),
+            defaultness: trait_item_ref.defaultness,
             def_id: def_id,
             container: TraitContainer(parent_def_id),
             method_has_self_argument: has_self
@@ -2187,11 +2181,11 @@ pub fn associated_item_def_ids(self, def_id: DefId) -> Rc<Vec<DefId>> {
             let id = self.map.as_local_node_id(def_id).unwrap();
             let item = self.map.expect_item(id);
             let vec: Vec<_> = match item.node {
-                hir::ItemTrait(.., ref trait_items) => {
-                    trait_items.iter()
-                               .map(|trait_item| trait_item.id)
-                               .map(|id| self.map.local_def_id(id))
-                               .collect()
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    trait_item_refs.iter()
+                                   .map(|trait_item_ref| trait_item_ref.id)
+                                   .map(|id| self.map.local_def_id(id.node_id))
+                                   .collect()
                 }
                 hir::ItemImpl(.., ref impl_item_refs) => {
                     impl_item_refs.iter()
index e01856b2a476265b161671e78b5760d249e545ae..4ddccbfd4c597ff59d5df2df0ec937b3d2acd821 100644 (file)
 #[derive(Clone, Copy, Debug)]
 pub struct ErrorReported;
 
+thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
+
+/// Read the current depth of `time()` calls. This is used to
+/// encourage indentation across threads.
+pub fn time_depth() -> usize {
+    TIME_DEPTH.with(|slot| slot.get())
+}
+
+/// Set the current depth of `time()` calls. The idea is to call
+/// `set_time_depth()` with the result from `time_depth()` in the
+/// parent thread.
+pub fn set_time_depth(depth: usize) {
+    TIME_DEPTH.with(|slot| slot.set(depth));
+}
+
 pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
     F: FnOnce() -> T,
 {
-    thread_local!(static DEPTH: Cell<usize> = Cell::new(0));
     if !do_it { return f(); }
 
-    let old = DEPTH.with(|slot| {
+    let old = TIME_DEPTH.with(|slot| {
         let r = slot.get();
         slot.set(r + 1);
         r
@@ -56,7 +70,7 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
              mem_string,
              what);
 
-    DEPTH.with(|slot| slot.set(old));
+    TIME_DEPTH.with(|slot| slot.set(old));
 
     rv
 }
index 8c37eb6986a7cd77a6887dcd75eaeaef4482de64..6a409edf0feccbf564f38d91cfbbf24888e29765 100644 (file)
@@ -376,6 +376,9 @@ pub struct TargetOptions {
     // file
     pub no_integrated_as: bool,
 
+    /// Don't use this field; instead use the `.min_atomic_width()` method.
+    pub min_atomic_width: Option<u64>,
+
     /// Don't use this field; instead use the `.max_atomic_width()` method.
     pub max_atomic_width: Option<u64>,
 
@@ -439,6 +442,7 @@ fn default() -> TargetOptions {
             has_elf_tls: false,
             obj_is_bitcode: false,
             no_integrated_as: false,
+            min_atomic_width: None,
             max_atomic_width: None,
             panic_strategy: PanicStrategy::Unwind,
             abi_blacklist: vec![],
@@ -462,6 +466,12 @@ pub fn adjust_abi(&self, abi: Abi) -> Abi {
         }
     }
 
+    /// Minimum integer size in bits that this target can perform atomic
+    /// operations on.
+    pub fn min_atomic_width(&self) -> u64 {
+        self.options.min_atomic_width.unwrap_or(8)
+    }
+
     /// Maximum integer size in bits that this target can perform atomic
     /// operations on.
     pub fn max_atomic_width(&self) -> u64 {
@@ -604,6 +614,7 @@ macro_rules! key {
         key!(obj_is_bitcode, bool);
         key!(no_integrated_as, bool);
         key!(max_atomic_width, Option<u64>);
+        key!(min_atomic_width, Option<u64>);
         try!(key!(panic_strategy, PanicStrategy));
         key!(crt_static_default, bool);
 
@@ -766,6 +777,7 @@ macro_rules! target_option_val {
         target_option_val!(has_elf_tls);
         target_option_val!(obj_is_bitcode);
         target_option_val!(no_integrated_as);
+        target_option_val!(min_atomic_width);
         target_option_val!(max_atomic_width);
         target_option_val!(panic_strategy);
         target_option_val!(crt_static_default);
index 5ed628d7dcae5f8be847efa4e5c71043bfd67c3f..dc2214dd34e72141ae4f6a02d59599fcaef22afb 100644 (file)
@@ -189,9 +189,8 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                      move_data: &move_data::FlowedMoveData<'c, 'tcx>,
                                      all_loans: &[Loan<'tcx>],
                                      fn_id: ast::NodeId,
-                                     decl: &hir::FnDecl,
-                                     body: &hir::Expr) {
-    debug!("check_loans(body id={})", body.id);
+                                     body: &hir::Body) {
+    debug!("check_loans(body id={})", body.value.id);
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
     let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env);
@@ -202,7 +201,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         all_loans: all_loans,
         param_env: &infcx.parameter_environment
     };
-    euv::ExprUseVisitor::new(&mut clcx, &infcx).walk_fn(decl, body);
+    euv::ExprUseVisitor::new(&mut clcx, &infcx).consume_body(body);
 }
 
 #[derive(PartialEq)]
index 5d59b58b847d9e0eabc99315c5352f0dd67c60d2..34f1ad57c6211e8317a21fa15365030f8db23e1f 100644 (file)
 
 pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                     fn_id: NodeId,
-                                    decl: &hir::FnDecl,
-                                    body: &hir::Expr)
+                                    body: &hir::Body)
                                     -> (Vec<Loan<'tcx>>,
                                         move_data::MoveData<'tcx>) {
     let mut glcx = GatherLoanCtxt {
         bccx: bccx,
         all_loans: Vec::new(),
-        item_ub: bccx.tcx.region_maps.node_extent(body.id),
+        item_ub: bccx.tcx.region_maps.node_extent(body.value.id),
         move_data: MoveData::new(),
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
     let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env);
-    euv::ExprUseVisitor::new(&mut glcx, &infcx).walk_fn(decl, body);
+    euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body);
 
     glcx.report_potential_errors();
     let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
@@ -548,14 +547,14 @@ fn visit_expr(&mut self, ex: &'tcx Expr) {
 
 pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>,
                                                     item_id: ast::NodeId,
-                                                    expr: &'tcx hir::Expr) {
+                                                    body: hir::BodyId) {
 
-    debug!("gather_loans_in_static_initializer(expr={:?})", expr);
+    debug!("gather_loans_in_static_initializer(expr={:?})", body);
 
     let mut sicx = StaticInitializerCtxt {
         bccx: bccx,
         item_id: item_id
     };
 
-    sicx.visit_expr(expr);
+    sicx.visit_nested_body(body);
 }
index 8461f6d061a5577f7505369459cbc7f16b5aa754..b15c1873f9bd84506dbe3cd7b3f5946bf83dad59 100644 (file)
 use std::mem;
 use std::path::Path;
 
-use super::super::MoveDataParamEnv;
 use super::super::MirBorrowckCtxtPreDataflow;
 use super::{BitDenotation, DataflowState};
 
 impl<O: BitDenotation> DataflowState<O> {
-    fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
+    fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F)
         where F: FnMut(O::Idx) {
         //! Helper for iterating over the bits in a bitvector.
 
-        let bits_per_block = self.operator.bits_per_block(ctxt);
+        let bits_per_block = self.operator.bits_per_block();
         let usize_bits: usize = mem::size_of::<usize>() * 8;
 
         for (word_index, &word) in words.words().iter().enumerate() {
@@ -65,35 +64,33 @@ fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
     }
 
     pub fn interpret_set<'c, P>(&self,
-                                ctxt: &'c O::Ctxt,
+                                o: &'c O,
                                 words: &IdxSet<O::Idx>,
                                 render_idx: &P)
                                 -> Vec<&'c Debug>
-        where P: for <'b> Fn(&'b O::Ctxt, O::Idx) -> &'b Debug
+        where P: Fn(&O, O::Idx) -> &Debug
     {
         let mut v = Vec::new();
-        self.each_bit(ctxt, words, |i| {
-            v.push(render_idx(ctxt, i));
+        self.each_bit(words, |i| {
+            v.push(render_idx(o, i));
         });
         v
     }
 }
 
 pub trait MirWithFlowState<'tcx> {
-    type BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>;
+    type BD: BitDenotation;
     fn node_id(&self) -> NodeId;
     fn mir(&self) -> &Mir<'tcx>;
-    fn analysis_ctxt(&self) -> &<Self::BD as BitDenotation>::Ctxt;
     fn flow_state(&self) -> &DataflowState<Self::BD>;
 }
 
 impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where 'tcx: 'a, BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where 'tcx: 'a, BD: BitDenotation
 {
     type BD = BD;
     fn node_id(&self) -> NodeId { self.node_id }
     fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
-    fn analysis_ctxt(&self) -> &BD::Ctxt { &self.flow_state.ctxt }
     fn flow_state(&self) -> &DataflowState<Self::BD> { &self.flow_state.flow_state }
 }
 
@@ -110,8 +107,8 @@ pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
     path: &Path,
     render_idx: P)
     -> io::Result<()>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>,
-          P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug
+    where BD: BitDenotation,
+          P: Fn(&BD, BD::Idx) -> &Debug
 {
     let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };
     let mut v = Vec::new();
@@ -133,9 +130,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
 
 impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
     where MWF: MirWithFlowState<'tcx>,
-          P: for <'b> Fn(&'b <MWF::BD as BitDenotation>::Ctxt,
-                         <MWF::BD as BitDenotation>::Idx)
-                         -> &'b Debug,
+          P: for <'b> Fn(&'b MWF::BD, <MWF::BD as BitDenotation>::Idx) -> &'b Debug,
 {
     type Node = Node;
     type Edge = Edge;
@@ -227,9 +222,8 @@ fn chunked_present_left<W:io::Write>(w: &mut W,
         ::rustc_mir::graphviz::write_node_label(
             *n, self.mbcx.mir(), &mut v, 4,
             |w| {
-                let ctxt = self.mbcx.analysis_ctxt();
                 let flow = self.mbcx.flow_state();
-                let entry_interp = flow.interpret_set(ctxt,
+                let entry_interp = flow.interpret_set(&flow.operator,
                                                       flow.sets.on_entry_set_for(i),
                                                       &self.render_idx);
                 chunked_present_left(w, &entry_interp[..], chunk_size)?;
@@ -244,12 +238,11 @@ fn chunked_present_left<W:io::Write>(w: &mut W,
                        entrybits=bits_to_string(entry.words(), bits_per_block))
             },
             |w| {
-                let ctxt = self.mbcx.analysis_ctxt();
                 let flow = self.mbcx.flow_state();
                 let gen_interp =
-                    flow.interpret_set(ctxt, flow.sets.gen_set_for(i), &self.render_idx);
+                    flow.interpret_set(&flow.operator, flow.sets.gen_set_for(i), &self.render_idx);
                 let kill_interp =
-                    flow.interpret_set(ctxt, flow.sets.kill_set_for(i), &self.render_idx);
+                    flow.interpret_set(&flow.operator, flow.sets.kill_set_for(i), &self.render_idx);
                 chunked_present_left(w, &gen_interp[..], chunk_size)?;
                 let bits_per_block = flow.sets.bits_per_block();
                 {
index fcb453d81aa770c98a9fefca31bfddcc7280b42c..1fa4da94dd6bfae51f1052e820e0945ac66cdcf1 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
+use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
 use super::super::MoveDataParamEnv;
 use super::super::DropFlagState;
 use super::super::drop_flag_effects_for_function_entry;
 pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        MaybeInitializedLvals { tcx: tcx, mir: mir }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `MaybeUninitializedLvals` tracks all l-values that might be
 /// uninitialized upon reaching a particular point in the control flow
 /// for a function.
@@ -112,14 +121,23 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
 pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        MaybeUninitializedLvals { tcx: tcx, mir: mir }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `DefinitelyInitializedLvals` tracks all l-values that are definitely
 /// initialized upon reaching a particular point in the control flow
 /// for a function.
@@ -164,14 +182,23 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
 pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        DefinitelyInitializedLvals { tcx: tcx, mir: mir }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `MovingOutStatements` tracks the statements that perform moves out
 /// of particular l-values. More precisely, it tracks whether the
 /// *effect* of such moves (namely, the uninitialization of the
@@ -189,6 +216,11 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
 pub struct MovingOutStatements<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
 impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
@@ -226,16 +258,15 @@ fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
 
 impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "maybe_init" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>)
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>)
     {
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -243,60 +274,56 @@ fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathInd
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.add(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "maybe_uninit" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
     // sets on_entry bits for Arg lvalues
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>) {
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
         // set all bits to 1 (uninit) before gathering counterevidence
         for e in sets.on_entry.words_mut() { *e = !0; }
 
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.remove(&path);
@@ -304,59 +331,55 @@ fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathInd
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 0 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.remove(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "definite_init" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
     // sets on_entry bits for Arg lvalues
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>) {
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
         for e in sets.on_entry.words_mut() { *e = 0; }
 
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -364,63 +387,58 @@ fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathInd
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.add(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
     type Idx = MoveOutIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "moving_out" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.moves.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().moves.len()
     }
 
-    fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets<MoveOutIndex>) {
+    fn start_block_effect(&self, _sets: &mut BlockSets<MoveOutIndex>) {
         // no move-statements have been executed prior to function
         // execution, so this method has no effect on `_sets`.
     }
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MoveOutIndex>,
                         bb: mir::BasicBlock,
                         idx: usize) {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data);
+        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
         let stmt = &mir[bb].statements[idx];
         let loc_map = &move_data.loc_map;
         let path_map = &move_data.path_map;
@@ -435,7 +453,7 @@ fn statement_effect(&self,
             // here, in dataflow vector
             zero_to_one(sets.gen_set.words_mut(), *move_index);
         }
-        let bits_per_block = self.bits_per_block(ctxt);
+        let bits_per_block = self.bits_per_block();
         match stmt.kind {
             mir::StatementKind::SetDiscriminant { .. } => {
                 span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
@@ -460,18 +478,17 @@ fn statement_effect(&self,
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MoveOutIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
-        let (mir, move_data) = (self.mir, &ctxt.move_data);
+        let (mir, move_data) = (self.mir, self.move_data());
         let term = mir[bb].terminator();
         let loc_map = &move_data.loc_map;
         let loc = Location { block: bb, statement_index: statements_len };
         debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
                term, loc, &loc_map[loc]);
-        let bits_per_block = self.bits_per_block(ctxt);
+        let bits_per_block = self.bits_per_block();
         for move_index in &loc_map[loc] {
             assert!(move_index.index() < bits_per_block);
             zero_to_one(sets.gen_set.words_mut(), *move_index);
@@ -479,13 +496,12 @@ fn terminator_effect(&self,
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MoveOutIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
-        let move_data = &ctxt.move_data;
-        let bits_per_block = self.bits_per_block(ctxt);
+        let move_data = self.move_data();
+        let bits_per_block = self.bits_per_block();
 
         let path_map = &move_data.path_map;
         on_lookup_result_bits(self.tcx,
index 51817afbfeafdd53a7b24bc15f08a1d8dbc801ba..f11cf90834dd900f565c5f420f371b1fe34f6fee 100644 (file)
@@ -22,7 +22,6 @@
 use std::usize;
 
 use super::MirBorrowckCtxtPreDataflow;
-use super::MoveDataParamEnv;
 
 pub use self::sanity_check::sanity_check_via_rustc_peek;
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
 mod impls;
 
 pub trait Dataflow<BD: BitDenotation> {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug;
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug;
 }
 
 impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
+    where BD: BitDenotation + DataflowOperator
 {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
         self.flow_state.build_sets();
         self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
         self.flow_state.propagate();
@@ -48,7 +47,7 @@ fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
 }
 
 struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O>
-    where O: 'b + BitDenotation, O::Ctxt: 'a
+    where O: 'b + BitDenotation
 {
     builder: &'b mut DataflowAnalysis<'a, 'tcx, O>,
     changed: bool,
@@ -79,7 +78,7 @@ fn build_sets(&mut self) {
 
         {
             let sets = &mut self.flow_state.sets.for_block(mir::START_BLOCK.index());
-            self.flow_state.operator.start_block_effect(&self.ctxt, sets);
+            self.flow_state.operator.start_block_effect(sets);
         }
 
         for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
@@ -87,12 +86,12 @@ fn build_sets(&mut self) {
 
             let sets = &mut self.flow_state.sets.for_block(bb.index());
             for j_stmt in 0..statements.len() {
-                self.flow_state.operator.statement_effect(&self.ctxt, sets, bb, j_stmt);
+                self.flow_state.operator.statement_effect(sets, bb, j_stmt);
             }
 
             if terminator.is_some() {
                 let stmts_len = statements.len();
-                self.flow_state.operator.terminator_effect(&self.ctxt, sets, bb, stmts_len);
+                self.flow_state.operator.terminator_effect(sets, bb, stmts_len);
             }
         }
     }
@@ -137,10 +136,10 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
 }
 
 impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> &Debug
     {
         if let Some(ref path_str) = self.print_preflow_to {
             let path = dataflow_path(BD::name(), "preflow", path_str);
@@ -151,7 +150,7 @@ fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
     }
 
     fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> &Debug
     {
         if let Some(ref path_str) = self.print_postflow_to {
             let path = dataflow_path(BD::name(), "postflow", path_str);
@@ -179,11 +178,10 @@ fn new(bits: IdxSetBuf<E>) -> Self {
 }
 
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O>
-    where O: BitDenotation, O::Ctxt: 'a
+    where O: BitDenotation
 {
     flow_state: DataflowState<O>,
     mir: &'a Mir<'tcx>,
-    ctxt: &'a O::Ctxt,
 }
 
 impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
@@ -295,9 +293,6 @@ pub trait BitDenotation {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
 
-    /// Specifies what, if any, separate context needs to be supplied for methods below.
-    type Ctxt;
-
     /// A name describing the dataflow analysis that this
     /// BitDenotation is supporting.  The name should be something
     /// suitable for plugging in as part of a filename e.g. avoid
@@ -308,7 +303,7 @@ pub trait BitDenotation {
     fn name() -> &'static str;
 
     /// Size of each bitvector allocated for each block in the analysis.
-    fn bits_per_block(&self, &Self::Ctxt) -> usize;
+    fn bits_per_block(&self) -> usize;
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects that have been
@@ -319,7 +314,7 @@ pub trait BitDenotation {
     /// (Typically this should only modify `sets.on_entry`, since the
     /// gen and kill sets should reflect the effects of *executing*
     /// the start block itself.)
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<Self::Idx>);
+    fn start_block_effect(&self, sets: &mut BlockSets<Self::Idx>);
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects of evaluating statement.
@@ -332,7 +327,6 @@ pub trait BitDenotation {
     /// `bb_data` is the sequence of statements identifed by `bb` in
     /// the MIR.
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<Self::Idx>,
                         bb: mir::BasicBlock,
                         idx_stmt: usize);
@@ -348,7 +342,6 @@ fn statement_effect(&self,
     /// The effects applied here cannot depend on which branch the
     /// terminator took.
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<Self::Idx>,
                          bb: mir::BasicBlock,
                          idx_term: usize);
@@ -373,7 +366,6 @@ fn terminator_effect(&self,
     /// kill-sets associated with each edge coming out of the basic
     /// block.
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<Self::Idx>,
                              call_bb: mir::BasicBlock,
                              dest_bb: mir::BasicBlock,
@@ -385,9 +377,8 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
 {
     pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               ctxt: &'a D::Ctxt,
                denotation: D) -> Self {
-        let bits_per_block = denotation.bits_per_block(&ctxt);
+        let bits_per_block = denotation.bits_per_block();
         let usize_bits = mem::size_of::<usize>() * 8;
         let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
 
@@ -405,7 +396,6 @@ pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
         });
 
         DataflowAnalysis {
-            ctxt: ctxt,
             mir: mir,
             flow_state: DataflowState {
                 sets: AllSets {
@@ -482,7 +472,7 @@ fn propagate_bits_into_graph_successors_of(
                     // N.B.: This must be done *last*, after all other
                     // propagation, as documented in comment above.
                     self.flow_state.operator.propagate_call_return(
-                        &self.ctxt, in_out, bb, *dest_bb, dest_lval);
+                        in_out, bb, *dest_bb, dest_lval);
                     self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
                 }
             }
index 916d17dcc91deff5b598dd9d7f5f7dab7a3c915b..ea6ef423c92cebb89f577a6d8055111bc5d83f20 100644 (file)
@@ -17,9 +17,9 @@
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::super::gather_moves::{MovePathIndex, LookupResult};
-use super::super::MoveDataParamEnv;
 use super::BitDenotation;
 use super::DataflowResults;
+use super::super::gather_moves::HasMoveData;
 
 /// This function scans `mir` for all calls to the intrinsic
 /// `rustc_peek` that have the expression form `rustc_peek(&expr)`.
@@ -41,9 +41,8 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 mir: &Mir<'tcx>,
                                                 id: ast::NodeId,
                                                 _attributes: &[ast::Attribute],
-                                                flow_ctxt: &O::Ctxt,
                                                 results: &DataflowResults<O>)
-    where O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
+    where O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx>
 {
     debug!("sanity_check_via_rustc_peek id: {:?}", id);
     // FIXME: this is not DRY. Figure out way to abstract this and
@@ -51,18 +50,17 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // stuff, so such generalization may not be realistic.)
 
     for bb in mir.basic_blocks().indices() {
-        each_block(tcx, mir, flow_ctxt, results, bb);
+        each_block(tcx, mir, results, bb);
     }
 }
 
 fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            mir: &Mir<'tcx>,
-                           ctxt: &O::Ctxt,
                            results: &DataflowResults<O>,
                            bb: mir::BasicBlock) where
-    O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
+    O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx>
 {
-    let move_data = &ctxt.move_data;
+    let move_data = results.0.operator.move_data();
     let mir::BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = mir[bb];
 
     let (args, span) = match is_rustc_peek(tcx, terminator) {
@@ -146,7 +144,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // reset GEN and KILL sets before emulating their effect.
         for e in sets.gen_set.words_mut() { *e = 0; }
         for e in sets.kill_set.words_mut() { *e = 0; }
-        results.0.operator.statement_effect(ctxt, &mut sets, bb, j);
+        results.0.operator.statement_effect(&mut sets, bb, j);
         sets.on_entry.union(sets.gen_set);
         sets.on_entry.subtract(sets.kill_set);
     }
index 4f49bfc9725b345078da7699fe1b680b9a5cfd31..8e0d9c147824d81642d2d16ba76e88292be141eb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::gather_moves::{MoveData, MovePathIndex, LookupResult};
+use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
 use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use super::dataflow::{DataflowResults};
 use super::{drop_flag_effects_for_location, on_all_children_bits};
@@ -51,11 +51,13 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 param_env: param_env
             };
             let flow_inits =
-                super::do_dataflow(tcx, mir, id, &[], &env,
-                                   MaybeInitializedLvals::new(tcx, mir));
+                super::do_dataflow(tcx, mir, id, &[],
+                                   MaybeInitializedLvals::new(tcx, mir, &env),
+                                   |bd, p| &bd.move_data().move_paths[p]);
             let flow_uninits =
-                super::do_dataflow(tcx, mir, id, &[], &env,
-                                   MaybeUninitializedLvals::new(tcx, mir));
+                super::do_dataflow(tcx, mir, id, &[],
+                                   MaybeUninitializedLvals::new(tcx, mir, &env),
+                                   |bd, p| &bd.move_data().move_paths[p]);
 
             ElaborateDropsCtxt {
                 tcx: tcx,
@@ -481,54 +483,55 @@ fn drop_halfladder<'a>(&mut self,
                            is_cleanup: bool)
                            -> Vec<BasicBlock>
     {
-        let mut succ = succ;
         let mut unwind_succ = if is_cleanup {
             None
         } else {
             c.unwind
         };
-        let mut update_drop_flag = true;
+
+        let mut succ = self.new_block(
+            c, c.is_cleanup, TerminatorKind::Goto { target: succ }
+        );
+
+        // Always clear the "master" drop flag at the bottom of the
+        // ladder. This is needed because the "master" drop flag
+        // protects the ADT's discriminant, which is invalidated
+        // after the ADT is dropped.
+        self.set_drop_flag(
+            Location { block: succ, statement_index: 0 },
+            c.path,
+            DropFlagState::Absent
+        );
 
         fields.iter().rev().enumerate().map(|(i, &(ref lv, path))| {
-            let drop_block = match path {
-                Some(path) => {
-                    debug!("drop_ladder: for std field {} ({:?})", i, lv);
-
-                    self.elaborated_drop_block(&DropCtxt {
-                        source_info: c.source_info,
-                        is_cleanup: is_cleanup,
-                        init_data: c.init_data,
-                        lvalue: lv,
-                        path: path,
-                        succ: succ,
-                        unwind: unwind_succ,
-                    })
-                }
-                None => {
-                    debug!("drop_ladder: for rest field {} ({:?})", i, lv);
-
-                    let blk = self.complete_drop(&DropCtxt {
-                        source_info: c.source_info,
-                        is_cleanup: is_cleanup,
-                        init_data: c.init_data,
-                        lvalue: lv,
-                        path: c.path,
-                        succ: succ,
-                        unwind: unwind_succ,
-                    }, update_drop_flag);
-
-                    // the drop flag has been updated - updating
-                    // it again would clobber it.
-                    update_drop_flag = false;
-
-                    blk
-                }
+            succ = if let Some(path) = path {
+                debug!("drop_ladder: for std field {} ({:?})", i, lv);
+
+                self.elaborated_drop_block(&DropCtxt {
+                    source_info: c.source_info,
+                    is_cleanup: is_cleanup,
+                    init_data: c.init_data,
+                    lvalue: lv,
+                    path: path,
+                    succ: succ,
+                    unwind: unwind_succ,
+                })
+            } else {
+                debug!("drop_ladder: for rest field {} ({:?})", i, lv);
+
+                self.complete_drop(&DropCtxt {
+                    source_info: c.source_info,
+                    is_cleanup: is_cleanup,
+                    init_data: c.init_data,
+                    lvalue: lv,
+                    path: c.path,
+                    succ: succ,
+                    unwind: unwind_succ,
+                }, false)
             };
 
-            succ = drop_block;
             unwind_succ = unwind_ladder.as_ref().map(|p| p[i]);
-
-            drop_block
+            succ
         }).collect()
     }
 
index 02064b52cb1fb2c24b264f621bc879294d29e021..2a9acaf58b8f2bf091ccce29eb8aede48a6abb88 100644 (file)
@@ -120,6 +120,10 @@ pub struct MoveData<'tcx> {
     pub rev_lookup: MovePathLookup<'tcx>,
 }
 
+pub trait HasMoveData<'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx>;
+}
+
 #[derive(Debug)]
 pub struct LocationMap<T> {
     /// Location-indexed (BasicBlock for outer index, index within BB
index 9035c2ab3c236e05cf85fb26813a69dab174bbee..c7bd5b7ed0461c2c7bd0ef3340a4b7304ee5ba96 100644 (file)
 use borrowck::BorrowckCtxt;
 
 use syntax::ast::{self, MetaItem};
-use syntax_pos::{Span, DUMMY_SP};
-
-use rustc::hir;
-use rustc::hir::intravisit::{FnKind};
+use syntax_pos::DUMMY_SP;
 
 use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
 use rustc::session::Session;
@@ -32,7 +29,9 @@
 use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults};
 use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use self::dataflow::{DefinitelyInitializedLvals};
-use self::gather_moves::{MoveData, MovePathIndex, LookupResult};
+use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+
+use std::fmt;
 
 fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
     for attr in attrs {
@@ -55,44 +54,34 @@ pub struct MoveDataParamEnv<'tcx> {
 }
 
 pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
-                    fk: FnKind,
-                    _decl: &hir::FnDecl,
-                    body: &hir::Expr,
-                    _sp: Span,
                     id: ast::NodeId,
                     attributes: &[ast::Attribute]) {
-    match fk {
-        FnKind::ItemFn(name, ..) |
-        FnKind::Method(name, ..) => {
-            debug!("borrowck_mir({}) UNIMPLEMENTED", name);
-        }
-        FnKind::Closure(_) => {
-            debug!("borrowck_mir closure (body.id={}) UNIMPLEMENTED", body.id);
-        }
-    }
-
     let tcx = bcx.tcx;
-    let param_env = ty::ParameterEnvironment::for_item(tcx, id);
-
-    let mir = &tcx.item_mir(tcx.map.local_def_id(id));
+    let def_id = tcx.map.local_def_id(id);
+    debug!("borrowck_mir({}) UNIMPLEMENTED", tcx.item_path_str(def_id));
 
+    let mir = &tcx.item_mir(def_id);
+    let param_env = ty::ParameterEnvironment::for_item(tcx, id);
     let move_data = MoveData::gather_moves(mir, tcx, &param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
     let flow_inits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeInitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, MaybeInitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
     let flow_uninits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeUninitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
     let flow_def_inits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, DefinitelyInitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
 
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits);
     }
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_uninits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits);
     }
     if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_def_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits);
     }
 
     if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
@@ -103,7 +92,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
         bcx: bcx,
         mir: mir,
         node_id: id,
-        move_data: mdpe.move_data,
+        move_data: &mdpe.move_data,
         flow_inits: flow_inits,
         flow_uninits: flow_uninits,
     };
@@ -115,13 +104,15 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     debug!("borrowck_mir done");
 }
 
-fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             mir: &Mir<'tcx>,
-                             node_id: ast::NodeId,
-                             attributes: &[ast::Attribute],
-                             ctxt: &BD::Ctxt,
-                             bd: BD) -> DataflowResults<BD>
-    where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
+fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                mir: &Mir<'tcx>,
+                                node_id: ast::NodeId,
+                                attributes: &[ast::Attribute],
+                                bd: BD,
+                                p: P)
+                                -> DataflowResults<BD>
+    where BD: BitDenotation<Idx=MovePathIndex> + DataflowOperator,
+          P: Fn(&BD, BD::Idx) -> &fmt::Debug
 {
     let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
         if let Some(item) = has_rustc_mir_with(attrs, name) {
@@ -146,16 +137,15 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         node_id: node_id,
         print_preflow_to: print_preflow_to,
         print_postflow_to: print_postflow_to,
-        flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd),
+        flow_state: DataflowAnalysis::new(tcx, mir, bd),
     };
 
-    mbcx.dataflow(|ctxt, i| &ctxt.move_data.move_paths[i]);
+    mbcx.dataflow(p);
     mbcx.flow_state.results()
 }
 
 
-pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD>
-    where BD: BitDenotation, BD::Ctxt: 'a
+pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation
 {
     node_id: ast::NodeId,
     flow_state: DataflowAnalysis<'a, 'tcx, BD>,
@@ -168,7 +158,7 @@ pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> {
     bcx: &'b mut BorrowckCtxt<'a, 'tcx>,
     mir: &'b Mir<'tcx>,
     node_id: ast::NodeId,
-    move_data: MoveData<'tcx>,
+    move_data: &'b MoveData<'tcx>,
     flow_inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
     flow_uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>
 }
index ecf5c3ef176e566f59003cbf943eaa0cdd98cca5..1ba313015d59685c82af9830cd77a9923b20352d 100644 (file)
@@ -68,7 +68,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: ast::NodeId) {
+                b: hir::BodyId, s: Span, id: ast::NodeId) {
         match fk {
             FnKind::ItemFn(..) |
             FnKind::Method(..) => {
@@ -88,15 +88,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
     }
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
-            gather_loans::gather_loans_in_static_initializer(self, ti.id, &expr);
+        if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node {
+            gather_loans::gather_loans_in_static_initializer(self, ti.id, expr);
         }
         intravisit::walk_trait_item(self, ti);
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
-            gather_loans::gather_loans_in_static_initializer(self, ii.id, &expr);
+        if let hir::ImplItemKind::Const(_, expr) = ii.node {
+            gather_loans::gather_loans_in_static_initializer(self, ii.id, expr);
         }
         intravisit::walk_impl_item(self, ii);
     }
@@ -141,9 +141,9 @@ fn borrowck_item<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, item: &'tcx hir::I
     // loan step is intended for things that have a data
     // flow dependent conditions.
     match item.node {
-        hir::ItemStatic(.., ref ex) |
-        hir::ItemConst(_, ref ex) => {
-            gather_loans::gather_loans_in_static_initializer(this, item.id, &ex);
+        hir::ItemStatic(.., ex) |
+        hir::ItemConst(_, ex) => {
+            gather_loans::gather_loans_in_static_initializer(this, item.id, ex);
         }
         _ => { }
     }
@@ -161,25 +161,25 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
 fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                          fk: FnKind<'tcx>,
                          decl: &'tcx hir::FnDecl,
-                         body_id: hir::ExprId,
+                         body_id: hir::BodyId,
                          sp: Span,
                          id: ast::NodeId,
                          attributes: &[ast::Attribute]) {
     debug!("borrowck_fn(id={})", id);
 
-    let body = this.tcx.map.expr(body_id);
+    let body = this.tcx.map.body(body_id);
 
     if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) {
         this.with_temp_region_map(id, |this| {
-            mir::borrowck_mir(this, fk, decl, body, sp, id, attributes)
+            mir::borrowck_mir(this, id, attributes)
         });
     }
 
-    let cfg = cfg::CFG::new(this.tcx, body);
+    let cfg = cfg::CFG::new(this.tcx, &body.value);
     let AnalysisData { all_loans,
                        loans: loan_dfcx,
                        move_data: flowed_moves } =
-        build_borrowck_dataflow_data(this, fk, decl, &cfg, body, sp, id);
+        build_borrowck_dataflow_data(this, &cfg, body, id);
 
     move_data::fragments::instrument_move_fragments(&flowed_moves.move_data,
                                                     this.tcx,
@@ -194,31 +194,31 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                              &flowed_moves,
                              &all_loans[..],
                              id,
-                             decl,
                              body);
 
     intravisit::walk_fn(this, fk, decl, body_id, sp, id);
 }
 
 fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
-                                          fk: FnKind<'tcx>,
-                                          decl: &'tcx hir::FnDecl,
                                           cfg: &cfg::CFG,
-                                          body: &'tcx hir::Expr,
-                                          sp: Span,
+                                          body: &'tcx hir::Body,
                                           id: ast::NodeId)
                                           -> AnalysisData<'a, 'tcx>
 {
     // Check the body of fn items.
     let tcx = this.tcx;
-    let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id, &tcx.map);
+    let id_range = {
+        let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.map);
+        visitor.visit_body(body);
+        visitor.result()
+    };
     let (all_loans, move_data) =
-        gather_loans::gather_loans_in_fn(this, id, decl, body);
+        gather_loans::gather_loans_in_fn(this, id, body);
 
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
                              "borrowck",
-                             Some(decl),
+                             Some(body),
                              cfg,
                              LoanDataFlowOperator,
                              id_range,
@@ -235,7 +235,6 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                                                       this.tcx,
                                                       cfg,
                                                       id_range,
-                                                      decl,
                                                       body);
 
     AnalysisData { all_loans: all_loans,
@@ -263,14 +262,11 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
         }
     };
 
-    let body = tcx.map.expr(fn_parts.body);
+    let body = tcx.map.body(fn_parts.body);
 
     let dataflow_data = build_borrowck_dataflow_data(&mut bccx,
-                                                     fn_parts.kind,
-                                                     &fn_parts.decl,
                                                      cfg,
                                                      body,
-                                                     fn_parts.span,
                                                      fn_parts.id);
 
     (bccx, dataflow_data)
@@ -416,7 +412,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
     match tcx.map.get(closure_id) {
         hir_map::NodeExpr(expr) => match expr.node {
             hir::ExprClosure(.., body_id, _) => {
-                body_id.node_id()
+                body_id.node_id
             }
             _ => {
                 bug!("encountered non-closure id: {}", closure_id)
@@ -1121,22 +1117,21 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
                 if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat {
                     if let Categorization::Local(local_id) = inner_cmt.cat {
                         let parent = self.tcx.map.get_parent_node(local_id);
-                        let opt_fn_decl = FnLikeNode::from_node(self.tcx.map.get(parent))
-                            .map(|fn_like| fn_like.decl());
 
-                        if let Some(fn_decl) = opt_fn_decl {
-                            if let Some(ref arg) = fn_decl.inputs.iter()
-                                .find(|ref arg| arg.pat.id == local_id) {
+                        if let Some(fn_like) = FnLikeNode::from_node(self.tcx.map.get(parent)) {
+                            if let Some(i) = self.tcx.map.body(fn_like.body()).arguments.iter()
+                                                     .position(|arg| arg.pat.id == local_id) {
+                                let arg_ty = &fn_like.decl().inputs[i];
                                 if let hir::TyRptr(
                                     opt_lifetime,
                                     hir::MutTy{mutbl: hir::Mutability::MutImmutable, ref ty}) =
-                                    arg.ty.node {
+                                    arg_ty.node {
                                     if let Some(lifetime) = opt_lifetime {
                                         if let Ok(snippet) = self.tcx.sess.codemap()
                                             .span_to_snippet(ty.span) {
                                             if let Ok(lifetime_snippet) = self.tcx.sess.codemap()
                                                 .span_to_snippet(lifetime.span) {
-                                                    db.span_label(arg.ty.span,
+                                                    db.span_label(arg_ty.span,
                                                                   &format!("use `&{} mut {}` \
                                                                             here to make mutable",
                                                                             lifetime_snippet,
@@ -1145,9 +1140,9 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
                                         }
                                     }
                                     else if let Ok(snippet) = self.tcx.sess.codemap()
-                                        .span_to_snippet(arg.ty.span) {
+                                        .span_to_snippet(arg_ty.span) {
                                         if snippet.starts_with("&") {
-                                            db.span_label(arg.ty.span,
+                                            db.span_label(arg_ty.span,
                                                           &format!("use `{}` here to make mutable",
                                                                    snippet.replace("&", "&mut ")));
                                         }
index 32bda5e11620ac2429a3dd22be4257b4dc18adf4..a02aba7208c7fe4be3c6975eb1ac8d24a266e4d6 100644 (file)
@@ -655,13 +655,12 @@ pub fn new(move_data: MoveData<'tcx>,
                tcx: TyCtxt<'a, 'tcx, 'tcx>,
                cfg: &cfg::CFG,
                id_range: IdRange,
-               decl: &hir::FnDecl,
-               body: &hir::Expr)
+               body: &hir::Body)
                -> FlowedMoveData<'a, 'tcx> {
         let mut dfcx_moves =
             DataFlowContext::new(tcx,
                                  "flowed_move_data_moves",
-                                 Some(decl),
+                                 Some(body),
                                  cfg,
                                  MoveDataFlowOperator,
                                  id_range,
@@ -669,7 +668,7 @@ pub fn new(move_data: MoveData<'tcx>,
         let mut dfcx_assign =
             DataFlowContext::new(tcx,
                                  "flowed_move_data_assigns",
-                                 Some(decl),
+                                 Some(body),
                                  cfg,
                                  AssignDataFlowOperator,
                                  id_range,
index 786b59e818da2052de8fc7f4e7e3c65523698cfe..01b19e1f53979d8dd563a9ed60873b47983fe98b 100644 (file)
@@ -30,7 +30,6 @@
 
 use rustc::hir::def::*;
 use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
-use rustc::hir::print::pat_to_string;
 use rustc::hir::{self, Pat, PatKind};
 
 use rustc_back::slice;
@@ -43,39 +42,17 @@ struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
 
 impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_expr(&mut self, _expr: &'tcx hir::Expr) {
-        return // const, static and N in [T; N] - shouldn't contain anything
-    }
-
-    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(..) = item.node {
-            return // nothing worth match checking in a constant
-        } else {
-            intravisit::walk_trait_item(self, item);
-        }
-    }
-
-    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(..) = item.node {
-            return // nothing worth match checking in a constant
-        } else {
-            intravisit::walk_impl_item(self, item);
-        }
+        NestedVisitorMap::OnlyBodies(&self.tcx.map)
     }
 
     fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, id: ast::NodeId) {
-        if let FnKind::Closure(..) = fk {
-            span_bug!(s, "check_match: closure outside of function")
-        }
+                b: hir::BodyId, s: Span, id: ast::NodeId) {
+        intravisit::walk_fn(self, fk, fd, b, s, id);
 
         MatchVisitor {
             tcx: self.tcx,
             param_env: &ty::ParameterEnvironment::for_item(self.tcx, id)
-        }.visit_fn(fk, fd, b, s, id);
+        }.visit_body(self.tcx.map.body(b));
     }
 }
 
@@ -96,7 +73,7 @@ struct MatchVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
@@ -119,13 +96,12 @@ fn visit_local(&mut self, loc: &'tcx hir::Local) {
         self.check_patterns(false, slice::ref_slice(&loc.pat));
     }
 
-    fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
-                b: hir::ExprId, s: Span, n: ast::NodeId) {
-        intravisit::walk_fn(self, fk, fd, b, s, n);
+    fn visit_body(&mut self, body: &'tcx hir::Body) {
+        intravisit::walk_body(self, body);
 
-        for input in &fd.inputs {
-            self.check_irrefutable(&input.pat, true);
-            self.check_patterns(false, slice::ref_slice(&input.pat));
+        for arg in &body.arguments {
+            self.check_irrefutable(&arg.pat, true);
+            self.check_patterns(false, slice::ref_slice(&arg.pat));
         }
     }
 }
@@ -254,7 +230,9 @@ fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) {
                 Useful => bug!()
             };
 
-            let pattern_string = pat_to_string(witness[0].single_pattern());
+            let pattern_string = hir::print::to_string(&self.tcx.map, |s| {
+                s.print_pat(witness[0].single_pattern())
+            });
             let mut diag = struct_span_err!(
                 self.tcx.sess, pat.span, E0005,
                 "refutable pattern in {}: `{}` not covered",
@@ -405,7 +383,9 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                         },
                         _ => bug!(),
                     };
-                    let pattern_string = pat_to_string(witness);
+                    let pattern_string = hir::print::to_string(&cx.tcx.map, |s| {
+                        s.print_pat(witness)
+                    });
                     struct_span_err!(cx.tcx.sess, sp, E0297,
                         "refutable pattern in `for` loop binding: \
                                 `{}` not covered",
@@ -415,7 +395,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 },
                 _ => {
                     let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
-                        pat_to_string(w)
+                        hir::print::to_string(&cx.tcx.map, |s| s.print_pat(w))
                     }).collect();
                     const LIMIT: usize = 3;
                     let joined_patterns = match pattern_strings.len() {
index 83b0d9dec6d904c087a7f16ec18404a6006b267d..b24cd261dd58474730ee98fc242ef15f222e803f 100644 (file)
@@ -576,18 +576,18 @@ enum Enum {
 
 
 E0306: r##"
-In an array literal `[x; N]`, `N` is the number of elements in the array. This
+In an array type `[T; N]`, `N` is the number of elements in the array. This
 must be an unsigned integer. Erroneous code example:
 
 ```compile_fail,E0306
-let x = [0i32; true]; // error: expected positive integer for repeat count,
-                      //        found boolean
+const X: [i32; true] = [0]; // error: expected `usize` for array length,
+                            //        found boolean
 ```
 
 Working example:
 
 ```
-let x = [0i32; 2];
+const X: [i32; 1] = [0];
 ```
 "##,
 }
index 9fcab1239899fed2b44055026b324cb5f3ee3c80..e8e7a2eb7ede0919fb3c167aa0416312ee0350e5 100644 (file)
@@ -17,7 +17,6 @@
 
 use rustc::hir::map as ast_map;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::middle::cstore::InlinedItem;
 use rustc::traits;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
@@ -56,15 +55,17 @@ macro_rules! math {
 fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   variant_def: DefId)
                                   -> Option<&'tcx Expr> {
-    fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId)
-                        -> Option<&'a Expr> {
+    let variant_expr = |variants: &'tcx [hir::Variant], id: ast::NodeId |
+                        -> Option<&'tcx Expr> {
         for variant in variants {
             if variant.node.data.id() == id {
-                return variant.node.disr_expr.as_ref().map(|e| &**e);
+                return variant.node.disr_expr.map(|e| {
+                    &tcx.map.body(e).value
+                });
             }
         }
         None
-    }
+    };
 
     if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) {
         let enum_node_id = tcx.map.get_parent(variant_node_id);
@@ -96,21 +97,24 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         match tcx.map.find(node_id) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
-                hir::ItemConst(ref ty, ref const_expr) => {
-                    Some((&const_expr, tcx.ast_ty_to_prim_ty(ty)))
+                hir::ItemConst(ref ty, body) => {
+                    Some((&tcx.map.body(body).value,
+                          tcx.ast_ty_to_prim_ty(ty)))
                 }
                 _ => None
             },
             Some(ast_map::NodeTraitItem(ti)) => match ti.node {
-                hir::ConstTraitItem(ref ty, ref expr_option) => {
+                hir::TraitItemKind::Const(ref ty, default) => {
                     if let Some(substs) = substs {
                         // If we have a trait item and the substitutions for it,
                         // `resolve_trait_associated_const` will select an impl
                         // or the default.
                         let trait_id = tcx.map.get_parent(node_id);
                         let trait_id = tcx.map.local_def_id(trait_id);
-                        let default_value = expr_option.as_ref()
-                            .map(|expr| (&**expr, tcx.ast_ty_to_prim_ty(ty)));
+                        let default_value = default.map(|body| {
+                            (&tcx.map.body(body).value,
+                             tcx.ast_ty_to_prim_ty(ty))
+                        });
                         resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs)
                     } else {
                         // Technically, without knowing anything about the
@@ -125,29 +129,19 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => None
             },
             Some(ast_map::NodeImplItem(ii)) => match ii.node {
-                hir::ImplItemKind::Const(ref ty, ref expr) => {
-                    Some((&expr, tcx.ast_ty_to_prim_ty(ty)))
+                hir::ImplItemKind::Const(ref ty, body) => {
+                    Some((&tcx.map.body(body).value,
+                          tcx.ast_ty_to_prim_ty(ty)))
                 }
                 _ => None
             },
             Some(_) => None
         }
     } else {
-        match tcx.extern_const_statics.borrow().get(&def_id) {
-            Some(&None) => return None,
-            Some(&Some((expr_id, ty))) => {
-                return Some((tcx.map.expect_expr(expr_id), ty));
-            }
-            None => {}
-        }
-        let mut used_substs = false;
-        let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-            Some((&InlinedItem { body: ref const_expr, .. }, _)) => {
-                Some((&**const_expr, Some(tcx.sess.cstore.item_type(tcx, def_id))))
-            }
-            _ => None
-        };
-        let expr_ty = match tcx.sess.cstore.describe_def(def_id) {
+        let expr_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
+            (&body.value, Some(tcx.sess.cstore.item_type(tcx, def_id)))
+        });
+        match tcx.sess.cstore.describe_def(def_id) {
             Some(Def::AssociatedConst(_)) => {
                 let trait_id = tcx.sess.cstore.trait_of_item(def_id);
                 // As mentioned in the comments above for in-crate
@@ -155,8 +149,6 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // trait-associated const if the caller gives us the
                 // substitutions for the reference to it.
                 if let Some(trait_id) = trait_id {
-                    used_substs = true;
-
                     if let Some(substs) = substs {
                         resolve_trait_associated_const(tcx, def_id, expr_ty, trait_id, substs)
                     } else {
@@ -168,70 +160,27 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             },
             Some(Def::Const(..)) => expr_ty,
             _ => None
-        };
-        // If we used the substitutions, particularly to choose an impl
-        // of a trait-associated const, don't cache that, because the next
-        // lookup with the same def_id may yield a different result.
-        if !used_substs {
-            tcx.extern_const_statics
-               .borrow_mut()
-               .insert(def_id, expr_ty.map(|(e, t)| (e.id, t)));
         }
-        expr_ty
     }
 }
 
-fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                 def_id: DefId)
-                                                 -> Option<ast::NodeId> {
-    match tcx.extern_const_fns.borrow().get(&def_id) {
-        Some(&ast::DUMMY_NODE_ID) => return None,
-        Some(&fn_id) => return Some(fn_id),
-        None => {}
-    }
-
-    if !tcx.sess.cstore.is_const_fn(def_id) {
-        tcx.extern_const_fns.borrow_mut().insert(def_id, ast::DUMMY_NODE_ID);
-        return None;
-    }
-
-    let fn_id = tcx.sess.cstore.maybe_get_item_ast(tcx, def_id).map(|t| t.1);
-    tcx.extern_const_fns.borrow_mut().insert(def_id,
-                                             fn_id.unwrap_or(ast::DUMMY_NODE_ID));
-    fn_id
-}
-
-pub enum ConstFnNode<'tcx> {
-    Local(FnLikeNode<'tcx>),
-    Inlined(&'tcx InlinedItem)
-}
-
-pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                                       -> Option<ConstFnNode<'tcx>>
+fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+                                   -> Option<&'tcx hir::Body>
 {
-    let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
-        node_id
-    } else {
-        if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) {
-            if let ast_map::NodeInlinedItem(ii) = tcx.map.get(fn_id) {
-                return Some(ConstFnNode::Inlined(ii));
+    if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
+        FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| {
+            if fn_like.constness() == hir::Constness::Const {
+                Some(tcx.map.body(fn_like.body()))
             } else {
-                bug!("Got const fn from external crate, but it's not inlined")
+                None
             }
+        })
+    } else {
+        if tcx.sess.cstore.is_const_fn(def_id) {
+            tcx.sess.cstore.maybe_get_item_body(tcx, def_id)
         } else {
-            return None;
+            None
         }
-    };
-
-    let fn_like = match FnLikeNode::from_node(tcx.map.get(fn_id)) {
-        Some(fn_like) => fn_like,
-        None => return None
-    };
-
-    if fn_like.constness() == hir::Constness::Const {
-        Some(ConstFnNode::Local(fn_like))
-    } else {
-        None
     }
 }
 
@@ -864,18 +813,15 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
               Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
               callee => signal!(e, CallOn(callee)),
           };
-          let (arg_defs, body_id) = match lookup_const_fn_by_id(tcx, did) {
-              Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), ii.body.expr_id()),
-              Some(ConstFnNode::Local(fn_like)) =>
-                  (fn_like.decl().inputs.iter()
-                   .map(|arg| match arg.pat.node {
-                       hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
-                       _ => None
-                   }).collect(),
-                   fn_like.body()),
+          let body = match lookup_const_fn_by_id(tcx, did) {
+              Some(body) => body,
               None => signal!(e, NonConstPath),
           };
-          let result = tcx.map.expr(body_id);
+
+          let arg_defs = body.arguments.iter().map(|arg| match arg.pat.node {
+               hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
+               _ => None
+           }).collect::<Vec<_>>();
           assert_eq!(arg_defs.len(), args.len());
 
           let mut call_args = DefIdMap();
@@ -893,7 +839,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
               }
           }
           debug!("const call({:?})", call_args);
-          eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))?
+          eval_const_expr_partial(tcx, &body.value, ty_hint, Some(&call_args))?
       },
       hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) {
           Ok(val) => val,
@@ -953,11 +899,12 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
       }
       hir::ExprArray(ref v) => Array(e.id, v.len() as u64),
-      hir::ExprRepeat(_, ref n) => {
+      hir::ExprRepeat(_, n) => {
           let len_hint = ty_hint.checked_or(tcx.types.usize);
+          let n = &tcx.map.body(n).value;
           Repeat(
               e.id,
-              match eval_const_expr_partial(tcx, &n, len_hint, fn_args)? {
+              match eval_const_expr_partial(tcx, n, len_hint, fn_args)? {
                   Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
                   Integral(_) => signal!(e, RepeatCountNotNatural),
                   _ => signal!(e, RepeatCountNotInt),
@@ -1373,7 +1320,8 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
                 if let Def::Local(..) = path.def {
-                    diag.note(&format!("`{}` is a variable", path));
+                    diag.note(&format!("`{}` is a variable",
+                                       tcx.map.node_to_pretty_string(count_expr.id)));
                 }
             }
 
index 4db620b2bec3b1ec507be9519bcf13e70ae1a09f..6a884bafce752dcc0060cfc68247830c2800459c 100644 (file)
@@ -35,6 +35,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 8da9a23f4faad2d5b949592641fafe752a91b279..291f0e0d50d8fa4ea83421224d030e2ff741ad36 100644 (file)
@@ -1182,9 +1182,6 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
                          Some(ref n) if *n == "rlib" => {
                              Some(config::CrateTypeRlib)
                          }
-                         Some(ref n) if *n == "metadata" => {
-                             Some(config::CrateTypeMetadata)
-                         }
                          Some(ref n) if *n == "dylib" => {
                              Some(config::CrateTypeDylib)
                          }
index f84622c2f028553a547113d7f0b2ef6a40c499b0..5ceec9edda3d07a5aaef494ac70e3b864b7018e1 100644 (file)
@@ -493,7 +493,8 @@ fn build_controller(&mut self,
             control.after_hir_lowering.stop = Compilation::Stop;
         }
 
-        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) {
+        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
+                                                   i == OutputType::Metadata) {
             control.after_llvm.stop = Compilation::Stop;
         }
 
index 74df1e52bde43143a7dab39a42aee28611022fc9..5103a55fd71e1bd673df5b4e5b3533bbd89db23e 100644 (file)
@@ -47,7 +47,7 @@
 use std::str::FromStr;
 
 use rustc::hir::map as hir_map;
-use rustc::hir::map::{blocks, NodePrinter};
+use rustc::hir::map::blocks;
 use rustc::hir;
 use rustc::hir::print as pprust_hir;
 
@@ -320,7 +320,16 @@ fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
 }
 
 impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
-impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {}
+impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {
+    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
+              -> io::Result<()> {
+        if let Some(ref map) = self.ast_map {
+            pprust_hir::PpAnn::nested(map, state, nested)
+        } else {
+            Ok(())
+        }
+    }
+}
 
 struct IdentifiedAnnotation<'ast> {
     sess: &'ast Session,
@@ -393,6 +402,14 @@ fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn {
 }
 
 impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
+    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
+              -> io::Result<()> {
+        if let Some(ref map) = self.ast_map {
+            pprust_hir::PpAnn::nested(map, state, nested)
+        } else {
+            Ok(())
+        }
+    }
     fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
             pprust_hir::NodeExpr(_) => s.popen(),
@@ -488,6 +505,10 @@ fn node_path(&self, id: ast::NodeId) -> Option<String> {
 }
 
 impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
+    fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
+              -> io::Result<()> {
+        pprust_hir::PpAnn::nested(&self.tcx.map, state, nested)
+    }
     fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
             pprust_hir::NodeExpr(_) => s.popen(),
@@ -702,8 +723,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
     let cfg = match code {
         blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr),
         blocks::Code::FnLike(fn_like) => {
-            let body = tcx.map.expr(fn_like.body());
-            cfg::CFG::new(tcx, body)
+            let body = tcx.map.body(fn_like.body());
+            cfg::CFG::new(tcx, &body.value)
         },
     };
     let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
@@ -909,11 +930,10 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                                          &mut rdr,
                                                                          box out,
                                                                          annotation.pp_ann(),
-                                                                         true,
-                                                                         Some(ast_map.krate()));
+                                                                         true);
                     for node_id in uii.all_matching_node_ids(ast_map) {
                         let node = ast_map.get(node_id);
-                        pp_state.print_node(&node)?;
+                        pp_state.print_node(node)?;
                         pp::space(&mut pp_state.s)?;
                         let path = annotation.node_path(node_id)
                             .expect("--unpretty missing node paths");
index 87e6b2befdc3281fcbbb9359c11bf499d4eaccfd..b5fe158f158cac7aead2d5fe5d8144a75243b3fa 100644 (file)
@@ -171,6 +171,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.process_attrs(item.id, &item.attrs);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.process_attrs(trait_item.id, &trait_item.attrs);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.process_attrs(impl_item.id, &impl_item.attrs);
     }
index eb31be4a8ade289d58edc0c3c1eff942cee0fb74..49609fbc7984f937c84ea3ab51b227db64a7f45f 100644 (file)
@@ -234,13 +234,13 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         visit::walk_item(self, item);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.calculate_node_id(trait_item.id, |v| v.visit_trait_item(trait_item));
+        visit::walk_trait_item(self, trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.calculate_node_id(impl_item.id, |v| v.visit_impl_item(impl_item));
         visit::walk_impl_item(self, impl_item);
     }
-
-    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
-        self.calculate_node_id(item.id, |v| v.visit_foreign_item(item));
-        visit::walk_foreign_item(self, item);
-    }
 }
index ccae5f3b003662a08cca8ac62fe3173bef9259c4..4bb12667bbc147f861ed2583909c9758c89fcef0 100644 (file)
@@ -180,14 +180,15 @@ enum SawAbiComponent<'a> {
     SawLifetimeDef(usize),
 
     SawMod,
-    SawForeignItem,
+    SawForeignItem(SawForeignItemComponent),
     SawItem(SawItemComponent),
     SawTy(SawTyComponent),
+    SawFnDecl(bool),
     SawGenerics,
     SawTraitItem(SawTraitOrImplItemComponent),
     SawImplItem(SawTraitOrImplItemComponent),
     SawStructField,
-    SawVariant,
+    SawVariant(bool),
     SawQPath,
     SawPathSegment,
     SawPathParameters,
@@ -363,7 +364,7 @@ enum SawItemComponent {
     SawItemConst,
     SawItemFn(Unsafety, Constness, Abi),
     SawItemMod,
-    SawItemForeignMod,
+    SawItemForeignMod(Abi),
     SawItemTy,
     SawItemEnum,
     SawItemStruct,
@@ -381,7 +382,7 @@ fn saw_item(node: &Item_) -> SawItemComponent {
         ItemConst(..) =>SawItemConst,
         ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi),
         ItemMod(..) => SawItemMod,
-        ItemForeignMod(..) => SawItemForeignMod,
+        ItemForeignMod(ref fm) => SawItemForeignMod(fm.abi),
         ItemTy(..) => SawItemTy,
         ItemEnum(..) => SawItemEnum,
         ItemStruct(..) => SawItemStruct,
@@ -392,6 +393,12 @@ fn saw_item(node: &Item_) -> SawItemComponent {
     }
 }
 
+#[derive(Hash)]
+enum SawForeignItemComponent {
+    Static { mutable: bool },
+    Fn,
+}
+
 #[derive(Hash)]
 enum SawPatComponent {
     SawPatWild,
@@ -466,12 +473,14 @@ enum SawTraitOrImplItemComponent {
     SawTraitOrImplItemType
 }
 
-fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent {
+fn saw_trait_item(ti: &TraitItemKind) -> SawTraitOrImplItemComponent {
     match *ti {
-        ConstTraitItem(..) => SawTraitOrImplItemConst,
-        MethodTraitItem(ref sig, ref body) =>
-            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()),
-        TypeTraitItem(..) => SawTraitOrImplItemType
+        TraitItemKind::Const(..) => SawTraitOrImplItemConst,
+        TraitItemKind::Method(ref sig, TraitMethod::Required(_)) =>
+            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, false),
+        TraitItemKind::Method(ref sig, TraitMethod::Provided(_)) =>
+            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
+        TraitItemKind::Type(..) => SawTraitOrImplItemType
     }
 }
 
@@ -577,7 +586,7 @@ fn visit_variant(&mut self,
                      g: &'tcx Generics,
                      item_id: NodeId) {
         debug!("visit_variant: st={:?}", self.st);
-        SawVariant.hash(self.st);
+        SawVariant(v.node.disr_expr.is_some()).hash(self.st);
         hash_attrs!(self, &v.node.attrs);
         visit::walk_variant(self, v, g, item_id)
     }
@@ -609,7 +618,12 @@ fn visit_expr(&mut self, ex: &'tcx Expr) {
         // implicitly hashing the discriminant of SawExprComponent.
         hash_span!(self, ex.span, force_span);
         hash_attrs!(self, &ex.attrs);
-        visit::walk_expr(self, ex)
+
+        // Always hash nested constant bodies (e.g. n in `[x; n]`).
+        let hash_bodies = self.hash_bodies;
+        self.hash_bodies = true;
+        visit::walk_expr(self, ex);
+        self.hash_bodies = hash_bodies;
     }
 
     fn visit_stmt(&mut self, s: &'tcx Stmt) {
@@ -641,7 +655,17 @@ fn visit_stmt(&mut self, s: &'tcx Stmt) {
     fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
         debug!("visit_foreign_item: st={:?}", self.st);
 
-        SawForeignItem.hash(self.st);
+        match i.node {
+            ForeignItemFn(..) => {
+                SawForeignItem(SawForeignItemComponent::Fn)
+            }
+            ForeignItemStatic(_, mutable) => {
+                SawForeignItem(SawForeignItemComponent::Static {
+                    mutable: mutable
+                })
+            }
+        }.hash(self.st);
+
         hash_span!(self, i.span);
         hash_attrs!(self, &i.attrs);
         visit::walk_foreign_item(self, i)
@@ -669,7 +693,12 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         debug!("visit_ty: st={:?}", self.st);
         SawTy(saw_ty(&t.node)).hash(self.st);
         hash_span!(self, t.span);
-        visit::walk_ty(self, t)
+
+        // Always hash nested constant bodies (e.g. N in `[T; N]`).
+        let hash_bodies = self.hash_bodies;
+        self.hash_bodies = true;
+        visit::walk_ty(self, t);
+        self.hash_bodies = hash_bodies;
     }
 
     fn visit_generics(&mut self, g: &'tcx Generics) {
@@ -678,6 +707,12 @@ fn visit_generics(&mut self, g: &'tcx Generics) {
         visit::walk_generics(self, g)
     }
 
+    fn visit_fn_decl(&mut self, fd: &'tcx FnDecl) {
+        debug!("visit_fn_decl: st={:?}", self.st);
+        SawFnDecl(fd.variadic).hash(self.st);
+        visit::walk_fn_decl(self, fd)
+    }
+
     fn visit_trait_item(&mut self, ti: &'tcx TraitItem) {
         debug!("visit_trait_item: st={:?}", self.st);
 
@@ -1134,8 +1169,9 @@ pub fn hash_crate_root_module(&mut self, krate: &'tcx Crate) {
             // These fields are handled separately:
             exported_macros: _,
             items: _,
+            trait_items: _,
             impl_items: _,
-            exprs: _,
+            bodies: _,
         } = *krate;
 
         visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID);
index 40873011a7b8d7fc73aaa76fa17fc9c75b91a8ac..481462dff86e479289e36f363defdd3598877cd2 100644 (file)
@@ -185,6 +185,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
@@ -229,6 +232,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 1d384741d9660b974ed3e53643229dbdc3581a18..2baef47c214c28ae54b17906a0be338afc8e2253 100644 (file)
@@ -243,7 +243,7 @@ fn check_fn(&mut self,
                 cx: &LateContext,
                 fk: FnKind,
                 _: &hir::FnDecl,
-                _: &hir::Expr,
+                _: &hir::Body,
                 span: Span,
                 id: ast::NodeId) {
         match fk {
@@ -271,12 +271,15 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
-        if let hir::MethodTraitItem(_, None) = trait_item.node {
+    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref names)) = item.node {
             self.check_snake_case(cx,
                                   "trait method",
-                                  &trait_item.name.as_str(),
-                                  Some(trait_item.span));
+                                  &item.name.as_str(),
+                                  Some(item.span));
+            for name in names {
+                self.check_snake_case(cx, "variable", &name.node.as_str(), Some(name.span));
+            }
         }
     }
 
@@ -288,14 +291,6 @@ fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
     }
 
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
-        // Exclude parameter names from foreign functions
-        let parent_node = cx.tcx.map.get_parent_node(p.id);
-        if let hir::map::NodeForeignItem(item) = cx.tcx.map.get(parent_node) {
-            if let hir::ForeignItemFn(..) = item.node {
-                return;
-            }
-        }
-
         if let &PatKind::Binding(_, _, ref path1, _) = &p.node {
             self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));
         }
@@ -363,7 +358,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 
     fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
         match ti.node {
-            hir::ConstTraitItem(..) => {
+            hir::TraitItemKind::Const(..) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ti.name, ti.span);
             }
             _ => {}
index cd414846af4fb610f0f9dc56157218542daed3d6..c021ffee81899002c9c6a4273fdec2c97df20d34 100644 (file)
@@ -222,7 +222,7 @@ fn check_fn(&mut self,
                 cx: &LateContext,
                 fk: FnKind<'tcx>,
                 _: &hir::FnDecl,
-                _: &hir::Expr,
+                _: &hir::Body,
                 span: Span,
                 _: ast::NodeId) {
         match fk {
@@ -240,11 +240,11 @@ fn check_fn(&mut self,
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
-        if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
+    fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node {
             if sig.unsafety == hir::Unsafety::Unsafe {
                 cx.span_lint(UNSAFE_CODE,
-                             trait_item.span,
+                             item.span,
                              "declaration of an `unsafe` method")
             }
         }
@@ -374,12 +374,12 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             hir::ItemEnum(..) => "an enum",
             hir::ItemStruct(..) => "a struct",
             hir::ItemUnion(..) => "a union",
-            hir::ItemTrait(.., ref items) => {
+            hir::ItemTrait(.., ref trait_item_refs) => {
                 // Issue #11592, traits are always considered exported, even when private.
                 if it.vis == hir::Visibility::Inherited {
                     self.private_traits.insert(it.id);
-                    for itm in items {
-                        self.private_traits.insert(itm.id);
+                    for trait_item_ref in trait_item_refs {
+                        self.private_traits.insert(trait_item_ref.id.node_id);
                     }
                     return;
                 }
@@ -418,9 +418,9 @@ fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
         }
 
         let desc = match trait_item.node {
-            hir::ConstTraitItem(..) => "an associated constant",
-            hir::MethodTraitItem(..) => "a trait method",
-            hir::TypeTraitItem(..) => "an associated type",
+            hir::TraitItemKind::Const(..) => "an associated constant",
+            hir::TraitItemKind::Method(..) => "a trait method",
+            hir::TraitItemKind::Type(..) => "an associated type",
         };
 
         self.check_missing_docs_attrs(cx,
@@ -674,7 +674,7 @@ fn check_fn(&mut self,
                 cx: &LateContext,
                 fn_kind: FnKind,
                 _: &hir::FnDecl,
-                blk: &hir::Expr,
+                body: &hir::Body,
                 sp: Span,
                 id: ast::NodeId) {
         let method = match fn_kind {
@@ -712,7 +712,7 @@ fn check_fn(&mut self,
         // to have behaviour like the above, rather than
         // e.g. accidentally recurring after an assert.
 
-        let cfg = cfg::CFG::new(cx.tcx, blk);
+        let cfg = cfg::CFG::new(cx.tcx, &body.value);
 
         let mut work_queue = vec![cfg.entry];
         let mut reached_exit_without_self_call = false;
index 751c9c3440f66326a06454204416c9cf237f388f..a3aa4af493aaf72bb1ffa2fc613980f2490f5d70 100644 (file)
@@ -679,7 +679,7 @@ fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
-            self.check_type_for_ffi_and_report_errors(input_hir.ty.span, input_ty);
+            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
         }
 
         if let hir::Return(ref ret_hir) = decl.output {
@@ -713,7 +713,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic {
                 for ni in &nmod.items {
                     match ni.node {
-                        hir::ForeignItemFn(ref decl, _) => {
+                        hir::ForeignItemFn(ref decl, _, _) => {
                             vis.check_foreign_fn(ni.id, decl);
                         }
                         hir::ForeignItemStatic(ref ty, _) => {
index 429bfb8e3d60667bc683ee829c17d5ce76fb7b59..b7ee688117d93a07149632464d4eafcb6d1d2e9d 100644 (file)
@@ -97,11 +97,11 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
     fn check_fn(&mut self,
                 cx: &LateContext,
                 _: FnKind,
-                decl: &hir::FnDecl,
-                _: &hir::Expr,
+                _: &hir::FnDecl,
+                body: &hir::Body,
                 _: Span,
                 _: ast::NodeId) {
-        for a in &decl.inputs {
+        for a in &body.arguments {
             self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
         }
     }
index 334a1dbdec160b10125d1e3fcef084240825798d..c1705815165939b505ed948ab23434f655a145bd 100644 (file)
@@ -473,9 +473,7 @@ pub enum DIBuilder_opaque {}
 // generates an llvmdeps.rs file next to this one which will be
 // automatically updated whenever LLVM is updated to include an up-to-date
 // set of the libraries we need to link to LLVM for.
-#[cfg_attr(not(all(stage0,cargobuild)),
-           link(name = "rustllvm", kind = "static"))] // not quite true but good enough
-#[cfg_attr(stage0, linked_from = "rustllvm")]
+#[link(name = "rustllvm", kind = "static")] // not quite true but good enough
 extern "C" {
     // Create and destroy contexts.
     pub fn LLVMContextCreate() -> ContextRef;
index 679e9c17a8b924ee16fef09a6b2743d583d1ac9a..1e45ea083c9e011046d33475e8e0df4852d48161 100644 (file)
@@ -27,9 +27,8 @@
 #![feature(concat_idents)]
 #![feature(libc)]
 #![feature(link_args)]
-#![cfg_attr(stage0, feature(linked_from))]
 #![feature(staged_api)]
-#![cfg_attr(not(stage0), feature(rustc_private))]
+#![feature(rustc_private)]
 
 extern crate libc;
 #[macro_use]
index 926c44824ce482393083697b4569d9a8dbbeee16..b27b164bd47aaffec7910ac2f3ca775b22f0f119 100644 (file)
@@ -16,8 +16,7 @@
 use encoder::EncodeContext;
 use schema::*;
 
-use rustc::middle::cstore::{InlinedItem, InlinedItemRef};
-use rustc::middle::const_qualif::ConstQualif;
+use rustc::hir;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TyCtxt, Ty};
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
     id_range: IdRange,
-    item: Lazy<InlinedItem>,
+    body: Lazy<hir::Body>,
     side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>,
+    pub nested_bodies: LazySeq<hir::Body>,
+    pub rvalue_promotable_to_static: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -39,16 +40,17 @@ enum TableEntry<'tcx> {
     NodeType(Ty<'tcx>),
     ItemSubsts(ty::ItemSubsts<'tcx>),
     Adjustment(ty::adjustment::Adjustment<'tcx>),
-    ConstQualif(ConstQualif),
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    pub fn encode_inlined_item(&mut self, ii: InlinedItemRef<'tcx>) -> Lazy<Ast<'tcx>> {
+    pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy<Ast<'tcx>> {
+        let body = self.tcx.map.body(body);
+
         let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map);
-        ii.visit(&mut id_visitor);
+        id_visitor.visit_body(body);
 
-        let ii_pos = self.position();
-        ii.encode(self).unwrap();
+        let body_pos = self.position();
+        body.encode(self).unwrap();
 
         let tables_pos = self.position();
         let tables_count = {
@@ -56,14 +58,29 @@ pub fn encode_inlined_item(&mut self, ii: InlinedItemRef<'tcx>) -> Lazy<Ast<'tcx
                 ecx: self,
                 count: 0,
             };
-            ii.visit(&mut visitor);
+            visitor.visit_body(body);
             visitor.count
         };
 
+        let nested_pos = self.position();
+        let nested_count = {
+            let mut visitor = NestedBodyEncodingVisitor {
+                ecx: self,
+                count: 0,
+            };
+            visitor.visit_body(body);
+            visitor.count
+        };
+
+        let rvalue_promotable_to_static =
+            self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
+
         self.lazy(&Ast {
             id_range: id_visitor.result(),
-            item: Lazy::with_position(ii_pos),
+            body: Lazy::with_position(body_pos),
             side_tables: LazySeq::with_position_and_length(tables_pos, tables_count),
+            nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
+            rvalue_promotable_to_static: rvalue_promotable_to_static
         })
     }
 }
@@ -94,18 +111,36 @@ fn visit_id(&mut self, id: ast::NodeId) {
         encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType));
         encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts));
         encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment));
-        encode(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif));
     }
 }
 
-/// Decodes an item from its AST in the cdata's metadata and adds it to the
+struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
+    ecx: &'a mut EncodeContext<'b, 'tcx>,
+    count: usize,
+}
+
+impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, '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.map.body(body);
+        body.encode(self.ecx).unwrap();
+        self.count += 1;
+
+        self.visit_body(body);
+    }
+}
+
+/// Decodes an item's body from its AST in the cdata's metadata and adds it to the
 /// ast-map.
-pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
-                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     ast: Ast<'tcx>,
-                                     orig_did: DefId)
-                                     -> &'tcx InlinedItem {
-    debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did));
+pub fn decode_body<'a, 'tcx>(cdata: &CrateMetadata,
+                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             def_id: DefId,
+                             ast: Ast<'tcx>)
+                             -> &'tcx hir::Body {
+    debug!("> Decoding inlined fn: {}", tcx.item_path_str(def_id));
 
     let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize();
     let start = tcx.sess.reserve_node_ids(cnt);
@@ -115,12 +150,6 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
                          max: ast::NodeId::new(start.as_usize() + cnt),
                      }];
 
-    let ii = ast.item.decode((cdata, tcx, id_ranges));
-    let item_node_id = tcx.sess.next_node_id();
-    let ii = ast_map::map_decoded_item(&tcx.map,
-                                       ii,
-                                       item_node_id);
-
     for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) {
         match entry {
             TableEntry::TypeRelativeDef(def) => {
@@ -135,11 +164,9 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
             TableEntry::Adjustment(adj) => {
                 tcx.tables.borrow_mut().adjustments.insert(id, adj);
             }
-            TableEntry::ConstQualif(qualif) => {
-                tcx.const_qualif_map.borrow_mut().insert(id, qualif);
-            }
         }
     }
 
-    ii
+    let body = ast.body.decode((cdata, tcx, id_ranges));
+    ast_map::map_decoded_body(&tcx.map, def_id, body, tcx.sess.next_node_id())
 }
index a9af4118c5957f7266fe05bfdf6252fe58192696..724c164b3b41af747310df2a02c2917b6fb30310 100644 (file)
@@ -799,8 +799,7 @@ fn inject_allocator_crate(&mut self) {
                 config::CrateTypeProcMacro |
                 config::CrateTypeCdylib |
                 config::CrateTypeStaticlib => need_lib_alloc = true,
-                config::CrateTypeRlib |
-                config::CrateTypeMetadata => {}
+                config::CrateTypeRlib => {}
             }
         }
         if !need_lib_alloc && !need_exe_alloc { return }
index 7ec847d24cfa3fc73823ce1a427550454ef172ba..aab4034b7705aee99a5747a42d74bcc44a8e4e15 100644 (file)
@@ -88,13 +88,6 @@ pub struct CrateMetadata {
     pub dllimport_foreign_items: FxHashSet<DefIndex>,
 }
 
-pub struct CachedInlinedItem {
-    /// The NodeId of the RootInlinedParent HIR map entry
-    pub inlined_root: ast::NodeId,
-    /// The local NodeId of the inlined entity
-    pub item_id: ast::NodeId,
-}
-
 pub struct CStore {
     pub dep_graph: DepGraph,
     metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
@@ -104,8 +97,7 @@ pub struct CStore {
     used_link_args: RefCell<Vec<String>>,
     statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
-    pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
-    pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
+    pub inlined_item_cache: RefCell<DefIdMap<Option<ast::NodeId>>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
 }
 
@@ -121,7 +113,6 @@ pub fn new(dep_graph: &DepGraph) -> CStore {
             dllimport_foreign_items: RefCell::new(FxHashSet()),
             visible_parent_map: RefCell::new(FxHashMap()),
             inlined_item_cache: RefCell::new(FxHashMap()),
-            defid_for_inlined_node: RefCell::new(FxHashMap()),
         }
     }
 
index 0ac3ffd5cb9ce2a4d6f8a3073bfd0a6df74b60a6..64513fa41b219d03938faa1328369aa54df3b1c6 100644 (file)
@@ -13,7 +13,7 @@
 use locator;
 use schema;
 
-use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
+use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
 use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
 use rustc::hir::def::{self, Def};
 use rustc::middle::lang_items;
@@ -36,6 +36,8 @@
 use rustc_back::target::Target;
 use rustc::hir;
 
+use std::collections::BTreeMap;
+
 impl<'tcx> CrateStore<'tcx> for cstore::CStore {
     fn describe_def(&self, def: DefId) -> Option<Def> {
         self.dep_graph.read(DepNode::MetaData(def));
@@ -128,7 +130,11 @@ fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtD
 
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>
     {
-        self.dep_graph.read(DepNode::MetaData(did));
+        // FIXME(#38501) We've skipped a `read` on the `HirBody` of
+        // a `fn` when encoding, so the dep-tracking wouldn't work.
+        // This is only used by rustdoc anyway, which shouldn't have
+        // incremental recompilation ever enabled.
+        assert!(!self.dep_graph.is_fully_enabled());
         self.get_crate_data(did.krate).get_fn_arg_names(did.index)
     }
 
@@ -423,94 +429,42 @@ fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
         })
     }
 
-    fn maybe_get_item_ast<'a>(&'tcx self,
-                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              def_id: DefId)
-                              -> Option<(&'tcx InlinedItem, ast::NodeId)>
+    fn maybe_get_item_body<'a>(&'tcx self,
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               def_id: DefId)
+                               -> Option<&'tcx hir::Body>
     {
         self.dep_graph.read(DepNode::MetaData(def_id));
 
-        match self.inlined_item_cache.borrow().get(&def_id) {
-            Some(&None) => {
-                return None; // Not inlinable
-            }
-            Some(&Some(ref cached_inlined_item)) => {
+        if let Some(&cached) = self.inlined_item_cache.borrow().get(&def_id) {
+            return cached.map(|root_id| {
                 // Already inline
-                debug!("maybe_get_item_ast({}): already inline as node id {}",
-                          tcx.item_path_str(def_id), cached_inlined_item.item_id);
-                return Some((tcx.map.expect_inlined_item(cached_inlined_item.inlined_root),
-                             cached_inlined_item.item_id));
-            }
-            None => {
-                // Not seen yet
-            }
+                debug!("maybe_get_item_body({}): already inline", tcx.item_path_str(def_id));
+                tcx.map.expect_inlined_body(root_id)
+            });
         }
 
-        debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id));
+        debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id));
 
-        let inlined = self.get_crate_data(def_id.krate).maybe_get_item_ast(tcx, def_id.index);
-
-        let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| {
-            let cache_entry = cstore::CachedInlinedItem {
-                inlined_root: inlined_root_node_id,
-                item_id: inlined_item_id,
-            };
-            self.inlined_item_cache
-                .borrow_mut()
-                .insert(original_def_id, Some(cache_entry));
-            self.defid_for_inlined_node
-                .borrow_mut()
-                .insert(inlined_item_id, original_def_id);
-        };
-
-        let find_inlined_item_root = |inlined_item_id| {
-            let mut node = inlined_item_id;
-
-            // If we can't find the inline root after a thousand hops, we can
-            // be pretty sure there's something wrong with the HIR map.
-            for _ in 0 .. 1000 {
-                let parent_node = tcx.map.get_parent_node(node);
-                if parent_node == node {
-                    return node;
-                }
-                node = parent_node;
-            }
-            bug!("cycle in HIR map parent chain")
-        };
+        let inlined = self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index);
 
-        match inlined {
-            None => {
-                self.inlined_item_cache
-                    .borrow_mut()
-                    .insert(def_id, None);
-            }
-            Some(&InlinedItem { ref body, .. }) => {
-                let inlined_root_node_id = find_inlined_item_root(body.id);
-                cache_inlined_item(def_id, inlined_root_node_id, inlined_root_node_id);
-            }
-        }
+        self.inlined_item_cache.borrow_mut().insert(def_id, inlined.map(|body| {
+            let root_id = tcx.map.get_parent_node(body.value.id);
+            assert_eq!(tcx.map.get_parent_node(root_id), root_id);
+            root_id
+        }));
 
-        // We can be sure to hit the cache now
-        return self.maybe_get_item_ast(tcx, def_id);
+        inlined
     }
 
-    fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
-        assert!(!def_id.is_local());
-        match self.inlined_item_cache.borrow().get(&def_id) {
-            Some(&Some(ref cached_inlined_item)) => {
-                Some(cached_inlined_item.item_id)
-            }
-            Some(&None) => {
-                None
-            }
-            _ => {
-                bug!("Trying to lookup inlined NodeId for unexpected item");
-            }
-        }
+    fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
+        self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).item_body_nested_bodies(def.index)
     }
 
-    fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
-        self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x)
+    fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool {
+        self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).const_is_rvalue_promotable_to_static(def.index)
     }
 
     fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx> {
index 93c79046580794be7825f1e5c8403b87cbc9f50d..c27e06c50222be8e123094038dfba0b1424fd07b 100644 (file)
@@ -10,7 +10,7 @@
 
 // Decoding metadata from a single crate's metadata
 
-use astencode::decode_inlined_item;
+use astencode::decode_body;
 use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
 use schema::*;
 
@@ -18,7 +18,7 @@
 use rustc::hir;
 use rustc::hir::intravisit::IdRange;
 
-use rustc::middle::cstore::{InlinedItem, LinkagePreference};
+use rustc::middle::cstore::LinkagePreference;
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::middle::lang_items;
@@ -32,6 +32,7 @@
 
 use std::borrow::Cow;
 use std::cell::Ref;
+use std::collections::BTreeMap;
 use std::io;
 use std::mem;
 use std::str;
@@ -819,20 +820,27 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
         }
     }
 
-    pub fn maybe_get_item_ast(&self,
-                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: DefIndex)
-                              -> Option<&'tcx InlinedItem> {
-        debug!("Looking up item: {:?}", id);
+    pub fn maybe_get_item_body(&self,
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               id: DefIndex)
+                               -> Option<&'tcx hir::Body> {
         if self.is_proc_macro(id) { return None; }
-        let item_doc = self.entry(id);
-        let item_did = self.local_def_id(id);
-        item_doc.ast.map(|ast| {
-            let ast = ast.decode(self);
-            decode_inlined_item(self, tcx, ast, item_did)
+        self.entry(id).ast.map(|ast| {
+            decode_body(self, tcx, self.local_def_id(id), ast.decode(self))
         })
     }
 
+    pub fn item_body_nested_bodies(&self, id: DefIndex) -> BTreeMap<hir::BodyId, hir::Body> {
+        self.entry(id).ast.into_iter().flat_map(|ast| {
+            ast.decode(self).nested_bodies.decode(self).map(|body| (body.id(), body))
+        }).collect()
+    }
+
+    pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
+        self.entry(id).ast.expect("const item missing `ast`")
+            .decode(self).rvalue_promotable_to_static
+    }
+
     pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
         !self.is_proc_macro(id) &&
         self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
@@ -1006,6 +1014,7 @@ pub fn get_implementations_for_trait(&self, filter: Option<DefId>, result: &mut
         let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
             Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
             Some(None) => return,
+            None if self.proc_macros.is_some() => return,
             None => None,
         };
 
index bc0a64b9a51700a58426fc0608fdfdd61ea852a5..72dcb4ba9a3a8f3f1ab460f68b133cfc773c9ca4 100644 (file)
@@ -12,8 +12,7 @@
 use index::Index;
 use schema::*;
 
-use rustc::middle::cstore::{InlinedItemRef, LinkMeta};
-use rustc::middle::cstore::{LinkagePreference, NativeLibrary};
+use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
 use rustc::hir::def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
 use rustc::hir::map::definitions::DefPathTable;
@@ -34,6 +33,7 @@
 use std::rc::Rc;
 use std::u32;
 use syntax::ast::{self, CRATE_NODE_ID};
+use syntax::codemap::Spanned;
 use syntax::attr;
 use syntax::symbol::Symbol;
 use syntax_pos;
@@ -442,10 +442,18 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         let kind = match trait_item.kind {
             ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
             ty::AssociatedKind::Method => {
-                let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node {
+                let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
+                    let arg_names = match *m {
+                        hir::TraitMethod::Required(ref names) => {
+                            self.encode_fn_arg_names(names)
+                        }
+                        hir::TraitMethod::Provided(body) => {
+                            self.encode_fn_arg_names_for_body(body)
+                        }
+                    };
                     FnData {
                         constness: hir::Constness::NotConst,
-                        arg_names: self.encode_fn_arg_names(&sig.decl),
+                        arg_names: arg_names
                     }
                 } else {
                     bug!()
@@ -486,13 +494,8 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: if let hir::ConstTraitItem(_, Some(_)) = ast_item.node {
-                // We only save the HIR for associated consts with bodies
-                // (InlinedItemRef::from_trait_item panics otherwise)
-                let trait_def_id = trait_item.container.id();
-                Some(self.encode_inlined_item(
-                    InlinedItemRef::from_trait_item(trait_def_id, ast_item, tcx)
-                ))
+            ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node {
+                Some(self.encode_body(body))
             } else {
                 None
             },
@@ -501,12 +504,9 @@ 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> {
-        let tcx = self.tcx;
-
         let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.map.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
-        let impl_def_id = impl_item.container.id();
 
         let container = match impl_item.defaultness {
             hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault,
@@ -518,10 +518,10 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         let kind = match impl_item.kind {
             ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
             ty::AssociatedKind::Method => {
-                let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
+                let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
                     FnData {
                         constness: sig.constness,
-                        arg_names: self.encode_fn_arg_names(&sig.decl),
+                        arg_names: self.encode_fn_arg_names_for_body(body),
                     }
                 } else {
                     bug!()
@@ -535,17 +535,18 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
         };
 
-        let (ast, mir) = if impl_item.kind == ty::AssociatedKind::Const {
-            (true, true)
-        } else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
+        let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node {
+            (Some(body), true)
+        } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
             let generics = self.tcx.item_generics(def_id);
             let types = generics.parent_types as usize + generics.types.len();
             let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
             let is_const_fn = sig.constness == hir::Constness::Const;
+            let ast = if is_const_fn { Some(body) } else { None };
             let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-            (is_const_fn, needs_inline || is_const_fn || always_encode_mir)
+            (ast, needs_inline || is_const_fn || always_encode_mir)
         } else {
-            (false, false)
+            (None, false)
         };
 
         Entry {
@@ -563,27 +564,28 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
-            ast: if ast {
-                Some(self.encode_inlined_item(
-                    InlinedItemRef::from_impl_item(impl_def_id, ast_item, tcx)
-                ))
-            } else {
-                None
-            },
+            ast: ast.map(|body| self.encode_body(body)),
             mir: if mir { self.encode_mir(def_id) } else { None },
         }
     }
 
-    fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq<ast::Name> {
-        self.lazy_seq(decl.inputs.iter().map(|arg| {
-            if let PatKind::Binding(_, _, ref path1, _) = arg.pat.node {
-                path1.node
-            } else {
-                Symbol::intern("")
+    fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
+                                    -> LazySeq<ast::Name> {
+        let _ignore = self.tcx.dep_graph.in_ignore();
+        let body = self.tcx.map.body(body_id);
+        self.lazy_seq(body.arguments.iter().map(|arg| {
+            match arg.pat.node {
+                PatKind::Binding(_, _, name, _) => name.node,
+                _ => Symbol::intern("")
             }
         }))
     }
 
+    fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
+                           -> LazySeq<ast::Name> {
+        self.lazy_seq(names.iter().map(|name| name.node))
+    }
+
     fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
         self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
     }
@@ -619,10 +621,10 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
             hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
             hir::ItemConst(..) => EntryKind::Const,
-            hir::ItemFn(ref decl, _, constness, ..) => {
+            hir::ItemFn(_, _, constness, .., body) => {
                 let data = FnData {
                     constness: constness,
-                    arg_names: self.encode_fn_arg_names(&decl),
+                    arg_names: self.encode_fn_arg_names_for_body(body),
                 };
 
                 EntryKind::Fn(self.lazy(&data))
@@ -793,16 +795,16 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             },
 
             ast: match item.node {
-                hir::ItemConst(..) |
-                hir::ItemFn(_, _, hir::Constness::Const, ..) => {
-                    Some(self.encode_inlined_item(
-                        InlinedItemRef::from_item(def_id, item, tcx)
-                    ))
+                hir::ItemConst(_, body) |
+                hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => {
+                    Some(self.encode_body(body))
                 }
                 _ => None,
             },
             mir: match item.node {
-                hir::ItemStatic(..) |
+                hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => {
+                    self.encode_mir(def_id)
+                }
                 hir::ItemConst(..) => self.encode_mir(def_id),
                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
                     let tps_len = generics.ty_params.len();
@@ -913,10 +915,10 @@ fn encode_info_for_foreign_item(&mut self,
         debug!("writing foreign item {}", tcx.node_path_str(nitem.id));
 
         let kind = match nitem.node {
-            hir::ForeignItemFn(ref fndecl, _) => {
+            hir::ForeignItemFn(_, ref names, _) => {
                 let data = FnData {
                     constness: hir::Constness::NotConst,
-                    arg_names: self.encode_fn_arg_names(&fndecl),
+                    arg_names: self.encode_fn_arg_names(names),
                 };
                 EntryKind::ForeignFn(self.lazy(&data))
             }
@@ -1162,6 +1164,8 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
+
     fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
         // handled in `visit_item` above
     }
index e06d940de7e58238713e82d98a13846ae6ccb87f..63bb1bf20c06c41bccba9d59f7e7fb6f06017c44 100644 (file)
@@ -729,7 +729,7 @@ fn declare_binding(&mut self,
             name: Some(name),
             source_info: Some(source_info),
         });
-        let extent = self.extent_of_innermost_scope();
+        let extent = self.hir.tcx().region_maps.var_scope(var_id);
         self.schedule_drop(source_info.span, extent, &Lvalue::Local(var), var_ty);
         self.var_indices.insert(var_id, var);
 
index 0e4dbb0477716a246acaa97d24c15c02c4d2860d..cfdc1bf27df35411c6f008ba6f4aff42c821980e 100644 (file)
@@ -126,7 +126,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                        arguments: A,
                                        abi: Abi,
                                        return_ty: Ty<'gcx>,
-                                       ast_body: &'gcx hir::Expr)
+                                       body: &'gcx hir::Body)
                                        -> Mir<'tcx>
     where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
 {
@@ -136,17 +136,16 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     let span = tcx.map.span(fn_id);
     let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
 
-    let body_id = ast_body.id;
     let call_site_extent =
         tcx.region_maps.lookup_code_extent(
-            CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id });
+            CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body.value.id });
     let arg_extent =
         tcx.region_maps.lookup_code_extent(
-            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
+            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.value.id });
     let mut block = START_BLOCK;
     unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
         unpack!(block = builder.in_scope(arg_extent, block, |builder| {
-            builder.args_and_body(block, &arguments, arg_extent, ast_body)
+            builder.args_and_body(block, &arguments, arg_extent, &body.value)
         }));
         // Attribute epilogue to function's closing brace
         let fn_end = Span { lo: span.hi, ..span };
@@ -197,9 +196,10 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
 
 pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
                                        item_id: ast::NodeId,
-                                       ast_expr: &'tcx hir::Expr)
+                                       body_id: hir::BodyId)
                                        -> Mir<'tcx> {
     let tcx = hir.tcx();
+    let ast_expr = &tcx.map.body(body_id).value;
     let ty = tcx.tables().expr_ty_adjusted(ast_expr);
     let span = tcx.map.span(item_id);
     let mut builder = Builder::new(hir, span, 0, ty);
index c02a1822d736961e39f3b894db8a097664245f76..59a11782e08566744d1e027849a56e60e8506ce4 100644 (file)
@@ -253,7 +253,7 @@ pub fn in_loop_scope<F>(&mut self,
                             f: F)
         where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>)
     {
-        let extent = self.extent_of_innermost_scope();
+        let extent = self.scopes.last().map(|scope| scope.extent).unwrap();
         let loop_scope = LoopScope {
             extent: extent.clone(),
             continue_block: loop_block,
@@ -411,10 +411,6 @@ pub fn source_info(&self, span: Span) -> SourceInfo {
         }
     }
 
-    pub fn extent_of_innermost_scope(&self) -> CodeExtent {
-        self.scopes.last().map(|scope| scope.extent).unwrap()
-    }
-
     /// Returns the extent of the scope which should be exited by a
     /// return.
     pub fn extent_of_return_scope(&self) -> CodeExtent {
index d579cdb042fb3f3b7d4075beacff0eef321d121b..cc65fdede092ff042575c6b4dd388e0344c8abe7 100644 (file)
@@ -575,7 +575,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         // Now comes the rote stuff:
-        hir::ExprRepeat(ref v, ref c) => {
+        hir::ExprRepeat(ref v, c) => {
+            let c = &cx.tcx.map.body(c).value;
             ExprKind::Repeat {
                 value: v.to_ref(),
                 count: TypedConstVal {
@@ -585,7 +586,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         ConstVal::Integral(ConstInt::Usize(u)) => u,
                         other => bug!("constant evaluation of repeat count yielded {:?}", other),
                     },
-                },
+                }
             }
         }
         hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
@@ -780,7 +781,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let body_id = match cx.tcx.map.find(closure_expr_id) {
                 Some(map::NodeExpr(expr)) => {
                     match expr.node {
-                        hir::ExprClosure(.., body_id, _) => body_id.node_id(),
+                        hir::ExprClosure(.., body, _) => body.node_id,
                         _ => {
                             span_bug!(expr.span, "closure expr is not a closure expr");
                         }
index 617bd81d96a2c90f3f83fe1c86d1ca8651b9ac20..56dadd2d673e1e7fc9bfa7aa9e86c9a358f937c3 100644 (file)
@@ -22,7 +22,6 @@
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
-#![cfg_attr(stage0, feature(item_like_imports))]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
index e2a516edbc8354ff69a7108d3ba416f03b98d832..cbc53ea3c51c747ae5e38399e6ace1c76d4ee0cf 100644 (file)
@@ -129,16 +129,17 @@ fn build<F>(&'tcx mut self, f: F)
 }
 
 impl<'a, 'gcx> BuildMir<'a, 'gcx> {
-    fn build_const_integer(&mut self, expr: &'gcx hir::Expr) {
+    fn build_const_integer(&mut self, body: hir::BodyId) {
+        let body = self.tcx.map.body(body);
         // FIXME(eddyb) Closures should have separate
         // function definition IDs and expression IDs.
         // Type-checking should not let closures get
         // this far in an integer constant position.
-        if let hir::ExprClosure(..) = expr.node {
+        if let hir::ExprClosure(..) = body.value.node {
             return;
         }
-        self.cx(MirSource::Const(expr.id)).build(|cx| {
-            build::construct_const(cx, expr.id, expr)
+        self.cx(MirSource::Const(body.value.id)).build(|cx| {
+            build::construct_const(cx, body.value.id, body.id())
         });
     }
 }
@@ -151,12 +152,12 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     // Const and static items.
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
-            hir::ItemConst(_, ref expr) => {
+            hir::ItemConst(_, expr) => {
                 self.cx(MirSource::Const(item.id)).build(|cx| {
                     build::construct_const(cx, item.id, expr)
                 });
             }
-            hir::ItemStatic(_, m, ref expr) => {
+            hir::ItemStatic(_, m, expr) => {
                 self.cx(MirSource::Static(item.id, m)).build(|cx| {
                     build::construct_const(cx, item.id, expr)
                 });
@@ -168,7 +169,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
 
     // Trait associated const defaults.
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
+        if let hir::TraitItemKind::Const(_, Some(expr)) = item.node {
             self.cx(MirSource::Const(item.id)).build(|cx| {
                 build::construct_const(cx, item.id, expr)
             });
@@ -178,7 +179,7 @@ fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
 
     // Impl associated const.
     fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        if let hir::ImplItemKind::Const(_, ref expr) = item.node {
+        if let hir::ImplItemKind::Const(_, expr) = item.node {
             self.cx(MirSource::Const(item.id)).build(|cx| {
                 build::construct_const(cx, item.id, expr)
             });
@@ -188,7 +189,7 @@ fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
 
     // Repeat counts, i.e. [expr; constant].
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
-        if let hir::ExprRepeat(_, ref count) = expr.node {
+        if let hir::ExprRepeat(_, count) = expr.node {
             self.build_const_integer(count);
         }
         intravisit::walk_expr(self, expr);
@@ -196,7 +197,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
 
     // Array lengths, i.e. [T; constant].
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyArray(_, ref length) = ty.node {
+        if let hir::TyArray(_, length) = ty.node {
             self.build_const_integer(length);
         }
         intravisit::walk_ty(self, ty);
@@ -205,7 +206,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
     // Enum variant discriminant values.
     fn visit_variant(&mut self, v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics, item_id: ast::NodeId) {
-        if let Some(ref expr) = v.node.disr_expr {
+        if let Some(expr) = v.node.disr_expr {
             self.build_const_integer(expr);
         }
         intravisit::walk_variant(self, v, g, item_id);
@@ -214,7 +215,7 @@ fn visit_variant(&mut self, v: &'tcx hir::Variant,
     fn visit_fn(&mut self,
                 fk: FnKind<'tcx>,
                 decl: &'tcx hir::FnDecl,
-                body_id: hir::ExprId,
+                body_id: hir::BodyId,
                 span: Span,
                 id: ast::NodeId) {
         // fetch the fully liberated fn signature (that is, all bound
@@ -227,22 +228,21 @@ fn visit_fn(&mut self,
         };
 
         let (abi, implicit_argument) = if let FnKind::Closure(..) = fk {
-            (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id()), None)))
+            (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id), None)))
         } else {
             let def_id = self.tcx.map.local_def_id(id);
             (self.tcx.item_type(def_id).fn_abi(), None)
         };
 
+        let body = self.tcx.map.body(body_id);
         let explicit_arguments =
-            decl.inputs
+            body.arguments
                 .iter()
                 .enumerate()
                 .map(|(index, arg)| {
                     (fn_sig.inputs()[index], Some(&*arg.pat))
                 });
 
-        let body = self.tcx.map.expr(body_id);
-
         let arguments = implicit_argument.into_iter().chain(explicit_arguments);
         self.cx(MirSource::Fn(id)).build(|cx| {
             build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body)
index 86f56d003584155205fe623628809f055c4deefb..d1d9a201567bbc6ba022672d3134019f96e9f459 100644 (file)
@@ -26,8 +26,8 @@
 
 use rustc::dep_graph::DepNode;
 use rustc::ty::cast::CastKind;
-use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
-use rustc_const_eval::{ConstFnNode, eval_const_expr_partial, lookup_const_by_id};
+use rustc_const_eval::{ConstEvalErr, compare_lit_exprs};
+use rustc_const_eval::{eval_const_expr_partial};
 use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math};
 use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath};
 use rustc_const_eval::ErrKind::UnresolvedPath;
 use rustc_const_math::{ConstMathErr, Op};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
+use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
+use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
-use rustc::util::nodemap::NodeMap;
-use rustc::middle::const_qualif::ConstQualif;
+use rustc::util::nodemap::NodeSet;
 use rustc::lint::builtin::CONST_ERR;
 
 use rustc::hir::{self, PatKind};
 use syntax::ast;
 use syntax_pos::Span;
-use rustc::hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap};
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 
 use std::collections::hash_map::Entry;
 use std::cmp::Ordering;
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-enum Mode {
-    Const,
-    ConstFn,
-    Static,
-    StaticMut,
-
-    // An expression that occurs outside of any constant context
-    // (i.e. `const`, `static`, array lengths, etc.). The value
-    // can be variable at runtime, but will be promotable to
-    // static memory if we can prove it is actually constant.
-    Var,
-}
+use std::mem;
 
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mode: Mode,
-    qualif: ConstQualif,
-    rvalue_borrows: NodeMap<hir::Mutability>,
+    in_fn: bool,
+    promotable: bool,
+    mut_rvalue_borrows: NodeSet,
+    param_env: ty::ParameterEnvironment<'tcx>,
 }
 
 impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
-    fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R
-        where F: FnOnce(&mut CheckCrateVisitor<'a, 'gcx>) -> R
-    {
-        let (old_mode, old_qualif) = (self.mode, self.qualif);
-        self.mode = mode;
-        self.qualif = ConstQualif::empty();
-        let r = f(self);
-        self.mode = old_mode;
-        self.qualif = old_qualif;
-        r
-    }
-
-    fn with_euv<F, R>(&mut self, item_id: Option<ast::NodeId>, f: F) -> R
-        where F: for<'b, 'tcx> FnOnce(&mut euv::ExprUseVisitor<'b, 'gcx, 'tcx>) -> R
-    {
-        let param_env = match item_id {
-            Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
-            None => self.tcx.empty_parameter_environment(),
-        };
-
-        self.tcx
-            .infer_ctxt(None, Some(param_env), Reveal::NotSpecializable)
-            .enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx)))
-    }
-
-    fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif {
-        assert!(mode != Mode::Var);
-        match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
-        }
+    fn check_const_eval(&self, expr: &'gcx hir::Expr) {
         if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) {
             match err.kind {
                 UnimplementedConstVal(_) => {}
@@ -124,184 +80,78 @@ fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif {
                 }
             }
         }
-        self.with_mode(mode, |this| {
-            this.with_euv(None, |euv| euv.consume_expr(expr));
-            this.visit_expr(expr);
-            this.qualif
-        })
     }
 
-    fn fn_like(&mut self,
-               fk: FnKind<'gcx>,
-               fd: &'gcx hir::FnDecl,
-               b: hir::ExprId,
-               s: Span,
-               fn_id: ast::NodeId)
-               -> ConstQualif {
-        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
+    // Adds the worst effect out of all the values of one type.
+    fn add_type(&mut self, ty: Ty<'gcx>) {
+        if ty.type_contents(self.tcx).interior_unsafe() {
+            self.promotable = false;
         }
 
-        let mode = match fk {
-            FnKind::ItemFn(_, _, _, hir::Constness::Const, ..)
-                => Mode::ConstFn,
-            FnKind::Method(_, m, ..) => {
-                if m.constness == hir::Constness::Const {
-                    Mode::ConstFn
-                } else {
-                    Mode::Var
-                }
-            }
-            _ => Mode::Var,
-        };
-
-        let qualif = self.with_mode(mode, |this| {
-            let body = this.tcx.map.expr(b);
-            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, body));
-            intravisit::walk_fn(this, fk, fd, b, s, fn_id);
-            this.qualif
-        });
-
-        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
-        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
-        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-
-        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
-        qualif
-    }
-
-    fn add_qualif(&mut self, qualif: ConstQualif) {
-        self.qualif = self.qualif | qualif;
-    }
-
-    /// Returns true if the call is to a const fn or method.
-    fn handle_const_fn_call(&mut self, _expr: &hir::Expr, def_id: DefId, ret_ty: Ty<'gcx>) -> bool {
-        match lookup_const_fn_by_id(self.tcx, def_id) {
-            Some(ConstFnNode::Local(fn_like)) => {
-                let qualif = self.fn_like(fn_like.kind(),
-                                          fn_like.decl(),
-                                          fn_like.body(),
-                                          fn_like.span(),
-                                          fn_like.id());
-
-                self.add_qualif(qualif);
-
-                if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                    self.add_qualif(ConstQualif::MUTABLE_MEM);
-                }
-
-                true
-            },
-            Some(ConstFnNode::Inlined(ii)) => {
-                let node_id = ii.body.id;
-
-                let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) {
-                    Entry::Occupied(entry) => *entry.get(),
-                    _ => bug!("const qualif entry missing for inlined item")
-                };
-
-                self.add_qualif(qualif);
-
-                if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                    self.add_qualif(ConstQualif::MUTABLE_MEM);
-                }
-
-                true
-            },
-            None => false
+        if self.tcx.type_needs_drop_given_env(ty, &self.param_env) {
+            self.promotable = false;
         }
     }
 
-    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
-        match self.rvalue_borrows.entry(id) {
-            Entry::Occupied(mut entry) => {
-                // Merge the two borrows, taking the most demanding
-                // one, mutability-wise.
-                if mutbl == hir::MutMutable {
-                    entry.insert(mutbl);
-                }
-            }
-            Entry::Vacant(entry) => {
-                entry.insert(mutbl);
-            }
-        }
+    fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>) {
+        self.add_type(ret_ty);
+
+        self.promotable &= if let Some(fn_id) = self.tcx.map.as_local_node_id(def_id) {
+            FnLikeNode::from_node(self.tcx.map.get(fn_id)).map_or(false, |fn_like| {
+                fn_like.constness() == hir::Constness::Const
+            })
+        } else {
+            self.tcx.sess.cstore.is_const_fn(def_id)
+        };
     }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.map)
+        NestedVisitorMap::None
     }
 
-    fn visit_item(&mut self, i: &'tcx hir::Item) {
-        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
-        assert_eq!(self.mode, Mode::Var);
-        match i.node {
-            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
-                self.global_expr(Mode::Static, &expr);
-            }
-            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
-                self.global_expr(Mode::StaticMut, &expr);
-            }
-            hir::ItemConst(_, ref expr) => {
-                self.global_expr(Mode::Const, &expr);
-            }
-            hir::ItemEnum(ref enum_definition, _) => {
-                for var in &enum_definition.variants {
-                    if let Some(ref ex) = var.node.disr_expr {
-                        self.global_expr(Mode::Const, &ex);
-                    }
-                }
-            }
-            _ => {
-                intravisit::walk_item(self, i);
+    fn visit_nested_body(&mut self, body: hir::BodyId) {
+        match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body.node_id) {
+            Entry::Occupied(_) => return,
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(false);
             }
         }
-    }
 
-    fn visit_trait_item(&mut self, t: &'tcx hir::TraitItem) {
-        match t.node {
-            hir::ConstTraitItem(_, ref default) => {
-                if let Some(ref expr) = *default {
-                    self.global_expr(Mode::Const, &expr);
-                } else {
-                    intravisit::walk_trait_item(self, t);
-                }
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)),
-        }
-    }
+        let item_id = self.tcx.map.body_owner(body);
 
-    fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
-        match i.node {
-            hir::ImplItemKind::Const(_, ref expr) => {
-                self.global_expr(Mode::Const, &expr);
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
+        let outer_in_fn = self.in_fn;
+        self.in_fn = match MirSource::from_node(self.tcx, item_id) {
+            MirSource::Fn(_) => true,
+            _ => false
+        };
+
+        let body = self.tcx.map.body(body);
+        if !self.in_fn {
+            self.check_const_eval(&body.value);
         }
-    }
 
-    fn visit_fn(&mut self,
-                fk: FnKind<'tcx>,
-                fd: &'tcx hir::FnDecl,
-                b: hir::ExprId,
-                s: Span,
-                fn_id: ast::NodeId) {
-        self.fn_like(fk, fd, b, s, fn_id);
+        let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
+        let outer_param_env = mem::replace(&mut self.param_env, param_env);
+        self.tcx.infer_ctxt(None, Some(self.param_env.clone()), Reveal::NotSpecializable)
+            .enter(|infcx| euv::ExprUseVisitor::new(self, &infcx).consume_body(body));
+
+        self.visit_body(body);
+
+        self.param_env = outer_param_env;
+        self.in_fn = outer_in_fn;
     }
 
     fn visit_pat(&mut self, p: &'tcx hir::Pat) {
         match p.node {
             PatKind::Lit(ref lit) => {
-                self.global_expr(Mode::Const, &lit);
+                self.check_const_eval(lit);
             }
             PatKind::Range(ref start, ref end) => {
-                self.global_expr(Mode::Const, &start);
-                self.global_expr(Mode::Const, &end);
+                self.check_const_eval(start);
+                self.check_const_eval(end);
 
                 match compare_lit_exprs(self.tcx, p.span, start, end) {
                     Ok(Ordering::Less) |
@@ -315,119 +165,60 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat) {
                     Err(ErrorReported) => {}
                 }
             }
-            _ => intravisit::walk_pat(self, p),
+            _ => {}
         }
+        intravisit::walk_pat(self, p);
     }
 
-    fn visit_block(&mut self, block: &'tcx hir::Block) {
-        // Check all statements in the block
-        for stmt in &block.stmts {
-            match stmt.node {
-                hir::StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        hir::DeclLocal(_) => {}
-                        // Item statements are allowed
-                        hir::DeclItem(_) => continue,
+    fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) {
+        match stmt.node {
+            hir::StmtDecl(ref decl, _) => {
+                match decl.node {
+                    hir::DeclLocal(_) => {
+                        self.promotable = false;
                     }
+                    // Item statements are allowed
+                    hir::DeclItem(_) => {}
                 }
-                hir::StmtExpr(..) => {}
-                hir::StmtSemi(..) => {}
             }
-            self.add_qualif(ConstQualif::NOT_CONST);
+            hir::StmtExpr(..) |
+            hir::StmtSemi(..) => {
+                self.promotable = false;
+            }
         }
-        intravisit::walk_block(self, block);
+        intravisit::walk_stmt(self, stmt);
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
-        let mut outer = self.qualif;
-        self.qualif = ConstQualif::empty();
+        let outer = self.promotable;
+        self.promotable = true;
 
         let node_ty = self.tcx.tables().node_id_to_type(ex.id);
         check_expr(self, ex, node_ty);
         check_adjustments(self, ex);
 
-        // Special-case some expressions to avoid certain flags bubbling up.
-        match ex.node {
-            hir::ExprCall(ref callee, ref args) => {
-                for arg in args {
-                    self.visit_expr(&arg)
+        if let hir::ExprMatch(ref discr, ref arms, _) = ex.node {
+            // Compute the most demanding borrow from all the arms'
+            // patterns and set that on the discriminator.
+            let mut mut_borrow = false;
+            for pat in arms.iter().flat_map(|arm| &arm.pats) {
+                if self.mut_rvalue_borrows.remove(&pat.id) {
+                    mut_borrow = true;
                 }
-
-                let inner = self.qualif;
-                self.visit_expr(&callee);
-                // The callee's size doesn't count in the call.
-                let added = self.qualif - inner;
-                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
             }
-            hir::ExprRepeat(ref element, _) => {
-                self.visit_expr(&element);
-                // The count is checked elsewhere (typeck).
-                let count = match node_ty.sty {
-                    ty::TyArray(_, n) => n,
-                    _ => bug!(),
-                };
-                // [element; 0] is always zero-sized.
-                if count == 0 {
-                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-                }
+            if mut_borrow {
+                self.mut_rvalue_borrows.insert(discr.id);
             }
-            hir::ExprMatch(ref discr, ref arms, _) => {
-                // Compute the most demanding borrow from all the arms'
-                // patterns and set that on the discriminator.
-                let mut borrow = None;
-                for pat in arms.iter().flat_map(|arm| &arm.pats) {
-                    let pat_borrow = self.rvalue_borrows.remove(&pat.id);
-                    match (borrow, pat_borrow) {
-                        (None, _) |
-                        (_, Some(hir::MutMutable)) => {
-                            borrow = pat_borrow;
-                        }
-                        _ => {}
-                    }
-                }
-                if let Some(mutbl) = borrow {
-                    self.record_borrow(discr.id, mutbl);
-                }
-                intravisit::walk_expr(self, ex);
-            }
-            _ => intravisit::walk_expr(self, ex),
         }
 
+        intravisit::walk_expr(self, ex);
+
         // Handle borrows on (or inside the autorefs of) this expression.
-        match self.rvalue_borrows.remove(&ex.id) {
-            Some(hir::MutImmutable) => {
-                // Constants cannot be borrowed if they contain interior mutability as
-                // it means that our "silent insertion of statics" could change
-                // initializer values (very bad).
-                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
-                // propagated from another error, so erroring again would be just noise.
-                let tc = node_ty.type_contents(self.tcx);
-                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
-                    outer = outer | ConstQualif::NOT_CONST;
-                }
-                // If the reference has to be 'static, avoid in-place initialization
-                // as that will end up pointing to the stack instead.
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            Some(hir::MutMutable) => {
-                // `&mut expr` means expr could be mutated, unless it's zero-sized.
-                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
-                    if self.mode == Mode::Var {
-                        outer = outer | ConstQualif::NOT_CONST;
-                        self.add_qualif(ConstQualif::MUTABLE_MEM);
-                    }
-                }
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            None => {}
+        if self.mut_rvalue_borrows.remove(&ex.id) {
+            self.promotable = false;
         }
 
-        if self.mode == Mode::Var && !self.qualif.intersects(ConstQualif::NOT_CONST) {
+        if self.in_fn && self.promotable {
             match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) {
                 Ok(_) => {}
                 Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) |
@@ -448,9 +239,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
             }
         }
 
-        self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
-        // Don't propagate certain flags.
-        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
+        self.tcx.rvalue_promotable_to_static.borrow_mut().insert(ex.id, self.promotable);
+        self.promotable &= outer;
     }
 }
 
@@ -463,7 +253,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
 fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) {
     match node_ty.sty {
         ty::TyAdt(def, _) if def.has_dtor() => {
-            v.add_qualif(ConstQualif::NEEDS_DROP);
+            v.promotable = false;
         }
         _ => {}
     }
@@ -473,17 +263,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprUnary(..) |
         hir::ExprBinary(..) |
         hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
+            v.promotable = false;
         }
         hir::ExprBox(_) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
+            v.promotable = false;
         }
         hir::ExprUnary(op, ref inner) => {
             match v.tcx.tables().node_id_to_type(inner.id).sty {
                 ty::TyRawPtr(_) => {
                     assert!(op == hir::UnDeref);
 
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
                 _ => {}
             }
@@ -495,7 +285,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
                             op.node == hir::BiLe || op.node == hir::BiLt ||
                             op.node == hir::BiGe || op.node == hir::BiGt);
 
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
                 _ => {}
             }
@@ -505,7 +295,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             match v.tcx.cast_kinds.borrow().get(&from.id) {
                 None => span_bug!(e.span, "no kind for cast"),
                 Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
                 _ => {}
             }
@@ -513,33 +303,24 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprPath(ref qpath) => {
             let def = v.tcx.tables().qpath_def(qpath, e.id);
             match def {
-                Def::VariantCtor(_, CtorKind::Const) => {
-                    // Size is determined by the whole enum, may be non-zero.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                }
                 Def::VariantCtor(..) | Def::StructCtor(..) |
                 Def::Fn(..) | Def::Method(..) => {}
-                Def::Static(..) => {
-                    match v.mode {
-                        Mode::Static | Mode::StaticMut => {}
-                        Mode::Const | Mode::ConstFn => {}
-                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
-                    }
-                }
-                Def::Const(did) | Def::AssociatedConst(did) => {
-                    let substs = Some(v.tcx.tables().node_id_item_substs(e.id)
-                        .unwrap_or_else(|| v.tcx.intern_substs(&[])));
-                    if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) {
-                        let inner = v.global_expr(Mode::Const, expr);
-                        v.add_qualif(inner);
-                    }
-                }
-                Def::Local(..) if v.mode == Mode::ConstFn => {
-                    // Sadly, we can't determine whether the types are zero-sized.
-                    v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
+                Def::AssociatedConst(_) => v.add_type(node_ty),
+                Def::Const(did) => {
+                    v.promotable &= if let Some(node_id) = v.tcx.map.as_local_node_id(did) {
+                        match v.tcx.map.expect_item(node_id).node {
+                            hir::ItemConst(_, body) => {
+                                v.visit_nested_body(body);
+                                v.tcx.rvalue_promotable_to_static.borrow()[&body.node_id]
+                            }
+                            _ => false
+                        }
+                    } else {
+                        v.tcx.sess.cstore.const_is_rvalue_promotable_to_static(did)
+                    };
                 }
                 _ => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
+                    v.promotable = false;
                 }
             }
         }
@@ -560,65 +341,48 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             } else {
                 Def::Err
             };
-            let is_const = match def {
+            match def {
                 Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Fn) => {
-                    // `NON_ZERO_SIZED` is about the call result, not about the ctor itself.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                    true
-                }
+                Def::VariantCtor(_, CtorKind::Fn) => {}
                 Def::Fn(did) => {
-                    v.handle_const_fn_call(e, did, node_ty)
+                    v.handle_const_fn_call(did, node_ty)
                 }
                 Def::Method(did) => {
                     match v.tcx.associated_item(did).container {
                         ty::ImplContainer(_) => {
-                            v.handle_const_fn_call(e, did, node_ty)
+                            v.handle_const_fn_call(did, node_ty)
                         }
-                        ty::TraitContainer(_) => false
+                        ty::TraitContainer(_) => v.promotable = false
                     }
                 }
-                _ => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
+                _ => v.promotable = false
             }
         }
         hir::ExprMethodCall(..) => {
             let method = v.tcx.tables().method_map[&method_call];
-            let is_const = match v.tcx.associated_item(method.def_id).container {
-                ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
-                ty::TraitContainer(_) => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
+            match v.tcx.associated_item(method.def_id).container {
+                ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty),
+                ty::TraitContainer(_) => v.promotable = false
             }
         }
         hir::ExprStruct(..) => {
             if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty {
                 // unsafe_cell_type doesn't necessarily exist with no_core
                 if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() {
-                    v.add_qualif(ConstQualif::MUTABLE_MEM);
+                    v.promotable = false;
                 }
             }
         }
 
         hir::ExprLit(_) |
-        hir::ExprAddrOf(..) => {
-            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-        }
-
-        hir::ExprRepeat(..) => {
-            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
-        }
+        hir::ExprAddrOf(..) |
+        hir::ExprRepeat(..) => {}
 
         hir::ExprClosure(..) => {
             // Paths in constant contexts cannot refer to local variables,
             // as there are none, and thus closures can't have upvars there.
             if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
-                assert!(v.mode == Mode::Var,
-                        "global closures can't capture anything");
-                v.add_qualif(ConstQualif::NOT_CONST);
+                v.promotable = false;
             }
         }
 
@@ -647,7 +411,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprAssign(..) |
         hir::ExprAssignOp(..) |
         hir::ExprInlineAsm(..) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
+            v.promotable = false;
         }
     }
 }
@@ -666,7 +430,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
         Some(Adjust::DerefRef { autoderefs, .. }) => {
             if (0..autoderefs as u32)
                 .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) {
-                v.add_qualif(ConstQualif::NOT_CONST);
+                v.promotable = false;
             }
         }
     }
@@ -676,9 +440,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.visit_all_item_likes_in_krate(DepNode::CheckConst,
                                       &mut CheckCrateVisitor {
                                           tcx: tcx,
-                                          mode: Mode::Var,
-                                          qualif: ConstQualif::NOT_CONST,
-                                          rvalue_borrows: NodeMap(),
+                                          in_fn: false,
+                                          promotable: false,
+                                          mut_rvalue_borrows: NodeSet(),
+                                          param_env: tcx.empty_parameter_environment(),
                                       }.as_deep_visitor());
     tcx.sess.abort_if_errors();
 }
@@ -687,24 +452,9 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
     fn consume(&mut self,
                _consume_id: ast::NodeId,
                _consume_span: Span,
-               cmt: mc::cmt,
-               _mode: euv::ConsumeMode) {
-        let mut cur = &cmt;
-        loop {
-            match cur.cat {
-                Categorization::StaticItem => {
-                    break;
-                }
-                Categorization::Deref(ref cmt, ..) |
-                Categorization::Downcast(ref cmt, _) |
-                Categorization::Interior(ref cmt, _) => cur = cmt,
+               _cmt: mc::cmt,
+               _mode: euv::ConsumeMode) {}
 
-                Categorization::Rvalue(..) |
-                Categorization::Upvar(..) |
-                Categorization::Local(..) => break,
-            }
-        }
-    }
     fn borrow(&mut self,
               borrow_id: ast::NodeId,
               _borrow_span: Span,
@@ -731,21 +481,9 @@ fn borrow(&mut self,
                         // Ignore the dummy immutable borrow created by EUV.
                         break;
                     }
-                    let mutbl = bk.to_mutbl_lossy();
-                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
-                        // Mutable slices are the only `&mut` allowed in
-                        // globals, but only in `static mut`, nowhere else.
-                        // FIXME: This exception is really weird... there isn't
-                        // any fundamental reason to restrict this based on
-                        // type of the expression.  `&mut [1]` has exactly the
-                        // same representation as &mut 1.
-                        match cmt.ty.sty {
-                            ty::TyArray(..) |
-                            ty::TySlice(_) => break,
-                            _ => {}
-                        }
+                    if bk.to_mutbl_lossy() == hir::MutMutable {
+                        self.mut_rvalue_borrows.insert(borrow_id);
                     }
-                    self.record_borrow(borrow_id, mutbl);
                     break;
                 }
                 Categorization::StaticItem => {
index f7e026866e2df04d0bbc7820f0124b78fbf3216a..65a60732fc8074e423790ba73597b0e387316d64 100644 (file)
@@ -115,6 +115,11 @@ fn visit_nested_item(&mut self, id: hir::ItemId) {
         self.visit_item(nested_item)
     }
 
+    fn visit_nested_trait_item(&mut self, trait_item_id: hir::TraitItemId) {
+        let nested_trait_item = self.krate.unwrap().trait_item(trait_item_id);
+        self.visit_trait_item(nested_trait_item)
+    }
+
     fn visit_nested_impl_item(&mut self, impl_item_id: hir::ImplItemId) {
         let nested_impl_item = self.krate.unwrap().impl_item(impl_item_id);
         self.visit_impl_item(nested_impl_item)
@@ -172,7 +177,7 @@ fn visit_ty(&mut self, t: &'v hir::Ty) {
     fn visit_fn(&mut self,
                 fk: hir_visit::FnKind<'v>,
                 fd: &'v hir::FnDecl,
-                b: hir::ExprId,
+                b: hir::BodyId,
                 s: Span,
                 id: NodeId) {
         self.record("FnDecl", Id::None, fd);
index 10f464a9901d0beebb54f19fc72c9852f70447fe..df9fe00e9a88e23d99f9e248d6843b0c12610a14 100644 (file)
@@ -84,7 +84,7 @@ fn visit_expr(&mut self, e: &'ast hir::Expr) {
                 self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
             }
             hir::ExprClosure(.., b, _) => {
-                self.with_context(Closure, |v| v.visit_body(b));
+                self.with_context(Closure, |v| v.visit_nested_body(b));
             }
             hir::ExprBreak(label, ref opt_expr) => {
                 if opt_expr.is_some() {
index ddb5af1e80c345a00973628fb3cb1a4a97051034..3da4f24b6c2fe077243b34e0c25a60f9dd84f77e 100644 (file)
@@ -39,7 +39,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     fn visit_fn(&mut self,
                 fk: intravisit::FnKind<'tcx>,
                 fd: &'tcx hir::FnDecl,
-                b: hir::ExprId,
+                b: hir::BodyId,
                 s: Span,
                 fn_id: ast::NodeId) {
         // FIXME (@jroesch) change this to be an inference context
@@ -50,9 +50,9 @@ fn visit_fn(&mut self,
                 tcx: infcx.tcx,
                 param_env: &param_env
             };
-            let body = infcx.tcx.map.expr(b);
+            let body = infcx.tcx.map.body(b);
             let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
-            euv.walk_fn(fd, body);
+            euv.consume_body(body);
         });
         intravisit::walk_fn(self, fk, fd, b, s, fn_id)
     }
index b5be4aa5e64e2ac25195bbf653f0220238cb6808..ba4fc57276b2ce21a2709b118ef6098d7785676b 100644 (file)
@@ -30,7 +30,7 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
     // variant definitions with the discriminant expression that applies to
     // each one. If the variant uses the default values (starting from `0`),
     // then `None` is stored.
-    discriminant_map: NodeMap<Option<&'ast hir::Expr>>,
+    discriminant_map: NodeMap<Option<hir::BodyId>>,
     detected_recursive_ids: NodeSet,
 }
 
@@ -66,7 +66,7 @@ fn visit_item(&mut self, it: &'ast hir::Item) {
 
     fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
         match ti.node {
-            hir::ConstTraitItem(_, ref default) => {
+            hir::TraitItemKind::Const(_, ref default) => {
                 if let Some(_) = *default {
                     let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ti.span);
                     recursion_visitor.visit_trait_item(ti);
@@ -108,7 +108,7 @@ struct CheckItemRecursionVisitor<'a, 'b: 'a, 'ast: 'b> {
     root_span: &'b Span,
     sess: &'b Session,
     ast_map: &'b ast_map::Map<'ast>,
-    discriminant_map: &'a mut NodeMap<Option<&'ast hir::Expr>>,
+    discriminant_map: &'a mut NodeMap<Option<hir::BodyId>>,
     idstack: Vec<ast::NodeId>,
     detected_recursive_ids: &'a mut NodeSet,
 }
@@ -189,7 +189,7 @@ fn populate_enum_discriminants(&mut self, enum_definition: &'ast hir::EnumDef) {
             variant_stack.push(variant.node.data.id());
             // When we find an expression, every variant currently on the stack
             // is affected by that expression.
-            if let Some(ref expr) = variant.node.disr_expr {
+            if let Some(expr) = variant.node.disr_expr {
                 for id in &variant_stack {
                     self.discriminant_map.insert(*id, Some(expr));
                 }
@@ -226,19 +226,15 @@ fn visit_variant(&mut self,
                      _: &'ast hir::Generics,
                      _: ast::NodeId) {
         let variant_id = variant.node.data.id();
-        let maybe_expr;
-        if let Some(get_expr) = self.discriminant_map.get(&variant_id) {
-            // This is necessary because we need to let the `discriminant_map`
-            // borrow fall out of scope, so that we can reborrow farther down.
-            maybe_expr = (*get_expr).clone();
-        } else {
+        let maybe_expr = *self.discriminant_map.get(&variant_id).unwrap_or_else(|| {
             span_bug!(variant.span,
                       "`check_static_recursion` attempted to visit \
                       variant with unknown discriminant")
-        }
+        });
         // If `maybe_expr` is `None`, that's because no discriminant is
         // specified that affects this variant. Thus, no risk of recursion.
         if let Some(expr) = maybe_expr {
+            let expr = &self.ast_map.body(expr).value;
             self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr), expr.span);
         }
     }
index 514d81ecc94f2a9f6b27ca8f5c39520b69f9c1b7..48d4437358c58ef5c58f7e633b517343ee12f51e 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "rustc_plugin"
 version = "0.0.0"
+build = false
 
 [lib]
 name = "rustc_plugin"
index 75046f6aeb8742fd581b3f669bcdb30ffeb98126..34ebd12de9c18fbc38b56baedf7ff4ddcbf50e1c 100644 (file)
@@ -33,6 +33,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index ca3e4e1c762c72e837bd3e0a49439b5aff75641d..81863a3fadfd36f69badeacf39ac631fe6905b38 100644 (file)
@@ -160,21 +160,19 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             }
             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
                 for impl_item_ref in impl_item_refs {
-                    let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
-                    if impl_item.vis == hir::Public {
-                        self.update(impl_item.id, item_level);
+                    if impl_item_ref.vis == hir::Public {
+                        self.update(impl_item_ref.id.node_id, item_level);
                     }
                 }
             }
             hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
                 for impl_item_ref in impl_item_refs {
-                    let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
-                    self.update(impl_item.id, item_level);
+                    self.update(impl_item_ref.id.node_id, item_level);
                 }
             }
-            hir::ItemTrait(.., ref trait_items) => {
-                for trait_item in trait_items {
-                    self.update(trait_item.id, item_level);
+            hir::ItemTrait(.., ref trait_item_refs) => {
+                for trait_item_ref in trait_item_refs {
+                    self.update(trait_item_ref.id.node_id, item_level);
                 }
             }
             hir::ItemStruct(ref def, _) | hir::ItemUnion(ref def, _) => {
@@ -214,15 +212,16 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     self.reach(item.id).generics().predicates().item_type();
                 }
             }
-            hir::ItemTrait(.., ref trait_items) => {
+            hir::ItemTrait(.., ref trait_item_refs) => {
                 if item_level.is_some() {
                     self.reach(item.id).generics().predicates();
 
-                    for trait_item in trait_items {
-                        let mut reach = self.reach(trait_item.id);
+                    for trait_item_ref in trait_item_refs {
+                        let mut reach = self.reach(trait_item_ref.id.node_id);
                         reach.generics().predicates();
 
-                        if let hir::TypeTraitItem(_, None) = trait_item.node {
+                        if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                           !trait_item_ref.defaultness.has_value() {
                             // No type to visit.
                         } else {
                             reach.item_type();
@@ -231,12 +230,12 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 }
             }
             // Visit everything except for private impl items
-            hir::ItemImpl(.., ref trait_ref, _, ref impl_items) => {
+            hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
                 if item_level.is_some() {
                     self.reach(item.id).generics().predicates().impl_trait_ref();
 
-                    for impl_item in impl_items {
-                        let id = impl_item.id.node_id;
+                    for impl_item_ref in impl_item_refs {
+                        let id = impl_item_ref.id.node_id;
                         if trait_ref.is_some() || self.get(id).is_some() {
                             self.reach(id).generics().predicates().item_type();
                         }
@@ -789,22 +788,19 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
                     for impl_item_ref in impl_item_refs {
-                        let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
-                        match impl_item.node {
-                            hir::ImplItemKind::Const(..) => {
-                                if self.item_is_public(&impl_item.id, &impl_item.vis) {
+                        if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
+                            let impl_item = self.tcx.map.impl_item(impl_item_ref.id);
+                            match impl_item_ref.kind {
+                                hir::AssociatedItemKind::Const => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
-                            }
-                            hir::ImplItemKind::Method(ref sig, _) => {
-                                if !sig.decl.has_self() &&
-                                        self.item_is_public(&impl_item.id, &impl_item.vis) {
+                                hir::AssociatedItemKind::Method { has_self: false } => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
+                                _ => {}
                             }
-                            _ => {}
                         }
                     }
                     if found_pub_static {
@@ -1092,14 +1088,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 self.inner_visibility = item_visibility;
                 intravisit::walk_item(self, item);
             }
-            hir::ItemTrait(.., ref trait_items) => {
+            hir::ItemTrait(.., ref trait_item_refs) => {
                 self.check(item.id, item_visibility).generics().predicates();
 
-                for trait_item in trait_items {
-                    let mut check = self.check(trait_item.id, item_visibility);
+                for trait_item_ref in trait_item_refs {
+                    let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
                     check.generics().predicates();
 
-                    if let hir::TypeTraitItem(_, None) = trait_item.node {
+                    if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                       !trait_item_ref.defaultness.has_value() {
                         // No type to visit.
                     } else {
                         check.item_type();
index a0af4c456535990c0b9ce9f7f91a52353bd9584b..865195d3db488e3914ae34ac82ec3a633c333d93 100644 (file)
@@ -571,6 +571,17 @@ fn visit_local(&mut self, local: &'tcx Local) {
     fn visit_ty(&mut self, ty: &'tcx Ty) {
         if let TyKind::Path(ref qself, ref path) = ty.node {
             self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
+        } else if let TyKind::ImplicitSelf = ty.node {
+            let self_ty = keywords::SelfType.ident();
+            let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span))
+                          .map_or(Def::Err, |d| d.def());
+            self.record_def(ty.id, PathResolution::new(def));
+        } else if let TyKind::Array(ref element, ref length) = ty.node {
+            self.visit_ty(element);
+            self.with_constant_rib(|this| {
+                this.visit_expr(length);
+            });
+            return;
         }
         visit::walk_ty(self, ty);
     }
@@ -741,6 +752,13 @@ fn item(self) -> Option<&'a NameBinding<'a>> {
             _ => None,
         }
     }
+
+    fn def(self) -> Def {
+        match self {
+            LexicalScopeBinding::Item(binding) => binding.def(),
+            LexicalScopeBinding::Def(def) => def,
+        }
+    }
 }
 
 #[derive(Clone)]
@@ -2721,6 +2739,13 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
                     self.visit_ty(ty);
                 }
             }
+
+            ExprKind::Repeat(ref element, ref count) => {
+                self.visit_expr(element);
+                self.with_constant_rib(|this| {
+                    this.visit_expr(count);
+                });
+            }
             ExprKind::Call(ref callee, ref arguments) => {
                 self.resolve_expr(callee, Some(&expr.node));
                 for argument in arguments {
index 491521a3239495454e9bb5680bf1535b26b1dff0..43e3b1dd2b50a9d5e62d225da8f5c777698d5861 100644 (file)
@@ -349,7 +349,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
                     match item.node {
                         hir::ItemImpl(.., ref ty, _) => {
                             let mut result = String::from("<");
-                            result.push_str(&rustc::hir::print::ty_to_string(&ty));
+                            result.push_str(&self.tcx.map.node_to_pretty_string(ty.id));
 
                             let trait_id = self.tcx.trait_id_of_impl(impl_id);
                             let mut decl_id = None;
index 648dc4c24c9a658c79426f2b53d2f5c707ca7f6a..defbb44448a9f3a5f4b7ce77ecc494086f5a9f61 100644 (file)
@@ -191,7 +191,8 @@ pub fn link_binary(sess: &Session,
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-trans, as they will error.
-        if sess.opts.debugging_opts.no_trans &&
+        if (sess.opts.debugging_opts.no_trans ||
+            !sess.opts.output_types.should_trans()) &&
            crate_type == config::CrateTypeExecutable {
             continue;
         }
@@ -200,15 +201,16 @@ pub fn link_binary(sess: &Session,
            bug!("invalid output type `{:?}` for target os `{}`",
                 crate_type, sess.opts.target_triple);
         }
-        let out_file = link_binary_output(sess, trans, crate_type, outputs,
-                                          crate_name);
-        out_filenames.push(out_file);
+        let mut out_files = link_binary_output(sess, trans, crate_type, outputs, crate_name);
+        out_filenames.append(&mut out_files);
     }
 
     // Remove the temporary object file and metadata if we aren't saving temps
     if !sess.opts.cg.save_temps {
-        for obj in object_filenames(trans, outputs) {
-            remove(sess, &obj);
+        if sess.opts.output_types.should_trans() {
+            for obj in object_filenames(trans, outputs) {
+                remove(sess, &obj);
+            }
         }
         remove(sess, &outputs.with_extension("metadata.o"));
     }
@@ -254,18 +256,25 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
+fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
+    let out_filename = outputs.single_output_file.clone()
+        .unwrap_or(outputs
+            .out_directory
+            .join(&format!("lib{}{}.rmeta", crate_name, sess.opts.cg.extra_filename)));
+    check_file_is_writeable(&out_filename, sess);
+    out_filename
+}
+
 pub fn filename_for_input(sess: &Session,
                           crate_type: config::CrateType,
                           crate_name: &str,
                           outputs: &OutputFilenames) -> PathBuf {
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
+
     match crate_type {
         config::CrateTypeRlib => {
             outputs.out_directory.join(&format!("lib{}.rlib", libname))
         }
-        config::CrateTypeMetadata => {
-            outputs.out_directory.join(&format!("lib{}.rmeta", libname))
-        }
         config::CrateTypeCdylib |
         config::CrateTypeProcMacro |
         config::CrateTypeDylib => {
@@ -323,27 +332,41 @@ pub fn each_linked_rlib(sess: &Session,
     }
 }
 
+fn out_filename(sess: &Session,
+                crate_type: config::CrateType,
+                outputs: &OutputFilenames,
+                crate_name: &str)
+                -> PathBuf {
+    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
+    let out_filename = outputs.outputs.get(&OutputType::Exe)
+                              .and_then(|s| s.to_owned())
+                              .or_else(|| outputs.single_output_file.clone())
+                              .unwrap_or(default_filename);
+
+    check_file_is_writeable(&out_filename, sess);
+
+    out_filename
+}
+
+// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
+// check this already -- however, the Linux linker will happily overwrite a
+// read-only file.  We should be consistent.
+fn check_file_is_writeable(file: &Path, sess: &Session) {
+    if !is_writeable(file) {
+        sess.fatal(&format!("output file {} is not writeable -- check its \
+                            permissions", file.display()));
+    }
+}
+
 fn link_binary_output(sess: &Session,
                       trans: &CrateTranslation,
                       crate_type: config::CrateType,
                       outputs: &OutputFilenames,
-                      crate_name: &str) -> PathBuf {
+                      crate_name: &str) -> Vec<PathBuf> {
     let objects = object_filenames(trans, outputs);
-    let default_filename = filename_for_input(sess, crate_type, crate_name,
-                                              outputs);
-    let out_filename = outputs.outputs.get(&OutputType::Exe)
-                              .and_then(|s| s.to_owned())
-                              .or_else(|| outputs.single_output_file.clone())
-                              .unwrap_or(default_filename);
 
-    // Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
-    // check this already -- however, the Linux linker will happily overwrite a
-    // read-only file.  We should be consistent.
-    for file in objects.iter().chain(Some(&out_filename)) {
-        if !is_writeable(file) {
-            sess.fatal(&format!("output file {} is not writeable -- check its \
-                                permissions", file.display()));
-        }
+    for file in &objects {
+        check_file_is_writeable(file, sess);
     }
 
     let tmpdir = match TempDir::new("rustc") {
@@ -351,24 +374,33 @@ fn link_binary_output(sess: &Session,
         Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
     };
 
-    match crate_type {
-        config::CrateTypeRlib => {
-            link_rlib(sess, Some(trans), &objects, &out_filename,
-                      tmpdir.path()).build();
-        }
-        config::CrateTypeStaticlib => {
-            link_staticlib(sess, &objects, &out_filename, tmpdir.path());
-        }
-        config::CrateTypeMetadata => {
-            emit_metadata(sess, trans, &out_filename);
-        }
-        _ => {
-            link_natively(sess, crate_type, &objects, &out_filename, trans,
-                          outputs, tmpdir.path());
+    let mut out_filenames = vec![];
+
+    if outputs.outputs.contains_key(&OutputType::Metadata) {
+        let out_filename = filename_for_metadata(sess, crate_name, outputs);
+        emit_metadata(sess, trans, &out_filename);
+        out_filenames.push(out_filename);
+    }
+
+    if outputs.outputs.should_trans() {
+        let out_filename = out_filename(sess, crate_type, outputs, crate_name);
+        match crate_type {
+            config::CrateTypeRlib => {
+                link_rlib(sess, Some(trans), &objects, &out_filename,
+                          tmpdir.path()).build();
+            }
+            config::CrateTypeStaticlib => {
+                link_staticlib(sess, &objects, &out_filename, tmpdir.path());
+            }
+            _ => {
+                link_natively(sess, crate_type, &objects, &out_filename, trans,
+                              outputs, tmpdir.path());
+            }
         }
+        out_filenames.push(out_filename);
     }
 
-    out_filename
+    out_filenames
 }
 
 fn object_filenames(trans: &CrateTranslation,
index f137bfff034d0e37c7cc9af7afd364a86d42064b..0ef3f351a2a4bffdb58292beb058e482a73416cc 100644 (file)
@@ -34,7 +34,6 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
 
         config::CrateTypeDylib     |
         config::CrateTypeRlib      |
-        config::CrateTypeMetadata  |
         config::CrateTypeProcMacro => false,
     }
 }
index eef464eb7f4dc61098e64884dd9f9a70ae1ac756..5f16291892387fb6b2622895a4979b37625b0618 100644 (file)
@@ -149,7 +149,6 @@ pub fn crate_export_threshold(crate_type: config::CrateType)
         config::CrateTypeProcMacro  |
         config::CrateTypeCdylib     => SymbolExportLevel::C,
         config::CrateTypeRlib       |
-        config::CrateTypeMetadata   |
         config::CrateTypeDylib      => SymbolExportLevel::Rust,
     }
 }
index de8814f143e04f62b4c07b046a7c5ac0039b01f7..dac1e3b8dc1ce6a65ddf6d73a6105822cf6d3ad1 100644 (file)
@@ -19,7 +19,7 @@
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
 use llvm::SMDiagnosticRef;
 use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation};
-use util::common::time;
+use util::common::{time, time_depth, set_time_depth};
 use util::common::path2cstr;
 use util::fs::link_or_copy;
 use errors::{self, Handler, Level, DiagnosticBuilder};
@@ -701,8 +701,8 @@ pub fn run_passes(sess: &Session,
 
     for output_type in output_types.keys() {
         match *output_type {
-            OutputType::Bitcode => { modules_config.emit_bc = true; },
-            OutputType::LlvmAssembly => { modules_config.emit_ir = true; },
+            OutputType::Bitcode => { modules_config.emit_bc = true; }
+            OutputType::LlvmAssembly => { modules_config.emit_ir = true; }
             OutputType::Assembly => {
                 modules_config.emit_asm = true;
                 // If we're not using the LLVM assembler, this function
@@ -711,8 +711,9 @@ pub fn run_passes(sess: &Session,
                 if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
                     metadata_config.emit_obj = true;
                 }
-            },
-            OutputType::Object => { modules_config.emit_obj = true; },
+            }
+            OutputType::Object => { modules_config.emit_obj = true; }
+            OutputType::Metadata => { metadata_config.emit_obj = true; }
             OutputType::Exe => {
                 modules_config.emit_obj = true;
                 metadata_config.emit_obj = true;
@@ -853,6 +854,7 @@ pub fn run_passes(sess: &Session,
                 user_wants_objects = true;
                 copy_if_one_unit(OutputType::Object, true);
             }
+            OutputType::Metadata |
             OutputType::Exe |
             OutputType::DepInfo => {}
         }
@@ -1033,7 +1035,10 @@ fn run_work_multithreaded(sess: &Session,
 
         let incr_comp_session_dir = sess.incr_comp_session_dir_opt().map(|r| r.clone());
 
+        let depth = time_depth();
         thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
+            set_time_depth(depth);
+
             let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
 
             // Must construct cgcx inside the proc because it has non-Send
index 76bb1c56af3818aa155be237b4bb5da7292aded4..47b76658bdd1481689e5c960e8c7862004c232df 100644 (file)
@@ -807,8 +807,7 @@ enum MetadataKind {
             config::CrateTypeStaticlib |
             config::CrateTypeCdylib => MetadataKind::None,
 
-            config::CrateTypeRlib |
-            config::CrateTypeMetadata => MetadataKind::Uncompressed,
+            config::CrateTypeRlib => MetadataKind::Uncompressed,
 
             config::CrateTypeDylib |
             config::CrateTypeProcMacro => MetadataKind::Compressed,
@@ -1191,7 +1190,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Skip crate items and just output metadata in -Z no-trans mode.
     if tcx.sess.opts.debugging_opts.no_trans ||
-       tcx.sess.crate_types.borrow().iter().all(|ct| ct == &config::CrateTypeMetadata) {
+       tcx.sess.opts.output_types.contains_key(&config::OutputType::Metadata) {
         let linker_info = LinkerInfo::new(&shared_ccx, &ExportedSymbols::empty());
         return CrateTranslation {
             modules: modules,
index d8c212745376d69225bd2ff424dd1c15f4731f62..2bc42a461528da2bfb28b779341c40ad1e8ec73c 100644 (file)
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
-use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
+use rustc::middle::lang_items::{BoxFreeFnLangItem, ExchangeMallocFnLangItem};
 use rustc::traits;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::{Kind, Substs, Subst};
 use rustc::ty::{self, TypeFoldable, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::{self, Location};
 use rustc::mir::visit as mir_visit;
 use rustc::mir::visit::Visitor as MirVisitor;
 
-use rustc_const_eval as const_eval;
-
 use syntax::abi::Abi;
 use syntax_pos::DUMMY_SP;
 use base::custom_coerce_unsize_info;
 
 use trans_item::{TransItem, DefPathBasedNames};
 
+use std::iter;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
     Eager,
@@ -342,19 +342,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
 
             recursion_depth_reset = None;
 
-            // Scan the MIR in order to find function calls, closures, and
-            // drop-glue
-            let mir = scx.tcx().item_mir(def_id);
-
-            let empty_substs = scx.empty_substs_for_def_id(def_id);
-            let visitor = MirNeighborCollector {
-                scx: scx,
-                mir: &mir,
-                output: &mut neighbors,
-                param_substs: empty_substs
-            };
-
-            visit_mir_and_promoted(visitor, &mir);
+            collect_neighbours(scx, Instance::mono(scx, def_id), &mut neighbors);
         }
         TransItem::Fn(instance) => {
             // Keep track of the monomorphization recursion depth
@@ -363,18 +351,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
                                                                recursion_depths));
             check_type_length_limit(scx.tcx(), instance);
 
-            // Scan the MIR in order to find function calls, closures, and
-            // drop-glue
-            let mir = scx.tcx().item_mir(instance.def);
-
-            let visitor = MirNeighborCollector {
-                scx: scx,
-                mir: &mir,
-                output: &mut neighbors,
-                param_substs: instance.substs
-            };
-
-            visit_mir_and_promoted(visitor, &mir);
+            collect_neighbours(scx, instance, &mut neighbors);
         }
     }
 
@@ -561,33 +538,12 @@ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
                     // This is not a callee, but we still have to look for
                     // references to `const` items
                     if let mir::Literal::Item { def_id, substs } = constant.literal {
-                        let tcx = self.scx.tcx();
                         let substs = monomorphize::apply_param_substs(self.scx,
                                                                       self.param_substs,
                                                                       &substs);
 
-                        // If the constant referred to here is an associated
-                        // item of a trait, we need to resolve it to the actual
-                        // constant in the corresponding impl. Luckily
-                        // const_eval::lookup_const_by_id() does that for us.
-                        if let Some((expr, _)) = const_eval::lookup_const_by_id(tcx,
-                                                                                def_id,
-                                                                                Some(substs)) {
-                            // The hir::Expr we get here is the initializer of
-                            // the constant, what we really want is the item
-                            // DefId.
-                            let const_node_id = tcx.map.get_parent(expr.id);
-                            let def_id = if tcx.map.is_inlined_node_id(const_node_id) {
-                                tcx.sess.cstore.defid_for_inlined_node(const_node_id).unwrap()
-                            } else {
-                                tcx.map.local_def_id(const_node_id)
-                            };
-
-                            collect_const_item_neighbours(self.scx,
-                                                          def_id,
-                                                          substs,
-                                                          self.output);
-                        }
+                        let instance = Instance::new(def_id, substs).resolve_const(self.scx);
+                        collect_neighbours(self.scx, instance, self.output);
                     }
 
                     None
@@ -723,23 +679,17 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 
     debug!("find_drop_glue_neighbors: {}", type_to_string(scx.tcx(), ty));
 
-    // Make sure the exchange_free_fn() lang-item gets translated if
-    // there is a boxed value.
-    if let ty::TyBox(_) = ty.sty {
-        let exchange_free_fn_def_id = scx.tcx()
-                                         .lang_items
-                                         .require(ExchangeFreeFnLangItem)
-                                         .unwrap_or_else(|e| scx.sess().fatal(&e));
-
-        assert!(can_have_local_instance(scx.tcx(), exchange_free_fn_def_id));
-        let fn_substs = scx.empty_substs_for_def_id(exchange_free_fn_def_id);
-        let exchange_free_fn_trans_item =
+    // Make sure the BoxFreeFn lang-item gets translated if there is a boxed value.
+    if let ty::TyBox(content_type) = ty.sty {
+        let def_id = scx.tcx().require_lang_item(BoxFreeFnLangItem);
+        assert!(can_have_local_instance(scx.tcx(), def_id));
+        let box_free_fn_trans_item =
             create_fn_trans_item(scx,
-                                 exchange_free_fn_def_id,
-                                 fn_substs,
+                                 def_id,
+                                 scx.tcx().mk_substs(iter::once(Kind::from(content_type))),
                                  scx.tcx().intern_substs(&[]));
 
-        output.push(exchange_free_fn_trans_item);
+        output.push(box_free_fn_trans_item);
     }
 
     // If the type implements Drop, also add a translation item for the
@@ -1126,6 +1076,11 @@ fn visit_item(&mut self, item: &'v hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _: &'v hir::TraitItem) {
+        // Even if there's a default body with no explicit generics,
+        // it's still generic over some `Self: Trait`, so not a root.
+    }
+
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Method(hir::MethodSig {
@@ -1232,29 +1187,20 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
     }
 }
 
-// There are no translation items for constants themselves but their
-// initializers might still contain something that produces translation items,
-// such as cast that introduce a new vtable.
-fn collect_const_item_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                           def_id: DefId,
-                                           substs: &'tcx Substs<'tcx>,
-                                           output: &mut Vec<TransItem<'tcx>>)
+/// Scan the MIR in order to find function calls, closures, and drop-glue
+fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                                instance: Instance<'tcx>,
+                                output: &mut Vec<TransItem<'tcx>>)
 {
-    // Scan the MIR in order to find function calls, closures, and
-    // drop-glue
-    let mir = scx.tcx().item_mir(def_id);
+    let mir = scx.tcx().item_mir(instance.def);
 
-    let visitor = MirNeighborCollector {
+    let mut visitor = MirNeighborCollector {
         scx: scx,
         mir: &mir,
         output: output,
-        param_substs: substs
+        param_substs: instance.substs
     };
 
-    visit_mir_and_promoted(visitor, &mir);
-}
-
-fn visit_mir_and_promoted<'tcx, V: MirVisitor<'tcx>>(mut visitor: V, mir: &mir::Mir<'tcx>) {
     visitor.visit_mir(&mir);
     for promoted in &mir.promoted {
         visitor.visit_mir(promoted);
index f292a70965004c0a2c3964b043d1842cc1889e5b..d9179d6a6fa73888a7f9e4a5c4fad00562364518 100644 (file)
@@ -737,14 +737,6 @@ pub fn drop_glues<'a>(&'a self)
         &self.local().drop_glues
     }
 
-    pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option<ast::NodeId> {
-        self.sess().cstore.local_node_for_inlined_defid(def_id)
-    }
-
-    pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> {
-        self.sess().cstore.defid_for_inlined_node(node_id)
-    }
-
     pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
         &self.local().instances
     }
index 7549f80f94db85f6d9473d4921735e809ac7eda5..3989dae553ffca928818fe265bd40b83702ac7f9 100644 (file)
 // Code relating to drop glue.
 
 use std;
+use std::iter;
 
 use llvm;
 use llvm::{ValueRef, get_param};
-use middle::lang_items::ExchangeFreeFnLangItem;
+use middle::lang_items::BoxFreeFnLangItem;
 use rustc::ty::subst::{Substs};
 use rustc::traits;
 use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc::ty::subst::Kind;
 use adt::{self, MaybeSizedValue};
 use base::*;
 use callee::Callee;
 
 use syntax_pos::DUMMY_SP;
 
-pub fn trans_exchange_free_dyn<'a, 'tcx>(
+pub fn trans_exchange_free_ty<'a, 'tcx>(
     bcx: &BlockAndBuilder<'a, 'tcx>,
-    v: ValueRef,
-    size: ValueRef,
-    align: ValueRef
+    ptr: MaybeSizedValue,
+    content_ty: Ty<'tcx>
 ) {
-    let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem);
-    let args = [bcx.pointercast(v, Type::i8p(bcx.ccx)), size, align];
-    let callee = Callee::def(bcx.ccx, def_id, bcx.tcx().intern_substs(&[]));
+    let def_id = langcall(bcx.tcx(), None, "", BoxFreeFnLangItem);
+    let substs = bcx.tcx().mk_substs(iter::once(Kind::from(content_ty)));
+    let callee = Callee::def(bcx.ccx, def_id, substs);
 
-    let ccx = bcx.ccx;
-    let fn_ty = callee.direct_fn_type(ccx, &[]);
+    let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
 
-    let llret = bcx.call(callee.reify(ccx), &args[..], None);
+    let llret = bcx.call(callee.reify(bcx.ccx),
+        &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize], None);
     fn_ty.apply_attrs_callsite(llret);
 }
 
-pub fn trans_exchange_free_ty<'a, 'tcx>(
-    bcx: &BlockAndBuilder<'a, 'tcx>, ptr: ValueRef, content_ty: Ty<'tcx>
-) {
-    assert!(bcx.ccx.shared().type_is_sized(content_ty));
-    let sizing_type = sizing_type_of(bcx.ccx, content_ty);
-    let content_size = llsize_of_alloc(bcx.ccx, sizing_type);
-
-    // `Box<ZeroSizeType>` does not allocate.
-    if content_size != 0 {
-        let content_align = align_of(bcx.ccx, content_ty);
-        let ccx = bcx.ccx;
-        trans_exchange_free_dyn(bcx, ptr, C_uint(ccx, content_size), C_uint(ccx, content_align));
-    }
-}
-
 pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
     assert!(t.is_normalized_for_trans());
 
@@ -224,30 +210,16 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
             // special. It may move to library and have Drop impl. As
             // a safe-guard, assert TyBox not used with TyContents.
             assert!(!skip_dtor);
-            if !bcx.ccx.shared().type_is_sized(content_ty) {
+            let ptr = if !bcx.ccx.shared().type_is_sized(content_ty) {
                 let llbox = bcx.load(get_dataptr(&bcx, ptr.value));
                 let info = bcx.load(get_meta(&bcx, ptr.value));
-                drop_ty(&bcx, MaybeSizedValue::unsized_(llbox, info), content_ty);
-                let (llsize, llalign) = size_and_align_of_dst(&bcx, content_ty, info);
-
-                // `Box<ZeroSizeType>` does not allocate.
-                let needs_free = bcx.icmp(llvm::IntNE, llsize, C_uint(bcx.ccx, 0u64));
-                if const_to_opt_uint(needs_free) == Some(0) {
-                    bcx
-                } else {
-                    let next_cx = bcx.fcx().build_new_block("next");
-                    let cond_cx = bcx.fcx().build_new_block("cond");
-                    bcx.cond_br(needs_free, cond_cx.llbb(), next_cx.llbb());
-                    trans_exchange_free_dyn(&cond_cx, llbox, llsize, llalign);
-                    cond_cx.br(next_cx.llbb());
-                    next_cx
-                }
+                MaybeSizedValue::unsized_(llbox, info)
             } else {
-                let llbox = bcx.load(ptr.value);
-                drop_ty(&bcx, MaybeSizedValue::sized(llbox), content_ty);
-                trans_exchange_free_ty(&bcx, llbox, content_ty);
-                bcx
-            }
+                MaybeSizedValue::sized(bcx.load(ptr.value))
+            };
+            drop_ty(&bcx, ptr, content_ty);
+            trans_exchange_free_ty(&bcx, ptr, content_ty);
+            bcx
         }
         ty::TyDynamic(..) => {
             // No support in vtable for distinguishing destroying with
index 08f68f8d49c78a8465ff7c5ec56d239a10e0b729..1cedaa0a4e1a4ee68d9da82dd60fd881c41befff 100644 (file)
@@ -18,7 +18,6 @@
 use rustc::infer::TransNormalize;
 use rustc::mir;
 use rustc::mir::tcx::LvalueTy;
-use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::subst::Substs;
@@ -36,7 +35,7 @@
 use value::Value;
 
 use syntax::ast;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::Span;
 
 use std::fmt;
 use std::ptr;
@@ -238,24 +237,10 @@ fn new(ccx: &'a CrateContext<'a, 'tcx>,
     }
 
     fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
-                 mut instance: Instance<'tcx>,
+                 instance: Instance<'tcx>,
                  args: IndexVec<mir::Local, Const<'tcx>>)
                  -> Result<Const<'tcx>, ConstEvalErr> {
-        // Try to resolve associated constants.
-        if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) {
-            let trait_ref = ty::TraitRef::new(trait_id, instance.substs);
-            let trait_ref = ty::Binder(trait_ref);
-            let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
-            if let traits::VtableImpl(vtable_impl) = vtable {
-                let name = ccx.tcx().item_name(instance.def);
-                let ac = ccx.tcx().associated_items(vtable_impl.impl_def_id)
-                    .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
-                if let Some(ac) = ac {
-                    instance = Instance::new(ac.def_id, vtable_impl.substs);
-                }
-            }
-        }
-
+        let instance = instance.resolve_const(ccx.shared());
         let mir = ccx.tcx().item_mir(instance.def);
         MirConstContext::new(ccx, &mir, instance.substs, args).trans()
     }
index 8f05cc793ef224f73b35f4eed64d3273b706874d..4b31d5b7f88de1ac9258351683a9c222e41e8c72 100644 (file)
 use common::*;
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
+use rustc::traits;
 use rustc::ty::fold::{TypeFolder, TypeFoldable};
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::ppaux;
 use rustc::util::common::MemoizationMap;
+
+use syntax::codemap::DUMMY_SP;
+
 use std::fmt;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -30,15 +34,35 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> Instance<'tcx> {
+impl<'a, 'tcx> Instance<'tcx> {
     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
                -> Instance<'tcx> {
         assert!(substs.regions().all(|&r| r == ty::ReErased));
         Instance { def: def_id, substs: substs }
     }
-    pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
+
+    pub fn mono(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
         Instance::new(def_id, scx.empty_substs_for_def_id(def_id))
     }
+
+    /// For associated constants from traits, return the impl definition.
+    pub fn resolve_const(&self, scx: &SharedCrateContext<'a, 'tcx>) -> Self {
+        if let Some(trait_id) = scx.tcx().trait_of_item(self.def) {
+            let trait_ref = ty::TraitRef::new(trait_id, self.substs);
+            let trait_ref = ty::Binder(trait_ref);
+            let vtable = fulfill_obligation(scx, DUMMY_SP, trait_ref);
+            if let traits::VtableImpl(vtable_impl) = vtable {
+                let name = scx.tcx().item_name(self.def);
+                let ac = scx.tcx().associated_items(vtable_impl.impl_def_id)
+                    .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
+                if let Some(ac) = ac {
+                    return Instance::new(ac.def_id, vtable_impl.substs);
+                }
+            }
+        }
+
+        *self
+    }
 }
 
 /// Monomorphizes a type from the AST by first applying the in-scope
index 598003a3925127607c4347cf77c4e177ad4beb4e..75c25a605af252cd6a57138c857d4cafe6d3b033 100644 (file)
 
 use rustc_const_eval::eval_length;
 use rustc_data_structures::accumulate_vec::AccumulateVec;
-use hir::{self, SelfKind};
+use hir;
 use hir::def::Def;
 use hir::def_id::DefId;
-use hir::print as pprust;
 use middle::resolve_lifetime as rl;
 use rustc::lint;
 use rustc::ty::subst::{Kind, Subst, Substs};
@@ -227,6 +226,7 @@ pub fn ast_region_to_region<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 }
 
 fn report_elision_failure(
+    tcx: TyCtxt,
     db: &mut DiagnosticBuilder,
     params: Vec<ElisionFailureInfo>)
 {
@@ -241,13 +241,14 @@ fn report_elision_failure(
 
     for (i, info) in elided_params.into_iter().enumerate() {
         let ElisionFailureInfo {
-            name, lifetime_count: n, have_bound_regions
+            parent, index, lifetime_count: n, have_bound_regions
         } = info;
 
-        let help_name = if name.is_empty() {
-            format!("argument {}", i + 1)
+        let help_name = if let Some(body) = parent {
+            let arg = &tcx.map.body(body).arguments[index];
+            format!("`{}`", tcx.map.node_to_pretty_string(arg.pat.id))
         } else {
-            format!("`{}`", name)
+            format!("argument {}", index + 1)
         };
 
         m.push_str(&(if n == 1 {
@@ -315,7 +316,7 @@ pub fn opt_ast_region_to_region(&self,
                     err.span_label(ampersand_span, &format!("expected lifetime parameter"));
 
                     if let Some(params) = params {
-                        report_elision_failure(&mut err, params);
+                        report_elision_failure(self.tcx(), &mut err, params);
                     }
                     err.emit();
                     ty::ReStatic
@@ -540,15 +541,16 @@ fn create_substs_for_ast_path(&self,
     /// corresponding to each input type/pattern.
     fn find_implied_output_region<I>(&self,
                                      input_tys: &[Ty<'tcx>],
-                                     input_pats: I) -> ElidedLifetime
-        where I: Iterator<Item=String>
+                                     parent: Option<hir::BodyId>,
+                                     input_indices: I) -> ElidedLifetime
+        where I: Iterator<Item=usize>
     {
         let tcx = self.tcx();
         let mut lifetimes_for_params = Vec::with_capacity(input_tys.len());
         let mut possible_implied_output_region = None;
         let mut lifetimes = 0;
 
-        for input_type in input_tys.iter() {
+        for (input_type, index) in input_tys.iter().zip(input_indices) {
             let mut regions = FxHashSet();
             let have_bound_regions = tcx.collect_regions(input_type, &mut regions);
 
@@ -564,11 +566,9 @@ fn find_implied_output_region<I>(&self,
                 possible_implied_output_region = regions.iter().cloned().next();
             }
 
-            // Use a placeholder for `name` because computing it can be
-            // expensive and we don't want to do it until we know it's
-            // necessary.
             lifetimes_for_params.push(ElisionFailureInfo {
-                name: String::new(),
+                parent: parent,
+                index: index,
                 lifetime_count: regions.len(),
                 have_bound_regions: have_bound_regions
             });
@@ -577,11 +577,6 @@ fn find_implied_output_region<I>(&self,
         if lifetimes == 1 {
             Ok(*possible_implied_output_region.unwrap())
         } else {
-            // Fill in the expensive `name` fields now that we know they're
-            // needed.
-            for (info, input_pat) in lifetimes_for_params.iter_mut().zip(input_pats) {
-                info.name = input_pat;
-            }
             Err(Some(lifetimes_for_params))
         }
     }
@@ -618,8 +613,8 @@ fn convert_parenthesized_parameters(&self,
         let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
             self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
         }));
-        let input_params = iter::repeat(String::new()).take(inputs.len());
-        let implied_output_region = self.find_implied_output_region(&inputs, input_params);
+        let input_params = 0..inputs.len();
+        let implied_output_region = self.find_implied_output_region(&inputs, None, input_params);
 
         let (output, output_span) = match data.output {
             Some(ref output_ty) => {
@@ -689,7 +684,7 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
             }
             _ => {
                 span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait",
-                            path);
+                            self.tcx().map.node_to_pretty_string(trait_ref.ref_id));
             }
         }
     }
@@ -976,7 +971,7 @@ fn ast_ty_to_object_trait_ref(&self,
                 let mut err = struct_span_err!(tcx.sess, ty.span, E0178,
                                                "expected a path on the left-hand side \
                                                 of `+`, not `{}`",
-                                               pprust::ty_to_string(ty));
+                                               tcx.map.node_to_pretty_string(ty.id));
                 err.span_label(ty.span, &format!("expected a path"));
                 let hi = bounds.iter().map(|x| match *x {
                     hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
@@ -988,22 +983,21 @@ fn ast_ty_to_object_trait_ref(&self,
                     expn_id: ty.span.expn_id,
                 });
                 match (&ty.node, full_span) {
-                    (&hir::TyRptr(None, ref mut_ty), Some(full_span)) => {
-                        let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
+                    (&hir::TyRptr(ref lifetime, ref mut_ty), Some(full_span)) => {
+                        let ty_str = hir::print::to_string(&tcx.map, |s| {
+                            use syntax::print::pp::word;
+                            use syntax::print::pprust::PrintState;
+
+                            word(&mut s.s, "&")?;
+                            s.print_opt_lifetime(lifetime)?;
+                            s.print_mutability(mut_ty.mutbl)?;
+                            s.popen()?;
+                            s.print_type(&mut_ty.ty)?;
+                            s.print_bounds(" +", bounds)?;
+                            s.pclose()
+                        });
                         err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
-                                            format!("&{}({} +{})",
-                                                    mutbl_str,
-                                                    pprust::ty_to_string(&mut_ty.ty),
-                                                    pprust::bounds_to_string(bounds)));
-                    }
-                    (&hir::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
-                        let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
-                        err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
-                                            format!("&{} {}({} +{})",
-                                                    pprust::lifetime_to_string(lt),
-                                                    mutbl_str,
-                                                    pprust::ty_to_string(&mut_ty.ty),
-                                                    pprust::bounds_to_string(bounds)));
+                                            ty_str);
                     }
 
                     _ => {
@@ -1572,6 +1566,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                                                               bf.abi,
                                                               None,
                                                               &bf.decl,
+                                                              None,
                                                               anon_scope,
                                                               anon_scope);
 
@@ -1664,8 +1659,9 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 };
                 self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
             }
-            hir::TyArray(ref ty, ref e) => {
-                if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
+            hir::TyArray(ref ty, length) => {
+                let e = &tcx.map.body(length).value;
+                if let Ok(length) = eval_length(tcx.global_tcx(), e, "array length") {
                     tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
                 } else {
                     self.tcx().types.err
@@ -1695,26 +1691,28 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
 
     pub fn ty_of_arg(&self,
                      rscope: &RegionScope,
-                     a: &hir::Arg,
+                     ty: &hir::Ty,
                      expected_ty: Option<Ty<'tcx>>)
                      -> Ty<'tcx>
     {
-        match a.ty.node {
+        match ty.node {
             hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
-            hir::TyInfer => self.ty_infer(a.ty.span),
-            _ => self.ast_ty_to_ty(rscope, &a.ty),
+            hir::TyInfer => self.ty_infer(ty.span),
+            _ => self.ast_ty_to_ty(rscope, ty),
         }
     }
 
     pub fn ty_of_method(&self,
                         sig: &hir::MethodSig,
-                        untransformed_self_ty: Ty<'tcx>,
+                        opt_self_value_ty: Option<Ty<'tcx>>,
+                        body: Option<hir::BodyId>,
                         anon_scope: Option<AnonTypeScope>)
                         -> &'tcx ty::BareFnTy<'tcx> {
         self.ty_of_method_or_bare_fn(sig.unsafety,
                                      sig.abi,
-                                     Some(untransformed_self_ty),
+                                     opt_self_value_ty,
                                      &sig.decl,
+                                     body,
                                      None,
                                      anon_scope)
     }
@@ -1723,16 +1721,18 @@ pub fn ty_of_bare_fn(&self,
                          unsafety: hir::Unsafety,
                          abi: abi::Abi,
                          decl: &hir::FnDecl,
+                         body: hir::BodyId,
                          anon_scope: Option<AnonTypeScope>)
                          -> &'tcx ty::BareFnTy<'tcx> {
-        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope)
+        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, Some(body), None, anon_scope)
     }
 
     fn ty_of_method_or_bare_fn(&self,
                                unsafety: hir::Unsafety,
                                abi: abi::Abi,
-                               opt_untransformed_self_ty: Option<Ty<'tcx>>,
+                               opt_self_value_ty: Option<Ty<'tcx>>,
                                decl: &hir::FnDecl,
+                               body: Option<hir::BodyId>,
                                arg_anon_scope: Option<AnonTypeScope>,
                                ret_anon_scope: Option<AnonTypeScope>)
                                -> &'tcx ty::BareFnTy<'tcx>
@@ -1743,38 +1743,29 @@ fn ty_of_method_or_bare_fn(&self,
         // declaration are bound to that function type.
         let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope);
 
-        // `implied_output_region` is the region that will be assumed for any
-        // region parameters in the return type. In accordance with the rules for
-        // lifetime elision, we can determine it in two ways. First (determined
-        // here), if self is by-reference, then the implied output region is the
-        // region of the self parameter.
-        let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) {
-            (Some(untransformed_self_ty), Some(explicit_self)) => {
-                let self_type = self.determine_self_type(&rb, untransformed_self_ty,
-                                                         &explicit_self);
-                (Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type)))
-            }
-            _ => (None, None),
-        };
+        let input_tys: Vec<Ty> =
+            decl.inputs.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
 
-        // HACK(eddyb) replace the fake self type in the AST with the actual type.
-        let arg_params = if self_ty.is_some() {
-            &decl.inputs[1..]
-        } else {
-            &decl.inputs[..]
-        };
-        let arg_tys: Vec<Ty> =
-            arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
+        let has_self = opt_self_value_ty.is_some();
+        let explicit_self = opt_self_value_ty.map(|self_value_ty| {
+            ExplicitSelf::determine(self_value_ty, input_tys[0])
+        });
 
-        // Second, if there was exactly one lifetime (either a substitution or a
-        // reference) in the arguments, then any anonymous regions in the output
-        // have that lifetime.
         let implied_output_region = match explicit_self {
+            // `implied_output_region` is the region that will be assumed for any
+            // region parameters in the return type. In accordance with the rules for
+            // lifetime elision, we can determine it in two ways. First (determined
+            // here), if self is by-reference, then the implied output region is the
+            // region of the self parameter.
             Some(ExplicitSelf::ByReference(region, _)) => Ok(*region),
+
+            // Second, if there was exactly one lifetime (either a substitution or a
+            // reference) in the arguments, then any anonymous regions in the output
+            // have that lifetime.
             _ => {
-                self.find_implied_output_region(&arg_tys,
-                                                arg_params.iter()
-                                                    .map(|a| pprust::pat_to_string(&a.pat)))
+                let arg_tys = &input_tys[has_self as usize..];
+                let arg_params = has_self as usize..input_tys.len();
+                self.find_implied_output_region(arg_tys, body, arg_params)
 
             }
         };
@@ -1793,37 +1784,13 @@ fn ty_of_method_or_bare_fn(&self,
             unsafety: unsafety,
             abi: abi,
             sig: ty::Binder(self.tcx().mk_fn_sig(
-                self_ty.into_iter().chain(arg_tys),
+                input_tys.into_iter(),
                 output_ty,
                 decl.variadic
             )),
         })
     }
 
-    fn determine_self_type<'a>(&self,
-                               rscope: &RegionScope,
-                               untransformed_self_ty: Ty<'tcx>,
-                               explicit_self: &hir::ExplicitSelf)
-                               -> Ty<'tcx>
-    {
-        match explicit_self.node {
-            SelfKind::Value(..) => untransformed_self_ty,
-            SelfKind::Region(ref lifetime, mutability) => {
-                let region =
-                    self.opt_ast_region_to_region(
-                                             rscope,
-                                             explicit_self.span,
-                                             lifetime);
-                self.tcx().mk_ref(region,
-                    ty::TypeAndMut {
-                        ty: untransformed_self_ty,
-                        mutbl: mutability
-                    })
-            }
-            SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type)
-        }
-    }
-
     pub fn ty_of_closure(&self,
         unsafety: hir::Unsafety,
         decl: &hir::FnDecl,
index ff50ee11b390e674a703b9cdd9837a22676da5af..9b86196b3ece234b91eb760575bd23989362d14d 100644 (file)
@@ -527,7 +527,8 @@ fn check_pat_path(&self,
         let report_unexpected_def = |def: Def| {
             span_err!(tcx.sess, pat.span, E0533,
                       "expected unit struct/variant or constant, found {} `{}`",
-                      def.kind_name(), qpath);
+                      def.kind_name(),
+                      hir::print::to_string(&tcx.map, |s| s.print_qpath(qpath, false)));
         };
 
         // Resolve the path and check the definition for errors.
@@ -568,7 +569,8 @@ fn check_pat_tuple_struct(&self,
         };
         let report_unexpected_def = |def: Def| {
             let msg = format!("expected tuple struct/variant, found {} `{}`",
-                              def.kind_name(), qpath);
+                              def.kind_name(),
+                              hir::print::to_string(&tcx.map, |s| s.print_qpath(qpath, false)));
             struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
                 .span_label(pat.span, &format!("not a tuple variant or struct")).emit();
             on_error();
index 4fba29def226c6eb0a0ed0fa359962e245eac116..0b9cf38fa073316a3d1adffa112f545029a1a013 100644 (file)
@@ -13,7 +13,6 @@
 use CrateCtxt;
 use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
-use hir::print;
 use rustc::{infer, traits};
 use rustc::ty::{self, LvaluePreference, Ty};
 use syntax::symbol::Symbol;
@@ -203,7 +202,7 @@ fn confirm_builtin_call(&self,
                 if let &ty::TyAdt(adt_def, ..) = t {
                     if adt_def.is_enum() {
                         if let hir::ExprCall(ref expr, _) = call_expr.node {
-                            unit_variant = Some(print::expr_to_string(expr))
+                            unit_variant = Some(self.tcx.map.node_to_pretty_string(expr.id))
                         }
                     }
                 }
index 1d81ed7d35956145de42a0d8d23ab3fb2bb67006..9412c9105c7aa572758785457f3ce5c366622efe 100644 (file)
@@ -25,7 +25,7 @@ pub fn check_expr_closure(&self,
                               expr: &hir::Expr,
                               _capture: hir::CaptureClause,
                               decl: &'gcx hir::FnDecl,
-                              body_id: hir::ExprId,
+                              body_id: hir::BodyId,
                               expected: Expectation<'tcx>)
                               -> Ty<'tcx> {
         debug!("check_expr_closure(expr={:?},expected={:?})",
@@ -39,7 +39,7 @@ pub fn check_expr_closure(&self,
             Some(ty) => self.deduce_expectations_from_expected_type(ty),
             None => (None, None),
         };
-        let body = self.tcx.map.expr(body_id);
+        let body = self.tcx.map.body(body_id);
         self.check_closure(expr, expected_kind, decl, body, expected_sig)
     }
 
@@ -47,7 +47,7 @@ fn check_closure(&self,
                      expr: &hir::Expr,
                      opt_kind: Option<ty::ClosureKind>,
                      decl: &'gcx hir::FnDecl,
-                     body: &'gcx hir::Expr,
+                     body: &'gcx hir::Body,
                      expected_sig: Option<ty::FnSig<'tcx>>)
                      -> Ty<'tcx> {
         debug!("check_closure opt_kind={:?} expected_sig={:?}",
@@ -73,10 +73,10 @@ fn check_closure(&self,
 
         debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
 
-        let fn_sig = self.tcx
-            .liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id),
-                                         &fn_ty.sig);
-        let fn_sig = (**self).normalize_associated_types_in(body.span, body.id, &fn_sig);
+        let extent = self.tcx.region_maps.call_site_extent(expr.id, body.value.id);
+        let fn_sig = self.tcx.liberate_late_bound_regions(extent, &fn_ty.sig);
+        let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
+                                                            body.value.id, &fn_sig);
 
         check_fn(self,
                  hir::Unsafety::Normal,
@@ -84,7 +84,7 @@ fn check_closure(&self,
                  &fn_sig,
                  decl,
                  expr.id,
-                 &body);
+                 body);
 
         // Tuple up the arguments and insert the resulting function type into
         // the `closures` table.
index 478de1673170f79ea03cb1836a421d3cccf88c19..be10b77bd8b90c33ea0e5ea6c13c28945329a26e 100644 (file)
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::hir;
+use rustc::hir::{self, ImplItemKind, TraitItemKind};
 use rustc::infer::{self, InferOk};
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::ty;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
 use rustc::ty::subst::{Subst, Substs};
-use rustc::hir::{ImplItemKind, TraitItem_, Ty_};
 use rustc::util::common::ErrorReported;
 
 use syntax::ast;
@@ -450,37 +449,24 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
         TypeError::Mutability => {
             if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                 let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node {
-                    TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                    TraitItemKind::Method(ref trait_m_sig, _) => {
                         trait_m_sig.decl.inputs.iter()
                     }
-                    _ => bug!("{:?} is not a MethodTraitItem", trait_m),
+                    _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
                 };
 
-                impl_m_iter.zip(trait_m_iter)
-                           .find(|&(ref impl_arg, ref trait_arg)| {
-                               match (&impl_arg.ty.node, &trait_arg.ty.node) {
-                                   (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) |
-                                   (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) => {
-                                       impl_mt.mutbl != trait_mt.mutbl
-                                   }
-                                   _ => false,
-                               }
-                           })
-                           .map(|(ref impl_arg, ref trait_arg)| {
-                               match (impl_arg.to_self(), trait_arg.to_self()) {
-                                   (Some(impl_self), Some(trait_self)) => {
-                                       (impl_self.span, Some(trait_self.span))
-                                   }
-                                   (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)),
-                                   _ => {
-                                       bug!("impl and trait fns have different first args, impl: \
-                                             {:?}, trait: {:?}",
-                                            impl_arg,
-                                            trait_arg)
-                                   }
-                               }
-                           })
-                           .unwrap_or((cause.span, tcx.map.span_if_local(trait_m.def_id)))
+                impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| {
+                    match (&impl_arg.node, &trait_arg.node) {
+                        (&hir::TyRptr(_, ref impl_mt), &hir::TyRptr(_, ref trait_mt)) |
+                        (&hir::TyPtr(ref impl_mt), &hir::TyPtr(ref trait_mt)) => {
+                            impl_mt.mutbl != trait_mt.mutbl
+                        }
+                        _ => false,
+                    }
+                }).map(|(ref impl_arg, ref trait_arg)| {
+                    (impl_arg.span, Some(trait_arg.span))
+                })
+                .unwrap_or_else(|| (cause.span, tcx.map.span_if_local(trait_m.def_id)))
             } else {
                 (cause.span, tcx.map.span_if_local(trait_m.def_id))
             }
@@ -489,10 +475,10 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
             if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                 let (trait_m_output, trait_m_iter) =
                     match tcx.map.expect_trait_item(trait_m_node_id).node {
-                        TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                        TraitItemKind::Method(ref trait_m_sig, _) => {
                             (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter())
                         }
-                        _ => bug!("{:?} is not a MethodTraitItem", trait_m),
+                        _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
                     };
 
                 let impl_iter = impl_sig.inputs().iter();
@@ -503,7 +489,7 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
                          .filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| {
                              match infcx.sub_types(true, &cause, trait_arg_ty, impl_arg_ty) {
                                  Ok(_) => None,
-                                 Err(_) => Some((impl_arg.ty.span, Some(trait_arg.ty.span))),
+                                 Err(_) => Some((impl_arg.span, Some(trait_arg.span))),
                              }
                          })
                          .next()
@@ -688,13 +674,13 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let trait_m_node_id = tcx.map.as_local_node_id(trait_m.def_id);
         let trait_span = if let Some(trait_id) = trait_m_node_id {
             match tcx.map.expect_trait_item(trait_id).node {
-                TraitItem_::MethodTraitItem(ref trait_m_sig, _) => {
+                TraitItemKind::Method(ref trait_m_sig, _) => {
                     if let Some(arg) = trait_m_sig.decl.inputs.get(if trait_number_args > 0 {
                         trait_number_args - 1
                     } else {
                         0
                     }) {
-                        Some(arg.pat.span)
+                        Some(arg.span)
                     } else {
                         trait_item_span
                     }
@@ -712,7 +698,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 } else {
                     0
                 }) {
-                    arg.pat.span
+                    arg.span
                 } else {
                     impl_m_span
                 }
@@ -839,7 +825,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             // Add a label to the Span containing just the type of the item
             let trait_c_node_id = tcx.map.as_local_node_id(trait_c.def_id).unwrap();
             let trait_c_span = match tcx.map.expect_trait_item(trait_c_node_id).node {
-                TraitItem_::ConstTraitItem(ref ty, _) => ty.span,
+                TraitItemKind::Const(ref ty, _) => ty.span,
                 _ => bug!("{:?} is not a trait const", trait_c),
             };
 
index 183a2a48ff523664a30cf9dd0d165bdefb64244c..c733c0856c6da2d12ad75e949413eef0ff1bfa8a 100644 (file)
@@ -48,7 +48,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let i_n_tps = tcx.item_generics(def_id).types.len();
     if i_n_tps != n_tps {
         let span = match it.node {
-            hir::ForeignItemFn(_, ref generics) => generics.span,
+            hir::ForeignItemFn(_, _, ref generics) => generics.span,
             hir::ForeignItemStatic(..) => it.span
         };
 
index 86bfede87b333c6d6e7a7897c8d95d991fdf905c..04ec9292d1410ee727c3684ffe90b060adcb2df1 100644 (file)
@@ -26,7 +26,6 @@
 use errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
-use rustc::hir::print as pprust;
 use rustc::hir;
 use rustc::infer::type_variable::TypeVariableOrigin;
 
@@ -266,7 +265,7 @@ macro_rules! report_function {
                 let msg = if let Some(callee) = rcvr_expr {
                     format!("{}; use overloaded call notation instead (e.g., `{}()`)",
                             msg,
-                            pprust::expr_to_string(callee))
+                            self.tcx.map.node_to_pretty_string(callee.id))
                 } else {
                     msg
                 };
@@ -463,6 +462,9 @@ fn visit_item(&mut self, i: &'v hir::Item) {
                 }
             }
 
+            fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+            }
+
             fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
             }
         }
index a2dceed8d2653f4c74261db5714e963d2dfabd54..7275fbd12036b308768b7fc53259bf3c8e28384b 100644 (file)
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::{self, PatKind};
-use rustc::hir::print as pprust;
 use rustc::middle::lang_items;
 use rustc_back::slice;
 use rustc_const_eval::eval_length;
@@ -550,14 +549,25 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
 
     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
         match t.node {
-            hir::TyArray(_, ref expr) => {
-                check_const_with_type(self.ccx, &expr, self.ccx.tcx.types.usize, expr.id);
+            hir::TyArray(_, length) => {
+                check_const_with_type(self.ccx, length, self.ccx.tcx.types.usize, length.node_id);
             }
             _ => {}
         }
 
         intravisit::walk_ty(self, t);
     }
+
+    fn visit_expr(&mut self, e: &'tcx hir::Expr) {
+        match e.node {
+            hir::ExprRepeat(_, count) => {
+                check_const_with_type(self.ccx, count, self.ccx.tcx.types.usize, count.node_id);
+            }
+            _ => {}
+        }
+
+        intravisit::walk_expr(self, e);
+    }
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
@@ -565,6 +575,10 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
         check_item_body(self.ccx, i);
     }
 
+    fn visit_trait_item(&mut self, _item: &'tcx hir::TraitItem) {
+        // done as part of `visit_item` above
+    }
+
     fn visit_impl_item(&mut self, _item: &'tcx hir::ImplItem) {
         // done as part of `visit_item` above
     }
@@ -635,28 +649,28 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
 
 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            decl: &'tcx hir::FnDecl,
-                           body_id: hir::ExprId,
+                           body_id: hir::BodyId,
                            fn_id: ast::NodeId,
                            span: Span) {
-    let body = ccx.tcx.map.expr(body_id);
+    let body = ccx.tcx.map.body(body_id);
 
     let raw_fty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(fn_id));
     let fn_ty = match raw_fty.sty {
         ty::TyFnDef(.., f) => f,
-        _ => span_bug!(body.span, "check_bare_fn: function type expected")
+        _ => span_bug!(body.value.span, "check_bare_fn: function type expected")
     };
 
     check_abi(ccx, span, fn_ty.abi);
 
     ccx.inherited(fn_id).enter(|inh| {
         // Compute the fty from point of view of inside fn.
-        let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id());
+        let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id);
         let fn_sig =
             fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
         let fn_sig =
             inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
         let fn_sig =
-            inh.normalize_associated_types_in(body.span, body_id.node_id(), &fn_sig);
+            inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
 
         let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body);
 
@@ -666,8 +680,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         fcx.check_casts();
         fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
 
-        fcx.regionck_fn(fn_id, decl, body_id);
-        fcx.resolve_type_vars_in_fn(decl, body, fn_id);
+        fcx.regionck_fn(fn_id, body);
+        fcx.resolve_type_vars_in_body(body, fn_id);
     });
 }
 
@@ -736,32 +750,9 @@ fn visit_pat(&mut self, p: &'gcx hir::Pat) {
         intravisit::walk_pat(self, p);
     }
 
-    fn visit_block(&mut self, b: &'gcx hir::Block) {
-        // non-obvious: the `blk` variable maps to region lb, so
-        // we have to keep this up-to-date.  This
-        // is... unfortunate.  It'd be nice to not need this.
-        intravisit::walk_block(self, b);
-    }
-
-    // Since an expr occurs as part of the type fixed size arrays we
-    // need to record the type for that node
-    fn visit_ty(&mut self, t: &'gcx hir::Ty) {
-        match t.node {
-            hir::TyArray(ref ty, ref count_expr) => {
-                self.visit_ty(&ty);
-                self.fcx.check_expr_with_hint(&count_expr, self.fcx.tcx.types.usize);
-            }
-            hir::TyBareFn(ref function_declaration) => {
-                intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
-                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
-            }
-            _ => intravisit::walk_ty(self, t)
-        }
-    }
-
     // Don't descend into the bodies of nested closures
     fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
-                _: hir::ExprId, _: Span, _: ast::NodeId) { }
+                _: hir::BodyId, _: Span, _: ast::NodeId) { }
 }
 
 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
@@ -776,7 +767,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                             fn_sig: &ty::FnSig<'tcx>,
                             decl: &'gcx hir::FnDecl,
                             fn_id: ast::NodeId,
-                            body: &'gcx hir::Expr)
+                            body: &'gcx hir::Body)
                             -> FnCtxt<'a, 'gcx, 'tcx>
 {
     let mut fn_sig = fn_sig.clone();
@@ -785,7 +776,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Create the function context.  This is either derived from scratch or,
     // in the case of function expressions, based on the outer context.
-    let mut fcx = FnCtxt::new(inherited, None, body.id);
+    let mut fcx = FnCtxt::new(inherited, None, body.value.id);
     let ret_ty = fn_sig.output();
     *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id);
 
@@ -794,36 +785,26 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     fn_sig = fcx.tcx.mk_fn_sig(fn_sig.inputs().iter().cloned(), &fcx.ret_ty.unwrap(),
                                fn_sig.variadic);
 
-    {
-        let mut visit = GatherLocalsVisitor { fcx: &fcx, };
-
-        // Add formal parameters.
-        for (arg_ty, input) in fn_sig.inputs().iter().zip(&decl.inputs) {
-            // The type of the argument must be well-formed.
-            //
-            // NB -- this is now checked in wfcheck, but that
-            // currently only results in warnings, so we issue an
-            // old-style WF obligation here so that we still get the
-            // errors that we used to get.
-            fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation);
-
-            // Create type variables for each argument.
-            input.pat.each_binding(|_bm, pat_id, sp, _path| {
-                let var_ty = visit.assign(sp, pat_id, None);
-                fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id));
-            });
+    GatherLocalsVisitor { fcx: &fcx, }.visit_body(body);
 
-            // Check the pattern.
-            fcx.check_pat(&input.pat, arg_ty);
-            fcx.write_ty(input.id, arg_ty);
-        }
+    // Add formal parameters.
+    for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
+        // The type of the argument must be well-formed.
+        //
+        // NB -- this is now checked in wfcheck, but that
+        // currently only results in warnings, so we issue an
+        // old-style WF obligation here so that we still get the
+        // errors that we used to get.
+        fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
 
-        visit.visit_expr(body);
+        // Check the pattern.
+        fcx.check_pat(&arg.pat, arg_ty);
+        fcx.write_ty(arg.id, arg_ty);
     }
 
     inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
 
-    fcx.check_expr_coercable_to_type(body, fcx.ret_ty.unwrap());
+    fcx.check_expr_coercable_to_type(&body.value, fcx.ret_ty.unwrap());
 
     fcx
 }
@@ -848,8 +829,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     let _indenter = indenter();
     match it.node {
       // Consts can play a role in type-checking, so they are included here.
-      hir::ItemStatic(.., ref e) |
-      hir::ItemConst(_, ref e) => check_const(ccx, &e, it.id),
+      hir::ItemStatic(.., e) |
+      hir::ItemConst(_, e) => check_const(ccx, e, it.id),
       hir::ItemEnum(ref enum_definition, _) => {
         check_enum_variants(ccx,
                             it.span,
@@ -908,7 +889,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
                     err.emit();
                 }
 
-                if let hir::ForeignItemFn(ref fn_decl, _) = item.node {
+                if let hir::ForeignItemFn(ref fn_decl, _, _) = item.node {
                     require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span);
                 }
             }
@@ -933,8 +914,8 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
         for impl_item_ref in impl_item_refs {
             let impl_item = ccx.tcx.map.impl_item(impl_item_ref.id);
             match impl_item.node {
-                hir::ImplItemKind::Const(_, ref expr) => {
-                    check_const(ccx, &expr, impl_item.id)
+                hir::ImplItemKind::Const(_, expr) => {
+                    check_const(ccx, expr, impl_item.id)
                 }
                 hir::ImplItemKind::Method(ref sig, body_id) => {
                     check_bare_fn(ccx, &sig.decl, body_id, impl_item.id, impl_item.span);
@@ -945,18 +926,19 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
             }
         }
       }
-      hir::ItemTrait(.., ref trait_items) => {
-        for trait_item in trait_items {
+      hir::ItemTrait(.., ref trait_item_refs) => {
+        for trait_item_ref in trait_item_refs {
+            let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id);
             match trait_item.node {
-                hir::ConstTraitItem(_, Some(ref expr)) => {
-                    check_const(ccx, &expr, trait_item.id)
+                hir::TraitItemKind::Const(_, Some(expr)) => {
+                    check_const(ccx, expr, trait_item.id)
                 }
-                hir::MethodTraitItem(ref sig, Some(body_id)) => {
+                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => {
                     check_bare_fn(ccx, &sig.decl, body_id, trait_item.id, trait_item.span);
                 }
-                hir::MethodTraitItem(_, None) |
-                hir::ConstTraitItem(_, None) |
-                hir::TypeTraitItem(..) => {
+                hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+                hir::TraitItemKind::Const(_, None) |
+                hir::TraitItemKind::Type(..) => {
                     // Nothing to do.
                 }
             }
@@ -1122,7 +1104,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         compare_impl_method(ccx,
                                             &ty_impl_item,
                                             impl_item.span,
-                                            body_id.node_id(),
+                                            body_id.node_id,
                                             &ty_trait_item,
                                             impl_trait_ref,
                                             trait_span,
@@ -1132,7 +1114,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             compare_impl_method(ccx,
                                                 &ty_impl_item,
                                                 impl_item.span,
-                                                body_id.node_id(),
+                                                body_id.node_id,
                                                 &ty_trait_item,
                                                 impl_trait_ref,
                                                 trait_span,
@@ -1243,37 +1225,38 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
 /// Checks a constant with a given type.
 fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
-                                   expr: &'tcx hir::Expr,
+                                   body: hir::BodyId,
                                    expected_type: Ty<'tcx>,
                                    id: ast::NodeId) {
+    let body = ccx.tcx.map.body(body);
     ccx.inherited(id).enter(|inh| {
-        let fcx = FnCtxt::new(&inh, None, expr.id);
-        fcx.require_type_is_sized(expected_type, expr.span, traits::ConstSized);
+        let fcx = FnCtxt::new(&inh, None, body.value.id);
+        fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
         // Gather locals in statics (because of block expressions).
         // This is technically unnecessary because locals in static items are forbidden,
         // but prevents type checking from blowing up before const checking can properly
         // emit an error.
-        GatherLocalsVisitor { fcx: &fcx }.visit_expr(expr);
+        GatherLocalsVisitor { fcx: &fcx }.visit_body(body);
 
-        fcx.check_expr_coercable_to_type(expr, expected_type);
+        fcx.check_expr_coercable_to_type(&body.value, expected_type);
 
         fcx.select_all_obligations_and_apply_defaults();
-        fcx.closure_analyze(expr);
+        fcx.closure_analyze(body);
         fcx.select_obligations_where_possible();
         fcx.check_casts();
         fcx.select_all_obligations_or_error();
 
-        fcx.regionck_expr(expr);
-        fcx.resolve_type_vars_in_expr(expr, id);
+        fcx.regionck_expr(body);
+        fcx.resolve_type_vars_in_body(body, id);
     });
 }
 
 fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                         expr: &'tcx hir::Expr,
+                         body: hir::BodyId,
                          id: ast::NodeId) {
     let decl_ty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(id));
-    check_const_with_type(ccx, expr, decl_ty, id);
+    check_const_with_type(ccx, body, decl_ty, id);
 }
 
 /// Checks whether a type can be represented in memory. In particular, it
@@ -1348,8 +1331,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
     let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
     for v in vs {
-        if let Some(ref e) = v.node.disr_expr {
-            check_const_with_type(ccx, e, repr_type_ty, e.id);
+        if let Some(e) = v.node.disr_expr {
+            check_const_with_type(ccx, e, repr_type_ty, e.node_id);
         }
     }
 
@@ -1365,11 +1348,11 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
             let variant_i = ccx.tcx.map.expect_variant(variant_i_node_id);
             let i_span = match variant_i.node.disr_expr {
-                Some(ref expr) => expr.span,
+                Some(expr) => ccx.tcx.map.span(expr.node_id),
                 None => ccx.tcx.map.span(variant_i_node_id)
             };
             let span = match v.node.disr_expr {
-                Some(ref expr) => expr.span,
+                Some(expr) => ccx.tcx.map.span(expr.node_id),
                 None => v.span
             };
             struct_span_err!(ccx.tcx.sess, span, E0081,
@@ -1643,12 +1626,8 @@ pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
         match self.locals.borrow().get(&nid) {
             Some(&t) => t,
             None => {
-                struct_span_err!(self.tcx.sess, span, E0513,
-                                 "no type for local variable {}",
-                                 self.tcx.map.node_to_string(nid))
-                    .span_label(span, &"no type for variable")
-                    .emit();
-                self.tcx.types.err
+                span_bug!(span, "no type for local variable {}",
+                          self.tcx.map.node_to_string(nid));
             }
         }
     }
@@ -3065,7 +3044,9 @@ fn check_field(&self,
                 }
                 ty::TyRawPtr(..) => {
                     err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \
-                                      `(*{0}).{1}`", pprust::expr_to_string(base), field.node));
+                                      `(*{0}).{1}`",
+                                      self.tcx.map.node_to_pretty_string(base.id),
+                                      field.node));
                 }
                 _ => {}
             }
@@ -3479,11 +3460,8 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
         self.diverges.set(self.diverges.get() | old_diverges);
         self.has_errors.set(self.has_errors.get() | old_has_errors);
 
-        debug!("type of expr({}) {} is...", expr.id,
-               pprust::expr_to_string(expr));
-        debug!("... {:?}, expected is {:?}",
-               ty,
-               expected);
+        debug!("type of {} is...", self.tcx.map.node_to_string(expr.id));
+        debug!("... {:?}, expected is {:?}", ty, expected);
 
         // Add adjustments to !-expressions
         if ty.is_never() {
@@ -3821,10 +3799,6 @@ fn check_expr_kind(&self,
               self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
           }
           hir::ExprCast(ref e, ref t) => {
-            if let hir::TyArray(_, ref count_expr) = t.node {
-                self.check_expr_with_hint(&count_expr, tcx.types.usize);
-            }
-
             // Find the type of `e`. Supply hints based on the type we are casting to,
             // if appropriate.
             let t_cast = self.to_ty(t);
@@ -3886,9 +3860,9 @@ fn check_expr_kind(&self,
             }
             tcx.mk_array(unified, args.len())
           }
-          hir::ExprRepeat(ref element, ref count_expr) => {
-            self.check_expr_has_type(&count_expr, tcx.types.usize);
-            let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count")
+          hir::ExprRepeat(ref element, count) => {
+            let count_expr = &tcx.map.body(count).value;
+            let count = eval_length(self.tcx.global_tcx(), count_expr, "repeat count")
                   .unwrap_or(0);
 
             let uty = match expected {
index eb08e70d4c3e445d0a4da8ae9be41a0f98020fcc..bd63eb6ad25effeb2aa95536a598c8f5b48ba62d 100644 (file)
@@ -113,12 +113,13 @@ macro_rules! ignore_err {
 // PUBLIC ENTRY POINTS
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn regionck_expr(&self, e: &'gcx hir::Expr) {
-        let mut rcx = RegionCtxt::new(self, RepeatingScope(e.id), e.id, Subject(e.id));
+    pub fn regionck_expr(&self, body: &'gcx hir::Body) {
+        let id = body.value.id;
+        let mut rcx = RegionCtxt::new(self, RepeatingScope(id), id, Subject(id));
         if self.err_count_since_creation() == 0 {
             // regionck assumes typeck succeeded
-            rcx.visit_expr(e);
-            rcx.visit_region_obligations(e.id);
+            rcx.visit_body(body);
+            rcx.visit_region_obligations(id);
         }
         rcx.resolve_regions_and_report_errors();
     }
@@ -140,15 +141,14 @@ pub fn regionck_item(&self,
 
     pub fn regionck_fn(&self,
                        fn_id: ast::NodeId,
-                       decl: &hir::FnDecl,
-                       body_id: hir::ExprId) {
+                       body: &'gcx hir::Body) {
         debug!("regionck_fn(id={})", fn_id);
-        let node_id = body_id.node_id();
+        let node_id = body.value.id;
         let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(fn_id));
 
         if self.err_count_since_creation() == 0 {
             // regionck assumes typeck succeeded
-            rcx.visit_fn_body(fn_id, decl, body_id, self.tcx.map.span(fn_id));
+            rcx.visit_fn_body(fn_id, body, self.tcx.map.span(fn_id));
         }
 
         rcx.free_region_map.relate_free_regions_from_predicates(
@@ -267,15 +267,16 @@ pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
 
     fn visit_fn_body(&mut self,
                      id: ast::NodeId, // the id of the fn itself
-                     fn_decl: &hir::FnDecl,
-                     body_id: hir::ExprId,
+                     body: &'gcx hir::Body,
                      span: Span)
     {
         // When we enter a function, we can derive
         debug!("visit_fn_body(id={})", id);
 
+        let body_id = body.id();
+
         let call_site = self.tcx.region_maps.lookup_code_extent(
-            region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() });
+            region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
         let old_call_site_scope = self.set_call_site_scope(Some(call_site));
 
         let fn_sig = {
@@ -298,20 +299,18 @@ fn visit_fn_body(&mut self,
         let fn_sig_tys: Vec<_> =
             fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
 
-        let old_body_id = self.set_body_id(body_id.node_id());
-        self.relate_free_regions(&fn_sig_tys[..], body_id.node_id(), span);
-        self.link_fn_args(self.tcx.region_maps.node_extent(body_id.node_id()),
-                          &fn_decl.inputs[..]);
-        let body = self.tcx.map.expr(body_id);
-        self.visit_expr(body);
-        self.visit_region_obligations(body_id.node_id());
+        let old_body_id = self.set_body_id(body_id.node_id);
+        self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span);
+        self.link_fn_args(self.tcx.region_maps.node_extent(body_id.node_id), &body.arguments);
+        self.visit_body(body);
+        self.visit_region_obligations(body_id.node_id);
 
         let call_site_scope = self.call_site_scope.unwrap();
-        debug!("visit_fn_body body.id {} call_site_scope: {:?}",
-               body.id, call_site_scope);
+        debug!("visit_fn_body body.id {:?} call_site_scope: {:?}",
+               body.id(), call_site_scope);
         let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
         self.type_of_node_must_outlive(infer::CallReturn(span),
-                                       body_id.node_id(),
+                                       body_id.node_id,
                                        call_site_region);
 
         self.region_bound_pairs.truncate(old_region_bounds_pairs_len);
@@ -478,12 +477,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
     // regions, until regionck, as described in #3238.
 
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.map)
+        NestedVisitorMap::None
     }
 
-    fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, fd: &'gcx hir::FnDecl,
-                b: hir::ExprId, span: Span, id: ast::NodeId) {
-        self.visit_fn_body(id, fd, b, span)
+    fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
+                b: hir::BodyId, span: Span, id: ast::NodeId) {
+        let body = self.tcx.map.body(b);
+        self.visit_fn_body(id, body, span)
     }
 
     //visit_pat: visit_pat, // (..) see above
@@ -826,8 +826,8 @@ fn walk_cast(&mut self,
 
     fn check_expr_fn_block(&mut self,
                            expr: &'gcx hir::Expr,
-                           body_id: hir::ExprId) {
-        let repeating_scope = self.set_repeating_scope(body_id.node_id());
+                           body_id: hir::BodyId) {
+        let repeating_scope = self.set_repeating_scope(body_id.node_id);
         intravisit::walk_expr(self, expr);
         self.set_repeating_scope(repeating_scope);
     }
@@ -1113,7 +1113,7 @@ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
         for arg in args {
             let arg_ty = self.node_ty(arg.id);
             let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
-            let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty);
+            let arg_cmt = mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty);
             debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
                    arg_ty,
                    arg_cmt,
index 63d20416bded57bddc768bd720962c6975df04b9..5d927a503a116036bbf092882e80dcd4b7b32d4b 100644 (file)
 // PUBLIC ENTRY POINTS
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn closure_analyze(&self, body: &'gcx hir::Expr) {
+    pub fn closure_analyze(&self, body: &'gcx hir::Body) {
         let mut seed = SeedBorrowKind::new(self);
-        seed.visit_expr(body);
+        seed.visit_body(body);
 
         let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
-        adjust.visit_expr(body);
+        adjust.visit_body(body);
 
         // it's our job to process these.
         assert!(self.deferred_call_resolutions.borrow().is_empty());
@@ -79,13 +79,15 @@ struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         match expr.node {
             hir::ExprClosure(cc, _, body_id, _) => {
-                self.check_closure(expr, cc, body_id);
+                let body = self.fcx.tcx.map.body(body_id);
+                self.visit_body(body);
+                self.check_closure(expr, cc);
             }
 
             _ => { }
@@ -102,8 +104,7 @@ fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> {
 
     fn check_closure(&mut self,
                      expr: &hir::Expr,
-                     capture_clause: hir::CaptureClause,
-                     _body_id: hir::ExprId)
+                     capture_clause: hir::CaptureClause)
     {
         let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
         if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
@@ -156,23 +157,21 @@ fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     fn analyze_closure(&mut self,
                        id: ast::NodeId,
                        span: Span,
-                       decl: &hir::FnDecl,
-                       body_id: hir::ExprId) {
+                       body: &hir::Body) {
         /*!
          * Analysis starting point.
          */
 
-        debug!("analyze_closure(id={:?}, body.id={:?})", id, body_id);
+        debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id());
 
         {
-            let body = self.fcx.tcx.map.expr(body_id);
             let mut euv =
                 euv::ExprUseVisitor::with_options(self,
                                                   self.fcx,
                                                   mc::MemCategorizationOptions {
                                                       during_closure_kind_inference: true
                                                   });
-            euv.walk_fn(decl, body);
+            euv.consume_body(body);
         }
 
         // Now that we've analyzed the closure, we know how each
@@ -491,18 +490,21 @@ fn adjust_closure_kind(&mut self,
 
 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_fn(&mut self,
                 fn_kind: intravisit::FnKind<'gcx>,
                 decl: &'gcx hir::FnDecl,
-                body: hir::ExprId,
+                body: hir::BodyId,
                 span: Span,
                 id: ast::NodeId)
     {
         intravisit::walk_fn(self, fn_kind, decl, body, span, id);
-        self.analyze_closure(id, span, decl, body);
+
+        let body = self.fcx.tcx.map.body(body);
+        self.visit_body(body);
+        self.analyze_closure(id, span, body);
     }
 }
 
index ffdb56753fdc1a028550ff20930843aca48e8334..c80db7fa4d0e02b47c5ab4b2b800f63f8065b886 100644 (file)
@@ -159,10 +159,10 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
         }
     }
 
-    fn check_trait_or_impl_item(&mut self,
-                                item_id: ast::NodeId,
-                                span: Span,
-                                sig_if_method: Option<&hir::MethodSig>) {
+    fn check_associated_item(&mut self,
+                             item_id: ast::NodeId,
+                             span: Span,
+                             sig_if_method: Option<&hir::MethodSig>) {
         let code = self.code.clone();
         self.for_id(item_id, span).with_fcx(|fcx, this| {
             let free_substs = &fcx.parameter_environment.free_substs;
@@ -337,7 +337,7 @@ fn check_trait(&mut self, item: &hir::Item) {
 
     fn check_item_fn(&mut self,
                      item: &hir::Item,
-                     body_id: hir::ExprId)
+                     body_id: hir::BodyId)
     {
         self.for_item(item).with_fcx(|fcx, this| {
             let free_substs = &fcx.parameter_environment.free_substs;
@@ -354,7 +354,7 @@ fn check_item_fn(&mut self,
             let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
 
             let mut implied_bounds = vec![];
-            let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id());
+            let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id);
             this.check_fn_or_method(fcx, item.span, bare_fn_ty, &predicates,
                                     free_id_outlive, &mut implied_bounds);
             implied_bounds
@@ -478,7 +478,7 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
             return;
         }
 
-        let span = method_sig.decl.inputs[0].pat.span;
+        let span = method_sig.decl.inputs[0].span;
 
         let free_substs = &fcx.parameter_environment.free_substs;
         let method_ty = fcx.tcx.item_type(method.def_id);
@@ -607,10 +607,10 @@ fn visit_item(&mut self, i: &hir::Item) {
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
         let method_sig = match trait_item.node {
-            hir::TraitItem_::MethodTraitItem(ref sig, _) => Some(sig),
+            hir::TraitItemKind::Method(ref sig, _) => Some(sig),
             _ => None
         };
-        self.check_trait_or_impl_item(trait_item.id, trait_item.span, method_sig);
+        self.check_associated_item(trait_item.id, trait_item.span, method_sig);
         intravisit::walk_trait_item(self, trait_item)
     }
 
@@ -620,7 +620,7 @@ fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
             hir::ImplItemKind::Method(ref sig, _) => Some(sig),
             _ => None
         };
-        self.check_trait_or_impl_item(impl_item.id, impl_item.span, method_sig);
+        self.check_associated_item(impl_item.id, impl_item.span, method_sig);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
index 56de75995fd2e820bc4929c1a74eeb51ebbaa82f..9a2bfbf715af9785bb6432e24c9264dd63d65459 100644 (file)
 use syntax::ast;
 use syntax_pos::Span;
 
-use rustc::hir::print::pat_to_string;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir::{self, PatKind};
+use rustc::hir;
 
 ///////////////////////////////////////////////////////////////////////////
-// Entry point functions
+// Entry point
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn resolve_type_vars_in_expr(&self, e: &'gcx hir::Expr, item_id: ast::NodeId) {
+    pub fn resolve_type_vars_in_body(&self,
+                                     body: &'gcx hir::Body,
+                                     item_id: ast::NodeId) {
         assert_eq!(self.writeback_errors.get(), false);
         let mut wbcx = WritebackCx::new(self);
-        wbcx.visit_expr(e);
-        wbcx.visit_upvar_borrow_map();
-        wbcx.visit_closures();
-        wbcx.visit_liberated_fn_sigs();
-        wbcx.visit_fru_field_types();
-        wbcx.visit_deferred_obligations(item_id);
-        wbcx.visit_type_nodes();
-    }
-
-    pub fn resolve_type_vars_in_fn(&self,
-                                   decl: &'gcx hir::FnDecl,
-                                   body: &'gcx hir::Expr,
-                                   item_id: ast::NodeId) {
-        assert_eq!(self.writeback_errors.get(), false);
-        let mut wbcx = WritebackCx::new(self);
-        wbcx.visit_expr(body);
-        for arg in &decl.inputs {
+        for arg in &body.arguments {
             wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
-            wbcx.visit_pat(&arg.pat);
-
-            // Privacy needs the type for the whole pattern, not just each binding
-            if let PatKind::Binding(..) = arg.pat.node {} else {
-                wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.pat.id);
-            }
         }
+        wbcx.visit_body(body);
         wbcx.visit_upvar_borrow_map();
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
@@ -188,7 +168,7 @@ fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) {
 
 impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
-        NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map)
+        NestedVisitorMap::None
     }
 
     fn visit_stmt(&mut self, s: &'gcx hir::Stmt) {
@@ -211,10 +191,13 @@ fn visit_expr(&mut self, e: &'gcx hir::Expr) {
         self.visit_method_map_entry(ResolvingExpr(e.span),
                                     MethodCall::expr(e.id));
 
-        if let hir::ExprClosure(_, ref decl, ..) = e.node {
-            for input in &decl.inputs {
-                self.visit_node_id(ResolvingExpr(e.span), input.id);
+        if let hir::ExprClosure(_, _, body, _) = e.node {
+            let body = self.fcx.tcx.map.body(body);
+            for arg in &body.arguments {
+                self.visit_node_id(ResolvingExpr(e.span), arg.id);
             }
+
+            self.visit_body(body);
         }
 
         intravisit::walk_expr(self, e);
@@ -237,7 +220,7 @@ fn visit_pat(&mut self, p: &'gcx hir::Pat) {
         self.visit_node_id(ResolvingPattern(p.span), p.id);
 
         debug!("Type for pattern binding {} (id {}) resolved to {:?}",
-               pat_to_string(p),
+               self.tcx().map.node_to_pretty_string(p.id),
                p.id,
                self.tcx().tables().node_id_to_type(p.id));
 
@@ -254,20 +237,6 @@ fn visit_local(&mut self, l: &'gcx hir::Local) {
         self.write_ty_to_tcx(l.id, var_ty);
         intravisit::walk_local(self, l);
     }
-
-    fn visit_ty(&mut self, t: &'gcx hir::Ty) {
-        match t.node {
-            hir::TyArray(ref ty, ref count_expr) => {
-                self.visit_ty(&ty);
-                self.write_ty_to_tcx(count_expr.id, self.tcx().types.usize);
-            }
-            hir::TyBareFn(ref function_declaration) => {
-                intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
-                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
-            }
-            _ => intravisit::walk_ty(self, t)
-        }
-    }
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
index 0034a85f8e29e0b156da2ddf5d281f872b691189..cd9453770a6ab28ff7a3e63af12db965a526fcec 100644 (file)
@@ -50,6 +50,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 0e5a16987c12e408e9315cadd82ca3848872ae16..3bbe5aa1fef376272fd19e28e1f57ae5f4b741ae 100644 (file)
@@ -58,6 +58,9 @@ fn visit_item(&mut self, item: &Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 2e8206ec959678297bd00f183307b3b857f65ac4..bc1ead07c0ea7f77a042135dab3fbff32825a3eb 100644 (file)
@@ -67,13 +67,15 @@ fn check_primitive_impl(&self,
             }
         }
     }
+}
 
+impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
     /// Checks exactly one impl for orphan rules and other such
     /// restrictions.  In this fn, it can happen that multiple errors
     /// apply to a specific impl, so just return after reporting one
     /// to prevent inundating the user with a bunch of similar error
     /// reports.
-    fn check_item(&self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         let def_id = self.tcx.map.local_def_id(item.id);
         match item.node {
             hir::ItemImpl(.., None, ref ty, _) => {
@@ -368,7 +370,7 @@ fn check_item(&self, item: &hir::Item) {
                                       the crate they're defined in; define a new trait instead")
                         .span_label(item_trait_ref.path.span,
                                     &format!("`{}` trait not defined in this crate",
-                                             item_trait_ref.path))
+                            self.tcx.map.node_to_pretty_string(item_trait_ref.ref_id)))
                         .emit();
                     return;
                 }
@@ -378,11 +380,8 @@ fn check_item(&self, item: &hir::Item) {
             }
         }
     }
-}
 
-impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        self.check_item(item);
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
     }
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
index 815811675a54bff05321ee3fef482003bb8bf6c7..a09bdf0533a151ecd7373192412932bcf0561d6f 100644 (file)
@@ -205,6 +205,9 @@ fn visit_item(&mut self, item: &'v hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 6d5de8f250655e614603578355481a5ed210bc34..c4c7c699f65f62ba5c8a74524587d35e9de8e51d 100644 (file)
@@ -107,6 +107,9 @@ fn visit_item(&mut self, item: &'v hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index fba77d171797e1da459a8cb77716523cf671d078..fd51b38e1b557464becb775ed9503b21ed415853 100644 (file)
@@ -82,7 +82,7 @@
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::Span;
 
-use rustc::hir::{self, map as hir_map, print as pprust};
+use rustc::hir::{self, map as hir_map};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
@@ -204,6 +204,13 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
         intravisit::walk_ty(self, ty);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.with_collect_item_sig(trait_item.id, || {
+            convert_trait_item(self.ccx, trait_item)
+        });
+        intravisit::walk_trait_item(self, trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         self.with_collect_item_sig(impl_item.id, || {
             convert_impl_item(self.ccx, impl_item)
@@ -633,7 +640,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             id: ast::NodeId,
                             sig: &hir::MethodSig,
                             untransformed_rcvr_ty: Ty<'tcx>,
-                            rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
+                            body: Option<hir::BodyId>,
+                            rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) {
     let def_id = ccx.tcx.map.local_def_id(id);
     let ty_generics = generics_of_def_id(ccx, def_id);
 
@@ -644,8 +652,14 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
         TraitContainer(_) => None
     };
+    let assoc_item = ccx.tcx.associated_item(def_id);
+    let self_value_ty = if assoc_item.method_has_self_argument {
+        Some(untransformed_rcvr_ty)
+    } else {
+        None
+    };
     let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
-                                    sig, untransformed_rcvr_ty, anon_scope);
+                                    sig, self_value_ty, body, anon_scope);
 
     let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
                                 ccx.tcx.map.span(id), def_id);
@@ -785,56 +799,12 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
             tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone());
         },
-        hir::ItemTrait(.., ref trait_items) => {
+        hir::ItemTrait(..) => {
             generics_of_def_id(ccx, def_id);
             trait_def_of_item(ccx, it);
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
                 ccx.ensure_super_predicates(it.span, def_id);
             convert_trait_predicates(ccx, it);
-            let trait_predicates = tcx.item_predicates(def_id);
-
-            debug!("convert: trait_bounds={:?}", trait_predicates);
-
-            // FIXME: is the ordering here important? I think it is.
-            let container = TraitContainer(def_id);
-
-            // Convert all the associated constants.
-            for trait_item in trait_items {
-                if let hir::ConstTraitItem(ref ty, _) = trait_item.node {
-                    let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
-                    generics_of_def_id(ccx, const_def_id);
-                    let ty = ccx.icx(&trait_predicates)
-                        .to_ty(&ExplicitRscope, ty);
-                    tcx.item_types.borrow_mut().insert(const_def_id, ty);
-                    convert_associated_const(ccx, container, trait_item.id, ty)
-                }
-            }
-
-            // Convert all the associated types.
-            for trait_item in trait_items {
-                if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node {
-                    let type_def_id = ccx.tcx.map.local_def_id(trait_item.id);
-                    generics_of_def_id(ccx, type_def_id);
-
-                    let typ = opt_ty.as_ref().map({
-                        |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
-                    });
-
-                    convert_associated_type(ccx, container, trait_item.id, typ);
-                }
-            }
-
-            // Convert all the methods
-            for trait_item in trait_items {
-                if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
-                    convert_method(ccx,
-                                   container,
-                                   trait_item.id,
-                                   sig,
-                                   tcx.mk_self_type(),
-                                   &trait_predicates);
-                }
-            }
         },
         hir::ItemStruct(ref struct_def, _) |
         hir::ItemUnion(ref struct_def, _) => {
@@ -866,6 +836,48 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
     }
 }
 
+fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
+    let tcx = ccx.tcx;
+
+    // we can lookup details about the trait because items are visited
+    // before trait-items
+    let trait_def_id = tcx.map.get_parent_did(trait_item.id);
+    let trait_predicates = tcx.item_predicates(trait_def_id);
+
+    match trait_item.node {
+        hir::TraitItemKind::Const(ref ty, _) => {
+            let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
+            generics_of_def_id(ccx, const_def_id);
+            let ty = ccx.icx(&trait_predicates)
+                        .to_ty(&ExplicitRscope, &ty);
+            tcx.item_types.borrow_mut().insert(const_def_id, ty);
+            convert_associated_const(ccx, TraitContainer(trait_def_id),
+                                     trait_item.id, ty);
+        }
+
+        hir::TraitItemKind::Type(_, ref opt_ty) => {
+            let type_def_id = ccx.tcx.map.local_def_id(trait_item.id);
+            generics_of_def_id(ccx, type_def_id);
+
+            let typ = opt_ty.as_ref().map({
+                |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
+            });
+
+            convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ);
+        }
+
+        hir::TraitItemKind::Method(ref sig, ref method) => {
+            let body = match *method {
+                hir::TraitMethod::Required(_) => None,
+                hir::TraitMethod::Provided(body) => Some(body)
+            };
+            convert_method(ccx, TraitContainer(trait_def_id),
+                           trait_item.id, sig, tcx.mk_self_type(),
+                           body, &trait_predicates);
+        }
+    }
+}
+
 fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
     let tcx = ccx.tcx;
 
@@ -901,10 +913,10 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
             convert_associated_type(ccx, ImplContainer(impl_def_id), impl_item.id, Some(typ));
         }
 
-        hir::ImplItemKind::Method(ref sig, _) => {
+        hir::ImplItemKind::Method(ref sig, body) => {
             convert_method(ccx, ImplContainer(impl_def_id),
                            impl_item.id, sig, impl_self_ty,
-                           &impl_predicates);
+                           Some(body), &impl_predicates);
         }
     }
 }
@@ -1029,7 +1041,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
                           -> Option<ty::Disr> {
-        debug!("disr expr, checking {}", pprust::expr_to_string(e));
+        debug!("disr expr, checking {}", ccx.tcx.map.node_to_pretty_string(e.id));
 
         let ty_hint = repr_ty.to_ty(ccx.tcx);
         let print_err = |cv: ConstVal| {
@@ -1088,7 +1100,8 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let mut prev_disr = None::<ty::Disr>;
     let variants = def.variants.iter().map(|v| {
         let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr());
-        let disr = if let Some(ref e) = v.node.disr_expr {
+        let disr = if let Some(e) = v.node.disr_expr {
+            let e = &tcx.map.body(e).value;
             evaluate_disr_expr(ccx, repr_type, e)
         } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) {
             Some(disr)
@@ -1290,12 +1303,13 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                  ast_generics: &hir::Generics,
                                                  trait_predicates: &ty::GenericPredicates<'tcx>,
                                                  self_trait_ref: ty::TraitRef<'tcx>,
-                                                 trait_items: &[hir::TraitItem])
+                                                 trait_item_refs: &[hir::TraitItemRef])
                                                  -> Vec<ty::Predicate<'tcx>>
     {
-        trait_items.iter().flat_map(|trait_item| {
+        trait_item_refs.iter().flat_map(|trait_item_ref| {
+            let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id);
             let bounds = match trait_item.node {
-                hir::TypeTraitItem(ref bounds, _) => bounds,
+                hir::TraitItemKind::Type(ref bounds, _) => bounds,
                 _ => {
                     return vec![].into_iter();
                 }
@@ -1363,7 +1377,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let ast_generics = match node {
             NodeTraitItem(item) => {
                 match item.node {
-                    MethodTraitItem(ref sig, _) => &sig.generics,
+                    TraitItemKind::Method(ref sig, _) => &sig.generics,
                     _ => &no_generics
                 }
             }
@@ -1420,7 +1434,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             NodeForeignItem(item) => {
                 match item.node {
                     ForeignItemStatic(..) => &no_generics,
-                    ForeignItemFn(_, ref generics) => generics
+                    ForeignItemFn(_, _, ref generics) => generics
                 }
             }
 
@@ -1521,9 +1535,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     ItemStatic(ref t, ..) | ItemConst(ref t, _) => {
                         ccx.icx(&()).to_ty(&StaticRscope::new(&ccx.tcx), &t)
                     }
-                    ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
+                    ItemFn(ref decl, unsafety, _, abi, ref generics, body) => {
                         let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
-                                                          Some(AnonTypeScope::new(def_id)));
+                                                          body, Some(AnonTypeScope::new(def_id)));
                         let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
                         ccx.tcx.mk_fn_def(def_id, substs, tofd)
                     }
@@ -1563,7 +1577,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let abi = ccx.tcx.map.get_foreign_abi(node_id);
 
                 match foreign_item.node {
-                    ForeignItemFn(ref fn_decl, ref generics) => {
+                    ForeignItemFn(ref fn_decl, _, ref generics) => {
                         compute_type_of_foreign_fn_decl(
                             ccx, ccx.tcx.map.local_def_id(foreign_item.id),
                             fn_decl, generics, abi)
@@ -1628,7 +1642,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let no_generics = hir::Generics::empty();
     let generics = match it.node {
-        hir::ForeignItemFn(_, ref generics) => generics,
+        hir::ForeignItemFn(_, _, ref generics) => generics,
         hir::ForeignItemStatic(..) => &no_generics
     };
 
@@ -2058,13 +2072,13 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
                 ccx.tcx.sess.struct_span_err(ast_ty.span,
                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
                                         may result in invalid code",
-                                       pprust::ty_to_string(ast_ty)))
+                                       ccx.tcx.map.node_to_pretty_string(ast_ty.id)))
                     .help("add #![feature(simd_ffi)] to the crate attributes to enable")
                     .emit();
             }
         };
         for (input, ty) in decl.inputs.iter().zip(&input_tys) {
-            check(&input.ty, ty)
+            check(&input, ty)
         }
         if let hir::Return(ref ty) = decl.output {
             check(&ty, output)
index cea3ad43a95b84624b670df1f4e1f498ad2c7496..d3b671f2a4d6e05ee026dd921176c9cbb4bf6ae8 100644 (file)
@@ -3866,45 +3866,6 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
 ```
 "##,
 
-E0513: r##"
-The type of the variable couldn't be found out.
-
-Erroneous code example:
-
-```compile_fail,E0513
-use std::mem;
-
-unsafe {
-    let size = mem::size_of::<u32>();
-    mem::transmute_copy::<u32, [u8; size]>(&8_8);
-    // error: no type for local variable
-}
-```
-
-To fix this error, please use a constant size instead of `size`. To make
-this error more obvious, you could run:
-
-```compile_fail,E0080
-use std::mem;
-
-unsafe {
-    mem::transmute_copy::<u32, [u8; mem::size_of::<u32>()]>(&8_8);
-    // error: constant evaluation error
-}
-```
-
-So now, you can fix your code by setting the size directly:
-
-```
-use std::mem;
-
-unsafe {
-    mem::transmute_copy::<u32, [u8; 4]>(&8_8);
-    // `u32` is 4 bytes so we replace the `mem::size_of` call with its size
-}
-```
-"##,
-
 E0516: r##"
 The `typeof` keyword is currently reserved but unimplemented.
 Erroneous code example:
index 9f5b73d9b30752ed45f31aead3cda46a24e9958b..ce495e6fb4cd8a8cc689a4bcdb54e888e5cebf59 100644 (file)
@@ -87,6 +87,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) { }
+
     fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
 }
 
index 131ecfc6e0c78339d9ddb0e4972e70a33b081690..3f5e443a20a6854b575a7a57fdf197102483da43 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::ty;
 use rustc::ty::subst::Substs;
 
 #[derive(Clone)]
 pub struct ElisionFailureInfo {
-    pub name: String,
+    /// Where we can find the argument pattern.
+    pub parent: Option<hir::BodyId>,
+    /// The index of the argument in the original definition.
+    pub index: usize,
     pub lifetime_count: usize,
     pub have_bound_regions: bool
 }
index 39f996ee62b541e4d7cc003a54227908c7f73c77..507079a4f874cd93e017458416e75fd1c644695b 100644 (file)
@@ -120,6 +120,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 851cfcd87231f8a8790a1c6fafa1ec75ba1c8d48..d4d3edbcb126e8732f82b03d5ef4e1718a2a758f 100644 (file)
@@ -258,6 +258,9 @@ fn visit_item(&mut self, item: &hir::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
index 94e9fdbfc3e2ce703ef67bd07c1d82820e5ff1b8..cba5e1ba6f3184b2f928ce29ed60d915ff5c4726 100644 (file)
@@ -10,6 +10,8 @@
 
 //! Support for inlining external documentation into the current AST.
 
+use std::collections::BTreeMap;
+use std::io;
 use std::iter::once;
 
 use syntax::ast;
 
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
-use rustc::hir::print as pprust;
 use rustc::ty;
 use rustc::util::nodemap::FxHashSet;
 
-use rustc_const_eval::lookup_const_by_id;
-
 use core::{DocContext, DocAccessLevels};
 use doctree;
 use clean::{self, GetDefId};
@@ -345,8 +344,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
         match item.kind {
             ty::AssociatedKind::Const => {
                 let default = if item.defaultness.has_value() {
-                    Some(pprust::expr_to_string(
-                        lookup_const_by_id(tcx, item.def_id, None).unwrap().0))
+                    Some(print_inlined_const(cx, item.def_id))
                 } else {
                     None
                 };
@@ -476,17 +474,33 @@ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
     }
 }
 
-fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
-    let (expr, ty) = lookup_const_by_id(cx.tcx, did, None).unwrap_or_else(|| {
-        panic!("expected lookup_const_by_id to succeed for {:?}", did);
-    });
-    debug!("converting constant expr {:?} to snippet", expr);
-    let sn = pprust::expr_to_string(expr);
-    debug!("got snippet {}", sn);
+struct InlinedConst {
+    nested_bodies: BTreeMap<hir::BodyId, hir::Body>
+}
+
+impl hir::print::PpAnn for InlinedConst {
+    fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested)
+              -> io::Result<()> {
+        if let hir::print::Nested::Body(body) = nested {
+            state.print_expr(&self.nested_bodies[&body].value)
+        } else {
+            Ok(())
+        }
+    }
+}
 
+fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
+    let body = cx.tcx.sess.cstore.maybe_get_item_body(cx.tcx, did).unwrap();
+    let inlined = InlinedConst {
+        nested_bodies: cx.tcx.sess.cstore.item_body_nested_bodies(did)
+    };
+    hir::print::to_string(&inlined, |s| s.print_expr(&body.value))
+}
+
+fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
     clean::Constant {
-        type_: ty.map(|t| t.clean(cx)).unwrap_or_else(|| cx.tcx.item_type(did).clean(cx)),
-        expr: sn
+        type_: cx.tcx.item_type(did).clean(cx),
+        expr: print_inlined_const(cx, did)
     }
 }
 
index fdbd2f3647c0c482c787d2c82322567a48b593be..3b8281980696d74db037d65b52d3238ec444a7c0 100644 (file)
@@ -32,7 +32,6 @@
 use rustc::middle::lang_items;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::print as pprust;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind};
 use rustc::middle::stability;
@@ -1030,22 +1029,14 @@ pub struct Method {
     pub abi: Abi,
 }
 
-impl Clean<Method> for hir::MethodSig {
+impl<'a> Clean<Method> for (&'a hir::MethodSig, hir::BodyId) {
     fn clean(&self, cx: &DocContext) -> Method {
-        let decl = FnDecl {
-            inputs: Arguments {
-                values: self.decl.inputs.clean(cx),
-            },
-            output: self.decl.output.clean(cx),
-            variadic: false,
-            attrs: Attributes::default()
-        };
         Method {
-            generics: self.generics.clean(cx),
-            unsafety: self.unsafety,
-            constness: self.constness,
-            decl: decl,
-            abi: self.abi
+            generics: self.0.generics.clean(cx),
+            unsafety: self.0.unsafety,
+            constness: self.0.constness,
+            decl: (&*self.0.decl, self.1).clean(cx),
+            abi: self.0.abi
         }
     }
 }
@@ -1058,25 +1049,6 @@ pub struct TyMethod {
     pub abi: Abi,
 }
 
-impl Clean<TyMethod> for hir::MethodSig {
-    fn clean(&self, cx: &DocContext) -> TyMethod {
-        let decl = FnDecl {
-            inputs: Arguments {
-                values: self.decl.inputs.clean(cx),
-            },
-            output: self.decl.output.clean(cx),
-            variadic: false,
-            attrs: Attributes::default()
-        };
-        TyMethod {
-            unsafety: self.unsafety.clone(),
-            decl: decl,
-            generics: self.generics.clean(cx),
-            abi: self.abi
-        }
-    }
-}
-
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Function {
     pub decl: FnDecl,
@@ -1097,7 +1069,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             deprecation: self.depr.clean(cx),
             def_id: cx.tcx.map.local_def_id(self.id),
             inner: FunctionItem(Function {
-                decl: self.decl.clean(cx),
+                decl: (&self.decl, self.body).clean(cx),
                 generics: self.generics.clean(cx),
                 unsafety: self.unsafety,
                 constness: self.constness,
@@ -1130,14 +1102,47 @@ pub struct Arguments {
     pub values: Vec<Argument>,
 }
 
-impl Clean<FnDecl> for hir::FnDecl {
+impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) {
+    fn clean(&self, cx: &DocContext) -> Arguments {
+        Arguments {
+            values: self.0.iter().enumerate().map(|(i, ty)| {
+                let mut name = self.1.get(i).map(|n| n.node.to_string())
+                                            .unwrap_or(String::new());
+                if name.is_empty() {
+                    name = "_".to_string();
+                }
+                Argument {
+                    name: name,
+                    type_: ty.clean(cx),
+                }
+            }).collect()
+        }
+    }
+}
+
+impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], hir::BodyId) {
+    fn clean(&self, cx: &DocContext) -> Arguments {
+        let body = cx.tcx.map.body(self.1);
+
+        Arguments {
+            values: self.0.iter().enumerate().map(|(i, ty)| {
+                Argument {
+                    name: name_from_pat(&body.arguments[i].pat),
+                    type_: ty.clean(cx),
+                }
+            }).collect()
+        }
+    }
+}
+
+impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
+    where (&'a [P<hir::Ty>], A): Clean<Arguments>
+{
     fn clean(&self, cx: &DocContext) -> FnDecl {
         FnDecl {
-            inputs: Arguments {
-                values: self.inputs.clean(cx),
-            },
-            output: self.output.clean(cx),
-            variadic: self.variadic,
+            inputs: (&self.0.inputs[..], self.1).clean(cx),
+            output: self.0.output.clean(cx),
+            variadic: self.0.variadic,
             attrs: Attributes::default()
         }
     }
@@ -1159,7 +1164,6 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
                 values: sig.skip_binder().inputs().iter().map(|t| {
                     Argument {
                         type_: t.clean(cx),
-                        id: ast::CRATE_NODE_ID,
                         name: names.next().map_or("".to_string(), |name| name.to_string()),
                     }
                 }).collect(),
@@ -1172,7 +1176,6 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
 pub struct Argument {
     pub type_: Type,
     pub name: String,
-    pub id: ast::NodeId,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
@@ -1184,26 +1187,17 @@ pub enum SelfTy {
 
 impl Argument {
     pub fn to_self(&self) -> Option<SelfTy> {
-        if self.name == "self" {
-            match self.type_ {
-                Infer => Some(SelfValue),
-                BorrowedRef{ref lifetime, mutability, ref type_} if **type_ == Infer => {
-                    Some(SelfBorrowed(lifetime.clone(), mutability))
-                }
-                _ => Some(SelfExplicit(self.type_.clone()))
-            }
-        } else {
-            None
+        if self.name != "self" {
+            return None;
         }
-    }
-}
-
-impl Clean<Argument> for hir::Arg {
-    fn clean(&self, cx: &DocContext) -> Argument {
-        Argument {
-            name: name_from_pat(&*self.pat),
-            type_: (self.ty.clean(cx)),
-            id: self.id
+        if self.type_.is_self_type() {
+            return Some(SelfValue);
+        }
+        match self.type_ {
+            BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
+                Some(SelfBorrowed(lifetime.clone(), mutability))
+            }
+            _ => Some(SelfExplicit(self.type_.clone()))
         }
     }
 }
@@ -1269,17 +1263,22 @@ fn clean(&self, cx: &DocContext) -> PolyTrait {
 impl Clean<Item> for hir::TraitItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            hir::ConstTraitItem(ref ty, ref default) => {
+            hir::TraitItemKind::Const(ref ty, default) => {
                 AssociatedConstItem(ty.clean(cx),
-                                    default.as_ref().map(|e| pprust::expr_to_string(&e)))
+                                    default.map(|e| print_const_expr(cx, e)))
             }
-            hir::MethodTraitItem(ref sig, Some(_)) => {
-                MethodItem(sig.clean(cx))
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+                MethodItem((sig, body).clean(cx))
             }
-            hir::MethodTraitItem(ref sig, None) => {
-                TyMethodItem(sig.clean(cx))
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
+                TyMethodItem(TyMethod {
+                    unsafety: sig.unsafety.clone(),
+                    decl: (&*sig.decl, &names[..]).clean(cx),
+                    generics: sig.generics.clean(cx),
+                    abi: sig.abi
+                })
             }
-            hir::TypeTraitItem(ref bounds, ref default) => {
+            hir::TraitItemKind::Type(ref bounds, ref default) => {
                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
             }
         };
@@ -1299,12 +1298,12 @@ fn clean(&self, cx: &DocContext) -> Item {
 impl Clean<Item> for hir::ImplItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            hir::ImplItemKind::Const(ref ty, ref expr) => {
+            hir::ImplItemKind::Const(ref ty, expr) => {
                 AssociatedConstItem(ty.clean(cx),
-                                    Some(pprust::expr_to_string(expr)))
+                                    Some(print_const_expr(cx, expr)))
             }
-            hir::ImplItemKind::Method(ref sig, _) => {
-                MethodItem(sig.clean(cx))
+            hir::ImplItemKind::Method(ref sig, body) => {
+                MethodItem((sig, body).clean(cx))
             }
             hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
                 type_: ty.clean(cx),
@@ -1353,11 +1352,13 @@ fn clean(&self, cx: &DocContext) -> Item {
                     };
                     let self_arg_ty = *fty.sig.input(0).skip_binder();
                     if self_arg_ty == self_ty {
-                        decl.inputs.values[0].type_ = Infer;
+                        decl.inputs.values[0].type_ = Generic(String::from("Self"));
                     } else if let ty::TyRef(_, mt) = self_arg_ty.sty {
                         if mt.ty == self_ty {
                             match decl.inputs.values[0].type_ {
-                                BorrowedRef{ref mut type_, ..} => **type_ = Infer,
+                                BorrowedRef{ref mut type_, ..} => {
+                                    **type_ = Generic(String::from("Self"))
+                                }
                                 _ => unreachable!(),
                             }
                         }
@@ -1568,6 +1569,13 @@ pub fn is_generic(&self) -> bool {
             _ => false,
         }
     }
+
+    pub fn is_self_type(&self) -> bool {
+        match *self {
+            Generic(ref name) => name == "Self",
+            _ => false
+        }
+    }
 }
 
 impl GetDefId for Type {
@@ -1677,11 +1685,12 @@ fn clean(&self, cx: &DocContext) -> Type {
                 BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                              type_: box m.ty.clean(cx)},
             TySlice(ref ty) => Vector(box ty.clean(cx)),
-            TyArray(ref ty, ref e) => {
+            TyArray(ref ty, e) => {
                 use rustc_const_math::{ConstInt, ConstUsize};
                 use rustc_const_eval::eval_const_expr;
                 use rustc::middle::const_val::ConstVal;
 
+                let e = &cx.tcx.map.body(e).value;
                 let n = match eval_const_expr(cx.tcx, e) {
                     ConstVal::Integral(ConstInt::Usize(u)) => match u {
                         ConstUsize::Us16(u) => u.to_string(),
@@ -2332,7 +2341,7 @@ fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
                 type_params: Vec::new(),
                 where_predicates: Vec::new()
             },
-            decl: self.decl.clean(cx),
+            decl: (&*self.decl, &[][..]).clean(cx),
             abi: self.abi,
         }
     }
@@ -2362,7 +2371,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             inner: StaticItem(Static {
                 type_: self.type_.clean(cx),
                 mutability: self.mutability.clean(cx),
-                expr: pprust::expr_to_string(&self.expr),
+                expr: print_const_expr(cx, self.expr),
             }),
         }
     }
@@ -2386,7 +2395,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             deprecation: self.depr.clean(cx),
             inner: ConstantItem(Constant {
                 type_: self.type_.clean(cx),
-                expr: pprust::expr_to_string(&self.expr),
+                expr: print_const_expr(cx, self.expr),
             }),
         }
     }
@@ -2630,9 +2639,9 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
 impl Clean<Item> for hir::ForeignItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            hir::ForeignItemFn(ref decl, ref generics) => {
+            hir::ForeignItemFn(ref decl, ref names, ref generics) => {
                 ForeignFunctionItem(Function {
-                    decl: decl.clean(cx),
+                    decl: (&**decl, &names[..]).clean(cx),
                     generics: generics.clean(cx),
                     unsafety: hir::Unsafety::Unsafe,
                     abi: Abi::Rust,
@@ -2714,6 +2723,10 @@ fn name_from_pat(p: &hir::Pat) -> String {
     }
 }
 
+fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
+    cx.tcx.map.node_to_pretty_string(body.node_id)
+}
+
 /// Given a type Path, resolve it to a Type using the TyCtxt
 fn resolve_type(cx: &DocContext,
                 path: Path,
index 31e10fbd3b7d3e16ca57628798caceba41d79661..d819268240badca941579c315ac882df1194bcd0 100644 (file)
@@ -156,6 +156,7 @@ pub struct Function {
     pub whence: Span,
     pub generics: hir::Generics,
     pub abi: abi::Abi,
+    pub body: hir::BodyId,
 }
 
 pub struct Typedef {
@@ -174,7 +175,7 @@ pub struct Typedef {
 pub struct Static {
     pub type_: P<hir::Ty>,
     pub mutability: hir::Mutability,
-    pub expr: P<hir::Expr>,
+    pub expr: hir::BodyId,
     pub name: Name,
     pub attrs: hir::HirVec<ast::Attribute>,
     pub vis: hir::Visibility,
@@ -186,7 +187,7 @@ pub struct Static {
 
 pub struct Constant {
     pub type_: P<hir::Ty>,
-    pub expr: P<hir::Expr>,
+    pub expr: hir::BodyId,
     pub name: Name,
     pub attrs: hir::HirVec<ast::Attribute>,
     pub vis: hir::Visibility,
index eaa6f85906c5f29fb90b0adc09aa260951723d47..d66adb5ecfa35afc70bebcea83e3dc0d8fc76464 100644 (file)
@@ -1662,8 +1662,13 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
 }
 
 fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
-    for stability in short_stability(item, cx, true) {
-        write!(w, "<div class='stability'>{}</div>", stability)?;
+    let stabilities = short_stability(item, cx, true);
+    if !stabilities.is_empty() {
+        write!(w, "<div class='stability'>")?;
+        for stability in stabilities {
+            write!(w, "{}", stability)?;
+        }
+        write!(w, "</div>")?;
     }
     Ok(())
 }
@@ -1862,7 +1867,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
                 String::new()
             };
             let text = format!("Deprecated{}{}", since, Markdown(&deprecated_reason));
-            stability.push(format!("<em class='stab deprecated'>{}</em>", text))
+            stability.push(format!("<div class='stab deprecated'>{}</div>", text))
         };
 
         if stab.level == stability::Unstable {
@@ -1887,7 +1892,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
                 String::new()
             };
             let text = format!("Unstable{}{}", unstable_extra, Markdown(&unstable_reason));
-            stability.push(format!("<em class='stab unstable'>{}</em>", text))
+            stability.push(format!("<div class='stab unstable'>{}</div>", text))
         };
     } else if let Some(depr) = item.deprecation.as_ref() {
         let note = if show_reason && !depr.note.is_empty() {
@@ -1902,7 +1907,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
         };
 
         let text = format!("Deprecated{}{}", since, Markdown(&note));
-        stability.push(format!("<em class='stab deprecated'>{}</em>", text))
+        stability.push(format!("<div class='stab deprecated'>{}</div>", text))
     }
 
     stability
index ce7c6acdf47f921b5ca34d39583962075b43fb76..0ca4f7ea36f1be8cbdf78b7e9edca337174c4c10 100644 (file)
@@ -523,20 +523,20 @@ body.blur > :not(#help) {
        padding: 20px;
 }
 
-em.stab {
-       display: inline-block;
+.stab {
+       display: table;
        border-width: 1px;
        border-style: solid;
        padding: 3px;
        margin-bottom: 5px;
        font-size: 90%;
-       font-style: normal;
 }
-em.stab p {
+.stab p {
        display: inline;
 }
 
 .module-item .stab {
+       display: inline;
        border-width: 0;
        padding: 0;
        margin: 0;
index 6a9a24f69960a32c0750318e0318389132643a72..862d6d12b9ad99f28489d34bdda597a430fb477e 100644 (file)
@@ -30,10 +30,6 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t
     background-color: white;
 }
 
-div.stability > em > code {
-    background-color: initial;
-}
-
 .docblock code, .docblock-short code {
     background-color: #F5F5F5;
 }
@@ -129,5 +125,5 @@ a.test-arrow {
     background-color: white;
 }
 
-em.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
-em.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
+.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
index 835825d31eec98f46e954707fdf3dea03a2e7ff1..47616044879cd0df8396712cb5157048c8654daa 100644 (file)
@@ -267,13 +267,14 @@ pub fn main_args(args: &[String]) -> isize {
     };
     let crate_name = matches.opt_str("crate-name");
     let playground_url = matches.opt_str("playground-url");
+    let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
 
     match (should_test, markdown_input) {
         (true, true) => {
-            return markdown::test(input, cfgs, libs, externs, test_args)
+            return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot)
         }
         (true, false) => {
-            return test::run(input, cfgs, libs, externs, test_args, crate_name)
+            return test::run(input, cfgs, libs, externs, test_args, crate_name, maybe_sysroot)
         }
         (false, true) => return markdown::render(input,
                                                  output.unwrap_or(PathBuf::from("doc")),
index 9dbc9d30e606b48851c59384b1d3ff93b5fc2bb9..369e18948ad5b44dbd18e4ad1c0ff8bd8a31b456 100644 (file)
@@ -144,7 +144,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
 
 /// Run any tests/code examples in the markdown file `input`.
 pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
-            mut test_args: Vec<String>) -> isize {
+            mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>) -> isize {
     let input_str = match load_string(input) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
@@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
     let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
-                                       true, opts);
+                                       true, opts, maybe_sysroot);
     find_testable_code(&input_str, &mut collector);
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests);
index b96a737ed000748706375018180400470455950f..c242eea2362170206e7e33efeb84e2367d184e09 100644 (file)
@@ -54,14 +54,15 @@ pub fn run(input: &str,
            libs: SearchPaths,
            externs: Externs,
            mut test_args: Vec<String>,
-           crate_name: Option<String>)
+           crate_name: Option<String>,
+           maybe_sysroot: Option<PathBuf>)
            -> isize {
     let input_path = PathBuf::from(input);
     let input = config::Input::File(input_path.clone());
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
-                                              .parent().unwrap().to_path_buf()),
+        maybe_sysroot: maybe_sysroot.clone().or_else(
+            || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
         search_paths: libs.clone(),
         crate_types: vec![config::CrateTypeDylib],
         externs: externs.clone(),
@@ -99,7 +100,8 @@ pub fn run(input: &str,
                                        libs,
                                        externs,
                                        false,
-                                       opts);
+                                       opts,
+                                       maybe_sysroot);
 
     {
         let dep_graph = DepGraph::new(false);
@@ -157,7 +159,8 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
 fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
            externs: Externs,
            should_panic: bool, no_run: bool, as_test_harness: bool,
-           compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions) {
+           compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
+           maybe_sysroot: Option<PathBuf>) {
     // the test harness wants its own `main` & top level functions, so
     // never wrap the test in `fn main() { ... }`
     let test = maketest(test, Some(cratename), as_test_harness, opts);
@@ -168,8 +171,8 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
     let outputs = OutputTypes::new(&[(OutputType::Exe, None)]);
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
-                                              .parent().unwrap().to_path_buf()),
+        maybe_sysroot: maybe_sysroot.or_else(
+            || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
         search_paths: libs,
         crate_types: vec![config::CrateTypeExecutable],
         output_types: outputs,
@@ -379,11 +382,12 @@ pub struct Collector {
     current_header: Option<String>,
     cratename: String,
     opts: TestOptions,
+    maybe_sysroot: Option<PathBuf>,
 }
 
 impl Collector {
     pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
-               use_headers: bool, opts: TestOptions) -> Collector {
+               use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>) -> Collector {
         Collector {
             tests: Vec::new(),
             names: Vec::new(),
@@ -395,6 +399,7 @@ pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Ext
             current_header: None,
             cratename: cratename,
             opts: opts,
+            maybe_sysroot: maybe_sysroot,
         }
     }
 
@@ -413,6 +418,7 @@ pub fn add_test(&mut self, test: String,
         let externs = self.externs.clone();
         let cratename = self.cratename.to_string();
         let opts = self.opts.clone();
+        let maybe_sysroot = self.maybe_sysroot.clone();
         debug!("Creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
@@ -432,7 +438,8 @@ pub fn add_test(&mut self, test: String,
                         as_test_harness,
                         compile_fail,
                         error_codes,
-                        &opts);
+                        &opts,
+                        maybe_sysroot);
             })
         });
     }
@@ -495,7 +502,7 @@ fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'thi
 
     fn visit_item(&mut self, item: &'hir hir::Item) {
         let name = if let hir::ItemImpl(.., ref ty, _) = item.node {
-            hir::print::ty_to_string(ty)
+            self.map.node_to_pretty_string(ty.id)
         } else {
             item.name.to_string()
         };
index c93112657b96db239e9b9528f53754f50108919e..b0afc3d63f47932a0bc805092e48eff4ab3af833 100644 (file)
@@ -157,7 +157,8 @@ pub fn visit_fn(&mut self, item: &hir::Item,
                     unsafety: &hir::Unsafety,
                     constness: hir::Constness,
                     abi: &abi::Abi,
-                    gen: &hir::Generics) -> Function {
+                    gen: &hir::Generics,
+                    body: hir::BodyId) -> Function {
         debug!("Visiting fn");
         Function {
             id: item.id,
@@ -172,6 +173,7 @@ pub fn visit_fn(&mut self, item: &hir::Item,
             unsafety: *unsafety,
             constness: constness,
             abi: *abi,
+            body: body,
         }
     }
 
@@ -410,9 +412,9 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 om.structs.push(self.visit_variant_data(item, name, sd, gen)),
             hir::ItemUnion(ref sd, ref gen) =>
                 om.unions.push(self.visit_union_data(item, name, sd, gen)),
-            hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
+            hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, body) =>
                 om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
-                                          constness, abi, gen)),
+                                          constness, abi, gen, body)),
             hir::ItemTy(ref ty, ref gen) => {
                 let t = Typedef {
                     ty: ty.clone(),
@@ -456,11 +458,14 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 };
                 om.constants.push(s);
             },
-            hir::ItemTrait(unsafety, ref gen, ref b, ref items) => {
+            hir::ItemTrait(unsafety, ref gen, ref b, ref item_ids) => {
+                let items = item_ids.iter()
+                                    .map(|ti| self.cx.tcx.map.trait_item(ti.id).clone())
+                                    .collect();
                 let t = Trait {
                     unsafety: unsafety,
                     name: name,
-                    items: items.clone(),
+                    items: items,
                     generics: gen.clone(),
                     bounds: b.iter().cloned().collect(),
                     id: item.id,
index f6fea2f10761b0b423e3ac716d15a365a40077c0..212895d7b76fc661e2db49144288813d0ccffb5c 100644 (file)
@@ -52,10 +52,9 @@ fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
 mod imp {
     use os::unix::prelude::*;
     use mem;
-    use ffi::OsString;
+    use ffi::{CStr, OsString};
     use marker::PhantomData;
-    use slice;
-    use str;
+    use libc;
     use super::Args;
 
     use sys_common::mutex::Mutex;
@@ -64,12 +63,9 @@ mod imp {
     static LOCK: Mutex = Mutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
-        let mut args: Vec<Vec<u8>> = Vec::new();
-        for i in 0..argc {
-            let len = *(argv.offset(i * 2)) as usize;
-            let ptr = *(argv.offset(i * 2 + 1));
-            args.push(slice::from_raw_parts(ptr, len).to_vec());
-        }
+        let args = (0..argc).map(|i| {
+            CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
+        }).collect();
 
         LOCK.lock();
         let ptr = get_global_ptr();
index e3bd77f40099821ff6ece363b7f7ea5001e3a13f..a8391d2b8982f23de0b79337a4f8ddd92e602d8b 100644 (file)
@@ -43,7 +43,7 @@ pub struct DirEntry {
     name: Box<[u8]>
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct OpenOptions {
     // generic
     read: bool,
@@ -63,6 +63,7 @@ pub struct FilePermissions { mode: u16 }
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType { mode: u16 }
 
+#[derive(Debug)]
 pub struct DirBuilder { mode: u16 }
 
 impl FileAttr {
@@ -336,7 +337,7 @@ pub fn new() -> DirBuilder {
     }
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let flags = syscall::O_CREAT | syscall::O_DIRECTORY | syscall::O_EXCL;
+        let flags = syscall::O_CREAT | syscall::O_CLOEXEC | syscall::O_DIRECTORY | syscall::O_EXCL;
         let fd = cvt(syscall::open(p.to_str().unwrap(), flags | (self.mode as usize & 0o777)))?;
         let _ = syscall::close(fd);
         Ok(())
index 5384ef46e9ae3ce91816c577332c701b1f8e1317..d1c404195bc68d5bde33a61f08cb9765694c2394 100644 (file)
@@ -818,6 +818,16 @@ pub enum EXCEPTION_DISPOSITION {
     ExceptionCollidedUnwind
 }
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct CONSOLE_READCONSOLE_CONTROL {
+    pub nLength: ULONG,
+    pub nInitialChars: ULONG,
+    pub dwCtrlWakeupMask: ULONG,
+    pub dwControlKeyState: ULONG,
+}
+pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
+
 #[link(name = "ws2_32")]
 #[link(name = "userenv")]
 #[link(name = "shell32")]
@@ -848,12 +858,11 @@ pub fn WSASocketW(af: c_int,
     pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
     pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 
-    // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL
     pub fn ReadConsoleW(hConsoleInput: HANDLE,
                         lpBuffer: LPVOID,
                         nNumberOfCharsToRead: DWORD,
                         lpNumberOfCharsRead: LPDWORD,
-                        pInputControl: LPVOID) -> BOOL;
+                        pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
 
     pub fn WriteConsoleW(hConsoleOutput: HANDLE,
                          lpBuffer: LPCVOID,
index a74e7699ba0fd6421911fce216ce83647d2657ba..b1a57c349fbb909e942fc854571ed57967e708ee 100644 (file)
@@ -111,19 +111,27 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         if utf8.position() as usize == utf8.get_ref().len() {
             let mut utf16 = vec![0u16; 0x1000];
             let mut num = 0;
+            let mut input_control = readconsole_input_control(CTRL_Z_MASK);
             cvt(unsafe {
                 c::ReadConsoleW(handle,
                                 utf16.as_mut_ptr() as c::LPVOID,
                                 utf16.len() as u32,
                                 &mut num,
-                                ptr::null_mut())
+                                &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL)
             })?;
             utf16.truncate(num as usize);
             // FIXME: what to do about this data that has already been read?
-            let data = match String::from_utf16(&utf16) {
+            let mut data = match String::from_utf16(&utf16) {
                 Ok(utf8) => utf8.into_bytes(),
                 Err(..) => return Err(invalid_encoding()),
             };
+            if let Output::Console(_) = self.handle {
+                if let Some(&last_byte) = data.last() {
+                    if last_byte == CTRL_Z {
+                        data.pop();
+                    }
+                }
+            }
             *utf8 = Cursor::new(data);
         }
 
@@ -217,6 +225,18 @@ fn invalid_encoding() -> io::Error {
     io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
 
+fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CONTROL {
+    c::CONSOLE_READCONSOLE_CONTROL {
+        nLength: ::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
+        nInitialChars: 0,
+        dwCtrlWakeupMask: wakeup_mask,
+        dwControlKeyState: 0,
+    }
+}
+
+const CTRL_Z: u8 = 0x1A;
+const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A
+
 pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
 // The default buffer capacity is 64k, but apparently windows
 // doesn't like 64k reads on stdin. See #13304 for details, but the
index 6d8b3cc93d9de47cd0d5d507ba384a0e312c15aa..81979fd41a6bf6f16ed820eb705973831b46328c 100644 (file)
 
 /// Thread configuration. Provides detailed control over the properties
 /// and behavior of new threads.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// let builder = thread::Builder::new();
+///
+/// let handler = builder.spawn(|| {
+///     // thread code
+/// }).unwrap();
+///
+/// handler.join().unwrap();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Builder {
@@ -228,6 +242,22 @@ pub struct Builder {
 impl Builder {
     /// Generates the base configuration for spawning a thread, from which
     /// configuration methods can be chained.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new()
+    ///                               .name("foo".into())
+    ///                               .stack_size(10);
+    ///
+    /// let handler = builder.spawn(|| {
+    ///     // thread code
+    /// }).unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Builder {
         Builder {
@@ -241,7 +271,7 @@ pub fn new() -> Builder {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::thread;
     ///
     /// let builder = thread::Builder::new()
@@ -260,6 +290,14 @@ pub fn name(mut self, name: String) -> Builder {
     }
 
     /// Sets the size of the stack for the new thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new().stack_size(10);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stack_size(mut self, size: usize) -> Builder {
         self.stack_size = Some(size);
@@ -275,9 +313,26 @@ pub fn stack_size(mut self, size: usize) -> Builder {
     ///
     /// # Errors
     ///
-    /// Unlike the `spawn` free function, this method yields an
-    /// `io::Result` to capture any failure to create the thread at
+    /// Unlike the [`spawn`] free function, this method yields an
+    /// [`io::Result`] to capture any failure to create the thread at
     /// the OS level.
+    ///
+    /// [`spawn`]: ../../std/thread/fn.spawn.html
+    /// [`io::Result`]: ../../std/io/type.Result.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let handler = builder.spawn(|| {
+    ///     // thread code
+    /// }).unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
         F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
index a5abdd922d63fdb9a5770d41bcd171693b8d3b86..f72985fd91a3ea1702e42221ccb864433522fc49 100644 (file)
@@ -1471,12 +1471,13 @@ pub fn is_self(&self) -> bool {
     }
 
     pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
+        let span = mk_sp(eself.span.lo, eself_ident.span.hi);
         let infer_ty = P(Ty {
             id: DUMMY_NODE_ID,
             node: TyKind::ImplicitSelf,
-            span: DUMMY_SP,
+            span: span,
         });
-        let arg = |mutbl, ty, span| Arg {
+        let arg = |mutbl, ty| Arg {
             pat: P(Pat {
                 id: DUMMY_NODE_ID,
                 node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
@@ -1486,15 +1487,13 @@ pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
             id: DUMMY_NODE_ID,
         };
         match eself.node {
-            SelfKind::Explicit(ty, mutbl) => {
-                arg(mutbl, ty, mk_sp(eself.span.lo, eself_ident.span.hi))
-            }
-            SelfKind::Value(mutbl) => arg(mutbl, infer_ty, eself.span),
+            SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
+            SelfKind::Value(mutbl) => arg(mutbl, infer_ty),
             SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty {
                 id: DUMMY_NODE_ID,
                 node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }),
-                span: DUMMY_SP,
-            }), eself.span),
+                span: span,
+            })),
         }
     }
 }
index 187c56d7889ea52a27eb3d424a872f37e0e6558c..4be9e3e57baacbacef2d76e5630fd9a2f238fdca 100644 (file)
@@ -12,5 +12,5 @@
 # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was
 # released on `$date`
 
-rustc: beta-2016-12-16
-cargo: fbeea902d2c9a5be6d99cc35681565d8f7832592
+rustc: beta-2016-12-20
+cargo: bfee18f73287687c543bda8c35e4e33808792715
diff --git a/src/test/compile-fail/E0513.rs b/src/test/compile-fail/E0513.rs
deleted file mode 100644 (file)
index 726e232..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::mem;
-
-fn main() {
-    unsafe {
-        let size = mem::size_of::<u32>();
-        mem::transmute_copy::<u32, [u8; size]>(&8_8); //~ ERROR E0513
-                                                      //~| NOTE no type for variable
-    }
-}
index c3fa39659b968217fb83481c75edea49d0855a37..7c3f7a1d574f99fea3df47f3b596ba8f4ad3a9e0 100644 (file)
@@ -25,8 +25,10 @@ impl Foo for Def {
 }
 
 pub fn test<A: Foo, B: Foo>() {
-    let _array = [4; <A as Foo>::Y]; //~ ERROR E0080
-                                     //~| non-constant path in constant
+    let _array = [4; <A as Foo>::Y];
+    //~^ ERROR cannot use an outer type parameter in this context [E0402]
+    //~| ERROR constant evaluation error [E0080]
+    //~| non-constant path in constant
 }
 
 fn main() {
index ddf16a2278e5bd140cca704c6992e27dafb09f8e..dcf87d5f0fc44b97585cd070cc9f54ceab7fa4e6 100644 (file)
@@ -26,7 +26,9 @@ impl Foo for Def {
 
 pub fn test<A: Foo, B: Foo>() {
     let _array: [u32; <A as Foo>::Y];
-    //~^ ERROR the trait bound `A: Foo` is not satisfied
+    //~^ ERROR cannot use an outer type parameter in this context [E0402]
+    //~| ERROR constant evaluation error [E0080]
+    //~| non-constant path in constant
 }
 
 fn main() {
index 7bd1a96f452d83a53c47aaeb4cbe7a397c08b466..4207fc2373b1749ad49c929fe83655c1778cf4a2 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// compile-flags: --emit=metadata
 
-#![crate_type="metadata"]
+#![crate_type="rlib"]
 
 pub struct Foo {
     pub field: i32,
index 235fc5051d780f78a50b91a8c06bfd8c063acbb8..36382e776ce281fe4f4182303e2f2e52e291270f 100644 (file)
@@ -34,9 +34,11 @@ struct WontChange {
 mod signatures {
     use WillChange;
 
-    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path
+    #[rustc_then_this_would_need(CollectItem)] //~ ERROR no path
     trait Bar {
+        #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
+        #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK
         fn do_something(x: WillChange);
     }
 
index 2e33f11c04b4595ba708d46944facab51093a6a6..4cc15e8b522ac7add81492663a36395c325d2c06 100644 (file)
@@ -35,8 +35,9 @@ enum Enum {
     Variant2(i32)
 }
 
-#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
+#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path
 trait Trait {
+    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
     fn method(&self, _: TypeAlias);
 }
 
index f8aa1ea95f0f66d51039d8bb09d1c11502bf1ec2..eac134ff3cc7d6b287cf83a34ca4c67862897d20 100644 (file)
@@ -14,8 +14,8 @@ struct Foo<'a,'b> {
 }
 
 impl<'a,'b> Foo<'a,'b> {
-    fn bar(
-        self
+    fn bar(self:
+           Foo<'b,'a>
     //~^ ERROR mismatched method receiver
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
@@ -24,7 +24,7 @@ fn bar(
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
-            : Foo<'b,'a>) {}
+           ) {}
 }
 
 fn main() {}
index e89bff025e006bf6fed83b4939302027ecadf66f..f80135848e0c10fe4f8de3139b715a58fd4f82c3 100644 (file)
@@ -16,6 +16,4 @@ fn main() {
     //~| expected type `usize`
     //~| found type `S`
     //~| expected usize, found struct `S`
-    //~| ERROR expected `usize` for repeat count, found struct [E0306]
-    //~| expected `usize`
 }
index b5401f7d124e24e1d2c29aea4a44fdeef9dd386d..691d8d31b412d1c3934d8cbf2f7da2cff49b1788 100644 (file)
@@ -12,8 +12,8 @@
 
 fn main() {
     fn bar(n: isize) {
-        // FIXME (#24414): This error message needs improvement.
         let _x: [isize; n];
-        //~^ ERROR no type for local variable
+        //~^ ERROR attempt to use a non-constant value in a constant [E0435]
+        //~| ERROR constant evaluation error [E0080]
     }
 }
index a6f88a57b9125846a8f5ba8b52a91b18f7157736..f4769a78587280494ea4bab4f91ca3784317f148 100644 (file)
@@ -13,8 +13,9 @@
 fn main() {
     fn bar(n: usize) {
         let _x = [0; n];
-        //~^ ERROR constant evaluation error
-        //~| non-constant path in constant expression
-        //~| NOTE `n` is a variable
+        //~^ ERROR attempt to use a non-constant value in a constant [E0435]
+        //~| NOTE non-constant used with constant
+        //~| NOTE unresolved path in constant expression
+        //~| ERROR constant evaluation error [E0080]
     }
 }
index 5d5113ce07c719f66c2cf622d259cb7498f3e845..a716f3e29d488ce62adf8503f769b5deb70f6361 100644 (file)
 fn main() {
     let n = 1;
     let a = [0; n];
-    //~^ ERROR constant evaluation error
-    //~| non-constant path in constant expression
+    //~^ ERROR attempt to use a non-constant value in a constant [E0435]
     let b = [0; ()];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `()`
     //~| expected usize, found ()
-    //~| ERROR expected `usize` for repeat count, found tuple [E0306]
-    //~| expected `usize`
     let c = [0; true];
     //~^ ERROR mismatched types
     //~| expected usize, found bool
-    //~| ERROR expected `usize` for repeat count, found boolean [E0306]
-    //~| expected `usize`
     let d = [0; 0.5];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `{float}`
     //~| expected usize, found floating-point variable
-    //~| ERROR expected `usize` for repeat count, found float [E0306]
-    //~| expected `usize`
     let e = [0; "foo"];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `&'static str`
     //~| expected usize, found reference
-    //~| ERROR expected `usize` for repeat count, found string literal [E0306]
-    //~| expected `usize`
     let f = [0; -4_isize];
-    //~^ ERROR constant evaluation error
-    //~| expected usize, found isize
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     //~| expected usize, found isize
     let f = [0_usize; -1_isize];
-    //~^ ERROR constant evaluation error
-    //~| expected usize, found isize
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     //~| expected usize, found isize
     struct G {
         g: (),
@@ -59,6 +46,4 @@ struct G {
     //~| expected type `usize`
     //~| found type `main::G`
     //~| expected usize, found struct `main::G`
-    //~| ERROR expected `usize` for repeat count, found struct [E0306]
-    //~| expected `usize`
 }
index f2ac37a2ce9f597925d07daa1bde884abc3ca770..dde559b018cde55ecbc1f7fdac6f8cefc68e5262 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --emit=metadata
 // aux-build:rmeta_rlib.rs
 // no-prefer-dynamic
 // must-compile-successfully
@@ -15,8 +16,6 @@
 // Check that building a metadata crate works with a dependent, rlib crate.
 // This is a cfail test since there is no executable to run.
 
-#![crate_type="metadata"]
-
 extern crate rmeta_rlib;
 use rmeta_rlib::Foo;
 
index 2c0b6f77c1e08114d0239f36fac1192e5f71d86f..5b24da79a7e63a953d6eebadc9f997e3319a962a 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --emit=metadata
 // aux-build:rmeta_meta.rs
 // no-prefer-dynamic
 // must-compile-successfully
@@ -16,8 +17,6 @@
 // crate.
 // This is a cfail test since there is no executable to run.
 
-#![crate_type="metadata"]
-
 extern crate rmeta_meta;
 use rmeta_meta::Foo;
 
diff --git a/src/test/compile-fail/rmeta-priv-warn.rs b/src/test/compile-fail/rmeta-priv-warn.rs
new file mode 100644 (file)
index 0000000..3e7019e
--- /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.
+
+// compile-flags: --emit=metadata
+// no-prefer-dynamic
+// must-compile-successfully
+
+#[deny(warnings)]
+
+// Test that we don't get warnings for non-pub main when only emitting metadata.
+// (#38273)
+
+fn main() {
+}
index 455574bbb9dde58912e0f721fc2138730ab3c8ca..edcf98d99647654b66eb4d6c47f7b82e5b8d8ef3 100644 (file)
@@ -9,11 +9,10 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// compile-flags: --emit=metadata
 
 // Check that building a metadata crate finds an error.
 
-#![crate_type="metadata"]
-
 fn main() {
     let _ = Foo; //~ ERROR unresolved value `Foo`
 }
index 1c922c281397a8f45102c2d64a909a2819b05000..ffeb5bc3b858f26261364c70dc2059af9f25349f 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --emit=metadata
 // aux-build:rmeta_meta.rs
 // no-prefer-dynamic
 
 // Check that building a metadata crate finds an error with a dependent,
 // metadata-only crate.
 
-#![crate_type="metadata"]
 
 extern crate rmeta_meta;
 use rmeta_meta::Foo;
index 26e73a08ea137ce9c905776182d98fc04517afdd..ada9e0b30ccae1cc61010da8c3b819e4211e6dfe 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-macos FIXME(#37479)
 
 // compile-flags:-g
 
index 10c02d84b385e7105723652a177694a4c6700e13..28e85c94b664ce47882d2559402eeea53f64f259 100644 (file)
 const CONST_CHANGE_VALUE_1: i16 = 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_1: i16 = 2;
 const CONST_CHANGE_VALUE_2: i16 = 1 + 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_2: i16 = 1 + 2;
 const CONST_CHANGE_VALUE_3: i16 = 2 + 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_3: i16 = 2 * 3;
 const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
index aa17a24be23b6fab6027ea981dce126de9e41b99..da3a953d11eaa883367ebcdedcca038947c44a7f 100644 (file)
@@ -108,8 +108,10 @@ enum EnumChangeValueCStyleVariant0 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant0 {
@@ -126,6 +128,8 @@ enum EnumChangeValueCStyleVariant1 {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant1 {
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
new file mode 100644 (file)
index 0000000..03e621f
--- /dev/null
@@ -0,0 +1,272 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `extern` modules.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// must-compile-successfully
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(unboxed_closures)]
+#![feature(link_args)]
+#![crate_type="rlib"]
+
+
+// Change function name --------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_function_name1(c: 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="cfail3")]
+extern {
+    pub fn change_function_name2(c: i64) -> i32;
+}
+
+
+
+// Change parameter name -------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_parameter_name(c: 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="cfail3")]
+extern {
+    pub fn change_parameter_name(d: i64) -> i32;
+}
+
+
+
+// Change parameter type -------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_parameter_type(c: 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="cfail3")]
+extern {
+    pub fn change_parameter_type(c: i32) -> i32;
+}
+
+
+
+// Change return type ----------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn change_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="cfail3")]
+extern {
+    pub fn change_return_type(c: i32) -> i8;
+}
+
+
+
+// Add parameter ---------------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn add_parameter(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="cfail3")]
+extern {
+    pub fn add_parameter(c: i32, d: i32) -> i32;
+}
+
+
+
+// Add return type -------------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn add_return_type(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="cfail3")]
+extern {
+    pub fn add_return_type(c: i32) -> i32;
+}
+
+
+
+// Make function variadic ------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    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="cfail3")]
+extern {
+    pub fn make_function_variadic(c: i32, ...);
+}
+
+
+
+// Change calling convention ---------------------------------------------------
+#[cfg(cfail1)]
+extern "C" {
+    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="cfail3")]
+extern "rust-call" {
+    pub fn change_calling_convention(c: i32);
+}
+
+
+
+// Make function public --------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    fn make_function_public(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="cfail3")]
+extern {
+    pub fn make_function_public(c: i32);
+}
+
+
+
+// Add function ----------------------------------------------------------------
+#[cfg(cfail1)]
+extern {
+    pub fn add_function1(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="cfail3")]
+extern {
+    pub fn add_function1(c: i32);
+    pub fn add_function2();
+}
+
+
+
+// Change link-args ------------------------------------------------------------
+#[cfg(cfail1)]
+#[link_args = "-foo -bar"]
+extern {
+    pub fn change_link_args(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="cfail3")]
+#[link_args = "-foo -bar -baz"]
+extern {
+    pub fn change_link_args(c: i32);
+}
+
+
+
+// Change link-name ------------------------------------------------------------
+#[cfg(cfail1)]
+#[link(name = "foo")]
+extern {
+    pub fn change_link_name(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="cfail3")]
+#[link(name = "bar")]
+extern {
+    pub fn change_link_name(c: i32);
+}
+
+type c_i32 = i32;
+type c_i64 = i64;
+
+// Indirectly change parameter type --------------------------------------------
+mod indirectly_change_parameter_type {
+    #[cfg(cfail1)]
+    use super::c_i32 as c_int;
+    #[cfg(not(cfail1))]
+    use super::c_i64 as c_int;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    extern {
+        pub fn indirectly_change_parameter_type(c: c_int);
+    }
+}
+
+
+
+// Indirectly change return type --------------------------------------------
+mod indirectly_change_return_type {
+    #[cfg(cfail1)]
+    use super::c_i32 as c_int;
+    #[cfg(not(cfail1))]
+    use super::c_i64 as c_int;
+
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    extern {
+        pub fn indirectly_change_return_type() -> c_int;
+    }
+}
index ac67e4349013a8cad20e453dceaaee3ea1673572..7c6da3ba9fea6030f7d88d0628862c3f3c1be10e 100644 (file)
 static STATIC_CHANGE_VALUE_1: i16 = 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_1: i16 = 2;
 
 static STATIC_CHANGE_VALUE_2: i16 = 1 + 1;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_2: i16 = 1 + 2;
 
 static STATIC_CHANGE_VALUE_3: i16 = 2 + 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_3: i16 = 2 * 3;
 
 static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
 
index 391c2e75ba4d5770dbd81840130fe2708043ab5e..bc401ae93404f0a45e099b022e781654715d5e2b 100644 (file)
@@ -98,11 +98,15 @@ trait TraitAddReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddReturnType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method() -> u32;
 }
 
@@ -115,11 +119,15 @@ trait TraitChangeReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeReturnType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method() -> u64;
 }
 
@@ -132,11 +140,15 @@ trait TraitAddParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddParameterToMethod {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(a: u32);
 }
 
@@ -146,15 +158,29 @@ trait TraitAddParameterToMethod {
 #[cfg(cfail1)]
 trait TraitChangeMethodParameterName {
     fn method(a: u32);
+    fn with_default(x: i32) {}
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterName {
+    // FIXME(#38501) This should preferably always be clean.
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(b: u32);
+
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
+    fn with_default(y: i32) {}
 }
 
 
@@ -166,11 +192,15 @@ trait TraitChangeMethodParameterType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(a: i64);
 }
 
@@ -183,11 +213,15 @@ trait TraitChangeMethodParameterTypeRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(a: &mut i32);
 }
 
@@ -200,11 +234,15 @@ trait TraitChangeMethodParametersOrder {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(b: i64, a: i32);
 }
 
@@ -253,11 +291,15 @@ trait TraitChangeModeSelfRefToMut {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(&mut self);
 }
 
@@ -269,11 +311,15 @@ fn method(self) {}
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[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 TraitChangeModeSelfOwnToMut: Sized {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(mut self) {}
 }
 
@@ -285,11 +331,15 @@ trait TraitChangeModeSelfOwnToRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method(&self);
 }
 
@@ -302,11 +352,15 @@ trait TraitAddUnsafeModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddUnsafeModifier {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     unsafe fn method();
 }
 
@@ -319,11 +373,15 @@ trait TraitAddExternModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddExternModifier {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     extern fn method();
 }
 
@@ -336,11 +394,15 @@ trait TraitChangeExternCToRustIntrinsic {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     extern "rust-intrinsic" fn method();
 }
 
@@ -353,11 +415,15 @@ trait TraitAddTypeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T>();
 }
 
@@ -370,11 +436,15 @@ trait TraitAddLifetimeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(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="cfail3")]
     fn method<'a>();
 }
 
@@ -391,11 +461,15 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: ReferencedTrait0>();
 }
 
@@ -408,11 +482,15 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: Sized>();
 }
 
@@ -425,11 +503,15 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
@@ -442,11 +524,15 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
@@ -459,11 +545,15 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<T: Sized + Sync>();
 }
 
@@ -476,11 +566,15 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
@@ -514,11 +608,15 @@ trait TraitAddTraitBoundToAssociatedType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToAssociatedType {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
     fn mathod();
@@ -535,11 +633,15 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     type Associated: 'a;
 
     fn mathod();
@@ -617,11 +719,15 @@ trait TraitChangeTypeOfAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
+    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_metadata_dirty(cfg="cfail2")]
+    #[rustc_metadata_clean(cfg="cfail3")]
     const Value: f64;
 
     fn mathod();
@@ -1013,11 +1119,15 @@ mod change_return_type_of_method_indirectly_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ReturnType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeReturnType {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method() -> ReturnType;
     }
 }
@@ -1031,11 +1141,15 @@ mod change_method_parameter_type_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ArgType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeArgType {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method(a: ArgType);
     }
 }
@@ -1049,11 +1163,15 @@ mod change_method_parameter_type_bound_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method<T: Bound>(a: T);
     }
 }
@@ -1068,11 +1186,15 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
+        #[rustc_dirty(label="Hir", cfg="cfail2")]
+        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_metadata_dirty(cfg="cfail2")]
+        #[rustc_metadata_clean(cfg="cfail3")]
         fn method<T>(a: T) where T: Bound;
     }
 }
index ba8d3cc934bfc253e6f23651c57ded089f5a66e4..8651a67bae221e88a5d4e9a3e24347b259b27d6a 100644 (file)
@@ -23,14 +23,14 @@ fn main() { }
 mod x {
     #[cfg(rpass1)]
     pub fn x() {
-        println!("1");
+        println!("{}", "1");
     }
 
     #[cfg(rpass2)]
     #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
     #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
     pub fn x() {
-        println!("2");
+        println!("{}", "2");
     }
 }
 
index c1d6e3023fbc163eb6954560c05fad3a5fdb0621..b0491fe6e27fd44e7a1e01950641dcdfeb96ebaf 100644 (file)
@@ -1,15 +1,15 @@
 digraph block {
     N0[label="entry"];
     N1[label="exit"];
-    N2[label="stmt "];
+    N2[label="stmt fn inner(x: isize) -> isize { x + x }"];
     N3[label="expr inner"];
     N4[label="expr inner"];
     N5[label="expr 18"];
     N6[label="expr inner(18)"];
     N7[label="expr inner(inner(18))"];
     N8[label="stmt inner(inner(18));"];
-    N9[label="block { inner(inner(18)); }"];
-    N10[label="expr { inner(inner(18)); }"];
+    N9[label="block {\l    fn inner(x: isize) -> isize { x + x }\l    inner(inner(18));\l}\l"];
+    N10[label="expr {\l    fn inner(x: isize) -> isize { x + x }\l    inner(inner(18));\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
index d2f9f41f647beb48e6772f75f402e150abf6941d..223978c3d7634f7380960dc81d32f2c8eadda422 100644 (file)
@@ -1,8 +1,8 @@
 digraph block {
     N0[label="entry"];
     N1[label="exit"];
-    N2[label="stmt "];
-    N3[label="stmt "];
+    N2[label="stmt struct S19 {\l    x: isize,\l}\l"];
+    N3[label="stmt impl S19 {\l    fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l}\l"];
     N4[label="expr 19"];
     N5[label="expr S19{x: 19,}"];
     N6[label="local s"];
@@ -11,8 +11,8 @@ digraph block {
     N9[label="expr s.inner()"];
     N10[label="expr s.inner().inner()"];
     N11[label="stmt s.inner().inner();"];
-    N12[label="block { let s = S19{x: 19,}; s.inner().inner(); }"];
-    N13[label="expr { let s = S19{x: 19,}; s.inner().inner(); }"];
+    N12[label="block {\l    struct S19 {\l        x: isize,\l    }\l    impl S19 {\l        fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l    }\l    let s = S19{x: 19,};\l    s.inner().inner();\l}\l"];
+    N13[label="expr {\l    struct S19 {\l        x: isize,\l    }\l    impl S19 {\l        fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l    }\l    let s = S19{x: 19,};\l    s.inner().inner();\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
diff --git a/src/test/run-make/issue-38237/Makefile b/src/test/run-make/issue-38237/Makefile
new file mode 100644 (file)
index 0000000..0a68140
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) foo.rs; $(RUSTC) bar.rs
+       $(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR)
diff --git a/src/test/run-make/issue-38237/bar.rs b/src/test/run-make/issue-38237/bar.rs
new file mode 100644 (file)
index 0000000..794e08c
--- /dev/null
@@ -0,0 +1,14 @@
+// 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_type = "lib"]
+
+#[derive(Debug)]
+pub struct S;
diff --git a/src/test/run-make/issue-38237/baz.rs b/src/test/run-make/issue-38237/baz.rs
new file mode 100644 (file)
index 0000000..c2a2c89
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate foo;
+extern crate bar;
+
+pub struct Bar;
+impl ::std::ops::Deref for Bar {
+    type Target = bar::S;
+    fn deref(&self) -> &Self::Target { unimplemented!() }
+}
diff --git a/src/test/run-make/issue-38237/foo.rs b/src/test/run-make/issue-38237/foo.rs
new file mode 100644 (file)
index 0000000..c291ffb
--- /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.
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro, proc_macro_lib)]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+pub fn derive(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { ts }
+
+#[derive(Debug)]
+struct S;
index 696e0544fdc5793003c11493f059864c632f9040..fae134986872e06cac70ff4f8d22f1fb05e6bb01 100644 (file)
@@ -12,5 +12,6 @@
 
 
 
-fn foo_method(&self) -> &'static str { return "i am very similar to foo."; }
-/* nest::{{impl}}::foo_method */
+fn foo_method(self: &Self)
+ -> &'static str { return "i am very similar to foo."; } /*
+nest::{{impl}}::foo_method */
index c6892757c682f22cbc4d5d2c60b8d7ab9f69e71d..e1b1b441894b75eeeb087697d8e658a51b1a522c 100644 (file)
@@ -41,12 +41,12 @@ fn get_lints(&self) -> LintArray { lint_array!(REGION_HIERARCHY) }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_fn(&mut self, cx: &LateContext,
-                              fk: FnKind, _: &hir::FnDecl, expr: &hir::Expr,
+                              fk: FnKind, _: &hir::FnDecl, body: &hir::Body,
                               span: Span, node: ast::NodeId)
     {
         if let FnKind::Closure(..) = fk { return }
 
-        let mut extent = cx.tcx.region_maps.node_extent(expr.id);
+        let mut extent = cx.tcx.region_maps.node_extent(body.value.id);
         while let Some(parent) = cx.tcx.region_maps.opt_encl_scope(extent) {
             extent = parent;
         }
index 394845b66f3d3a105694589464d879349d60096a..c3cfe89ee5c3e9cca6b80d7a3721a682bc9e301d 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 // no-prefer-dynamic
+// compile-flags: --emit=metadata
 
-#![crate_type="metadata"]
+#![crate_type="rlib"]
 #![crate_name="rmeta_aux"]
 
 pub struct Foo {
diff --git a/src/test/run-pass/issue-38437.rs b/src/test/run-pass/issue-38437.rs
new file mode 100644 (file)
index 0000000..a6e7df1
--- /dev/null
@@ -0,0 +1,54 @@
+// 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.
+
+// Check that drop elaboration clears the "master" discriminant
+// drop flag even if it protects no fields.
+
+struct Good(usize);
+impl Drop for Good {
+    #[inline(never)]
+    fn drop(&mut self) {
+        println!("dropping Good({})", self.0);
+    }
+}
+
+struct Void;
+impl Drop for Void {
+    #[inline(never)]
+    fn drop(&mut self) {
+        panic!("Suddenly, a Void appears.");
+    }
+}
+
+enum E {
+    Never(Void),
+    Fine(Good)
+}
+
+fn main() {
+    let mut go = true;
+
+    loop {
+        let next;
+        match go {
+            true => next = E::Fine(Good(123)),
+            false => return,
+        }
+
+        match next {
+            E::Never(_) => return,
+            E::Fine(_good) => go = false,
+        }
+
+        // `next` is dropped and StorageDead'd here. We must reset the
+        // discriminant's drop flag to avoid random variants being
+        // dropped.
+    }
+}
index 5e9a0b915031e0a8c23a238fe860fc1f55d7659c..58f66c1358437132e9236fb7a0c6b3e677bcd297 100644 (file)
@@ -1,11 +1,3 @@
-error: cannot borrow immutable borrowed content `*a` as mutable
-  --> $DIR/mut-arg-hint.rs:13:9
-   |
-12 |     fn foo(mut a: &String) {
-   |                   ------- use `&mut String` here to make mutable
-13 |         a.push_str("bar");
-   |         ^
-
 error: cannot borrow immutable borrowed content `*a` as mutable
   --> $DIR/mut-arg-hint.rs:18:5
    |
@@ -14,6 +6,14 @@ error: cannot borrow immutable borrowed content `*a` as mutable
 18 |     a.push_str("foo");
    |     ^
 
+error: cannot borrow immutable borrowed content `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:13:9
+   |
+12 |     fn foo(mut a: &String) {
+   |                   ------- use `&mut String` here to make mutable
+13 |         a.push_str("bar");
+   |         ^
+
 error: cannot borrow immutable borrowed content `*a` as mutable
   --> $DIR/mut-arg-hint.rs:25:9
    |
index 26a2e96f571081ef8b6fff2c7b289d0b11988937..8c8e426604e11aeee6ab29d62a53552f2a5d5323 100644 (file)
@@ -21,19 +21,44 @@ struct Test {
     lock: Option<&'static str>,
 }
 
-const TEST_REPOS: &'static [Test] = &[Test {
-                                          name: "cargo",
-                                          repo: "https://github.com/rust-lang/cargo",
-                                          sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
-                                          lock: None,
-                                      },
-                                      Test {
-                                          name: "iron",
-                                          repo: "https://github.com/iron/iron",
-                                          sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
-                                          lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
-                                      }];
-
+const TEST_REPOS: &'static [Test] = &[
+    Test {
+        name: "cargo",
+        repo: "https://github.com/rust-lang/cargo",
+        sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
+        lock: None,
+    },
+    Test {
+        name: "iron",
+        repo: "https://github.com/iron/iron",
+        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
+        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
+    },
+    Test {
+        name: "ripgrep",
+        repo: "https://github.com/BurntSushi/ripgrep",
+        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
+        lock: None,
+    },
+    Test {
+        name: "tokei",
+        repo: "https://github.com/Aaronepower/tokei",
+        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
+        lock: None,
+    },
+    Test {
+        name: "treeify",
+        repo: "https://github.com/dzamlo/treeify",
+        sha: "999001b223152441198f117a68fb81f57bc086dd",
+        lock: None,
+    },
+    Test {
+        name: "xsv",
+        repo: "https://github.com/BurntSushi/xsv",
+        sha: "5ec4fff4a3f507eda887049469897f02c6fae036",
+        lock: None,
+    },
+];
 
 fn main() {
     // One of the projects being tested here is Cargo, and when being tested
index 956392ca540cd64c8efcd0c6b31b4af92cb2af40..e7690c03de5c3de88856a9b03c0d93405bdc8729 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "rustbook"
 version = "0.0.0"
+build = false
 
 [[bin]]
 name = "rustbook"