]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #61054 - estebank:mut-ref-reassign, r=zackmdavis
authorMazdak Farrokhzad <twingoow@gmail.com>
Thu, 23 May 2019 23:30:20 +0000 (01:30 +0200)
committerGitHub <noreply@github.com>
Thu, 23 May 2019 23:30:20 +0000 (01:30 +0200)
Suggest dereferencing on assignment to mutable borrow

Fix #33570

216 files changed:
Cargo.lock
src/bootstrap/compile.rs
src/build_helper/lib.rs
src/ci/docker/dist-various-2/Dockerfile
src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
src/liballoc/collections/binary_heap.rs
src/liballoc/collections/btree/map.rs
src/liballoc/collections/btree/set.rs
src/liballoc/string.rs
src/liballoc/vec.rs
src/libarena/lib.rs
src/libcore/ascii.rs
src/libcore/cell.rs
src/libcore/iter/adapters/mod.rs
src/libcore/num/mod.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libprofiler_builtins/build.rs
src/librustc/arena.rs
src/librustc/cfg/construct.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_syntax.rs
src/librustc/lint/mod.rs
src/librustc/middle/cstore.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/query/mod.rs
src/librustc/traits/auto_trait.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc/ty/print/pretty.rs
src/librustc/ty/query/values.rs
src/librustc/ty/sty.rs
src/librustc_allocator/expand.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_ssa/back/link.rs
src/librustc_codegen_ssa/back/symbol_export.rs
src/librustc_codegen_ssa/base.rs
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_errors/snippet.rs
src/librustc_interface/passes.rs
src/librustc_lint/builtin.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_macros/src/symbols.rs
src/librustc_metadata/Cargo.toml
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_metadata/index.rs
src/librustc_metadata/index_builder.rs [deleted file]
src/librustc_metadata/isolated_encoder.rs [deleted file]
src/librustc_metadata/lib.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/build/block.rs
src/librustc_mir/build/expr/as_operand.rs
src/librustc_mir/build/expr/as_place.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/error_codes.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/hir_stats.rs
src/librustc_plugin/load.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/outlives/mod.rs
src/librustc_typeck/variance/mod.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/highlight.rs
src/libstd/Cargo.toml
src/libstd/env.rs
src/libstd/path.rs
src/libstd/sys/unix/args.rs
src/libstd/sys/wasm/args.rs
src/libstd/sys/windows/args.rs
src/libsyntax/ast.rs
src/libsyntax/attr/mod.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/quoted.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/json.rs
src/libsyntax/mut_visit.rs
src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/literal.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/util/parser.rs
src/libsyntax_ext/assert.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/generic/ty.rs
src/libsyntax_ext/env.rs
src/libsyntax_ext/global_asm.rs
src/libsyntax_ext/proc_macro_decls.rs
src/libsyntax_ext/proc_macro_server.rs
src/libsyntax_ext/trace_macros.rs
src/libsyntax_pos/hygiene.rs
src/libsyntax_pos/symbol.rs
src/llvm-project
src/test/incremental/cyclic-trait-hierarchy.rs
src/test/mir-opt/box_expr.rs
src/test/mir-opt/issue-41110.rs
src/test/mir-opt/issue-49232.rs
src/test/mir-opt/match-arm-scopes.rs [new file with mode: 0644]
src/test/mir-opt/match_false_edges.rs
src/test/mir-opt/match_test.rs
src/test/mir-opt/packed-struct-drop-aligned.rs
src/test/mir-opt/remove_fake_borrows.rs
src/test/mir-opt/storage_live_dead_in_statics.rs
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/rustdoc/issue-60726.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.stderr
src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
src/test/ui/consts/const_let_refutable.stderr
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
src/test/ui/cycle-projection-based-on-where-clause.rs
src/test/ui/cycle-projection-based-on-where-clause.stderr
src/test/ui/emit-artifact-notifications.nll.stderr
src/test/ui/emit-artifact-notifications.stderr
src/test/ui/empty/empty-never-array.stderr
src/test/ui/feature-gates/feature-gate-nll.stderr
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
src/test/ui/issues/issue-15381.stderr
src/test/ui/issues/issue-20772.rs
src/test/ui/issues/issue-20772.stderr
src/test/ui/issues/issue-21177.rs
src/test/ui/issues/issue-21177.stderr
src/test/ui/issues/issue-23302-3.rs
src/test/ui/issues/issue-23302-3.stderr
src/test/ui/issues/issue-40510-1.migrate.stderr
src/test/ui/issues/issue-40510-3.migrate.stderr
src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
src/test/ui/issues/issue-49824.stderr
src/test/ui/lint/lint-ctypes-enum.rs
src/test/ui/lint/lint-ctypes-enum.stderr
src/test/ui/lint/lint-match-arms.rs [new file with mode: 0644]
src/test/ui/lint/lint-match-arms.stderr [new file with mode: 0644]
src/test/ui/lint/lint-unused-mut-variables.rs
src/test/ui/lint/lint-unused-mut-variables.stderr
src/test/ui/macros/issue-61033-1.rs [new file with mode: 0644]
src/test/ui/macros/issue-61033-1.stderr [new file with mode: 0644]
src/test/ui/macros/issue-61033-2.rs [new file with mode: 0644]
src/test/ui/macros/issue-61033-2.stderr [new file with mode: 0644]
src/test/ui/old-suffixes-are-really-forbidden.stderr
src/test/ui/parser/bad-lit-suffixes.rs
src/test/ui/parser/bad-lit-suffixes.stderr
src/test/ui/parser/int-literal-too-large-span.rs
src/test/ui/parser/int-literal-too-large-span.stderr
src/test/ui/parser/issue-5544-a.rs
src/test/ui/parser/issue-5544-a.stderr
src/test/ui/parser/issue-5544-b.rs
src/test/ui/parser/issue-5544-b.stderr
src/test/ui/parser/lex-bad-numeric-literals.rs
src/test/ui/parser/lex-bad-numeric-literals.stderr
src/test/ui/parser/no-binary-float-literal.rs
src/test/ui/parser/no-binary-float-literal.stderr
src/test/ui/pattern/pattern-bindings-after-at.stderr
src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
src/test/ui/thread-local-in-ctfe.stderr
src/tools/clippy

index db9f0069ced0c1c41f107d2625a618fdc23944d9..392f3e8e4bdce56b25b47b89bb32dc0c857dc9c0 100644 (file)
@@ -25,7 +25,7 @@ dependencies = [
 name = "alloc"
 version = "0.0.0"
 dependencies = [
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -123,7 +123,7 @@ version = "0.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
@@ -462,7 +462,7 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.14"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -744,7 +744,7 @@ name = "dlmalloc"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
@@ -910,7 +910,7 @@ name = "fortanix-sgx-abi"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -1071,7 +1071,7 @@ name = "hashbrown"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-alloc 1.0.0",
  "rustc-std-workspace-core 1.0.0",
 ]
@@ -1772,7 +1772,7 @@ dependencies = [
 name = "panic_abort"
 version = "0.0.0"
 dependencies = [
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1782,7 +1782,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "unwind 0.0.0",
@@ -1967,7 +1967,7 @@ name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2492,7 +2492,7 @@ name = "rustc-demangle"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -2620,7 +2620,7 @@ dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2850,7 +2850,7 @@ dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2877,6 +2877,7 @@ dependencies = [
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
  "serialize 0.0.0",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
@@ -2912,7 +2913,7 @@ dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -3029,7 +3030,7 @@ dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -3298,7 +3299,7 @@ dependencies = [
  "alloc 0.0.0",
  "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3889,7 +3890,7 @@ name = "unwind"
 version = "0.0.0"
 dependencies = [
  "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -4087,7 +4088,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc"
 "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
 "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
-"checksum compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f235c329e5cb9fa3d2ca2cc36256ba9a7f23fa76e0f4db6f68c23b73b2ac69"
+"checksum compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e899b947d7e71c3d35c0b6194d64025b84946640510e215090c815b20828964e"
 "checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6"
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
 "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887"
index e1cdd226fd6e5ba3e78152d43fec41f0ba257358..2da5e1c5902c11deadf028842a0b1d3d34c59b8e 100644 (file)
@@ -161,7 +161,33 @@ pub fn std_cargo(builder: &Builder<'_>,
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
 
+    // Determine if we're going to compile in optimized C intrinsics to
+    // the `compiler-builtins` crate. These intrinsics live in LLVM's
+    // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
+    // always checked out, so we need to conditionally look for this. (e.g. if
+    // an external LLVM is used we skip the LLVM submodule checkout).
+    //
+    // Note that this shouldn't affect the correctness of `compiler-builtins`,
+    // but only its speed. Some intrinsics in C haven't been translated to Rust
+    // yet but that's pretty rare. Other intrinsics have optimized
+    // implementations in C which have only had slower versions ported to Rust,
+    // so we favor the C version where we can, but it's not critical.
+    //
+    // If `compiler-rt` is available ensure that the `c` feature of the
+    // `compiler-builtins` crate is enabled and it's configured to learn where
+    // `compiler-rt` is located.
+    let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
+    let compiler_builtins_c_feature = if compiler_builtins_root.exists() {
+        cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
+        " compiler-builtins-c".to_string()
+    } else {
+        String::new()
+    };
+
     if builder.no_std(target) == Some(true) {
+        let mut features = "compiler-builtins-mem".to_string();
+        features.push_str(&compiler_builtins_c_feature);
+
         // for no-std targets we only compile a few no_std crates
         cargo
             .args(&["-p", "alloc"])
@@ -170,7 +196,8 @@ pub fn std_cargo(builder: &Builder<'_>,
             .arg("--features")
             .arg("compiler-builtins-mem compiler-builtins-c");
     } else {
-        let features = builder.std_features();
+        let mut features = builder.std_features();
+        features.push_str(&compiler_builtins_c_feature);
 
         if compiler.stage != 0 && builder.config.sanitizers {
             // This variable is used by the sanitizer runtime crates, e.g.
index 60911d917899f6f338da76cd30a96dfbadd470a4..8b00c1d81b08c4b6baf841b8c94d7b9daa2d5312 100644 (file)
@@ -288,9 +288,9 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
     } else {
         format!("static={}", link_name)
     };
-    // The source for `compiler-rt` comes from the `compiler-builtins` crate, so
-    // load our env var set by cargo to find the source code.
-    let dir = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap();
+    // This env var is provided by rustbuild to tell us where `compiler-rt`
+    // lives.
+    let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
     let lib = native_lib_boilerplate(
         dir.as_ref(),
         sanitizer_name,
index 869ee9883c1009e4c0d6f3e07276caf1308bdd87..e7d6f201b444ec757ec0775e644252999459f45c 100644 (file)
@@ -24,7 +24,7 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no
   gpg-agent
 
 RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486
-RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main'
+RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2 main'
 
 WORKDIR /tmp
 COPY dist-various-2/shared.sh /tmp/
index 70390c2ac1df18a52390b0196068d054a43561f3..a157fee16cfd5ddaabf87326fc7e5d4a31767454 100644 (file)
@@ -20,3 +20,9 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-full-bootstrap
 ENV SCRIPT python2.7 ../x.py build
+
+# In general this just slows down the build and we're just a smoke test that
+# a full bootstrap works in general, so there's not much need to take this
+# penalty in build times.
+ENV NO_LLVM_ASSERTIONS 1
+ENV NO_DEBUG_ASSERTIONS 1
index c5a0b6e877b65f124f61e925ab8989c5e02547e1..c898f064fd09f4fff4bb0e396a4384fe06049b26 100644 (file)
@@ -1035,11 +1035,6 @@ fn next(&mut self) -> Option<&'a T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a T> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1095,11 +1090,6 @@ fn next(&mut self) -> Option<T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<T> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1146,11 +1136,6 @@ fn next(&mut self) -> Option<T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<T> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
index 414abb00ef1fa760161d49cbaa0327939675ce94..6b079fc87cc78905f431a097a2aa8aaee7a33f3b 100644 (file)
@@ -1193,11 +1193,6 @@ fn next(&mut self) -> Option<(&'a K, &'a V)> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.length, Some(self.length))
     }
-
-    #[inline]
-    fn last(mut self) -> Option<(&'a K, &'a V)> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
@@ -1258,11 +1253,6 @@ fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.length, Some(self.length))
     }
-
-    #[inline]
-    fn last(mut self) -> Option<(&'a K, &'a mut V)> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1369,11 +1359,6 @@ fn next(&mut self) -> Option<(K, V)> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.length, Some(self.length))
     }
-
-    #[inline]
-    fn last(mut self) -> Option<(K, V)> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1436,11 +1421,6 @@ fn next(&mut self) -> Option<&'a K> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a K> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1478,11 +1458,6 @@ fn next(&mut self) -> Option<&'a V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a V> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1520,11 +1495,6 @@ fn next(&mut self) -> Option<(&'a K, &'a V)> {
             unsafe { Some(self.next_unchecked()) }
         }
     }
-
-    #[inline]
-    fn last(mut self) -> Option<(&'a K, &'a V)> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1538,11 +1508,6 @@ fn next(&mut self) -> Option<&'a mut V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a mut V> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1661,11 +1626,6 @@ fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
             unsafe { Some(self.next_unchecked()) }
         }
     }
-
-    #[inline]
-    fn last(mut self) -> Option<(&'a K, &'a mut V)> {
-        self.next_back()
-    }
 }
 
 impl<'a, K, V> RangeMut<'a, K, V> {
index 6f2467dfd6b513de6b41e7fec1a95a85f61feed9..16a96ca19b82462b4a99f2e234f3e1c85b630e4f 100644 (file)
@@ -1019,11 +1019,6 @@ fn next(&mut self) -> Option<&'a T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a T> {
-        self.next_back()
-    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
@@ -1049,11 +1044,6 @@ fn next(&mut self) -> Option<T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<T> {
-        self.next_back()
-    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
@@ -1083,11 +1073,6 @@ impl<'a, T> Iterator for Range<'a, T> {
     fn next(&mut self) -> Option<&'a T> {
         self.iter.next().map(|(k, _)| k)
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a T> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "btree_range", since = "1.17.0")]
index e74d37c1c2bae1b676b4c14a1dc08f4cb107efa1..7f7722548f581df43deca22d09a91d2950158911 100644 (file)
@@ -2385,10 +2385,6 @@ fn next(&mut self) -> Option<char> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-    #[inline]
-    fn last(mut self) -> Option<char> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
index c0cdffe596babc85e61fce4813ef1616682df183..073d3ab5937035a148053e8e6243a8c300903ab2 100644 (file)
@@ -2395,11 +2395,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     fn count(self) -> usize {
         self.len()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<T> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2519,11 +2514,6 @@ fn next(&mut self) -> Option<T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<T> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
@@ -2593,10 +2583,6 @@ fn next(&mut self) -> Option<Self::Item> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.drain.size_hint()
     }
-
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "vec_splice", since = "1.21.0")]
index ce5e5f23a94b81e0745d9acaae662bea75adf719..d6bec816e4ee60fcea0fb79e277a4ccd27d99990 100644 (file)
@@ -486,9 +486,31 @@ pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
         }
     }
 
+    #[inline]
+    unsafe fn write_from_iter<T, I: Iterator<Item = T>>(
+        &self,
+        mut iter: I,
+        len: usize,
+        mem: *mut T,
+    ) -> &mut [T] {
+        let mut i = 0;
+        // Use a manual loop since LLVM manages to optimize it better for
+        // slice iterators
+        loop {
+            let value = iter.next();
+            if i >= len || value.is_none() {
+                // We only return as many items as the iterator gave us, even
+                // though it was supposed to give us `len`
+                return slice::from_raw_parts_mut(mem, i);
+            }
+            ptr::write(mem.offset(i as isize), value.unwrap());
+            i += 1;
+        }
+    }
+
     #[inline]
     pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
-        let mut iter = iter.into_iter();
+        let iter = iter.into_iter();
         assert!(mem::size_of::<T>() != 0);
         assert!(!mem::needs_drop::<T>());
 
@@ -505,10 +527,7 @@ pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T]
                 let size = len.checked_mul(mem::size_of::<T>()).unwrap();
                 let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut _ as *mut T;
                 unsafe {
-                    for i in 0..len {
-                        ptr::write(mem.offset(i as isize), iter.next().unwrap())
-                    }
-                    slice::from_raw_parts_mut(mem, len)
+                    self.write_from_iter(iter, len, mem)
                 }
             }
             (_, _) => {
index ddee02ea232d1cf43f6428b8f82440ba21b4c943..c0ab364380fbd83d379fe22662e5d4eb20f80598 100644 (file)
@@ -117,8 +117,6 @@ impl Iterator for EscapeDefault {
     type Item = u8;
     fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
-    #[inline]
-    fn last(mut self) -> Option<u8> { self.next_back() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl DoubleEndedIterator for EscapeDefault {
index fcfd80d92660d8a28facb2ea90de54a5d731e551..9672cf4ffed36860db66de3fac8a5c2d5768ceeb 100644 (file)
 //! mutability:
 //!
 //! ```
+//! use std::cell::{RefCell, RefMut};
 //! use std::collections::HashMap;
-//! use std::cell::RefCell;
 //! use std::rc::Rc;
 //!
 //! fn main() {
 //!     let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
-//!     shared_map.borrow_mut().insert("africa", 92388);
-//!     shared_map.borrow_mut().insert("kyoto", 11837);
-//!     shared_map.borrow_mut().insert("piccadilly", 11826);
-//!     shared_map.borrow_mut().insert("marbles", 38);
+//!     // Create a new block to limit the scope of the dynamic borrow
+//!     {
+//!         let mut map: RefMut<_> = shared_map.borrow_mut();
+//!         map.insert("africa", 92388);
+//!         map.insert("kyoto", 11837);
+//!         map.insert("piccadilly", 11826);
+//!         map.insert("marbles", 38);
+//!     }
+//!
+//!     // Note that if we had not let the previous borrow of the cache fall out
+//!     // of scope then the subsequent borrow would cause a dynamic thread panic.
+//!     // This is the major hazard of using `RefCell`.
+//!     let total: i32 = shared_map.borrow().values().sum();
+//!     println!("{}", total);
 //! }
 //! ```
 //!
 //!
 //! impl Graph {
 //!     fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
-//!         // Create a new scope to contain the lifetime of the
-//!         // dynamic borrow
-//!         {
-//!             // Take a reference to the inside of cache cell
-//!             let mut cache = self.span_tree_cache.borrow_mut();
-//!             if cache.is_some() {
-//!                 return cache.as_ref().unwrap().clone();
-//!             }
-//!
-//!             let span_tree = self.calc_span_tree();
-//!             *cache = Some(span_tree);
-//!         }
+//!         self.span_tree_cache.borrow_mut()
+//!             .get_or_insert_with(|| self.calc_span_tree())
+//!             .clone()
+//!     }
 //!
-//!         // Recursive call to return the just-cached value.
-//!         // Note that if we had not let the previous borrow
-//!         // of the cache fall out of scope then the subsequent
-//!         // recursive borrow would cause a dynamic thread panic.
-//!         // This is the major hazard of using `RefCell`.
-//!         self.minimum_spanning_tree()
+//!     fn calc_span_tree(&self) -> Vec<(i32, i32)> {
+//!         // Expensive computation goes here
+//!         vec![]
 //!     }
-//! #   fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
 //! }
 //! ```
 //!
index 64e588f65b4688b5800b4c616455fc2a17b66c35..518442efe74172a3c35ed85a23c00ff979681d72 100644 (file)
@@ -73,11 +73,6 @@ fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
     {
         self.iter.position(predicate)
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 562a7a4b3c7196d1ef392299b7e68e7de66b3163..932c0eaa4c7b1ede320ad45c12243fb25f68f27e 100644 (file)
@@ -50,6 +50,7 @@ macro_rules! nonzero_integers {
                 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
                 #[repr(transparent)]
                 #[rustc_layout_scalar_valid_range_start(1)]
+                #[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
                 pub struct $Ty($Int);
             }
 
index 006b1e143eeec54772b4f7d06c385ad3b6c53c3f..4bb4d3ee46660796840a2e89ba73d03eb37be558 100644 (file)
@@ -2938,6 +2938,7 @@ fn from(p: NonNull<T>) -> Self {
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(1)]
+#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
 pub struct NonNull<T: ?Sized> {
     pointer: *const T,
 }
index d06d107d32a41cabbe8a3fca7e35bf6ed950d277..50d2ba0d3ef7fa06ee9c332bc59b4f5e3c96c3f8 100644 (file)
@@ -3547,11 +3547,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
             (1, Some(self.v.len() + 1))
         }
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -3650,11 +3645,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
             (1, Some(self.v.len() + 1))
         }
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -3720,11 +3710,6 @@ fn next(&mut self) -> Option<&'a [T]> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "slice_rsplit", since = "1.27.0")]
@@ -3789,11 +3774,6 @@ fn next(&mut self) -> Option<&'a mut [T]> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "slice_rsplit", since = "1.27.0")]
index 0e8a2da3c110d70a413a0a8b9ae76909116a982a..ef4bd83cbc5a695997a044e9fdc0677a59fe7a19 100644 (file)
@@ -1333,11 +1333,6 @@ fn next(&mut self) -> Option<&'a str> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.0.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1384,11 +1379,6 @@ fn next(&mut self) -> Option<&'a str> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.0.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -4231,11 +4221,6 @@ fn next(&mut self) -> Option<&'a str> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "split_whitespace", since = "1.1.0")]
@@ -4262,11 +4247,6 @@ fn next(&mut self) -> Option<&'a str> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
index 331edb73d6df96d810393f5c904d5667dd157cc3..491986480deba1082cce16d4b955915c2bce3121 100644 (file)
@@ -57,9 +57,7 @@ fn main() {
         cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1"));
     }
 
-    // The source for `compiler-rt` comes from the `compiler-builtins` crate, so
-    // load our env var set by cargo to find the source code.
-    let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap();
+    let root = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
     let root = Path::new(&root);
 
     for src in profile_sources {
index b48d81f2ef8f4731623fb7ffe50747ab64954529..c179b05683d1c91258bf53b335f9cc94d8e305c5 100644 (file)
@@ -6,6 +6,15 @@
 use std::marker::PhantomData;
 use smallvec::SmallVec;
 
+/// This declares a list of types which can be allocated by `Arena`.
+///
+/// The `few` modifier will cause allocation to use the shared arena and recording the destructor.
+/// This is faster and more memory efficient if there's only a few allocations of the type.
+/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is
+/// faster and more memory efficient if there is lots of allocations.
+///
+/// Specifying the `decode` modifier will add decode impls for &T and &[T] where T is the type
+/// listed. These impls will appear in the implement_ty_decoder! macro.
 #[macro_export]
 macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
@@ -14,7 +23,7 @@ macro_rules! arena_types {
                 rustc::hir::def_id::DefId,
                 rustc::ty::subst::SubstsRef<$tcx>
             )>,
-            [few] mir_keys: rustc::util::nodemap::DefIdSet,
+            [few, decode] mir_keys: rustc::util::nodemap::DefIdSet,
             [decode] specialization_graph: rustc::traits::specialization_graph::Graph,
             [] region_scope_tree: rustc::middle::region::ScopeTree,
             [] item_local_set: rustc::util::nodemap::ItemLocalSet,
@@ -58,6 +67,40 @@ macro_rules! arena_types {
                 rustc::infer::canonical::Canonical<'tcx,
                     rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::Ty<'tcx>>
                 >,
+            [few] crate_inherent_impls: rustc::ty::CrateInherentImpls,
+            [decode] borrowck: rustc::middle::borrowck::BorrowCheckResult,
+            [few] upstream_monomorphizations:
+                rustc::util::nodemap::DefIdMap<
+                    rustc_data_structures::fx::FxHashMap<
+                        rustc::ty::subst::SubstsRef<'tcx>,
+                        rustc::hir::def_id::CrateNum
+                    >
+                >,
+            [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes,
+            [decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>,
+            [few] lint_levels: rustc::lint::LintLevelMap,
+            [few] stability_index: rustc::middle::stability::Index<'tcx>,
+            [few] features: syntax::feature_gate::Features,
+            [few] all_traits: Vec<rustc::hir::def_id::DefId>,
+            [few] privacy_access_levels: rustc::middle::privacy::AccessLevels,
+            [few] target_features_whitelist: rustc_data_structures::fx::FxHashMap<
+                String,
+                Option<syntax::symbol::Symbol>
+            >,
+            [few] wasm_import_module_map: rustc_data_structures::fx::FxHashMap<
+                rustc::hir::def_id::DefId,
+                String
+            >,
+            [few] get_lib_features: rustc::middle::lib_features::LibFeatures,
+            [few] defined_lib_features: rustc::middle::lang_items::LanguageItems,
+            [few] visible_parent_map: rustc::util::nodemap::DefIdMap<rustc::hir::def_id::DefId>,
+            [few] foreign_module: rustc::middle::cstore::ForeignModule,
+            [few] foreign_modules: Vec<rustc::middle::cstore::ForeignModule>,
+            [few] reachable_non_generics: rustc::util::nodemap::DefIdMap<
+                rustc::middle::exported_symbols::SymbolExportLevel
+            >,
+            [few] crate_variances: rustc::ty::CrateVariancesMap<'tcx>,
+            [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
         ], $tcx);
     )
 }
@@ -119,7 +162,7 @@ pub trait ArenaAllocatable {}
 
 impl<T: Copy> ArenaAllocatable for T {}
 
-pub unsafe trait ArenaField<'tcx>: Sized {
+unsafe trait ArenaField<'tcx>: Sized {
     /// Returns a specific arena to allocate from.
     /// If None is returned, the DropArena will be used.
     fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
index 2e54165be1f1baf485b42ac331c8922ae7694b2e..ef0d4be268eaf36d1c60f2169f9f9f4bec3f1542 100644 (file)
@@ -419,7 +419,7 @@ fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr,
         for arm in arms {
             // Add an exit node for when we've visited all the
             // patterns and the guard (if there is one) in the arm.
-            let arm_exit = self.add_dummy_node(&[]);
+            let bindings_exit = self.add_dummy_node(&[]);
 
             for pat in &arm.pats {
                 // Visit the pattern, coming from the discriminant exit
@@ -453,14 +453,16 @@ fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr,
 
                 // Add an edge from the exit of this pattern to the
                 // exit of the arm
-                self.add_contained_edge(pat_exit, arm_exit);
+                self.add_contained_edge(pat_exit, bindings_exit);
             }
 
             // Visit the body of this arm
-            let body_exit = self.expr(&arm.body, arm_exit);
+            let body_exit = self.expr(&arm.body, bindings_exit);
+
+            let arm_exit = self.add_ast_node(arm.hir_id.local_id, &[body_exit]);
 
             // Link the body to the exit of the expression
-            self.add_contained_edge(body_exit, expr_exit);
+            self.add_contained_edge(arm_exit, expr_exit);
         }
 
         expr_exit
index 38d6d710868c08919821de9caf2b34a05cb2a761..517c99f99efea1e257339c96ca398c644e1b68a5 100644 (file)
@@ -1102,6 +1102,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
 }
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
+    visitor.visit_id(arm.hir_id);
     walk_list!(visitor, visit_pat, &arm.pats);
     if let Some(ref g) = arm.guard {
         match g {
index 3ec4d4e8cc8f68350eba397be435676d2c89fc91..6b82548f6dcde11e7ee9ce2ea6f397647c7e0935 100644 (file)
@@ -64,7 +64,7 @@
 use syntax::source_map::{respan, CompilerDesugaringKind, Spanned};
 use syntax::source_map::CompilerDesugaringKind::IfTemporary;
 use syntax::std_inject;
-use syntax::symbol::{keywords, Symbol, sym};
+use syntax::symbol::{kw, sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::parse::token::Token;
 use syntax::visit::{self, Visitor};
@@ -927,11 +927,11 @@ fn lifetime_to_generic_param(
                 hir::LifetimeParamKind::InBand,
             ),
             ParamName::Fresh(_) => (
-                keywords::UnderscoreLifetime.name().as_interned_str(),
+                kw::UnderscoreLifetime.as_interned_str(),
                 hir::LifetimeParamKind::Elided,
             ),
             ParamName::Error => (
-                keywords::UnderscoreLifetime.name().as_interned_str(),
+                kw::UnderscoreLifetime.as_interned_str(),
                 hir::LifetimeParamKind::Error,
             ),
         };
@@ -1314,6 +1314,7 @@ fn lower_token(&mut self, token: Token, span: Span) -> TokenStream {
 
     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
         hir::Arm {
+            hir_id: self.next_id(),
             attrs: self.lower_attrs(&arm.attrs),
             pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
             guard: match arm.guard {
@@ -1321,6 +1322,7 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
                 _ => None,
             },
             body: P(self.lower_expr(&arm.body)),
+            span: arm.span,
         }
     }
 
@@ -1415,7 +1417,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                     P(hir::Path {
                         res,
                         segments: hir_vec![hir::PathSegment::from_ident(
-                            keywords::SelfUpper.ident()
+                            Ident::with_empty_ctxt(kw::SelfUpper)
                         )],
                         span: t.span,
                     }),
@@ -1614,7 +1616,7 @@ fn generate_existential_type(
         trace!("registering existential type with id {:#?}", exist_ty_id);
         let exist_ty_item = hir::Item {
             hir_id: exist_ty_id,
-            ident: keywords::Invalid.ident(),
+            ident: Ident::invalid(),
             attrs: Default::default(),
             node: exist_ty_item_kind,
             vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
@@ -1747,7 +1749,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
 
                     let (name, kind) = match name {
                         hir::LifetimeName::Underscore => (
-                            hir::ParamName::Plain(keywords::UnderscoreLifetime.ident()),
+                            hir::ParamName::Plain(Ident::with_empty_ctxt(kw::UnderscoreLifetime)),
                             hir::LifetimeParamKind::Elided,
                         ),
                         hir::LifetimeName::Param(param_name) => (
@@ -2296,7 +2298,7 @@ fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
             .iter()
             .map(|arg| match arg.pat.node {
                 PatKind::Ident(_, ident, _) => ident,
-                _ => Ident::new(keywords::Invalid.name(), arg.pat.span),
+                _ => Ident::new(kw::Invalid, arg.pat.span),
             })
             .collect()
     }
@@ -2585,9 +2587,9 @@ fn lower_param_bound(
     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
         let span = l.ident.span;
         match l.ident {
-            ident if ident.name == keywords::StaticLifetime.name() =>
+            ident if ident.name == kw::StaticLifetime =>
                 self.new_named_lifetime(l.id, span, hir::LifetimeName::Static),
-            ident if ident.name == keywords::UnderscoreLifetime.name() =>
+            ident if ident.name == kw::UnderscoreLifetime =>
                 match self.anonymous_lifetime_mode {
                     AnonymousLifetimeMode::CreateParameter => {
                         let fresh_name = self.collect_fresh_in_band_lifetime(span);
@@ -2709,7 +2711,7 @@ fn lower_generic_param(&mut self,
                 // Don't expose `Self` (recovered "keyword used as ident" parse error).
                 // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
                 // Instead, use `gensym("Self")` to create a distinct name that looks the same.
-                let ident = if param.ident.name == keywords::SelfUpper.name() {
+                let ident = if param.ident.name == kw::SelfUpper {
                     param.ident.gensym()
                 } else {
                     param.ident
@@ -3325,7 +3327,7 @@ fn lower_use_tree(
 
                 // Correctly resolve `self` imports.
                 if path.segments.len() > 1
-                    && path.segments.last().unwrap().ident.name == keywords::SelfLower.name()
+                    && path.segments.last().unwrap().ident.name == kw::SelfLower
                 {
                     let _ = path.segments.pop();
                     if rename.is_none() {
@@ -5024,9 +5026,11 @@ fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBou
 
     fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
         hir::Arm {
+            hir_id: self.next_id(),
             attrs: hir_vec![],
             pats,
             guard: None,
+            span: expr.span,
             body: expr,
         }
     }
index eeba628b3bf2168ad943ac41fe4cca076ed5bf72..b5203f9ec1f72b030f68ce025ec7f68d3c273e06 100644 (file)
@@ -430,6 +430,16 @@ fn visit_pat(&mut self, pat: &'hir Pat) {
         });
     }
 
+    fn visit_arm(&mut self, arm: &'hir Arm) {
+        let node = Node::Arm(arm);
+
+        self.insert(arm.span, arm.hir_id, node);
+
+        self.with_parent(arm.hir_id, |this| {
+            intravisit::walk_arm(this, arm);
+        });
+    }
+
     fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
         self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
 
index 6e7a8f5bc234f01c1049dc0c514b1a39abcb04f1..bb9e76f02624651c2eb1483f89dad597fff6a78c 100644 (file)
@@ -5,7 +5,7 @@
 use syntax::ast::*;
 use syntax::ext::hygiene::Mark;
 use syntax::visit;
-use syntax::symbol::keywords;
+use syntax::symbol::kw;
 use syntax::symbol::Symbol;
 use syntax::parse::token::{self, Token};
 use syntax_pos::Span;
@@ -138,7 +138,7 @@ fn visit_item(&mut self, i: &'a Item) {
         // information we encapsulate into, the better
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
-            ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
+            ItemKind::Mod(..) if i.ident.name == kw::Invalid => {
                 return visit::walk_item(self, i);
             }
             ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
index 23f4d20857135f62036a61d111b126d239ccedc6..0741d9322c65328eff9d2fb7dcb1ffdac3883481 100644 (file)
@@ -373,6 +373,7 @@ fn def_kind(&self, node_id: NodeId) -> Option<DefKind> {
             Node::Pat(_) |
             Node::Binding(_) |
             Node::Local(_) |
+            Node::Arm(_) |
             Node::Lifetime(_) |
             Node::Visibility(_) |
             Node::Block(_) |
@@ -519,7 +520,7 @@ pub fn ty_param_owner(&self, id: HirId) -> HirId {
     pub fn ty_param_name(&self, id: HirId) -> Name {
         match self.get_by_hir_id(id) {
             Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
-            Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => keywords::SelfUpper.name(),
+            Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper,
             Node::GenericParam(param) => param.name.ident().name,
             _ => bug!("ty_param_name: {} not a type parameter", self.hir_to_string(id)),
         }
@@ -1000,6 +1001,7 @@ pub fn attrs_by_hir_id(&self, id: HirId) -> &'hir [ast::Attribute] {
             Some(Node::Field(ref f)) => Some(&f.attrs[..]),
             Some(Node::Expr(ref e)) => Some(&*e.attrs),
             Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
+            Some(Node::Arm(ref a)) => Some(&*a.attrs),
             Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
             // Unit/tuple structs/variants take the attributes straight from
             // the struct/variant definition.
@@ -1073,6 +1075,7 @@ pub fn span_by_hir_id(&self, hir_id: HirId) -> Span {
             Some(Node::TraitRef(tr)) => tr.path.span,
             Some(Node::Binding(pat)) => pat.span,
             Some(Node::Pat(pat)) => pat.span,
+            Some(Node::Arm(arm)) => arm.span,
             Some(Node::Block(block)) => block.span,
             Some(Node::Ctor(..)) => match self.find_by_hir_id(
                 self.get_parent_node_by_hir_id(hir_id))
@@ -1288,6 +1291,7 @@ pub fn print_node(&mut self, node: Node<'_>) -> io::Result<()> {
             Node::TraitRef(a)     => self.print_trait_ref(&a),
             Node::Binding(a)      |
             Node::Pat(a)          => self.print_pat(&a),
+            Node::Arm(a)          => self.print_arm(&a),
             Node::Block(a)        => {
                 use syntax::print::pprust::PrintState;
 
@@ -1417,6 +1421,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
         Some(Node::Pat(_)) => {
             format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
         }
+        Some(Node::Arm(_)) => {
+            format!("arm {}{}", map.hir_to_pretty_string(id), id_str)
+        }
         Some(Node::Block(_)) => {
             format!("block {}{}", map.hir_to_pretty_string(id), id_str)
         }
index d2b926d188697170c6be70a5426050ac17c990d0..2ae5f7a0b5531f4771c6c264320cb75fe3c6f71e 100644 (file)
@@ -24,7 +24,7 @@
 use syntax::attr::{InlineAttr, OptimizeAttr};
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::{Symbol, kw};
 use syntax::tokenstream::TokenStream;
 use syntax::util::parser::ExprPrecedence;
 use crate::ty::AdtKind;
@@ -160,7 +160,7 @@ pub struct Lifetime {
     pub span: Span,
 
     /// Either "`'a`", referring to a named lifetime definition,
-    /// or "``" (i.e., `keywords::Invalid`), for elision placeholders.
+    /// or "``" (i.e., `kw::Invalid`), for elision placeholders.
     ///
     /// HIR lowering inserts these placeholders in type paths that
     /// refer to type definitions needing lifetime parameters,
@@ -199,7 +199,8 @@ impl ParamName {
     pub fn ident(&self) -> Ident {
         match *self {
             ParamName::Plain(ident) => ident,
-            ParamName::Error | ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
+            ParamName::Fresh(_) |
+            ParamName::Error => Ident::with_empty_ctxt(kw::UnderscoreLifetime),
         }
     }
 
@@ -233,10 +234,9 @@ pub enum LifetimeName {
 impl LifetimeName {
     pub fn ident(&self) -> Ident {
         match *self {
-            LifetimeName::Implicit => keywords::Invalid.ident(),
-            LifetimeName::Error => keywords::Invalid.ident(),
-            LifetimeName::Underscore => keywords::UnderscoreLifetime.ident(),
-            LifetimeName::Static => keywords::StaticLifetime.ident(),
+            LifetimeName::Implicit | LifetimeName::Error => Ident::invalid(),
+            LifetimeName::Underscore => Ident::with_empty_ctxt(kw::UnderscoreLifetime),
+            LifetimeName::Static => Ident::with_empty_ctxt(kw::StaticLifetime),
             LifetimeName::Param(param_name) => param_name.ident(),
         }
     }
@@ -305,7 +305,7 @@ pub struct Path {
 
 impl Path {
     pub fn is_global(&self) -> bool {
-        !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name()
+        !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
     }
 }
 
@@ -1228,6 +1228,9 @@ pub struct Local {
 /// `<pats> (if <guard>) => <body>`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Arm {
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    pub span: Span,
     pub attrs: HirVec<Attribute>,
     /// Multiple patterns can be combined with `|`
     pub pats: HirVec<P<Pat>>,
@@ -2656,6 +2659,7 @@ pub enum Node<'hir> {
     TraitRef(&'hir TraitRef),
     Binding(&'hir Pat),
     Pat(&'hir Pat),
+    Arm(&'hir Arm),
     Block(&'hir Block),
     Local(&'hir Local),
     MacroDef(&'hir MacroDef),
index 8a9028e5443912471481ee6749b1065d4aadb7aa..c5337381a3d4f3dc7ae1722a361288d82ab7bbeb 100644 (file)
@@ -7,7 +7,7 @@
 use syntax::print::pp::Breaks::{Consistent, Inconsistent};
 use syntax::print::pprust::{self, PrintState};
 use syntax::ptr::P;
-use syntax::symbol::keywords;
+use syntax::symbol::kw;
 use syntax::util::parser::{self, AssocOp, Fixity};
 use syntax_pos::{self, BytePos, FileName};
 
@@ -798,7 +798,7 @@ pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
             hir::VisibilityKind::Restricted { ref path, .. } => {
                 self.s.word("pub(")?;
                 if path.segments.len() == 1 &&
-                   path.segments[0].ident.name == keywords::Super.name() {
+                   path.segments[0].ident.name == kw::Super {
                     // Special case: `super` can print like `pub(super)`.
                     self.s.word("super")?;
                 } else {
@@ -1249,8 +1249,7 @@ fn print_expr_addr_of(&mut self,
 
     fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> {
         self.maybe_print_comment(lit.span.lo())?;
-        let (token, suffix) = lit.node.to_lit_token();
-        self.writer().word(pprust::literal_to_string(token, suffix))
+        self.writer().word(pprust::literal_to_string(lit.node.to_lit_token()))
     }
 
     pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
@@ -1559,7 +1558,7 @@ pub fn print_path(&mut self,
             if i > 0 {
                 self.s.word("::")?
             }
-            if segment.ident.name != keywords::PathRoot.name() {
+            if segment.ident.name != kw::PathRoot {
                self.print_ident(segment.ident)?;
                segment.with_generic_args(|generic_args| {
                    self.print_generic_args(generic_args, segment.infer_types,
@@ -1572,7 +1571,7 @@ pub fn print_path(&mut self,
     }
 
     pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> {
-        if segment.ident.name != keywords::PathRoot.name() {
+        if segment.ident.name != kw::PathRoot {
            self.print_ident(segment.ident)?;
            segment.with_generic_args(|generic_args| {
                self.print_generic_args(generic_args, segment.infer_types, false)
@@ -1599,7 +1598,7 @@ pub fn print_qpath(&mut self,
                     if i > 0 {
                         self.s.word("::")?
                     }
-                    if segment.ident.name != keywords::PathRoot.name() {
+                    if segment.ident.name != kw::PathRoot {
                         self.print_ident(segment.ident)?;
                         segment.with_generic_args(|generic_args| {
                             self.print_generic_args(generic_args,
@@ -1862,7 +1861,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
         self.ann.post(self, AnnNode::Pat(pat))
     }
 
-    fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
+    pub fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
         // I have no idea why this check is necessary, but here it
         // is :(
         if arm.attrs.is_empty() {
index 4e5718cc5ef2a275e5057e0c42097ba040b80548..af53f686ae5481409b9e526c75a14c7fcd4747fc 100644 (file)
@@ -165,7 +165,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct ::syntax::ast::Lit {
     node,
     token,
-    suffix,
     span
 });
 
@@ -288,17 +287,23 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl_stable_hash_for!(enum token::Lit {
-    Bool(val),
-    Byte(val),
-    Char(val),
-    Err(val),
-    Integer(val),
-    Float(val),
-    Str_(val),
-    ByteStr(val),
-    StrRaw(val, n),
-    ByteStrRaw(val, n)
+impl_stable_hash_for!(enum token::LitKind {
+    Bool,
+    Byte,
+    Char,
+    Integer,
+    Float,
+    Str,
+    ByteStr,
+    StrRaw(n),
+    ByteStrRaw(n),
+    Err
+});
+
+impl_stable_hash_for!(struct token::Lit {
+    kind,
+    symbol,
+    suffix
 });
 
 fn hash_token<'a, 'gcx, W: StableHasherResult>(
@@ -348,10 +353,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
         token::Token::CloseDelim(delim_token) => {
             std_hash::Hash::hash(&delim_token, hasher);
         }
-        token::Token::Literal(lit, opt_name) => {
-            lit.hash_stable(hcx, hasher);
-            opt_name.hash_stable(hcx, hasher);
-        }
+        token::Token::Literal(lit) => lit.hash_stable(hcx, hasher),
 
         token::Token::Ident(ident, is_raw) => {
             ident.name.hash_stable(hcx, hasher);
index 9c4683e094634eea384d348ff8c2b9785a6c6dfe..2a684f4b0bb458f868ce9d22ed0d102d5c052a2b 100644 (file)
@@ -21,7 +21,7 @@
 pub use self::Level::*;
 pub use self::LintSource::*;
 
-use rustc_data_structures::sync::{self, Lrc};
+use rustc_data_structures::sync;
 
 use crate::hir::def_id::{CrateNum, LOCAL_CRATE};
 use crate::hir::intravisit;
@@ -767,7 +767,7 @@ pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
 }
 
 fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
-    -> Lrc<LintLevelMap>
+    -> &'tcx LintLevelMap
 {
     assert_eq!(cnum, LOCAL_CRATE);
     let mut builder = LintLevelMapBuilder {
@@ -784,7 +784,7 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
     intravisit::walk_crate(&mut builder, krate);
     builder.levels.pop(push);
 
-    Lrc::new(builder.levels.build_map())
+    tcx.arena.alloc(builder.levels.build_map())
 }
 
 struct LintLevelMapBuilder<'a, 'tcx: 'a> {
@@ -852,6 +852,12 @@ fn visit_local(&mut self, l: &'tcx hir::Local) {
         })
     }
 
+    fn visit_arm(&mut self, a: &'tcx hir::Arm) {
+        self.with_lint_attrs(a.hir_id, &a.attrs, |builder| {
+            intravisit::walk_arm(builder, a);
+        })
+    }
+
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |builder| {
             intravisit::walk_trait_item(builder, trait_item);
index d22de6c6476996ea85f254427de7fbb933b75784..6f9abcd624f9921abca3606fa11e73172449c2f1 100644 (file)
@@ -256,8 +256,8 @@ pub fn used_crates(tcx: TyCtxt<'_, '_, '_>, prefer: LinkagePreference)
             Some((cnum, path))
         })
         .collect::<Vec<_>>();
-    let mut ordering = tcx.postorder_cnums(LOCAL_CRATE);
-    Lrc::make_mut(&mut ordering).reverse();
+    let mut ordering = tcx.postorder_cnums(LOCAL_CRATE).to_owned();
+    ordering.reverse();
     libs.sort_by_cached_key(|&(a, _)| {
         ordering.iter().position(|x| *x == a)
     });
index cb333b5b0cba23e808ed1d3f6257c5aaef1ac081..91a19852c6c0e06b290a48c98e8713f8aa52501c 100644 (file)
 use std::rc::Rc;
 use syntax::ast::{self, NodeId};
 use syntax::ptr::P;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax_pos::Span;
 
 use crate::hir;
@@ -1552,7 +1552,7 @@ fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
                 let sp = ident.span;
                 let var = self.variable(hir_id, sp);
                 // Ignore unused self.
-                if ident.name != keywords::SelfLower.name() {
+                if ident.name != kw::SelfLower {
                     if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) {
                         if self.live_on_entry(entry_ln, var).is_none() {
                             self.report_dead_assign(hir_id, sp, var, true);
index 37681ad7fcdd2bc51708264a8246e7a8a3ede9f0..fa4e8e3d4769d34e2645048a60402aac2ff1757b 100644 (file)
@@ -119,18 +119,18 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 pub enum ScopeData {
     Node,
 
-    // Scope of the call-site for a function or closure
-    // (outlives the arguments as well as the body).
+    /// Scope of the call-site for a function or closure
+    /// (outlives the arguments as well as the body).
     CallSite,
 
-    // Scope of arguments passed to a function or closure
-    // (they outlive its body).
+    /// Scope of arguments passed to a function or closure
+    /// (they outlive its body).
     Arguments,
 
-    // Scope of destructors for temporaries of node-id.
+    /// Scope of destructors for temporaries of node-id.
     Destruction,
 
-    // Scope following a `let id = expr;` binding in a block.
+    /// Scope following a `let id = expr;` binding in a block.
     Remainder(FirstStatementIndex)
 }
 
@@ -152,11 +152,11 @@ pub enum ScopeData {
     ///
     /// * The subscope with `first_statement_index == 1` is scope of `c`,
     ///   and thus does not include EXPR_2, but covers the `...`.
-    pub struct FirstStatementIndex { .. }
+    pub struct FirstStatementIndex {
+        derive [HashStable]
+    }
 }
 
-impl_stable_hash_for!(struct crate::middle::region::FirstStatementIndex { private });
-
 // compilation error if size of `ScopeData` is not the same as a `u32`
 static_assert_size!(ScopeData, 4);
 
@@ -814,6 +814,16 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
 }
 
 fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) {
+    let prev_cx = visitor.cx;
+
+    visitor.enter_scope(
+        Scope {
+            id: arm.hir_id.local_id,
+            data: ScopeData::Node,
+        }
+    );
+    visitor.cx.var_parent = visitor.cx.parent;
+
     visitor.terminating_scopes.insert(arm.body.hir_id.local_id);
 
     if let Some(hir::Guard::If(ref expr)) = arm.guard {
@@ -821,6 +831,8 @@ fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &
     }
 
     intravisit::walk_arm(visitor, arm);
+
+    visitor.cx = prev_cx;
 }
 
 fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) {
@@ -893,10 +905,6 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
                 terminating(body.hir_id.local_id);
             }
 
-            hir::ExprKind::Match(..) => {
-                visitor.cx.var_parent = visitor.cx.parent;
-            }
-
             hir::ExprKind::DropTemps(ref expr) => {
                 // `DropTemps(expr)` does not denote a conditional scope.
                 // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
index 2402d0eefde4886e0bdc5e8e077a487753b58c8b..775da1de313fa0956286240569006e739022d4d9 100644 (file)
@@ -15,7 +15,6 @@
 use crate::session::Session;
 use crate::util::nodemap::{DefIdMap, FxHashMap, FxHashSet, HirIdMap, HirIdSet};
 use errors::{Applicability, DiagnosticBuilder};
-use rustc_data_structures::sync::Lrc;
 use rustc_macros::HashStable;
 use std::borrow::Cow;
 use std::cell::Cell;
@@ -23,7 +22,7 @@
 use syntax::ast;
 use syntax::attr;
 use syntax::ptr::P;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax_pos::Span;
 
 use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -211,10 +210,10 @@ struct NamedRegionMap {
 /// See [`NamedRegionMap`].
 #[derive(Default)]
 pub struct ResolveLifetimes {
-    defs: FxHashMap<LocalDefId, Lrc<FxHashMap<ItemLocalId, Region>>>,
-    late_bound: FxHashMap<LocalDefId, Lrc<FxHashSet<ItemLocalId>>>,
+    defs: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Region>>,
+    late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
     object_lifetime_defaults:
-        FxHashMap<LocalDefId, Lrc<FxHashMap<ItemLocalId, Lrc<Vec<ObjectLifetimeDefault>>>>>,
+        FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ObjectLifetimeDefault>>>,
 }
 
 impl_stable_hash_for!(struct crate::middle::resolve_lifetime::ResolveLifetimes {
@@ -347,7 +346,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
 
         named_region_map: |tcx, id| {
             let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
-            tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id).cloned()
+            tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id)
         },
 
         is_late_bound_map: |tcx, id| {
@@ -355,7 +354,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
             tcx.resolve_lifetimes(LOCAL_CRATE)
                 .late_bound
                 .get(&id)
-                .cloned()
         },
 
         object_lifetime_defaults_map: |tcx, id| {
@@ -363,7 +361,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
             tcx.resolve_lifetimes(LOCAL_CRATE)
                 .object_lifetime_defaults
                 .get(&id)
-                .cloned()
         },
 
         ..*providers
@@ -379,7 +376,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
 fn resolve_lifetimes<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     for_krate: CrateNum,
-) -> Lrc<ResolveLifetimes> {
+) -> &'tcx ResolveLifetimes {
     assert_eq!(for_krate, LOCAL_CRATE);
 
     let named_region_map = krate(tcx);
@@ -388,24 +385,22 @@ fn resolve_lifetimes<'tcx>(
 
     for (hir_id, v) in named_region_map.defs {
         let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default();
-        Lrc::get_mut(map).unwrap().insert(hir_id.local_id, v);
+        map.insert(hir_id.local_id, v);
     }
     for hir_id in named_region_map.late_bound {
         let map = rl.late_bound
             .entry(hir_id.owner_local_def_id())
             .or_default();
-        Lrc::get_mut(map).unwrap().insert(hir_id.local_id);
+        map.insert(hir_id.local_id);
     }
     for (hir_id, v) in named_region_map.object_lifetime_defaults {
         let map = rl.object_lifetime_defaults
             .entry(hir_id.owner_local_def_id())
             .or_default();
-        Lrc::get_mut(map)
-            .unwrap()
-            .insert(hir_id.local_id, Lrc::new(v));
+        map.insert(hir_id.local_id, v);
     }
 
-    Lrc::new(rl)
+    tcx.arena.alloc(rl)
 }
 
 fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap {
@@ -711,7 +706,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                         GenericParamKind::Lifetime { .. } => {
                             let (name, reg) = Region::early(&self.tcx.hir(), &mut index, &param);
                             if let hir::ParamName::Plain(param_name) = name {
-                                if param_name.name == keywords::UnderscoreLifetime.name() {
+                                if param_name.name == kw::UnderscoreLifetime {
                                     // Pick the elided lifetime "definition" if one exists
                                     // and use it to make an elision scope.
                                     elision = Some(reg);
@@ -1602,7 +1597,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                     } {
                         debug!("id = {:?} span = {:?} name = {:?}", id, span, name);
 
-                        if name == keywords::UnderscoreLifetime.ident() {
+                        if name.name == kw::UnderscoreLifetime {
                             continue;
                         }
 
@@ -2525,8 +2520,8 @@ fn check_lifetime_params(
         for (i, (lifetime_i, lifetime_i_name)) in lifetimes.iter().enumerate() {
             if let hir::ParamName::Plain(_) = lifetime_i_name {
                 let name = lifetime_i_name.ident().name;
-                if name == keywords::UnderscoreLifetime.name()
-                    || name == keywords::StaticLifetime.name()
+                if name == kw::UnderscoreLifetime
+                    || name == kw::StaticLifetime
                 {
                     let mut err = struct_span_err!(
                         self.tcx.sess,
index abcf164cda6d46f783eec9251c3311f79a9c73be..ac0e99137cbc3ea68f76f7affc21f4d991347ffe 100644 (file)
@@ -883,7 +883,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     remaining_lib_features.remove(&Symbol::intern("test"));
 
     let check_features =
-        |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &Vec<_>| {
+        |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| {
             for &(feature, since) in defined_features {
                 if let Some(since) = since {
                     if let Some(span) = remaining_lib_features.get(&feature) {
@@ -908,7 +908,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
             if remaining_lib_features.is_empty() {
                 break;
             }
-            check_features(&mut remaining_lib_features, &tcx.defined_lib_features(cnum));
+            check_features(&mut remaining_lib_features, tcx.defined_lib_features(cnum));
         }
     }
 
index 8825c94cdb81cb27c3abaef0002ffb80caaccc1c..c03cd7e268ef5ceed3e20e678624516bf12ed3fc 100644 (file)
         /// predicate gets in the way of some checks, which are intended
         /// to operate over only the actual where-clauses written by the
         /// user.)
-        query predicates_of(_: DefId) -> Lrc<ty::GenericPredicates<'tcx>> {}
+        query predicates_of(_: DefId) -> &'tcx ty::GenericPredicates<'tcx> {}
 
         query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
             desc { "looking up the native libraries of a linked crate" }
         }
 
-        query lint_levels(_: CrateNum) -> Lrc<lint::LintLevelMap> {
+        query lint_levels(_: CrateNum) -> &'tcx lint::LintLevelMap {
             eval_always
             desc { "computing the lint levels for items in this crate" }
         }
     }
 
     Linking {
-        query wasm_import_module_map(_: CrateNum) -> Lrc<FxHashMap<DefId, String>> {
+        query wasm_import_module_map(_: CrateNum) -> &'tcx FxHashMap<DefId, String> {
             desc { "wasm import module map" }
         }
     }
         /// equal to the `explicit_predicates_of` predicates plus the
         /// `inferred_outlives_of` predicates.
         query predicates_defined_on(_: DefId)
-            -> Lrc<ty::GenericPredicates<'tcx>> {}
+            -> &'tcx ty::GenericPredicates<'tcx> {}
 
         /// Returns the predicates written explicitly by the user.
         query explicit_predicates_of(_: DefId)
-            -> Lrc<ty::GenericPredicates<'tcx>> {}
+            -> &'tcx ty::GenericPredicates<'tcx> {}
 
         /// Returns the inferred outlives predicates (e.g., for `struct
         /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
         /// evaluate them even during type conversion, often before the
         /// full predicates are available (note that supertraits have
         /// additional acyclicity requirements).
-        query super_predicates_of(key: DefId) -> Lrc<ty::GenericPredicates<'tcx>> {
+        query super_predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
             desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
         }
 
         /// To avoid cycles within the predicates of a single item we compute
         /// per-type-parameter predicates for resolving `T::AssocTy`.
         query type_param_predicates(key: (DefId, DefId))
-            -> Lrc<ty::GenericPredicates<'tcx>> {
+            -> &'tcx ty::GenericPredicates<'tcx> {
             no_force
             desc { |tcx| "computing the bounds for type parameter `{}`", {
                 let id = tcx.hir().as_local_hir_id(key.1).unwrap();
         query static_mutability(_: DefId) -> Option<hir::Mutability> {}
 
         /// Gets a map with the variance of every item; use `item_variance` instead.
-        query crate_variances(_: CrateNum) -> Lrc<ty::CrateVariancesMap<'tcx>> {
+        query crate_variances(_: CrateNum) -> &'tcx ty::CrateVariancesMap<'tcx> {
             desc { "computing the variances for items in this crate" }
         }
 
     TypeChecking {
         /// Maps from thee `DefId` of a type to its (inferred) outlives.
         query inferred_outlives_crate(_: CrateNum)
-            -> Lrc<ty::CratePredicatesMap<'tcx>> {
+            -> &'tcx ty::CratePredicatesMap<'tcx> {
             desc { "computing the inferred outlives predicates for items in this crate" }
         }
     }
 
     Other {
         /// Maps from an impl/trait `DefId to a list of the `DefId`s of its items.
-        query associated_item_def_ids(_: DefId) -> Lrc<Vec<DefId>> {}
+        query associated_item_def_ids(_: DefId) -> &'tcx [DefId] {}
 
         /// Maps from a trait item to the trait item "descriptor".
         query associated_item(_: DefId) -> ty::AssociatedItem {}
         /// Maps a `DefId` of a type to a list of its inherent impls.
         /// Contains implementations of methods that are inherent to a type.
         /// Methods in these implementations don't need to be exported.
-        query inherent_impls(_: DefId) -> Lrc<Vec<DefId>> {
+        query inherent_impls(_: DefId) -> &'tcx [DefId] {
             eval_always
         }
     }
     }
 
     Other {
-        query used_trait_imports(_: DefId) -> Lrc<DefIdSet> {}
+        query used_trait_imports(_: DefId) -> &'tcx DefIdSet {}
     }
 
     TypeChecking {
     }
 
     BorrowChecking {
-        query borrowck(_: DefId) -> Lrc<BorrowCheckResult> {}
+        query borrowck(_: DefId) -> &'tcx BorrowCheckResult {}
 
         /// Borrow-checks the function body. If this is a closure, returns
         /// additional requirements that the closure's creator must verify.
         /// Not meant to be used directly outside of coherence.
         /// (Defined only for `LOCAL_CRATE`.)
         query crate_inherent_impls(k: CrateNum)
-            -> Lrc<CrateInherentImpls> {
+            -> &'tcx CrateInherentImpls {
             eval_always
             desc { "all inherent impls defined in crate `{:?}`", k }
         }
         query check_match(_: DefId) -> () {}
 
         /// Performs part of the privacy check and computes "access levels".
-        query privacy_access_levels(_: CrateNum) -> Lrc<AccessLevels> {
+        query privacy_access_levels(_: CrateNum) -> &'tcx AccessLevels {
             eval_always
             desc { "privacy access levels" }
         }
 
     Other {
         query dylib_dependency_formats(_: CrateNum)
-                                        -> Lrc<Vec<(CrateNum, LinkagePreference)>> {
+                                        -> &'tcx [(CrateNum, LinkagePreference)] {
             desc { "dylib dependency formats of crate" }
         }
     }
             desc { "test whether a crate has #![no_builtins]" }
         }
 
-        query extern_crate(_: DefId) -> Lrc<Option<ExternCrate>> {
+        query extern_crate(_: DefId) -> Option<&'tcx ExternCrate> {
             eval_always
             desc { "getting crate's ExternCrateData" }
         }
             desc { "computing whether impls specialize one another" }
         }
         query in_scope_traits_map(_: DefIndex)
-            -> Option<Lrc<FxHashMap<ItemLocalId, Lrc<StableVec<TraitCandidate>>>>> {
+            -> Option<&'tcx FxHashMap<ItemLocalId, StableVec<TraitCandidate>>> {
             eval_always
             desc { "traits in scope at a block" }
         }
     }
 
     Other {
-        query module_exports(_: DefId) -> Option<Lrc<Vec<Export<hir::HirId>>>> {
+        query module_exports(_: DefId) -> Option<&'tcx [Export<hir::HirId>]> {
             eval_always
         }
     }
         // Does not include external symbols that don't have a corresponding DefId,
         // like the compiler-generated `main` function and so on.
         query reachable_non_generics(_: CrateNum)
-            -> Lrc<DefIdMap<SymbolExportLevel>> {
+            -> &'tcx DefIdMap<SymbolExportLevel> {
             desc { "looking up the exported symbols of a crate" }
         }
         query is_reachable_non_generic(_: DefId) -> bool {}
     Codegen {
         query upstream_monomorphizations(
             k: CrateNum
-        ) -> Lrc<DefIdMap<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>> {
+        ) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
             desc { "collecting available upstream monomorphizations `{:?}`", k }
         }
         query upstream_monomorphizations_for(_: DefId)
-            -> Option<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>> {}
+            -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> {}
     }
 
     Other {
-        query foreign_modules(_: CrateNum) -> Lrc<Vec<ForeignModule>> {
+        query foreign_modules(_: CrateNum) -> &'tcx [ForeignModule] {
             desc { "looking up the foreign modules of a linked crate" }
         }
 
 
     TypeChecking {
         query implementations_of_trait(_: (CrateNum, DefId))
-            -> Lrc<Vec<DefId>> {
+            -> &'tcx [DefId] {
             no_force
             desc { "looking up implementations of a trait in a crate" }
         }
         query all_trait_implementations(_: CrateNum)
-            -> Lrc<Vec<DefId>> {
+            -> &'tcx [DefId] {
             desc { "looking up all (?) trait implementations" }
         }
     }
 
     Other {
         query dllimport_foreign_items(_: CrateNum)
-            -> Lrc<FxHashSet<DefId>> {
+            -> &'tcx FxHashSet<DefId> {
             desc { "dllimport_foreign_items" }
         }
         query is_dllimport_foreign_item(_: DefId) -> bool {}
 
     BorrowChecking {
         // Lifetime resolution. See `middle::resolve_lifetimes`.
-        query resolve_lifetimes(_: CrateNum) -> Lrc<ResolveLifetimes> {
+        query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes {
             desc { "resolving lifetimes" }
         }
         query named_region_map(_: DefIndex) ->
-            Option<Lrc<FxHashMap<ItemLocalId, Region>>> {
+            Option<&'tcx FxHashMap<ItemLocalId, Region>> {
             desc { "looking up a named region" }
         }
         query is_late_bound_map(_: DefIndex) ->
-            Option<Lrc<FxHashSet<ItemLocalId>>> {
+            Option<&'tcx FxHashSet<ItemLocalId>> {
             desc { "testing if a region is late bound" }
         }
         query object_lifetime_defaults_map(_: DefIndex)
-            -> Option<Lrc<FxHashMap<ItemLocalId, Lrc<Vec<ObjectLifetimeDefault>>>>> {
+            -> Option<&'tcx FxHashMap<ItemLocalId, Vec<ObjectLifetimeDefault>>> {
             desc { "looking up lifetime defaults for a region" }
         }
     }
             eval_always
             desc { "fetching what a crate is named" }
         }
-        query item_children(_: DefId) -> Lrc<Vec<Export<hir::HirId>>> {}
+        query item_children(_: DefId) -> &'tcx [Export<hir::HirId>] {}
         query extern_mod_stmt_cnum(_: DefId) -> Option<CrateNum> {}
 
-        query get_lib_features(_: CrateNum) -> Lrc<LibFeatures> {
+        query get_lib_features(_: CrateNum) -> &'tcx LibFeatures {
             eval_always
             desc { "calculating the lib features map" }
         }
         query defined_lib_features(_: CrateNum)
-            -> Lrc<Vec<(Symbol, Option<Symbol>)>> {
+            -> &'tcx [(Symbol, Option<Symbol>)] {
             desc { "calculating the lib features defined in a crate" }
         }
-        query get_lang_items(_: CrateNum) -> Lrc<LanguageItems> {
+        query get_lang_items(_: CrateNum) -> &'tcx LanguageItems {
             eval_always
             desc { "calculating the lang items map" }
         }
-        query defined_lang_items(_: CrateNum) -> Lrc<Vec<(DefId, usize)>> {
+        query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] {
             desc { "calculating the lang items defined in a crate" }
         }
-        query missing_lang_items(_: CrateNum) -> Lrc<Vec<LangItem>> {
+        query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] {
             desc { "calculating the missing lang items in a crate" }
         }
         query visible_parent_map(_: CrateNum)
-            -> Lrc<DefIdMap<DefId>> {
+            -> &'tcx DefIdMap<DefId> {
             desc { "calculating the visible parent map" }
         }
         query missing_extern_crate_item(_: CrateNum) -> bool {
             eval_always
             desc { "looking at the source for a crate" }
         }
-        query postorder_cnums(_: CrateNum) -> Lrc<Vec<CrateNum>> {
+        query postorder_cnums(_: CrateNum) -> &'tcx [CrateNum] {
             eval_always
             desc { "generating a postorder list of CrateNums" }
         }
 
-        query upvars(_: DefId) -> Option<Lrc<Vec<hir::Upvar>>> {
+        query upvars(_: DefId) -> Option<&'tcx [hir::Upvar]> {
             eval_always
         }
         query maybe_unused_trait_import(_: DefId) -> bool {
             eval_always
         }
         query maybe_unused_extern_crates(_: CrateNum)
-            -> Lrc<Vec<(DefId, Span)>> {
+            -> &'tcx [(DefId, Span)] {
             eval_always
             desc { "looking up all possibly unused extern crates" }
         }
             eval_always
         }
 
-        query stability_index(_: CrateNum) -> Lrc<stability::Index<'tcx>> {
+        query stability_index(_: CrateNum) -> &'tcx stability::Index<'tcx> {
             eval_always
             desc { "calculating the stability index for the local crate" }
         }
-        query all_crate_nums(_: CrateNum) -> Lrc<Vec<CrateNum>> {
+        query all_crate_nums(_: CrateNum) -> &'tcx [CrateNum] {
             eval_always
             desc { "fetching all foreign CrateNum instances" }
         }
         /// A vector of every trait accessible in the whole crate
         /// (i.e., including those from subcrates). This is used only for
         /// error reporting.
-        query all_traits(_: CrateNum) -> Lrc<Vec<DefId>> {
+        query all_traits(_: CrateNum) -> &'tcx [DefId] {
             desc { "fetching all foreign and local traits" }
         }
     }
     }
 
     Other {
-        query target_features_whitelist(_: CrateNum) -> Lrc<FxHashMap<String, Option<Symbol>>> {
+        query target_features_whitelist(_: CrateNum) -> &'tcx FxHashMap<String, Option<Symbol>> {
             eval_always
             desc { "looking up the whitelist of target features" }
         }
             desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
         }
 
-        query features_query(_: CrateNum) -> Lrc<feature_gate::Features> {
+        query features_query(_: CrateNum) -> &'tcx feature_gate::Features {
             eval_always
             desc { "looking up enabled feature gates" }
         }
index 57f5e23918884beee1911e713490425b8ca12969..2fa896962daf9f6c5442241ee41188b62bdd0409 100644 (file)
@@ -700,22 +700,64 @@ fn evaluate_nested_obligations<
                             }
                     }
 
-                    // We can only call poly_project_and_unify_type when our predicate's
-                    // Ty contains an inference variable - otherwise, there won't be anything to
-                    // unify
-                    if p.ty().skip_binder().has_infer_types() {
-                        debug!("Projecting and unifying projection predicate {:?}",
-                               predicate);
-                        match poly_project_and_unify_type(select, &obligation.with(p)) {
-                            Err(e) => {
-                                debug!(
-                                    "evaluate_nested_obligations: Unable to unify predicate \
-                                     '{:?}' '{:?}', bailing out",
-                                    ty, e
-                                );
-                                return false;
-                            }
-                            Ok(Some(v)) => {
+                    // There are three possible cases when we project a predicate:
+                    //
+                    // 1. We encounter an error. This means that it's impossible for
+                    // our current type to implement the auto trait - there's bound
+                    // that we could add to our ParamEnv that would 'fix' this kind
+                    // of error, as it's not caused by an unimplemented type.
+                    //
+                    // 2. We succesfully project the predicate (Ok(Some(_))), generating
+                    //  some subobligations. We then process these subobligations
+                    //  like any other generated sub-obligations.
+                    //
+                    // 3. We receieve an 'ambiguous' result (Ok(None))
+                    // If we were actually trying to compile a crate,
+                    // we would need to re-process this obligation later.
+                    // However, all we care about is finding out what bounds
+                    // are needed for our type to implement a particular auto trait.
+                    // We've already added this obligation to our computed ParamEnv
+                    // above (if it was necessary). Therefore, we don't need
+                    // to do any further processing of the obligation.
+                    //
+                    // Note that we *must* try to project *all* projection predicates
+                    // we encounter, even ones without inference variable.
+                    // This ensures that we detect any projection errors,
+                    // which indicate that our type can *never* implement the given
+                    // auto trait. In that case, we will generate an explicit negative
+                    // impl (e.g. 'impl !Send for MyType'). However, we don't
+                    // try to process any of the generated subobligations -
+                    // they contain no new information, since we already know
+                    // that our type implements the projected-through trait,
+                    // and can lead to weird region issues.
+                    //
+                    // Normally, we'll generate a negative impl as a result of encountering
+                    // a type with an explicit negative impl of an auto trait
+                    // (for example, raw pointers have !Send and !Sync impls)
+                    // However, through some **interesting** manipulations of the type
+                    // system, it's actually possible to write a type that never
+                    // implements an auto trait due to a projection error, not a normal
+                    // negative impl error. To properly handle this case, we need
+                    // to ensure that we catch any potential projection errors,
+                    // and turn them into an explicit negative impl for our type.
+                    debug!("Projecting and unifying projection predicate {:?}",
+                           predicate);
+
+                    match poly_project_and_unify_type(select, &obligation.with(p)) {
+                        Err(e) => {
+                            debug!(
+                                "evaluate_nested_obligations: Unable to unify predicate \
+                                 '{:?}' '{:?}', bailing out",
+                                ty, e
+                            );
+                            return false;
+                        }
+                        Ok(Some(v)) => {
+                            // We only care about sub-obligations
+                            // when we started out trying to unify
+                            // some inference variables. See the comment above
+                            // for more infomration
+                            if p.ty().skip_binder().has_infer_types() {
                                 if !self.evaluate_nested_obligations(
                                     ty,
                                     v.clone().iter().cloned(),
@@ -728,7 +770,16 @@ fn evaluate_nested_obligations<
                                     return false;
                                 }
                             }
-                            Ok(None) => {
+                        }
+                        Ok(None) => {
+                            // It's ok not to make progress when hvave no inference variables -
+                            // in that case, we were only performing unifcation to check if an
+                            // error occured (which would indicate that it's impossible for our
+                            // type to implement the auto trait).
+                            // However, we should always make progress (either by generating
+                            // subobligations or getting an error) when we started off with
+                            // inference variables
+                            if p.ty().skip_binder().has_infer_types() {
                                 panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
                             }
                         }
index c9fee02f66bbdf19970bd270fddf25bbfda9bda0..d83b2ce842a88057df2322e1d550ad88e7d1882e 100644 (file)
@@ -74,7 +74,7 @@
 use syntax::attr;
 use syntax::source_map::MultiSpan;
 use syntax::feature_gate;
-use syntax::symbol::{Symbol, keywords, InternedString, sym};
+use syntax::symbol::{Symbol, InternedString, kw, sym};
 use syntax_pos::Span;
 
 use crate::hir;
@@ -201,6 +201,10 @@ fn intern_ty(
     }
 }
 
+pub struct Common<'tcx> {
+    pub empty_predicates: ty::GenericPredicates<'tcx>,
+}
+
 pub struct CommonTypes<'tcx> {
     pub unit: Ty<'tcx>,
     pub bool: Ty<'tcx>,
@@ -1045,6 +1049,9 @@ pub struct GlobalCtxt<'tcx> {
 
     pub dep_graph: DepGraph,
 
+    /// Common objects.
+    pub common: Common<'tcx>,
+
     /// Common types, pre-interned for your convenience.
     pub types: CommonTypes<'tcx>,
 
@@ -1057,11 +1064,11 @@ pub struct GlobalCtxt<'tcx> {
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
     trait_map: FxHashMap<DefIndex,
-                         Lrc<FxHashMap<ItemLocalId,
-                                       Lrc<StableVec<TraitCandidate>>>>>,
+                         FxHashMap<ItemLocalId,
+                                   StableVec<TraitCandidate>>>,
 
     /// Export map produced by name resolution.
-    export_map: FxHashMap<DefId, Lrc<Vec<Export<hir::HirId>>>>,
+    export_map: FxHashMap<DefId, Vec<Export<hir::HirId>>>,
 
     hir_map: hir_map::Map<'tcx>,
 
@@ -1074,7 +1081,7 @@ pub struct GlobalCtxt<'tcx> {
     // Records the captured variables referenced by every closure
     // expression. Do not track deps for this, just recompute it from
     // scratch every time.
-    upvars: FxHashMap<DefId, Lrc<Vec<hir::Upvar>>>,
+    upvars: FxHashMap<DefId, Vec<hir::Upvar>>,
 
     maybe_unused_trait_imports: FxHashSet<DefId>,
     maybe_unused_extern_crates: Vec<(DefId, Span)>,
@@ -1252,6 +1259,12 @@ pub fn create_global_ctxt(
             s.fatal(&err);
         });
         let interners = CtxtInterners::new(&arenas.interner);
+        let common = Common {
+            empty_predicates: ty::GenericPredicates {
+                parent: None,
+                predicates: vec![],
+            },
+        };
         let common_types = CommonTypes::new(&interners);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
@@ -1292,13 +1305,11 @@ pub fn create_global_ctxt(
             None
         };
 
-        let mut trait_map: FxHashMap<_, Lrc<FxHashMap<_, _>>> = FxHashMap::default();
+        let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
         for (k, v) in resolutions.trait_map {
             let hir_id = hir.node_to_hir_id(k);
             let map = trait_map.entry(hir_id.owner).or_default();
-            Lrc::get_mut(map).unwrap()
-                             .insert(hir_id.local_id,
-                                     Lrc::new(StableVec::new(v)));
+            map.insert(hir_id.local_id, StableVec::new(v));
         }
 
         GlobalCtxt {
@@ -1308,6 +1319,7 @@ pub fn create_global_ctxt(
             global_arenas: &arenas.global,
             global_interners: interners,
             dep_graph,
+            common,
             types: common_types,
             lifetimes: common_lifetimes,
             consts: common_consts,
@@ -1316,13 +1328,13 @@ pub fn create_global_ctxt(
                 let exports: Vec<_> = v.into_iter().map(|e| {
                     e.map_id(|id| hir.node_to_hir_id(id))
                 }).collect();
-                (k, Lrc::new(exports))
+                (k, exports)
             }).collect(),
             upvars: resolutions.upvars.into_iter().map(|(k, v)| {
                 let vars: Vec<_> = v.into_iter().map(|e| {
                     e.map_id(|id| hir.node_to_hir_id(id))
                 }).collect();
-                (hir.local_def_id(k), Lrc::new(vars))
+                (hir.local_def_id(k), vars)
             }).collect(),
             maybe_unused_trait_imports:
                 resolutions.maybe_unused_trait_imports
@@ -1364,11 +1376,11 @@ pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
         self.sess.consider_optimizing(&cname, msg)
     }
 
-    pub fn lib_features(self) -> Lrc<middle::lib_features::LibFeatures> {
+    pub fn lib_features(self) -> &'gcx middle::lib_features::LibFeatures {
         self.get_lib_features(LOCAL_CRATE)
     }
 
-    pub fn lang_items(self) -> Lrc<middle::lang_items::LanguageItems> {
+    pub fn lang_items(self) -> &'gcx middle::lang_items::LanguageItems {
         self.get_lang_items(LOCAL_CRATE)
     }
 
@@ -1406,15 +1418,15 @@ pub fn is_binop_lang_item(&self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
         else { None }
     }
 
-    pub fn stability(self) -> Lrc<stability::Index<'tcx>> {
+    pub fn stability(self) -> &'gcx stability::Index<'gcx> {
         self.stability_index(LOCAL_CRATE)
     }
 
-    pub fn crates(self) -> Lrc<Vec<CrateNum>> {
+    pub fn crates(self) -> &'gcx [CrateNum] {
         self.all_crate_nums(LOCAL_CRATE)
     }
 
-    pub fn features(self) -> Lrc<feature_gate::Features> {
+    pub fn features(self) -> &'gcx feature_gate::Features {
         self.features_query(LOCAL_CRATE)
     }
 
@@ -2735,7 +2747,7 @@ pub fn mk_const_param(
 
     #[inline]
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_ty_param(0, keywords::SelfUpper.name().as_interned_str())
+        self.mk_ty_param(0, kw::SelfUpper.as_interned_str())
     }
 
     pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> {
@@ -2965,9 +2977,9 @@ pub fn struct_lint_node(self, lint: &'static Lint, id: HirId, msg: &str)
         lint::struct_lint_level(self.sess, lint, level, src, None, msg)
     }
 
-    pub fn in_scope_traits(self, id: HirId) -> Option<Lrc<StableVec<TraitCandidate>>> {
+    pub fn in_scope_traits(self, id: HirId) -> Option<&'gcx StableVec<TraitCandidate>> {
         self.in_scope_traits_map(id.owner)
-            .and_then(|map| map.get(&id.local_id).cloned())
+            .and_then(|map| map.get(&id.local_id))
     }
 
     pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
@@ -2982,10 +2994,10 @@ pub fn is_late_bound(self, id: HirId) -> bool {
     }
 
     pub fn object_lifetime_defaults(self, id: HirId)
-        -> Option<Lrc<Vec<ObjectLifetimeDefault>>>
+        -> Option<&'gcx [ObjectLifetimeDefault]>
     {
         self.object_lifetime_defaults_map(id.owner)
-            .and_then(|map| map.get(&id.local_id).cloned())
+            .and_then(|map| map.get(&id.local_id).map(|v| &**v))
     }
 }
 
@@ -3040,27 +3052,27 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
 }
 
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
-    providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();
+    providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id);
+    providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).map(|v| &v[..]);
     providers.crate_name = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
         tcx.crate_name
     };
     providers.get_lib_features = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
-        Lrc::new(middle::lib_features::collect(tcx))
+        tcx.arena.alloc(middle::lib_features::collect(tcx))
     };
     providers.get_lang_items = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
-        Lrc::new(middle::lang_items::collect(tcx))
+        tcx.arena.alloc(middle::lang_items::collect(tcx))
     };
-    providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id).cloned();
+    providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id).map(|v| &v[..]);
     providers.maybe_unused_trait_import = |tcx, id| {
         tcx.maybe_unused_trait_imports.contains(&id)
     };
     providers.maybe_unused_extern_crates = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(tcx.maybe_unused_extern_crates.clone())
+        &tcx.maybe_unused_extern_crates[..]
     };
     providers.names_imported_by_glob_use = |tcx, id| {
         assert_eq!(id.krate, LOCAL_CRATE);
@@ -3069,7 +3081,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
 
     providers.stability_index = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(stability::Index::new(tcx))
+        tcx.arena.alloc(stability::Index::new(tcx))
     };
     providers.lookup_stability = |tcx, id| {
         assert_eq!(id.krate, LOCAL_CRATE);
@@ -3087,11 +3099,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     };
     providers.all_crate_nums = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(tcx.cstore.crates_untracked())
+        tcx.arena.alloc_slice(&tcx.cstore.crates_untracked())
     };
     providers.postorder_cnums = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(tcx.cstore.postorder_cnums_untracked())
+        tcx.arena.alloc_slice(&tcx.cstore.postorder_cnums_untracked())
     };
     providers.output_filenames = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
@@ -3099,7 +3111,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     };
     providers.features_query = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(tcx.sess.features_untracked().clone())
+        tcx.arena.alloc(tcx.sess.features_untracked().clone())
     };
     providers.is_panic_runtime = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
index 4d242265e618fbebd0a2c1d3c127fcdbaf8a3f54..99c3293168754dd9a15cb2073996fa08088c0970 100644 (file)
@@ -47,7 +47,7 @@
 use syntax::ast::{self, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
-use syntax::symbol::{keywords, sym, Symbol, LocalInternedString, InternedString};
+use syntax::symbol::{kw, sym, Symbol, LocalInternedString, InternedString};
 use syntax_pos::Span;
 
 use smallvec;
@@ -835,7 +835,7 @@ pub fn to_bound_region(&self) -> ty::BoundRegion {
     /// Does this early bound region have a name? Early bound regions normally
     /// always have names except when using anonymous lifetimes (`'_`).
     pub fn has_name(&self) -> bool {
-        self.name != keywords::UnderscoreLifetime.name().as_interned_str()
+        self.name != kw::UnderscoreLifetime.as_interned_str()
     }
 }
 
@@ -2298,7 +2298,7 @@ pub fn non_enum_variant(&self) -> &VariantDef {
     }
 
     #[inline]
-    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc<GenericPredicates<'gcx>> {
+    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx GenericPredicates<'gcx> {
         tcx.predicates_of(self.did)
     }
 
@@ -3106,7 +3106,7 @@ pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: hir::HirId) ->
 
 pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    def_ids: Lrc<Vec<DefId>>,
+    def_ids: &'gcx [DefId],
     next_index: usize,
 }
 
@@ -3183,26 +3183,27 @@ fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      def_id: DefId)
-                                     -> Lrc<Vec<DefId>> {
+                                     -> &'tcx [DefId] {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let item = tcx.hir().expect_item_by_hir_id(id);
-    let vec: Vec<_> = match item.node {
+    match item.node {
         hir::ItemKind::Trait(.., ref trait_item_refs) => {
-            trait_item_refs.iter()
-                           .map(|trait_item_ref| trait_item_ref.id)
-                           .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
-                           .collect()
+            tcx.arena.alloc_from_iter(
+                trait_item_refs.iter()
+                               .map(|trait_item_ref| trait_item_ref.id)
+                               .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
+            )
         }
         hir::ItemKind::Impl(.., ref impl_item_refs) => {
-            impl_item_refs.iter()
-                          .map(|impl_item_ref| impl_item_ref.id)
-                          .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
-                          .collect()
+            tcx.arena.alloc_from_iter(
+                impl_item_refs.iter()
+                              .map(|impl_item_ref| impl_item_ref.id)
+                              .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
+            )
         }
-        hir::ItemKind::TraitAlias(..) => vec![],
+        hir::ItemKind::TraitAlias(..) => &[],
         _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
-    };
-    Lrc::new(vec)
+    }
 }
 
 fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span {
@@ -3388,7 +3389,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
 /// (constructing this map requires touching the entire crate).
 #[derive(Clone, Debug, Default, HashStable)]
 pub struct CrateInherentImpls {
-    pub inherent_impls: DefIdMap<Lrc<Vec<DefId>>>,
+    pub inherent_impls: DefIdMap<Vec<DefId>>,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
index c18852a832fce8bd6226e829c75f8a87074eb666..06db4b9b65bcaf545ebad92ab6f816d3b2015ab7 100644 (file)
@@ -8,7 +8,7 @@
 use crate::ty::subst::{Kind, Subst, UnpackedKind};
 use crate::mir::interpret::ConstValue;
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::{keywords, InternedString};
+use syntax::symbol::{kw, InternedString};
 
 use std::cell::Cell;
 use std::fmt::{self, Write as _};
@@ -253,8 +253,8 @@ fn try_print_visible_def_path(
             // 2. for an extern inferred from a path or an indirect crate,
             //    where there is no explicit `extern crate`, we just prepend
             //    the crate name.
-            match *self.tcx().extern_crate(def_id) {
-                Some(ExternCrate {
+            match self.tcx().extern_crate(def_id) {
+                Some(&ExternCrate {
                     src: ExternCrateSource::Extern(def_id),
                     direct: true,
                     span,
@@ -980,7 +980,7 @@ fn path_crate(
             if self.tcx.sess.rust_2018() {
                 // We add the `crate::` keyword on Rust 2018, only when desired.
                 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
-                    write!(self, "{}", keywords::Crate.name())?;
+                    write!(self, "{}", kw::Crate)?;
                     self.empty_path = false;
                 }
             }
@@ -1140,16 +1140,16 @@ fn region_should_not_be_omitted(
 
         match *region {
             ty::ReEarlyBound(ref data) => {
-                data.name.as_symbol() != keywords::Invalid.name() &&
-                data.name.as_symbol() != keywords::UnderscoreLifetime.name()
+                data.name.as_symbol() != kw::Invalid &&
+                data.name.as_symbol() != kw::UnderscoreLifetime
             }
 
             ty::ReLateBound(_, br) |
             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
-                    if name.as_symbol() != keywords::Invalid.name() &&
-                       name.as_symbol() != keywords::UnderscoreLifetime.name() {
+                    if name.as_symbol() != kw::Invalid &&
+                       name.as_symbol() != kw::UnderscoreLifetime {
                         return true;
                     }
                 }
@@ -1205,7 +1205,7 @@ pub fn pretty_print_region(
         // `explain_region()` or `note_and_explain_region()`.
         match *region {
             ty::ReEarlyBound(ref data) => {
-                if data.name.as_symbol() != keywords::Invalid.name() {
+                if data.name.as_symbol() != kw::Invalid {
                     p!(write("{}", data.name));
                     return Ok(self);
                 }
@@ -1214,8 +1214,8 @@ pub fn pretty_print_region(
             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
-                    if name.as_symbol() != keywords::Invalid.name() &&
-                       name.as_symbol() != keywords::UnderscoreLifetime.name() {
+                    if name.as_symbol() != kw::Invalid &&
+                       name.as_symbol() != kw::UnderscoreLifetime {
                         p!(write("{}", name));
                         return Ok(self);
                     }
index 2fb318a47befd80f6919cd0b22c9eb56bbe3f8f4..01d431b0ef0e7a04fb8c50f51dfe72c6ea4e5653 100644 (file)
@@ -14,12 +14,6 @@ impl<'tcx, T> Value<'tcx> for T {
     }
 }
 
-impl<'tcx, T: Default> Value<'tcx> for T {
-    default fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> T {
-        T::default()
-    }
-}
-
 impl<'tcx> Value<'tcx> for Ty<'tcx> {
     fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         tcx.types.err
index e8f3bad4d3ee32832666fd66f72f4cc502707da8..0b5a6fce5cb8759056f2ad85e2898efe1c95229a 100644 (file)
@@ -22,7 +22,7 @@
 use std::ops::Range;
 use rustc_target::spec::abi;
 use syntax::ast::{self, Ident};
-use syntax::symbol::{keywords, InternedString};
+use syntax::symbol::{kw, InternedString};
 
 use serialize;
 use self::InferTy::*;
@@ -1121,7 +1121,7 @@ pub fn new(index: u32, name: InternedString) -> ParamTy {
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, keywords::SelfUpper.name().as_interned_str())
+        ParamTy::new(0, kw::SelfUpper.as_interned_str())
     }
 
     pub fn for_def(def: &ty::GenericParamDef) -> ParamTy {
@@ -1136,7 +1136,7 @@ pub fn is_self(&self) -> bool {
         // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere,
         // but this should only be possible when using `-Z continue-parse-after-error` like
         // `compile-fail/issue-36638.rs`.
-        self.name.as_symbol() == keywords::SelfUpper.name() && self.index == 0
+        self.name.as_symbol() == kw::SelfUpper && self.index == 0
     }
 }
 
index 0c19d770194b2ea486f268ab30e526bdb9259451..b9cd30694f6e8efe5f4f4b6687dfc8ad2d0a0b5f 100644 (file)
@@ -19,7 +19,7 @@
     mut_visit::{self, MutVisitor},
     parse::ParseSess,
     ptr::P,
-    symbol::{keywords, Symbol, sym}
+    symbol::{kw, sym, Symbol}
 };
 use syntax_pos::Span;
 
@@ -116,8 +116,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
 
         // We will generate a new submodule. To `use` the static from that module, we need to get
         // the `super::...` path.
-        let super_path =
-            f.cx.path(f.span, vec![Ident::with_empty_ctxt(keywords::Super.name()), f.global]);
+        let super_path = f.cx.path(f.span, vec![Ident::with_empty_ctxt(kw::Super), f.global]);
 
         // Generate the items in the submodule
         let mut items = vec![
index 65a550b1b8914a821534615834e3eaa9b1febcae..7dca47485bb928d8f531083ef6b7d4affa8a3214 100644 (file)
@@ -32,7 +32,6 @@
 use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::rc::Rc;
-use rustc_data_structures::sync::Lrc;
 use std::hash::{Hash, Hasher};
 use syntax::source_map::CompilerDesugaringKind;
 use syntax_pos::{MultiSpan, Span};
@@ -75,7 +74,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
 }
 
 fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
-    -> Lrc<BorrowCheckResult>
+    -> &'tcx BorrowCheckResult
 {
     assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
 
@@ -89,7 +88,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
             // those things (notably the synthesized constructors from
             // tuple structs/variants) do not have an associated body
             // and do not need borrowchecking.
-            return Lrc::new(BorrowCheckResult {
+            return tcx.arena.alloc(BorrowCheckResult {
                 used_mut_nodes: Default::default(),
                 signalled_any_error: SignalledError::NoErrorsSeen,
             })
@@ -136,7 +135,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
         check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
     }
 
-    Lrc::new(BorrowCheckResult {
+    tcx.arena.alloc(BorrowCheckResult {
         used_mut_nodes: bccx.used_mut_nodes.into_inner(),
         signalled_any_error: bccx.signalled_any_error.into_inner(),
     })
index f26684d9ef04ae4a46c4ee87f1884a1f33af350b..9d0e7dde34d131eb590afb5d7fc3a065944498e5 100644 (file)
@@ -10,7 +10,6 @@
 use rustc::ty::layout::HasTyCtxt;
 use rustc::ty::query::Providers;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_target::spec::PanicStrategy;
 use rustc_codegen_ssa::traits::*;
@@ -320,11 +319,11 @@ pub fn provide(providers: &mut Providers<'_>) {
         if tcx.sess.opts.actually_rustdoc {
             // rustdoc needs to be able to document functions that use all the features, so
             // whitelist them all
-            Lrc::new(llvm_util::all_known_features()
+            tcx.arena.alloc(llvm_util::all_known_features()
                 .map(|(a, b)| (a.to_string(), b))
                 .collect())
         } else {
-            Lrc::new(llvm_util::target_feature_whitelist(tcx.sess)
+            tcx.arena.alloc(llvm_util::target_feature_whitelist(tcx.sess)
                 .iter()
                 .map(|&(a, b)| (a.to_string(), b))
                 .collect())
@@ -364,7 +363,7 @@ pub fn provide_extern(providers: &mut Providers<'_>) {
             }));
         }
 
-        Lrc::new(ret)
+        tcx.arena.alloc(ret)
     };
 }
 
index d5a56f6a09e02c8c5f6db44636b19b6deeeaa84e..c1ec2071789eb58d66ee39682dbe543202cc08e3 100644 (file)
@@ -96,7 +96,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
                 }
             }
             if sess.opts.debugging_opts.emit_artifact_notifications {
-                sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename);
+                sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link");
             }
         }
 
index a55f783df43a372b43294353c813199b5e1f1dcb..fb7ef87646296b4fbe1711f5eaf7ad7f6d1cc1f1 100644 (file)
@@ -1,4 +1,3 @@
-use rustc_data_structures::sync::Lrc;
 use std::sync::Arc;
 
 use rustc::ty::Instance;
@@ -49,12 +48,12 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExpor
 
 fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                              cnum: CrateNum)
-                                             -> Lrc<DefIdMap<SymbolExportLevel>>
+                                             -> &'tcx DefIdMap<SymbolExportLevel>
 {
     assert_eq!(cnum, LOCAL_CRATE);
 
     if !tcx.sess.opts.output_types.should_codegen() {
-        return Default::default();
+        return tcx.arena.alloc(Default::default());
     }
 
     // Check to see if this crate is a "special runtime crate". These
@@ -155,7 +154,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         reachable_non_generics.insert(id, SymbolExportLevel::C);
     }
 
-    Lrc::new(reachable_non_generics)
+    tcx.arena.alloc(reachable_non_generics)
 }
 
 fn is_reachable_non_generic_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -282,7 +281,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn upstream_monomorphizations_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cnum: CrateNum)
-    -> Lrc<DefIdMap<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>>
+    -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>>
 {
     debug_assert!(cnum == LOCAL_CRATE);
 
@@ -326,20 +325,16 @@ fn upstream_monomorphizations_provider<'a, 'tcx>(
         }
     }
 
-    Lrc::new(instances.into_iter()
-                      .map(|(key, value)| (key, Lrc::new(value)))
-                      .collect())
+    tcx.arena.alloc(instances)
 }
 
 fn upstream_monomorphizations_for_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId)
-    -> Option<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>
+    -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>>
 {
     debug_assert!(!def_id.is_local());
-    tcx.upstream_monomorphizations(LOCAL_CRATE)
-       .get(&def_id)
-       .cloned()
+    tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
 }
 
 fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
index 3cd47dfbb29fb7cf6387cecc36406e59999565b0..0b037f872475decc13b8adb23623f665d4c9b25f 100644 (file)
@@ -33,7 +33,6 @@
 use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::sync::Lrc;
 use rustc_codegen_utils::{symbol_names_test, check_for_rustc_errors_attr};
 use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use crate::mir::place::PlaceRef;
@@ -916,7 +915,7 @@ pub fn provide_both(providers: &mut Providers<'_>) {
             .map(|id| &module_map[&id])
             .flat_map(|module| module.foreign_items.iter().cloned())
             .collect();
-        Lrc::new(dllimports)
+        tcx.arena.alloc(dllimports)
     };
 
     providers.is_dllimport_foreign_item = |tcx, def_id| {
index 060d7d18625fcd358323405f1570db82a632d9cc..fed12c9a29fd2d9f8d31c3e71aaff2365576b58e 100644 (file)
@@ -10,7 +10,7 @@
 use crate::traits::*;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
-use syntax::symbol::keywords;
+use syntax::symbol::kw;
 
 use std::iter;
 
@@ -496,7 +496,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 };
                 bx.declare_local(
                     &fx.debug_context,
-                    arg_decl.name.unwrap_or(keywords::Invalid.name()),
+                    arg_decl.name.unwrap_or(kw::Invalid),
                     arg_ty, scope,
                     variable_access,
                     VariableKind::ArgumentVariable(arg_index + 1),
@@ -613,7 +613,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 
                 bx.declare_local(
                     &fx.debug_context,
-                    arg_decl.name.unwrap_or(keywords::Invalid.name()),
+                    arg_decl.name.unwrap_or(kw::Invalid),
                     arg.layout.ty,
                     scope,
                     variable_access,
index 3b8e5b449538324c522328192b3bd61d470ba74c..3db05b7214d659578533a4cc4ca701dc8ef9d5ce 100644 (file)
@@ -380,45 +380,47 @@ fn maybe_codegen_consume_direct(
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place={:?})", place);
 
-        // watch out for locals that do not have an
-        // alloca; they are handled somewhat differently
-        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
-            match self.locals[index] {
-                LocalRef::Operand(Some(o)) => {
-                    return Some(o);
-                }
-                LocalRef::Operand(None) => {
-                    bug!("use of {:?} before def", place);
-                }
-                LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
-                    // use path below
-                }
-            }
-        }
+        place.iterate(|place_base, place_projection| {
+            if let mir::PlaceBase::Local(index) = place_base {
+                match self.locals[*index] {
+                    LocalRef::Operand(Some(mut o)) => {
+                        // Moves out of scalar and scalar pair fields are trivial.
+                        for proj in place_projection {
+                            match proj.elem {
+                                mir::ProjectionElem::Field(ref f, _) => {
+                                    o = o.extract_field(bx, f.index());
+                                }
+                                mir::ProjectionElem::Index(_) |
+                                mir::ProjectionElem::ConstantIndex { .. } => {
+                                    // ZSTs don't require any actual memory access.
+                                    // FIXME(eddyb) deduplicate this with the identical
+                                    // checks in `codegen_consume` and `extract_field`.
+                                    let elem = o.layout.field(bx.cx(), 0);
+                                    if elem.is_zst() {
+                                        o = OperandRef::new_zst(bx, elem);
+                                    } else {
+                                        return None;
+                                    }
+                                }
+                                _ => return None,
+                            }
+                        }
 
-        // Moves out of scalar and scalar pair fields are trivial.
-        if let &mir::Place::Projection(ref proj) = place {
-            if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
-                match proj.elem {
-                    mir::ProjectionElem::Field(ref f, _) => {
-                        return Some(o.extract_field(bx, f.index()));
+                        Some(o)
                     }
-                    mir::ProjectionElem::Index(_) |
-                    mir::ProjectionElem::ConstantIndex { .. } => {
-                        // ZSTs don't require any actual memory access.
-                        // FIXME(eddyb) deduplicate this with the identical
-                        // checks in `codegen_consume` and `extract_field`.
-                        let elem = o.layout.field(bx.cx(), 0);
-                        if elem.is_zst() {
-                            return Some(OperandRef::new_zst(bx, elem));
-                        }
+                    LocalRef::Operand(None) => {
+                        bug!("use of {:?} before def", place);
+                    }
+                    LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
+                        // watch out for locals that do not have an
+                        // alloca; they are handled somewhat differently
+                        None
                     }
-                    _ => {}
                 }
+            } else {
+                None
             }
-        }
-
-        None
+        })
     }
 
     pub fn codegen_consume(
index 59cbd65f05c68a4a936192e58d49da99ecd4f09a..890d2c5ce0b80e2f534138073036c5b2853e7834 100644 (file)
@@ -56,7 +56,7 @@ pub trait Emitter {
     /// Emit a notification that an artifact has been output.
     /// This is currently only supported for the JSON format,
     /// other formats can, and will, simply ignore it.
-    fn emit_artifact_notification(&mut self, _path: &Path) {}
+    fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}
 
     /// Checks if should show explanations about "rustc --explain"
     fn should_show_explain(&self) -> bool {
@@ -1645,7 +1645,7 @@ fn apply_style(&mut self, lvl: Level, style: Style) -> io::Result<()> {
                 }
             }
             Style::Quotation => {}
-            Style::OldSchoolNoteText | Style::MainHeaderMsg => {
+            Style::MainHeaderMsg => {
                 spec.set_bold(true);
                 if cfg!(windows) {
                     spec.set_intense(true)
index 3aa87fad0717416fcf9993cdb80ab0561e86b19a..2dcf7be2aa8b1f9dadf8bfae1f6b121be7dbb235 100644 (file)
@@ -769,8 +769,8 @@ fn emit_db(&self, db: &DiagnosticBuilder<'_>) {
         }
     }
 
-    pub fn emit_artifact_notification(&self, path: &Path) {
-        self.emitter.borrow_mut().emit_artifact_notification(path);
+    pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
+        self.emitter.borrow_mut().emit_artifact_notification(path, artifact_type);
     }
 }
 
index a0af604026d4afa051aaba78b899662693e25894..47ba22d3d25aff6ebff6f6ee702bd1e4955df812 100644 (file)
@@ -188,7 +188,6 @@ pub enum Style {
     UnderlineSecondary,
     LabelPrimary,
     LabelSecondary,
-    OldSchoolNoteText,
     NoStyle,
     Level(Level),
     Highlight,
index 04041f88344204bf20efc4efda72f004d97d2ed3..4a96864dc9d661aed721057dc89c191b213b2abd 100644 (file)
@@ -1050,7 +1050,8 @@ enum MetadataKind {
             tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
         }
         if tcx.sess.opts.debugging_opts.emit_artifact_notifications {
-            tcx.sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename);
+            tcx.sess.parse_sess.span_diagnostic
+                .emit_artifact_notification(&out_filename, "metadata");
         }
     }
 
index d17a92efb066bb9dd3725577049292b578223f1d..d52e497cf63d9a14d8b78885285f3614239e107a 100644 (file)
@@ -42,7 +42,7 @@
 use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType};
 use syntax::feature_gate::{Stability, deprecated_attributes};
 use syntax_pos::{BytePos, Span, SyntaxContext};
-use syntax::symbol::{Symbol, keywords, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax::errors::{Applicability, DiagnosticBuilder};
 use syntax::print::pprust::expr_to_string;
 use syntax::visit::FnKind;
@@ -607,7 +607,7 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) {
                 for arg in sig.decl.inputs.iter() {
                     match arg.pat.node {
                         ast::PatKind::Ident(_, ident, None) => {
-                            if ident.name == keywords::Invalid.name() {
+                            if ident.name == kw::Invalid {
                                 let ty_snip = cx
                                     .sess
                                     .source_map()
index 38b6e2c197939769be2d3f3238bf2f9672b7df7c..ac18e131c4a3d7aafcf62cb5a1dd0e6b02d6546f 100644 (file)
@@ -1,10 +1,11 @@
 #![allow(non_snake_case)]
 
 use rustc::hir::{ExprKind, Node};
+use crate::hir::def_id::DefId;
 use rustc::hir::lowering::is_range_literal;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
-use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
+use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
 use rustc::{lint, util};
 use rustc_data_structures::indexed_vec::Idx;
 use util::nodemap::FxHashSet;
 use std::cmp;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 
-use syntax::{ast, attr};
+use syntax::{ast, attr, source_map};
 use syntax::errors::Applicability;
+use syntax::symbol::sym;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::Span;
-use syntax::source_map;
 
 use rustc::hir;
 
@@ -522,42 +523,79 @@ enum FfiResult<'tcx> {
     },
 }
 
+fn is_zst<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, ty: Ty<'tcx>) -> bool {
+    tcx.layout_of(tcx.param_env(did).and(ty)).map(|layout| layout.is_zst()).unwrap_or(false)
+}
+
+fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.sty {
+        ty::FnPtr(_) => true,
+        ty::Ref(..) => true,
+        ty::Adt(field_def, substs) if field_def.repr.transparent() && field_def.is_struct() => {
+            for field in &field_def.non_enum_variant().fields {
+                let field_ty = tcx.normalize_erasing_regions(
+                    ParamEnv::reveal_all(),
+                    field.ty(tcx, substs),
+                );
+                if is_zst(tcx, field.did, field_ty) {
+                    continue;
+                }
+
+                let attrs = tcx.get_attrs(field_def.did);
+                if attrs.iter().any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed)) ||
+                    ty_is_known_nonnull(tcx, field_ty) {
+                    return true;
+                }
+            }
+
+            false
+        }
+        _ => false,
+    }
+}
+
 /// Check if this enum can be safely exported based on the
 /// "nullable pointer optimization". Currently restricted
-/// to function pointers and references, but could be
-/// expanded to cover NonZero raw pointers and newtypes.
+/// to function pointers, references, core::num::NonZero*,
+/// core::ptr::NonNull, and #[repr(transparent)] newtypes.
 /// FIXME: This duplicates code in codegen.
 fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  def: &'tcx ty::AdtDef,
+                                  ty: Ty<'tcx>,
+                                  ty_def: &'tcx ty::AdtDef,
                                   substs: SubstsRef<'tcx>)
                                   -> bool {
-    if def.variants.len() == 2 {
-        let data_idx;
+    if ty_def.variants.len() != 2 {
+        return false;
+    }
 
-        let zero = VariantIdx::new(0);
-        let one = VariantIdx::new(1);
+    let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields;
+    let variant_fields = [get_variant_fields(0), get_variant_fields(1)];
+    let fields = if variant_fields[0].is_empty() {
+        &variant_fields[1]
+    } else if variant_fields[1].is_empty() {
+        &variant_fields[0]
+    } else {
+        return false;
+    };
 
-        if def.variants[zero].fields.is_empty() {
-            data_idx = one;
-        } else if def.variants[one].fields.is_empty() {
-            data_idx = zero;
-        } else {
-            return false;
-        }
+    if fields.len() != 1 {
+        return false;
+    }
 
-        if def.variants[data_idx].fields.len() == 1 {
-            match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
-                ty::FnPtr(_) => {
-                    return true;
-                }
-                ty::Ref(..) => {
-                    return true;
-                }
-                _ => {}
-            }
-        }
+    let field_ty = fields[0].ty(tcx, substs);
+    if !ty_is_known_nonnull(tcx, field_ty) {
+        return false;
     }
-    false
+
+    // At this point, the field's type is known to be nonnull and the parent enum is Option-like.
+    // If the computed size for the field and the enum are different, the nonnull optimization isn't
+    // being applied (and we've got a problem somewhere).
+    let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, ParamEnv::reveal_all()).unwrap();
+    if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) {
+        bug!("improper_ctypes: Option nonnull optimization not applied?");
+    }
+
+    true
 }
 
 impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
@@ -612,14 +650,8 @@ fn check_type_for_ffi(&self,
                             );
                             // repr(transparent) types are allowed to have arbitrary ZSTs, not just
                             // PhantomData -- skip checking all ZST fields
-                            if def.repr.transparent() {
-                                let is_zst = cx
-                                    .layout_of(cx.param_env(field.did).and(field_ty))
-                                    .map(|layout| layout.is_zst())
-                                    .unwrap_or(false);
-                                if is_zst {
-                                    continue;
-                                }
+                            if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
+                                continue;
                             }
                             let r = self.check_type_for_ffi(cache, field_ty);
                             match r {
@@ -682,7 +714,7 @@ fn check_type_for_ffi(&self,
                         // discriminant.
                         if !def.repr.c() && def.repr.int.is_none() {
                             // Special-case types like `Option<extern fn()>`.
-                            if !is_repr_nullable_ptr(cx, def, substs) {
+                            if !is_repr_nullable_ptr(cx, ty, def, substs) {
                                 return FfiUnsafe {
                                     ty: ty,
                                     reason: "enum has no representation hint",
index c3dfd44ad8572f46ebc4ebc67411296924d30c59..34f7e04c1642038d1d2c1f28fc907ee662cb834f 100644 (file)
@@ -12,7 +12,7 @@
 use syntax::errors::Applicability;
 use syntax::feature_gate::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use syntax::print::pprust;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax::symbol::Symbol;
 use syntax::util::parser;
 use syntax_pos::Span;
@@ -455,7 +455,7 @@ fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &
             match items[0].0.kind {
                 ast::UseTreeKind::Simple(rename, ..) => {
                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
-                    if orig_ident.name == keywords::SelfLower.name() {
+                    if orig_ident.name == kw::SelfLower {
                         return;
                     }
                     node_ident = rename.unwrap_or(orig_ident);
index a4c7daf088ff2c9e14e052bcd9cd21ffad50f64a..3883682fa9df57f6ec88c4b113d44c634fec6708 100644 (file)
@@ -97,7 +97,6 @@ pub fn symbols(input: TokenStream) -> TokenStream {
     let mut keyword_stream = quote! {};
     let mut symbols_stream = quote! {};
     let mut prefill_stream = quote! {};
-    let mut from_str_stream = quote! {};
     let mut counter = 0u32;
     let mut keys = HashSet::<String>::new();
 
@@ -115,12 +114,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
             #value,
         });
         keyword_stream.extend(quote! {
-            pub const #name: Keyword = Keyword {
-                ident: Ident::with_empty_ctxt(super::Symbol::new(#counter))
-            };
-        });
-        from_str_stream.extend(quote! {
-            #value => Ok(#name),
+            pub const #name: Symbol = Symbol::new(#counter);
         });
         counter += 1;
     }
@@ -145,17 +139,6 @@ pub fn symbols(input: TokenStream) -> TokenStream {
         macro_rules! keywords {
             () => {
                 #keyword_stream
-
-                impl std::str::FromStr for Keyword {
-                    type Err = ();
-
-                    fn from_str(s: &str) -> Result<Self, ()> {
-                        match s {
-                            #from_str_stream
-                            _ => Err(()),
-                        }
-                    }
-                }
             }
         }
 
index e234f4f88070382f99d9c9a85dcb9d8f2018f8bd..76aba33b6a404ddcb5cc6243106fb353701a9bb4 100644 (file)
@@ -13,6 +13,7 @@ crate-type = ["dylib"]
 flate2 = "1.0"
 log = "0.4"
 memmap = "0.6"
+smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
index 3e00ba3c62004bf435cea8598604e15a7a274b55..991bebc647d0f7ca48822c1af358f2010ba1c2e7 100644 (file)
@@ -162,7 +162,7 @@ fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
 
     fn verify_no_symbol_conflicts(&self,
                                   span: Span,
-                                  root: &CrateRoot) {
+                                  root: &CrateRoot<'_>) {
         // Check for (potential) conflicts with the local crate
         if self.local_crate_name == root.name &&
            self.sess.local_crate_disambiguator() == root.disambiguator {
@@ -476,7 +476,7 @@ fn update_extern_crate(&mut self,
     // Go through the crate metadata and load any crates that it references
     fn resolve_crate_deps(&mut self,
                           root: &Option<CratePaths>,
-                          crate_root: &CrateRoot,
+                          crate_root: &CrateRoot<'_>,
                           metadata: &MetadataBlob,
                           krate: CrateNum,
                           span: Span,
@@ -582,7 +582,7 @@ fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol
     /// implemented as dynamic libraries, but we have a possible future where
     /// custom derive (and other macro-1.1 style features) are implemented via
     /// executables and custom IPC.
-    fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span: Span)
+    fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, span: Span)
                           -> Vec<(ast::Name, Lrc<SyntaxExtension>)> {
         use std::{env, mem};
         use crate::dynamic_lib::DynamicLibrary;
index 22a13f37722b8cfced8117c8d8f7684b62ae7b37..5d8fabc7e69aeac1d01c3fc74c311948d3d2078a 100644 (file)
@@ -64,7 +64,11 @@ pub struct CrateMetadata {
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     pub alloc_decoding_state: AllocDecodingState,
 
-    pub root: schema::CrateRoot,
+    // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
+    // lifetime is only used behind `Lazy` / `LazySeq`, and therefore
+    // acts like an universal (`for<'tcx>`), that is paired up with
+    // whichever `TyCtxt` is being used to decode those values.
+    pub root: schema::CrateRoot<'static>,
 
     /// For each public item in this crate, we encode a key. When the
     /// crate is loaded, we read all the keys and put them in this
index 2070a38b7b85de5ef15715ca5394e487f7720863..fae4c244d6e1404a5e765c22255fa62b5e9386ff 100644 (file)
@@ -21,6 +21,7 @@
 use rustc::util::nodemap::DefIdMap;
 use rustc_data_structures::svh::Svh;
 
+use smallvec::SmallVec;
 use std::any::Any;
 use rustc_data_structures::sync::Lrc;
 use std::sync::Arc;
@@ -95,9 +96,11 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     generics_of => {
         tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
     }
-    predicates_of => { Lrc::new(cdata.get_predicates(def_id.index, tcx)) }
-    predicates_defined_on => { Lrc::new(cdata.get_predicates_defined_on(def_id.index, tcx)) }
-    super_predicates_of => { Lrc::new(cdata.get_super_predicates(def_id.index, tcx)) }
+    predicates_of => { tcx.arena.alloc(cdata.get_predicates(def_id.index, tcx)) }
+    predicates_defined_on => {
+        tcx.arena.alloc(cdata.get_predicates_defined_on(def_id.index, tcx))
+    }
+    super_predicates_of => { tcx.arena.alloc(cdata.get_super_predicates(def_id.index, tcx)) }
     trait_def => {
         tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
     }
@@ -108,10 +111,10 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     }
     variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) }
     associated_item_def_ids => {
-        let mut result = vec![];
+        let mut result = SmallVec::<[_; 8]>::new();
         cdata.each_child_of_item(def_id.index,
           |child| result.push(child.res.def_id()), tcx.sess);
-        Lrc::new(result)
+        tcx.arena.alloc_slice(&result)
     }
     associated_item => { cdata.get_associated_item(def_id.index) }
     impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
@@ -134,7 +137,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
         (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0)))
     }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
-    inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
+    inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
     is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     static_mutability => { cdata.static_mutability(def_id.index) }
@@ -160,7 +163,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
 
-    dylib_dependency_formats => { Lrc::new(cdata.get_dylib_dependency_formats()) }
+    dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
     is_panic_runtime => { cdata.root.panic_runtime }
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
@@ -169,8 +172,8 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
     extern_crate => {
-        let r = Lrc::new(*cdata.extern_crate.lock());
-        r
+        let r = *cdata.extern_crate.lock();
+        r.map(|c| &*tcx.arena.alloc(c))
     }
     is_no_builtins => { cdata.root.no_builtins }
     impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
@@ -187,10 +190,10 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
             })
             .collect();
 
-        Lrc::new(reachable_non_generics)
+        tcx.arena.alloc(reachable_non_generics)
     }
     native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
-    foreign_modules => { Lrc::new(cdata.get_foreign_modules(tcx.sess)) }
+    foreign_modules => { cdata.get_foreign_modules(tcx) }
     plugin_registrar_fn => {
         cdata.root.plugin_registrar_fn.map(|index| {
             DefId { krate: def_id.krate, index }
@@ -207,18 +210,12 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
 
     extra_filename => { cdata.root.extra_filename.clone() }
 
-
     implementations_of_trait => {
-        let mut result = vec![];
-        let filter = Some(other);
-        cdata.get_implementations_for_trait(filter, &mut result);
-        Lrc::new(result)
+        cdata.get_implementations_for_trait(tcx, Some(other))
     }
 
     all_trait_implementations => {
-        let mut result = vec![];
-        cdata.get_implementations_for_trait(None, &mut result);
-        Lrc::new(result)
+        cdata.get_implementations_for_trait(tcx, None)
     }
 
     visibility => { cdata.get_visibility(def_id.index) }
@@ -228,13 +225,13 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     }
     crate_name => { cdata.name }
     item_children => {
-        let mut result = vec![];
+        let mut result = SmallVec::<[_; 8]>::new();
         cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess);
-        Lrc::new(result)
+        tcx.arena.alloc_slice(&result)
     }
-    defined_lib_features => { Lrc::new(cdata.get_lib_features()) }
-    defined_lang_items => { Lrc::new(cdata.get_lang_items()) }
-    missing_lang_items => { Lrc::new(cdata.get_missing_lang_items()) }
+    defined_lib_features => { cdata.get_lib_features(tcx) }
+    defined_lang_items => { cdata.get_lang_items(tcx) }
+    missing_lang_items => { cdata.get_missing_lang_items(tcx) }
 
     missing_extern_crate_item => {
         let r = match *cdata.extern_crate.borrow() {
@@ -246,12 +243,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
 
     used_crate_source => { Lrc::new(cdata.source.clone()) }
 
-    exported_symbols => {
-        let cnum = cdata.cnum;
-        assert!(cnum != LOCAL_CRATE);
-
-        Arc::new(cdata.exported_symbols(tcx))
-    }
+    exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
 }
 
 pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
@@ -293,7 +285,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
         },
         foreign_modules: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
-            Lrc::new(foreign_modules::collect(tcx))
+            &tcx.arena.alloc(foreign_modules::collect(tcx))[..]
         },
         link_args: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
@@ -330,7 +322,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
             // which is to say, its not deterministic in general. But
             // we believe that libstd is consistently assigned crate
             // num 1, so it should be enough to resolve #46112.
-            let mut crates: Vec<CrateNum> = (*tcx.crates()).clone();
+            let mut crates: Vec<CrateNum> = (*tcx.crates()).to_owned();
             crates.sort();
 
             for &cnum in crates.iter() {
@@ -379,7 +371,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
                 }
             }
 
-            Lrc::new(visible_parent_map)
+            tcx.arena.alloc(visible_parent_map)
         },
 
         ..*providers
index d2ba82b5a1c9f04df492895bcc356a63c593db22..958c81989ffd6707328578b888c95146a20c0923 100644 (file)
@@ -365,7 +365,7 @@ fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error>
 
 implement_ty_decoder!( DecodeContext<'a, 'tcx> );
 
-impl<'a, 'tcx> MetadataBlob {
+impl<'tcx> MetadataBlob {
     pub fn is_compatible(&self) -> bool {
         self.raw_bytes().starts_with(METADATA_HEADER)
     }
@@ -374,7 +374,7 @@ pub fn get_rustc_version(&self) -> String {
         Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
     }
 
-    pub fn get_root(&self) -> CrateRoot {
+    pub fn get_root(&self) -> CrateRoot<'tcx> {
         let slice = self.raw_bytes();
         let offset = METADATA_HEADER.len();
         let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
@@ -444,7 +444,7 @@ fn def_kind(&self) -> Option<DefKind> {
 ///  |- proc macro #0 (DefIndex 1:N)
 ///  |- proc macro #1 (DefIndex 1:N+1)
 ///  \- ...
-crate fn proc_macro_def_path_table(crate_root: &CrateRoot,
+crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>,
                                    proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
                                    -> DefPathTable
 {
@@ -475,7 +475,7 @@ fn is_proc_macro(&self, id: DefIndex) -> bool {
 
     fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
         assert!(!self.is_proc_macro(item_id));
-        self.root.index.lookup(self.blob.raw_bytes(), item_id)
+        self.root.entries_index.lookup(self.blob.raw_bytes(), item_id)
     }
 
     fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
@@ -708,26 +708,30 @@ pub fn get_impl_trait(&self,
     }
 
     /// Iterates over all the stability attributes in the given crate.
-    pub fn get_lib_features(&self) -> Vec<(ast::Name, Option<ast::Name>)> {
+    pub fn get_lib_features(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+    ) -> &'tcx [(ast::Name, Option<ast::Name>)] {
         // FIXME: For a proc macro crate, not sure whether we should return the "host"
         // features or an empty Vec. Both don't cause ICEs.
-        self.root
+        tcx.arena.alloc_from_iter(self.root
             .lib_features
-            .decode(self)
-            .collect()
+            .decode(self))
     }
 
     /// Iterates over the language items in the given crate.
-    pub fn get_lang_items(&self) -> Vec<(DefId, usize)> {
+    pub fn get_lang_items(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+    ) -> &'tcx [(DefId, usize)] {
         if self.proc_macros.is_some() {
             // Proc macro crates do not export any lang-items to the target.
-            vec![]
+            &[]
         } else {
-            self.root
+            tcx.arena.alloc_from_iter(self.root
                 .lang_items
                 .decode(self)
-                .map(|(def_index, index)| (self.local_def_id(def_index), index))
-                .collect()
+                .map(|(def_index, index)| (self.local_def_id(def_index), index)))
         }
     }
 
@@ -1013,39 +1017,45 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
         None
     }
 
-    pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec<DefId> {
-        self.entry(id)
-            .inherent_impls
-            .decode(self)
-            .map(|index| self.local_def_id(index))
-            .collect()
+    pub fn get_inherent_implementations_for_type(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+        id: DefIndex
+    ) -> &'tcx [DefId] {
+        tcx.arena.alloc_from_iter(self.entry(id)
+                                      .inherent_impls
+                                      .decode(self)
+                                      .map(|index| self.local_def_id(index)))
     }
 
-    pub fn get_implementations_for_trait(&self,
-                                         filter: Option<DefId>,
-                                         result: &mut Vec<DefId>) {
+    pub fn get_implementations_for_trait(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+        filter: Option<DefId>,
+    ) -> &'tcx [DefId] {
         if self.proc_macros.is_some() {
             // proc-macro crates export no trait impls.
-            return
+            return &[]
         }
 
         // Do a reverse lookup beforehand to avoid touching the crate_num
         // hash map in the loop below.
         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,
+            Some(None) => return &[],
             None => None,
         };
 
         if let Some(filter) = filter {
-            if let Some(impls) = self.trait_impls
-                                     .get(&filter) {
-                result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
+            if let Some(impls) = self.trait_impls.get(&filter) {
+                tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
+            } else {
+                &[]
             }
         } else {
-            for impls in self.trait_impls.values() {
-                result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
-            }
+            tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| {
+                impls.decode(self).map(|idx| self.local_def_id(idx))
+            }))
         }
     }
 
@@ -1075,36 +1085,43 @@ pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
         }
     }
 
-    pub fn get_foreign_modules(&self, sess: &Session) -> Vec<ForeignModule> {
+    pub fn get_foreign_modules(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+    ) -> &'tcx [ForeignModule] {
         if self.proc_macros.is_some() {
             // Proc macro crates do not have any *target* foreign modules.
-            vec![]
+            &[]
         } else {
-            self.root.foreign_modules.decode((self, sess)).collect()
+            tcx.arena.alloc_from_iter(self.root.foreign_modules.decode((self, tcx.sess)))
         }
     }
 
-    pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
-        self.root
+    pub fn get_dylib_dependency_formats(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+    ) -> &'tcx [(CrateNum, LinkagePreference)] {
+        tcx.arena.alloc_from_iter(self.root
             .dylib_dependency_formats
             .decode(self)
             .enumerate()
             .flat_map(|(i, link)| {
                 let cnum = CrateNum::new(i + 1);
                 link.map(|link| (self.cnum_map[cnum], link))
-            })
-            .collect()
+            }))
     }
 
-    pub fn get_missing_lang_items(&self) -> Vec<lang_items::LangItem> {
+    pub fn get_missing_lang_items(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, '_>,
+    ) -> &'tcx [lang_items::LangItem] {
         if self.proc_macros.is_some() {
             // Proc macro crates do not depend on any target weak lang-items.
-            vec![]
+            &[]
         } else {
-            self.root
+            tcx.arena.alloc_from_iter(self.root
                 .lang_items_missing
-                .decode(self)
-                .collect()
+                .decode(self))
         }
     }
 
@@ -1126,10 +1143,7 @@ pub fn exported_symbols(&self,
             // link those in so we skip those crates.
             vec![]
         } else {
-            let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> =
-                LazySeq::with_position_and_length(self.root.exported_symbols.position,
-                                                  self.root.exported_symbols.len);
-            lazy_seq.decode((self, tcx)).collect()
+            self.root.exported_symbols.decode((self, tcx)).collect()
         }
     }
 
index 7f0993e799f5424031d143c432de3e0624cda489..1a9d996131dc0ee9325c99e0fcd94696cfd9ae80 100644 (file)
@@ -1,6 +1,4 @@
 use crate::index::Index;
-use crate::index_builder::{FromId, IndexBuilder, Untracked};
-use crate::isolated_encoder::IsolatedEncoder;
 use crate::schema::*;
 
 use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
@@ -33,7 +31,7 @@
 use syntax::ast;
 use syntax::attr;
 use syntax::source_map::Spanned;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax_pos::{self, FileName, SourceFile, Span};
 use log::{debug, trace};
 
@@ -46,6 +44,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
+    entries_index: Index<'tcx>,
+
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
@@ -300,28 +300,34 @@ pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
         })
     }
 
-    // Encodes something that corresponds to a single DepNode::GlobalMetaData
-    // and registers the Fingerprint in the `metadata_hashes` map.
-    pub fn tracked<'x, DATA, R>(&'x mut self,
-                                op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R,
-                                data: DATA)
-                                -> R {
-        op(&mut IsolatedEncoder::new(self), data)
+    /// Emit the data for a `DefId` to the metadata. The function to
+    /// emit the data is `op`, and it will be given `data` as
+    /// arguments. This `record` function will call `op` to generate
+    /// the `Entry` (which may point to other encoded information)
+    /// and will then record the `Lazy<Entry>` for use in the index.
+    // FIXME(eddyb) remove this.
+    pub fn record<DATA>(&mut self,
+                        id: DefId,
+                        op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>,
+                        data: DATA)
+    {
+        assert!(id.is_local());
+
+        let entry = op(self, data);
+        let entry = self.lazy(&entry);
+        self.entries_index.record(id, entry);
     }
 
-    fn encode_info_for_items(&mut self) -> Index {
+    fn encode_info_for_items(&mut self) {
         let krate = self.tcx.hir().krate();
-        let mut index = IndexBuilder::new(self);
         let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
-        index.record(DefId::local(CRATE_DEF_INDEX),
-                     IsolatedEncoder::encode_info_for_mod,
-                     FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis)));
-        let mut visitor = EncodeVisitor { index };
-        krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
+        self.record(DefId::local(CRATE_DEF_INDEX),
+                     EncodeContext::encode_info_for_mod,
+                     (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis));
+        krate.visit_all_item_likes(&mut self.as_deep_visitor());
         for macro_def in &krate.exported_macros {
-            visitor.visit_macro_def(macro_def);
+            self.visit_macro_def(macro_def);
         }
-        visitor.index.into_items()
     }
 
     fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
@@ -371,38 +377,30 @@ fn encode_source_map(&mut self) -> LazySeq<syntax_pos::SourceFile> {
         self.lazy_seq_ref(adapted.iter().map(|rc| &**rc))
     }
 
-    fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
+    fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
         let mut i = self.position();
 
-        let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ());
-        let dylib_dependency_formats = self.tracked(
-            IsolatedEncoder::encode_dylib_dependency_formats,
-            ());
+        let crate_deps = self.encode_crate_deps();
+        let dylib_dependency_formats = self.encode_dylib_dependency_formats();
         let dep_bytes = self.position() - i;
 
         // Encode the lib features.
         i = self.position();
-        let lib_features = self.tracked(IsolatedEncoder::encode_lib_features, ());
+        let lib_features = self.encode_lib_features();
         let lib_feature_bytes = self.position() - i;
 
         // Encode the language items.
         i = self.position();
-        let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ());
-        let lang_items_missing = self.tracked(
-            IsolatedEncoder::encode_lang_items_missing,
-            ());
+        let lang_items = self.encode_lang_items();
+        let lang_items_missing = self.encode_lang_items_missing();
         let lang_item_bytes = self.position() - i;
 
         // Encode the native libraries used
         i = self.position();
-        let native_libraries = self.tracked(
-            IsolatedEncoder::encode_native_libraries,
-            ());
+        let native_libraries = self.encode_native_libraries();
         let native_lib_bytes = self.position() - i;
 
-        let foreign_modules = self.tracked(
-            IsolatedEncoder::encode_foreign_modules,
-            ());
+        let foreign_modules = self.encode_foreign_modules();
 
         // Encode source_map
         i = self.position();
@@ -416,22 +414,20 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
 
         // Encode the def IDs of impls, for coherence checking.
         i = self.position();
-        let impls = self.tracked(IsolatedEncoder::encode_impls, ());
+        let impls = self.encode_impls();
         let impl_bytes = self.position() - i;
 
         // Encode exported symbols info.
         i = self.position();
         let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
-        let exported_symbols = self.tracked(
-            IsolatedEncoder::encode_exported_symbols,
-            &exported_symbols);
+        let exported_symbols = self.encode_exported_symbols(&exported_symbols);
         let exported_symbols_bytes = self.position() - i;
 
         let tcx = self.tcx;
 
         // Encode the items.
         i = self.position();
-        let items = self.encode_info_for_items();
+        self.encode_info_for_items();
         let item_bytes = self.position() - i;
 
         // Encode the allocation index
@@ -462,10 +458,9 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
             self.lazy_seq(interpret_alloc_index)
         };
 
-        // Index the items
         i = self.position();
-        let index = items.write_index(&mut self.opaque);
-        let index_bytes = self.position() - i;
+        let entries_index = self.entries_index.write_index(&mut self.opaque);
+        let entries_index_bytes = self.position() - i;
 
         let attrs = tcx.hir().krate_attrs();
         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
@@ -516,7 +511,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
             impls,
             exported_symbols,
             interpret_alloc_index,
-            index,
+            entries_index,
         });
 
         let total_bytes = self.position();
@@ -539,7 +534,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
             println!("  def-path table bytes: {}", def_path_table_bytes);
             println!("            item bytes: {}", item_bytes);
-            println!("           index bytes: {}", index_bytes);
+            println!("   entries index bytes: {}", entries_index_bytes);
             println!("            zero bytes: {}", zero_bytes);
             println!("           total bytes: {}", total_bytes);
         }
@@ -548,40 +543,29 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
     }
 }
 
-// These are methods for encoding various things. They are meant to be used with
-// IndexBuilder::record() and EncodeContext::tracked(). They actually
-// would not have to be methods of IsolatedEncoder (free standing functions
-// taking IsolatedEncoder as first argument would be just fine) but by making
-// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>`
-// clause again and again.
-impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
+impl EncodeContext<'_, 'tcx> {
     fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
-        debug!("IsolatedEncoder::encode_variances_of({:?})", def_id);
+        debug!("EncodeContext::encode_variances_of({:?})", def_id);
         let tcx = self.tcx;
-        self.lazy_seq_from_slice(&tcx.variances_of(def_id))
+        self.lazy_seq_ref(&tcx.variances_of(def_id)[..])
     }
 
     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
         let tcx = self.tcx;
         let ty = tcx.type_of(def_id);
-        debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty);
+        debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty);
         self.lazy(&ty)
     }
 
-    /// Encode data for the given variant of the given ADT. The
-    /// index of the variant is untracked: this is ok because we
-    /// will have to lookup the adt-def by its id, and that gives us
-    /// the right to access any information in the adt-def (including,
-    /// e.g., the length of the various vectors).
     fn encode_enum_variant_info(
         &mut self,
-        (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+        (enum_did, index): (DefId, VariantIdx),
     ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def = tcx.adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.def_id;
-        debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
+        debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -625,17 +609,15 @@ fn encode_enum_variant_info(
         }
     }
 
-    /// Encode the constructor for the given variant of the given ADT. See
-    /// `encode_enum_variant_info` for an explanation about why the index is untracked.
     fn encode_enum_variant_ctor(
         &mut self,
-        (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+        (enum_did, index): (DefId, VariantIdx),
     ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def = tcx.adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.ctor_def_id.unwrap();
-        debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id);
+        debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -681,18 +663,17 @@ fn encode_enum_variant_ctor(
         }
     }
 
-    fn encode_info_for_mod(&mut self,
-                           FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
-                                                                 &[ast::Attribute],
-                                                                 &hir::Visibility)>)
-                           -> Entry<'tcx> {
+    fn encode_info_for_mod(
+        &mut self,
+        (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility),
+    ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def_id = tcx.hir().local_def_id_from_hir_id(id);
-        debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
 
         let data = ModData {
             reexports: match tcx.module_exports(def_id) {
-                Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()),
+                Some(exports) => self.lazy_seq_ref(exports),
                 _ => LazySeq::empty(),
             },
         };
@@ -719,23 +700,16 @@ fn encode_info_for_mod(&mut self,
         }
     }
 
-    /// Encode data for the given field of the given variant of the
-    /// given ADT. The indices of the variant/field are untracked:
-    /// this is ok because we will have to lookup the adt-def by its
-    /// id, and that gives us the right to access any information in
-    /// the adt-def (including, e.g., the length of the various
-    /// vectors).
-    fn encode_field(&mut self,
-                    (adt_def_id, Untracked((variant_index, field_index))): (DefId,
-                                                                            Untracked<(VariantIdx,
-                                                                                       usize)>))
-                    -> Entry<'tcx> {
+    fn encode_field(
+        &mut self,
+        (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize),
+    ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
         let field = &variant.fields[field_index];
 
         let def_id = field.did;
-        debug!("IsolatedEncoder::encode_field({:?})", def_id);
+        debug!("EncodeContext::encode_field({:?})", def_id);
 
         let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
         let variant_data = tcx.hir().expect_variant_data(variant_id);
@@ -761,7 +735,7 @@ fn encode_field(&mut self,
     }
 
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
+        debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
         let adt_def = tcx.adt_def(adt_def_id);
         let variant = adt_def.non_enum_variant();
@@ -821,25 +795,25 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
     }
 
     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
-        debug!("IsolatedEncoder::encode_generics({:?})", def_id);
+        debug!("EncodeContext::encode_generics({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(tcx.generics_of(def_id))
     }
 
     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
-        debug!("IsolatedEncoder::encode_predicates({:?})", def_id);
+        debug!("EncodeContext::encode_predicates({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.predicates_of(def_id))
     }
 
     fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
-        debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
+        debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.predicates_defined_on(def_id))
     }
 
     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
         let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -949,7 +923,7 @@ fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif {
     }
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
         let tcx = self.tcx;
 
         let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -1042,7 +1016,7 @@ fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
             self.lazy_seq(body.arguments.iter().map(|arg| {
                 match arg.pat.node {
                     PatKind::Binding(_, _, ident, _) => ident.name,
-                    _ => keywords::Invalid.name(),
+                    _ => kw::Invalid,
                 }
             }))
         })
@@ -1064,7 +1038,7 @@ fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
-        debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id);
+        debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
         let implementations = self.tcx.inherent_impls(def_id);
         if implementations.is_empty() {
             LazySeq::empty()
@@ -1077,12 +1051,12 @@ fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex
     }
 
     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
-        debug!("IsolatedEncoder::encode_stability({:?})", def_id);
+        debug!("EncodeContext::encode_stability({:?})", def_id);
         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
     }
 
     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
-        debug!("IsolatedEncoder::encode_deprecation({:?})", def_id);
+        debug!("EncodeContext::encode_deprecation({:?})", def_id);
         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
     }
 
@@ -1096,7 +1070,7 @@ fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<Rende
     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_item({:?})", def_id);
 
         let kind = match item.node {
             hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic,
@@ -1118,7 +1092,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 EntryKind::Fn(self.lazy(&data))
             }
             hir::ItemKind::Mod(ref m) => {
-                return self.encode_info_for_mod(FromId(item.hir_id, (m, &item.attrs, &item.vis)));
+                return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis));
             }
             hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
@@ -1391,9 +1365,9 @@ fn encode_info_for_generic_param(
 
     fn encode_info_for_ty_param(
         &mut self,
-        (def_id, Untracked(encode_type)): (DefId, Untracked<bool>),
+        (def_id, encode_type): (DefId, bool),
     ) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id);
         self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type)
     }
 
@@ -1401,12 +1375,12 @@ fn encode_info_for_const_param(
         &mut self,
         def_id: DefId,
     ) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_const_param({:?})", def_id);
         self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true)
     }
 
     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
         let tcx = self.tcx;
 
         let tables = self.tcx.typeck_tables_of(def_id);
@@ -1450,7 +1424,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
         let tcx = self.tcx;
         let id = tcx.hir().as_local_hir_id(def_id).unwrap();
         let body_id = tcx.hir().body_owned_by(id);
@@ -1478,23 +1452,20 @@ fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
     }
 
     fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
-        // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
-        //       we rely on the HashStable specialization for [Attribute]
-        //       to properly filter things out.
-        self.lazy_seq_from_slice(attrs)
+        self.lazy_seq_ref(attrs)
     }
 
-    fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> {
+    fn encode_native_libraries(&mut self) -> LazySeq<NativeLibrary> {
         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
         self.lazy_seq(used_libraries.iter().cloned())
     }
 
-    fn encode_foreign_modules(&mut self, _: ()) -> LazySeq<ForeignModule> {
+    fn encode_foreign_modules(&mut self) -> LazySeq<ForeignModule> {
         let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
         self.lazy_seq(foreign_modules.iter().cloned())
     }
 
-    fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
+    fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
         let crates = self.tcx.crates();
 
         let mut deps = crates
@@ -1528,13 +1499,13 @@ fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
         self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep))
     }
 
-    fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option<ast::Name>)> {
+    fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option<ast::Name>)> {
         let tcx = self.tcx;
         let lib_features = tcx.lib_features();
         self.lazy_seq(lib_features.to_vec())
     }
 
-    fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
+    fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> {
         let tcx = self.tcx;
         let lang_items = tcx.lang_items();
         let lang_items = lang_items.items().iter();
@@ -1548,14 +1519,14 @@ fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
         }))
     }
 
-    fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> {
+    fn encode_lang_items_missing(&mut self) -> LazySeq<lang_items::LangItem> {
         let tcx = self.tcx;
         self.lazy_seq_ref(&tcx.lang_items().missing)
     }
 
     /// Encodes an index, mapping each trait to its (local) implementations.
-    fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
-        debug!("IsolatedEncoder::encode_impls()");
+    fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
+        debug!("EncodeContext::encode_impls()");
         let tcx = self.tcx;
         let mut visitor = ImplVisitor {
             tcx,
@@ -1580,12 +1551,12 @@ fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
 
                 TraitImpls {
                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
-                    impls: self.lazy_seq_from_slice(&impls[..]),
+                    impls: self.lazy_seq_ref(&impls),
                 }
             })
             .collect();
 
-        self.lazy_seq_from_slice(&all_impls[..])
+        self.lazy_seq_ref(&all_impls)
     }
 
     // Encodes all symbols exported from this crate into the metadata.
@@ -1595,13 +1566,13 @@ fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
     // symbol associated with them (they weren't translated) or if they're an FFI
     // definition (as that's not defined in this crate).
     fn encode_exported_symbols(&mut self,
-                               exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)])
-                               -> EncodedExportedSymbols {
+                               exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)])
+                               -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
         // The metadata symbol name is special. It should not show up in
         // downstream crates.
         let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
 
-        let lazy_seq = self.lazy_seq(exported_symbols
+        self.lazy_seq(exported_symbols
             .iter()
             .filter(|&&(ref exported_symbol, _)| {
                 match *exported_symbol {
@@ -1611,15 +1582,10 @@ fn encode_exported_symbols(&mut self,
                     _ => true,
                 }
             })
-            .cloned());
-
-        EncodedExportedSymbols {
-            len: lazy_seq.len,
-            position: lazy_seq.position,
-        }
+            .cloned())
     }
 
-    fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
+    fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreference>> {
         match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) {
             Some(arr) => {
                 self.lazy_seq(arr.iter().map(|slot| {
@@ -1641,7 +1607,7 @@ fn encode_info_for_foreign_item(&mut self,
                                     -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id);
 
         let kind = match nitem.node {
             hir::ForeignItemKind::Fn(_, ref names, _) => {
@@ -1681,33 +1647,29 @@ fn encode_info_for_foreign_item(&mut self,
     }
 }
 
-struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    index: IndexBuilder<'a, 'b, 'tcx>,
-}
-
-impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
+impl Visitor<'tcx> for EncodeContext<'_, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.index.tcx.hir())
+        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
         intravisit::walk_expr(self, ex);
-        self.index.encode_info_for_expr(ex);
+        self.encode_info_for_expr(ex);
     }
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         intravisit::walk_item(self, item);
-        let def_id = self.index.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
         match item.node {
             hir::ItemKind::ExternCrate(_) |
-            hir::ItemKind::Use(..) => (), // ignore these
-            _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)),
+            hir::ItemKind::Use(..) => {} // ignore these
+            _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
         }
-        self.index.encode_addl_info_for_item(item);
+        self.encode_addl_info_for_item(item);
     }
     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
         intravisit::walk_foreign_item(self, ni);
-        let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
-        self.index.record(def_id,
-                          IsolatedEncoder::encode_info_for_foreign_item,
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
+        self.record(def_id,
+                          EncodeContext::encode_info_for_foreign_item,
                           (def_id, ni));
     }
     fn visit_variant(&mut self,
@@ -1717,32 +1679,32 @@ fn visit_variant(&mut self,
         intravisit::walk_variant(self, v, g, id);
 
         if let Some(ref discr) = v.node.disr_expr {
-            let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
-            self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
+            let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
+            self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
         }
     }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
         intravisit::walk_generics(self, generics);
-        self.index.encode_info_for_generics(generics);
+        self.encode_info_for_generics(generics);
     }
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
         intravisit::walk_ty(self, ty);
-        self.index.encode_info_for_ty(ty);
+        self.encode_info_for_ty(ty);
     }
     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
-        let def_id = self.index.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
-        self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
+        self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
     }
 }
 
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
+impl EncodeContext<'_, 'tcx> {
     fn encode_fields(&mut self, adt_def_id: DefId) {
         let def = self.tcx.adt_def(adt_def_id);
         for (variant_index, variant) in def.variants.iter_enumerated() {
             for (field_index, field) in variant.fields.iter().enumerate() {
                 self.record(field.did,
-                            IsolatedEncoder::encode_field,
-                            (adt_def_id, Untracked((variant_index, field_index))));
+                            EncodeContext::encode_field,
+                            (adt_def_id, variant_index, field_index));
             }
         }
     }
@@ -1755,12 +1717,12 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
                 GenericParamKind::Type { ref default, .. } => {
                     self.record(
                         def_id,
-                        IsolatedEncoder::encode_info_for_ty_param,
-                        (def_id, Untracked(default.is_some())),
+                        EncodeContext::encode_info_for_ty_param,
+                        (def_id, default.is_some()),
                     );
                 }
                 GenericParamKind::Const { .. } => {
-                    self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id);
+                    self.record(def_id, EncodeContext::encode_info_for_const_param, def_id);
                 }
             }
         }
@@ -1770,7 +1732,7 @@ fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         match ty.node {
             hir::TyKind::Array(_, ref length) => {
                 let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
-                self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
+                self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
             }
             _ => {}
         }
@@ -1780,7 +1742,7 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
             hir::ExprKind::Closure(..) => {
                 let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
-                self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id);
+                self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
             }
             _ => {}
         }
@@ -1812,13 +1774,13 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 let def = self.tcx.adt_def(def_id);
                 for (i, variant) in def.variants.iter_enumerated() {
                     self.record(variant.def_id,
-                                IsolatedEncoder::encode_enum_variant_info,
-                                (def_id, Untracked(i)));
+                                EncodeContext::encode_enum_variant_info,
+                                (def_id, i));
 
                     if let Some(ctor_def_id) = variant.ctor_def_id {
                         self.record(ctor_def_id,
-                                    IsolatedEncoder::encode_enum_variant_ctor,
-                                    (def_id, Untracked(i)));
+                                    EncodeContext::encode_enum_variant_ctor,
+                                    (def_id, i));
                     }
                 }
             }
@@ -1829,7 +1791,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
                     let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
                     self.record(ctor_def_id,
-                                IsolatedEncoder::encode_struct_ctor,
+                                EncodeContext::encode_struct_ctor,
                                 (def_id, ctor_def_id));
                 }
             }
@@ -1839,14 +1801,14 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
             hir::ItemKind::Impl(..) => {
                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(trait_item_def_id,
-                                IsolatedEncoder::encode_info_for_impl_item,
+                                EncodeContext::encode_info_for_impl_item,
                                 trait_item_def_id);
                 }
             }
             hir::ItemKind::Trait(..) => {
                 for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(item_def_id,
-                                IsolatedEncoder::encode_info_for_trait_item,
+                                EncodeContext::encode_info_for_trait_item,
                                 item_def_id);
                 }
             }
@@ -1911,10 +1873,13 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     // Will be filled with the root position after encoding everything.
     encoder.emit_raw_bytes(&[0, 0, 0, 0]);
 
-    let (root, mut result) = {
+    // Since encoding metadata is not in a query, and nothing is cached,
+    // there's no need to do dep-graph tracking for any of it.
+    let (root, mut result) = tcx.dep_graph.with_ignore(move || {
         let mut ecx = EncodeContext {
             opaque: encoder,
             tcx,
+            entries_index: Index::new(tcx.hir().definitions().def_index_count()),
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
@@ -1930,7 +1895,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
         // culminating in the `CrateRoot` which points to all of it.
         let root = ecx.encode_crate_root();
         (root, ecx.opaque.into_inner())
-    };
+    });
 
     // Encode the root position.
     let header = METADATA_HEADER.len();
index 934e871559c79939010ffb30377007afc5b96ba6..dd2f59922ef9238ca34d6276dce219ab8fed9f03 100644 (file)
@@ -2,6 +2,7 @@
 
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc_serialize::opaque::Encoder;
+use std::marker::PhantomData;
 use std::u32;
 use log::debug;
 
@@ -74,23 +75,25 @@ fn write_to_bytes(self, b: &mut [u8]) {
 /// `u32::MAX`. Whenever an index is visited, we fill in the
 /// appropriate spot by calling `record_position`. We should never
 /// visit the same index twice.
-pub struct Index {
+pub struct Index<'tcx> {
     positions: Vec<u8>,
+    _marker: PhantomData<&'tcx ()>,
 }
 
-impl Index {
-    pub fn new(max_index: usize) -> Index {
+impl Index<'tcx> {
+    pub fn new(max_index: usize) -> Self {
         Index {
             positions: vec![0xff; max_index * 4],
+            _marker: PhantomData,
         }
     }
 
-    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'_>>) {
+    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
         assert!(def_id.is_local());
         self.record_index(def_id.index, entry);
     }
 
-    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'_>>) {
+    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
         assert!(entry.position < (u32::MAX as usize));
         let position = entry.position as u32;
         let array_index = item.index();
@@ -105,7 +108,7 @@ pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'_>>) {
         position.write_to_bytes_at(positions, array_index)
     }
 
-    pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
+    pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Self> {
         let pos = buf.position();
 
         // First we write the length of the lower range ...
@@ -116,7 +119,7 @@ pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
     }
 }
 
-impl<'tcx> LazySeq<Index> {
+impl LazySeq<Index<'tcx>> {
     /// Given the metadata, extract out the offset of a particular
     /// DefIndex (if any).
     #[inline(never)]
diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs
deleted file mode 100644 (file)
index e780693..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-//! Builder types for generating the "item data" section of the
-//! metadata. This section winds up looking like this:
-//!
-//! ```
-//! <common::data> // big list of item-like things...
-//!    <common::data_item> // ...for most `DefId`s, there is an entry.
-//!    </common::data_item>
-//! </common::data>
-//! ```
-//!
-//! As we generate this listing, we collect the offset of each
-//! `data_item` entry and store it in an index. Then, when we load the
-//! metadata, we can skip right to the metadata for a particular item.
-//!
-//! In addition to the offset, we need to track the data that was used
-//! to generate the contents of each `data_item`. This is so that we
-//! can figure out which HIR nodes contributed to that data for
-//! incremental compilation purposes.
-//!
-//! The `IndexBuilder` facilitates both of these. It is created
-//! with an `EncodingContext` (`ecx`), which it encapsulates.
-//! It has one main method, `record()`. You invoke `record`
-//! like so to create a new `data_item` element in the list:
-//!
-//! ```
-//! index.record(some_def_id, callback_fn, data)
-//! ```
-//!
-//! What record will do is to (a) record the current offset, (b) emit
-//! the `common::data_item` tag, and then call `callback_fn` with the
-//! given data as well as the `EncodingContext`. Once `callback_fn`
-//! returns, the `common::data_item` tag will be closed.
-//!
-//! `EncodingContext` does not offer the `record` method, so that we
-//! can ensure that `common::data_item` elements are never nested.
-//!
-//! In addition, while the `callback_fn` is executing, we will push a
-//! task `MetaData(some_def_id)`, which can then observe the
-//! reads/writes that occur in the task. For this reason, the `data`
-//! argument that is given to the `callback_fn` must implement the
-//! trait `DepGraphRead`, which indicates how to register reads on the
-//! data in this new task (note that many types of data, such as
-//! `DefId`, do not currently require any reads to be registered,
-//! since they are not derived from a HIR node). This is also why we
-//! give a callback fn, rather than taking a closure: it allows us to
-//! easily control precisely what data is given to that fn.
-
-use crate::encoder::EncodeContext;
-use crate::index::Index;
-use crate::schema::*;
-use crate::isolated_encoder::IsolatedEncoder;
-
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::ty::TyCtxt;
-use syntax::ast;
-
-use std::ops::{Deref, DerefMut};
-
-/// Builder that can encode new items, adding them into the index.
-/// Item encoding cannot be nested.
-pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
-    items: Index,
-    pub ecx: &'a mut EncodeContext<'b, 'tcx>,
-}
-
-impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> {
-    type Target = EncodeContext<'b, 'tcx>;
-    fn deref(&self) -> &Self::Target {
-        self.ecx
-    }
-}
-
-impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        self.ecx
-    }
-}
-
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
-    pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
-        IndexBuilder {
-            items: Index::new(ecx.tcx.hir().definitions().def_index_count()),
-            ecx,
-        }
-    }
-
-    /// Emit the data for a `DefId` to the metadata. The function to
-    /// emit the data is `op`, and it will be given `data` as
-    /// arguments. This `record` function will call `op` to generate
-    /// the `Entry` (which may point to other encoded information)
-    /// and will then record the `Lazy<Entry>` for use in the index.
-    ///
-    /// In addition, it will setup a dep-graph task to track what data
-    /// `op` accesses to generate the metadata, which is later used by
-    /// incremental compilation to compute a hash for the metadata and
-    /// track changes.
-    ///
-    /// The reason that `op` is a function pointer, and not a closure,
-    /// is that we want to be able to completely track all data it has
-    /// access to, so that we can be sure that `DATA: DepGraphRead`
-    /// holds, and that it is therefore not gaining "secret" access to
-    /// bits of HIR or other state that would not be trackd by the
-    /// content system.
-    pub fn record<'x, DATA>(&'x mut self,
-                            id: DefId,
-                            op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
-                            data: DATA)
-        where DATA: DepGraphRead
-    {
-        assert!(id.is_local());
-
-        // We don't track this since we are explicitly computing the incr. comp.
-        // hashes anyway. In theory we could do some tracking here and use it to
-        // avoid rehashing things (and instead cache the hashes) but it's
-        // unclear whether that would be a win since hashing is cheap enough.
-        self.ecx.tcx.dep_graph.with_ignore(move || {
-            let mut entry_builder = IsolatedEncoder::new(self.ecx);
-            let entry = op(&mut entry_builder, data);
-            let entry = entry_builder.lazy(&entry);
-
-            self.items.record(id, entry);
-        })
-    }
-
-    pub fn into_items(self) -> Index {
-        self.items
-    }
-}
-
-/// Trait used for data that can be passed from outside a dep-graph
-/// task. The data must either be of some safe type, such as a
-/// `DefId` index, or implement the `read` method so that it can add
-/// a read of whatever dep-graph nodes are appropriate.
-pub trait DepGraphRead {
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>);
-}
-
-impl DepGraphRead for DefId {
-    fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
-}
-
-impl DepGraphRead for ast::NodeId {
-    fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
-}
-
-impl<T> DepGraphRead for Option<T>
-    where T: DepGraphRead
-{
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-        match *self {
-            Some(ref v) => v.read(tcx),
-            None => (),
-        }
-    }
-}
-
-impl<T> DepGraphRead for [T]
-    where T: DepGraphRead
-{
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-        for i in self {
-            i.read(tcx);
-        }
-    }
-}
-
-macro_rules! read_tuple {
-    ($($name:ident),*) => {
-        impl<$($name),*> DepGraphRead for ($($name),*)
-            where $($name: DepGraphRead),*
-        {
-            #[allow(non_snake_case)]
-            fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-                let &($(ref $name),*) = self;
-                $($name.read(tcx);)*
-            }
-        }
-    }
-}
-read_tuple!(A, B);
-read_tuple!(A, B, C);
-
-macro_rules! read_hir {
-    ($t:ty) => {
-        impl<'tcx> DepGraphRead for &'tcx $t {
-            fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-                tcx.hir().read(self.hir_id);
-            }
-        }
-    }
-}
-read_hir!(hir::Item);
-read_hir!(hir::ImplItem);
-read_hir!(hir::TraitItem);
-read_hir!(hir::ForeignItem);
-read_hir!(hir::MacroDef);
-
-/// Leaks access to a value of type T without any tracking. This is
-/// suitable for ambiguous types like `usize`, which *could* represent
-/// tracked data (e.g., if you read it out of a HIR node) or might not
-/// (e.g., if it's an index). Adding in an `Untracked` is an
-/// assertion, essentially, that the data does not need to be tracked
-/// (or that read edges will be added by some other way).
-///
-/// A good idea is to add to each use of `Untracked` an explanation of
-/// why this value is ok.
-pub struct Untracked<T>(pub T);
-
-impl<T> DepGraphRead for Untracked<T> {
-    fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
-}
-
-/// Newtype that can be used to package up misc data extracted from a
-/// HIR node that doesn't carry its own ID. This will allow an
-/// arbitrary `T` to be passed in, but register a read on the given
-/// `NodeId`.
-pub struct FromId<T>(pub hir::HirId, pub T);
-
-impl<T> DepGraphRead for FromId<T> {
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-        tcx.hir().read(self.0);
-    }
-}
diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs
deleted file mode 100644 (file)
index e879a73..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::encoder::EncodeContext;
-use crate::schema::{Lazy, LazySeq};
-use rustc::ty::TyCtxt;
-use rustc_serialize::Encodable;
-
-/// The IsolatedEncoder provides facilities to write to crate metadata while
-/// making sure that anything going through it is also feed into an ICH hasher.
-pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> {
-    pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
-    ecx: &'a mut EncodeContext<'b, 'tcx>,
-}
-
-impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
-
-    pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
-        let tcx = ecx.tcx;
-        IsolatedEncoder {
-            tcx,
-            ecx,
-        }
-    }
-
-    pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
-        where T: Encodable
-    {
-        self.ecx.lazy(value)
-    }
-
-    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
-        where I: IntoIterator<Item = T>,
-              T: Encodable
-    {
-        self.ecx.lazy_seq(iter)
-    }
-
-    pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq<T>
-        where I: IntoIterator<Item = &'x T>,
-              T: 'x + Encodable
-    {
-        self.ecx.lazy_seq_ref(iter)
-    }
-
-    pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
-        where T: Encodable
-    {
-        self.ecx.lazy_seq_ref(slice.iter())
-    }
-}
index 4f84ca69b7f186d76d12298e24f45e6ffd93e12d..e0b92341575cc98252776ec0609a6f175739f485 100644 (file)
@@ -2,6 +2,7 @@
 
 #![feature(box_patterns)]
 #![feature(drain_filter)]
+#![feature(in_band_lifetimes)]
 #![feature(libc)]
 #![feature(nll)]
 #![feature(proc_macro_internals)]
 
 mod error_codes;
 
-mod index_builder;
 mod index;
 mod encoder;
 mod decoder;
 mod cstore_impl;
-mod isolated_encoder;
 mod schema;
 mod native_libs;
 mod link_args;
index 504c7da7d6b9e0fc25f5060c35fc45f9d31ac3c5..0ad3251540716306a31594dde118597f6e190e42 100644 (file)
@@ -2,8 +2,8 @@
 
 use rustc::hir;
 use rustc::hir::def::{self, CtorKind};
-use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
-use rustc::ich::StableHashingContext;
+use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
 use rustc::middle::lang_items;
 use rustc::mir;
 use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
-use std::mem;
-
-use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
-                                           StableHasherResult};
 
 pub fn rustc_version() -> String {
     format!("rustc {}",
@@ -91,15 +87,6 @@ fn clone(&self) -> Self {
 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
 
-impl<CTX, T> HashStable<CTX> for Lazy<T> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut CTX,
-                                          _: &mut StableHasher<W>) {
-        // There's nothing to do. Whatever got encoded within this Lazy<>
-        // wrapper has already been hashed.
-    }
-}
-
 /// A sequence of type T referred to by its absolute position
 /// in the metadata and length, and which can be decoded lazily.
 /// The sequence is a single node for the purposes of `Lazy`.
@@ -148,15 +135,6 @@ fn clone(&self) -> Self {
 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
 
-impl<CTX, T> HashStable<CTX> for LazySeq<T> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut CTX,
-                                          _: &mut StableHasher<W>) {
-        // There's nothing to do. Whatever got encoded within this Lazy<>
-        // wrapper has already been hashed.
-    }
-}
-
 /// Encoding / decoding state for `Lazy` and `LazySeq`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum LazyState {
@@ -174,7 +152,7 @@ pub enum LazyState {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct CrateRoot {
+pub struct CrateRoot<'tcx> {
     pub name: Symbol,
     pub triple: TargetTriple,
     pub extra_filename: String,
@@ -199,10 +177,10 @@ pub struct CrateRoot {
     pub source_map: LazySeq<syntax_pos::SourceFile>,
     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
     pub impls: LazySeq<TraitImpls>,
-    pub exported_symbols: EncodedExportedSymbols,
+    pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>,
     pub interpret_alloc_index: LazySeq<u32>,
 
-    pub index: LazySeq<index::Index>,
+    pub entries_index: LazySeq<index::Index<'tcx>>,
 
     pub compiler_builtins: bool,
     pub needs_allocator: bool,
@@ -221,36 +199,12 @@ pub struct CrateDep {
     pub extra_filename: String,
 }
 
-impl_stable_hash_for!(struct CrateDep {
-    name,
-    hash,
-    kind,
-    extra_filename
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitImpls {
     pub trait_id: (u32, DefIndex),
     pub impls: LazySeq<DefIndex>,
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TraitImpls {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        let TraitImpls {
-            trait_id: (krate, def_index),
-            ref impls,
-        } = *self;
-
-        DefId {
-            krate: CrateNum::from_u32(krate),
-            index: def_index
-        }.hash_stable(hcx, hasher);
-        impls.hash_stable(hcx, hasher);
-    }
-}
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Entry<'tcx> {
     pub kind: EntryKind<'tcx>,
@@ -271,23 +225,6 @@ pub struct Entry<'tcx> {
     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct Entry<'tcx> {
-    kind,
-    visibility,
-    span,
-    attributes,
-    children,
-    stability,
-    deprecation,
-    ty,
-    inherent_impls,
-    variances,
-    generics,
-    predicates,
-    predicates_defined_on,
-    mir
-});
-
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub enum EntryKind<'tcx> {
     Const(ConstQualif, Lazy<RenderedConst>),
@@ -322,82 +259,6 @@ pub enum EntryKind<'tcx> {
     TraitAlias(Lazy<TraitAliasData<'tcx>>),
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            EntryKind::ImmStatic        |
-            EntryKind::MutStatic        |
-            EntryKind::ForeignImmStatic |
-            EntryKind::ForeignMutStatic |
-            EntryKind::ForeignMod       |
-            EntryKind::GlobalAsm        |
-            EntryKind::ForeignType      |
-            EntryKind::Field |
-            EntryKind::Existential |
-            EntryKind::Type |
-            EntryKind::TypeParam |
-            EntryKind::ConstParam => {
-                // Nothing else to hash here.
-            }
-            EntryKind::Const(qualif, ref const_data) => {
-                qualif.hash_stable(hcx, hasher);
-                const_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Enum(ref repr_options) => {
-                repr_options.hash_stable(hcx, hasher);
-            }
-            EntryKind::Variant(ref variant_data) => {
-                variant_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Struct(ref variant_data, ref repr_options) |
-            EntryKind::Union(ref variant_data, ref repr_options)  => {
-                variant_data.hash_stable(hcx, hasher);
-                repr_options.hash_stable(hcx, hasher);
-            }
-            EntryKind::Fn(ref fn_data) |
-            EntryKind::ForeignFn(ref fn_data) => {
-                fn_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Mod(ref mod_data) => {
-                mod_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::MacroDef(ref macro_def) => {
-                macro_def.hash_stable(hcx, hasher);
-            }
-            EntryKind::Generator(data) => {
-                data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Closure(closure_data) => {
-                closure_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Trait(ref trait_data) => {
-                trait_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::TraitAlias(ref trait_alias_data) => {
-                trait_alias_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Impl(ref impl_data) => {
-                impl_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Method(ref method_data) => {
-                method_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::AssociatedExistential(associated_container) |
-            EntryKind::AssociatedType(associated_container) => {
-                associated_container.hash_stable(hcx, hasher);
-            }
-            EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => {
-                associated_container.hash_stable(hcx, hasher);
-                qualif.hash_stable(hcx, hasher);
-                const_data.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
 /// Additional data for EntryKind::Const and EntryKind::AssociatedConst
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
 pub struct ConstQualif {
@@ -405,37 +266,22 @@ pub struct ConstQualif {
     pub ast_promotable: bool,
 }
 
-impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable });
-
 /// Contains a constant which has been rendered to a String.
 /// Used by rustdoc.
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct RenderedConst(pub String);
 
-impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
-    #[inline]
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        self.0.hash_stable(hcx, hasher);
-    }
-}
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
     pub reexports: LazySeq<def::Export<hir::HirId>>,
 }
 
-impl_stable_hash_for!(struct ModData { reexports });
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct MacroDef {
     pub body: String,
     pub legacy: bool,
 }
 
-impl_stable_hash_for!(struct MacroDef { body, legacy });
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct FnData<'tcx> {
     pub constness: hir::Constness,
@@ -443,8 +289,6 @@ pub struct FnData<'tcx> {
     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
 
-impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
@@ -456,13 +300,6 @@ pub struct VariantData<'tcx> {
     pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct VariantData<'tcx> {
-    ctor_kind,
-    discr,
-    ctor,
-    ctor_sig
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
@@ -472,23 +309,11 @@ pub struct TraitData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
-impl_stable_hash_for!(struct TraitData<'tcx> {
-    unsafety,
-    paren_sugar,
-    has_auto_impl,
-    is_marker,
-    super_predicates
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitAliasData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
-impl_stable_hash_for!(struct TraitAliasData<'tcx> {
-    super_predicates
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
@@ -500,14 +325,6 @@ pub struct ImplData<'tcx> {
     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct ImplData<'tcx> {
-    polarity,
-    defaultness,
-    parent_impl,
-    coerce_unsized_info,
-    trait_ref
-});
-
 
 /// Describes whether the container of an associated item
 /// is a trait or an impl and whether, in a trait, it has
@@ -520,13 +337,6 @@ pub enum AssociatedContainer {
     ImplFinal,
 }
 
-impl_stable_hash_for!(enum crate::schema::AssociatedContainer {
-    TraitRequired,
-    TraitWithDefault,
-    ImplDefault,
-    ImplFinal
-});
-
 impl AssociatedContainer {
     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
         match *self {
@@ -560,26 +370,17 @@ pub struct MethodData<'tcx> {
     pub container: AssociatedContainer,
     pub has_self: bool,
 }
-impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ClosureData<'tcx> {
     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
-impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct GeneratorData<'tcx> {
     pub layout: mir::GeneratorLayout<'tcx>,
 }
-impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
 
 // Tags used for encoding Spans:
 pub const TAG_VALID_SPAN: u8 = 0;
 pub const TAG_INVALID_SPAN: u8 = 1;
-
-#[derive(RustcEncodable, RustcDecodable)]
-pub struct EncodedExportedSymbols {
-    pub position: usize,
-    pub len: usize,
-}
index fc1f5eb5d5a7a45a85db4fbf4d5a55a3a3216ae8..cf02878ec82ed28db372f7877d2b2c1626c9781c 100644 (file)
@@ -439,10 +439,11 @@ fn downgrade_if_error(diag: &mut Diagnostic) {
         diag.warn(
             "this error has been downgraded to a warning for backwards \
             compatibility with previous releases",
-        );
-        diag.warn(
+        ).warn(
             "this represents potential undefined behavior in your code and \
             this warning will become a hard error in the future",
+        ).note(
+            "for more information, try `rustc --explain E0729`"
         );
     }
 }
index 32088ff9f61eee5c1a094d59ee3d8f8b2d0c57ef..4bee7f9c4bf8616745d81365454d9a82a7ef23b5 100644 (file)
@@ -8,7 +8,7 @@
 use rustc::ty::{self, Const, DefIdTree, Ty, TyS, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
-use syntax_pos::symbol::keywords;
+use syntax_pos::symbol::kw;
 
 use crate::dataflow::move_paths::InitLocation;
 use crate::borrow_check::MirBorrowckCtxt;
@@ -256,7 +256,7 @@ pub(super) fn report_mutability_error(
                             // Deliberately fall into this case for all implicit self types,
                             // so that we don't fall in to the next case with them.
                             *kind == mir::ImplicitSelfKind::MutRef
-                        } else if Some(keywords::SelfLower.name()) == local_decl.name {
+                        } else if Some(kw::SelfLower) == local_decl.name {
                             // Otherwise, check if the name is the self kewyord - in which case
                             // we have an explicit self. Do the same thing in this case and check
                             // for a `self: &mut Self` to suggest removing the `&mut`.
index 00e81ee049183f255efe2ea4c0f910269a6b6d77..18ca105070e8f9149b4c5342775cc914f7626184 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use std::collections::VecDeque;
 use syntax::errors::Applicability;
-use syntax::symbol::keywords;
+use syntax::symbol::kw;
 use syntax_pos::Span;
 
 mod region_name;
@@ -631,7 +631,7 @@ fn add_static_impl_trait_suggestion(
                     "add_static_impl_trait_suggestion: has_static_predicate={:?}",
                     has_static_predicate
                 );
-                let static_str = keywords::StaticLifetime.name();
+                let static_str = kw::StaticLifetime;
                 // If there is a static predicate, then the only sensible suggestion is to replace
                 // fr with `'static`.
                 if has_static_predicate {
index 4d8acd241acd893f17910c81d87d8b09d8b979b6..f3cfc1a59a9811dfa05376085cd5c7eb5b63fec6 100644 (file)
@@ -12,7 +12,7 @@
 use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
 use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
-use syntax::symbol::keywords;
+use syntax::symbol::kw;
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
 
@@ -216,7 +216,7 @@ fn give_name_from_error_region(
             }
 
             ty::ReStatic => Some(RegionName {
-                name: keywords::StaticLifetime.name().as_interned_str(),
+                name: kw::StaticLifetime.as_interned_str(),
                 source: RegionNameSource::Static
             }),
 
index 7469aceee3a9ee959c7647fee82007ba20eaed77..b5bab1585342a1cacf4329ee69aacafcf31d31e1 100644 (file)
@@ -23,8 +23,8 @@ pub fn ast_block(&mut self,
             safety_mode
         } =
             self.hir.mirror(ast_block);
-        self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
-            this.in_scope((region_scope, source_info), LintLevel::Inherited, block, move |this| {
+        self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), move |this| {
+            this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
                 if targeted_by_break {
                     // This is a `break`-able block
                     let exit_block = this.cfg.start_new_block();
@@ -83,9 +83,9 @@ fn ast_block_stmts(&mut self,
                 StmtKind::Expr { scope, expr } => {
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
                     unpack!(block = this.in_opt_scope(
-                        opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
+                        opt_destruction_scope.map(|de|(de, source_info)), |this| {
                             let si = (scope, source_info);
-                            this.in_scope(si, LintLevel::Inherited, block, |this| {
+                            this.in_scope(si, LintLevel::Inherited, |this| {
                                 let expr = this.hir.mirror(expr);
                                 this.stmt_expr(block, expr, Some(stmt_span))
                             })
@@ -113,31 +113,39 @@ fn ast_block_stmts(&mut self,
                     let remainder_span = remainder_scope.span(this.hir.tcx(),
                                                               &this.hir.region_scope_tree);
 
-                    let scope;
+                    let visibility_scope =
+                        Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
 
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
                         let initializer_span = init.span();
 
-                        scope = this.declare_bindings(
-                            None,
-                            remainder_span,
-                            lint_level,
-                            &pattern,
-                            ArmHasGuard(false),
-                            Some((None, initializer_span)),
-                        );
                         unpack!(block = this.in_opt_scope(
-                            opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
+                            opt_destruction_scope.map(|de|(de, source_info)), |this| {
                                 let scope = (init_scope, source_info);
-                                this.in_scope(scope, lint_level, block, |this| {
+                                this.in_scope(scope, lint_level, |this| {
+                                    this.declare_bindings(
+                                        visibility_scope,
+                                        remainder_span,
+                                        &pattern,
+                                        ArmHasGuard(false),
+                                        Some((None, initializer_span)),
+                                    );
                                     this.expr_into_pattern(block, pattern, init)
                                 })
                             }));
                     } else {
-                        scope = this.declare_bindings(
-                            None, remainder_span, lint_level, &pattern,
-                            ArmHasGuard(false), None);
+                        let scope = (init_scope, source_info);
+                        unpack!(this.in_scope(scope, lint_level, |this| {
+                            this.declare_bindings(
+                                visibility_scope,
+                                remainder_span,
+                                &pattern,
+                                ArmHasGuard(false),
+                                None,
+                            );
+                            block.unit()
+                        }));
 
                         debug!("ast_block_stmts: pattern={:?}", pattern);
                         this.visit_bindings(
@@ -149,8 +157,8 @@ fn ast_block_stmts(&mut self,
                             })
                     }
 
-                    // Enter the source scope, after evaluating the initializer.
-                    if let Some(source_scope) = scope {
+                    // Enter the visibility scope, after evaluating the initializer.
+                    if let Some(source_scope) = visibility_scope {
                         this.source_scope = source_scope;
                     }
                 }
index e354a2ee8160b47f1f17c40b8561df9eb14e82e4..ed80cb1a16369e6286917c16d0dfe05d2a54031f 100644 (file)
@@ -57,7 +57,7 @@ fn expr_as_operand(
         {
             let source_info = this.source_info(expr.span);
             let region_scope = (region_scope, source_info);
-            return this.in_scope(region_scope, lint_level, block, |this| {
+            return this.in_scope(region_scope, lint_level, |this| {
                 this.as_operand(block, scope, value)
             });
         }
index 5f444d4ceeb8895fe40bae33b69969bad3ac3942..a956eacb0699fd3cd1276a0687645addc1282bf6 100644 (file)
@@ -52,7 +52,7 @@ fn expr_as_place(
                 region_scope,
                 lint_level,
                 value,
-            } => this.in_scope((region_scope, source_info), lint_level, block, |this| {
+            } => this.in_scope((region_scope, source_info), lint_level, |this| {
                 if mutability == Mutability::Not {
                     this.as_read_only_place(block, value)
                 } else {
index fbc4835a6557b4e2a7b34f744286a8c2c424fd72..a0b504a99de9a7981778362410688bec60663dd7 100644 (file)
@@ -58,7 +58,7 @@ fn expr_as_rvalue(
                 value,
             } => {
                 let region_scope = (region_scope, source_info);
-                this.in_scope(region_scope, lint_level, block, |this| {
+                this.in_scope(region_scope, lint_level, |this| {
                     this.as_rvalue(block, scope, value)
                 })
             }
index cba771f27065d93cd6649f94ee44bfccfd3a2a43..cffd8fb2892f5ce987d1946a431f998a1669dade 100644 (file)
@@ -1,6 +1,7 @@
 //! See docs in build/expr/mod.rs
 
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
+use crate::build::scope::{CachedBlock, DropKind};
 use crate::hair::*;
 use rustc::middle::region;
 use rustc::mir::*;
@@ -43,7 +44,7 @@ fn expr_as_temp(
             value,
         } = expr.kind
         {
-            return this.in_scope((region_scope, source_info), lint_level, block, |this| {
+            return this.in_scope((region_scope, source_info), lint_level, |this| {
                 this.as_temp(block, temp_lifetime, value, mutability)
             });
         }
@@ -63,6 +64,8 @@ fn expr_as_temp(
             }
             this.local_decls.push(local_decl)
         };
+        let temp_place = &Place::Base(PlaceBase::Local(temp));
+
         if !expr_ty.is_never() {
             this.cfg.push(
                 block,
@@ -71,25 +74,38 @@ fn expr_as_temp(
                     kind: StatementKind::StorageLive(temp),
                 },
             );
+
+            // In constants, `temp_lifetime` is `None` for temporaries that live for the
+            // `'static` lifetime. Thus we do not drop these temporaries and simply leak them.
+            // This is equivalent to what `let x = &foo();` does in functions. The temporary
+            // is lifted to their surrounding scope. In a function that means the temporary lives
+            // until just before the function returns. In constants that means it outlives the
+            // constant's initialization value computation. Anything outliving a constant
+            // must have the `'static` lifetime and live forever.
+            // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
+            // within a block will keep the regular drops just like runtime code.
+            if let Some(temp_lifetime) = temp_lifetime {
+                this.schedule_drop(
+                    expr_span,
+                    temp_lifetime,
+                    temp_place,
+                    expr_ty,
+                    DropKind::Storage,
+                );
+            }
         }
 
-        unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr));
+        unpack!(block = this.into(temp_place, block, expr));
 
-        // In constants, temp_lifetime is None for temporaries that live for the
-        // 'static lifetime. Thus we do not drop these temporaries and simply leak them.
-        // This is equivalent to what `let x = &foo();` does in functions. The temporary
-        // is lifted to their surrounding scope. In a function that means the temporary lives
-        // until just before the function returns. In constants that means it outlives the
-        // constant's initialization value computation. Anything outliving a constant
-        // must have the `'static` lifetime and live forever.
-        // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
-        // within a block will keep the regular drops just like runtime code.
         if let Some(temp_lifetime) = temp_lifetime {
-            this.schedule_drop_storage_and_value(
+            this.schedule_drop(
                 expr_span,
                 temp_lifetime,
-                &Place::Base(PlaceBase::Local(temp)),
+                temp_place,
                 expr_ty,
+                DropKind::Value {
+                    cached_block: CachedBlock::default(),
+                },
             );
         }
 
index 15795a64e3b7dcea2703280b12c3fc6024ff40dc..7bdfdf0b0895f9579fe4a0cd16cd9f2ae809ebf6 100644 (file)
@@ -46,7 +46,7 @@ pub fn into_expr(
                 value,
             } => {
                 let region_scope = (region_scope, source_info);
-                this.in_scope(region_scope, lint_level, block, |this| {
+                this.in_scope(region_scope, lint_level, |this| {
                     this.into(destination, block, value)
                 })
             }
index b58914b017fd4601f4a677772ed2fa9d93c0ac17..ac690f89264bfdd0d84f163ecbc3f79df3534733 100644 (file)
@@ -29,7 +29,7 @@ pub fn stmt_expr(&mut self,
                 value,
             } => {
                 let value = this.hir.mirror(value);
-                this.in_scope((region_scope, source_info), lint_level, block, |this| {
+                this.in_scope((region_scope, source_info), lint_level, |this| {
                     this.stmt_expr(block, value, opt_stmt_span)
                 })
             }
index 51d5c96083d8f61b6b15b28b9a5278cae7242372..58ca35abcb123ddb5f8cbec5470d3e652b80325f 100644 (file)
@@ -12,6 +12,7 @@
 use crate::hair::{self, *};
 use rustc::hir::HirId;
 use rustc::mir::*;
+use rustc::middle::region;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc::ty::layout::VariantIdx;
 use rustc_data_structures::bit_set::BitSet;
@@ -251,37 +252,39 @@ pub fn match_expr(
 
         // Step 5. Create everything else: the guards and the arms.
 
-        let outer_source_info = self.source_info(span);
         let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, candidates)| {
-            let mut arm_block = self.cfg.start_new_block();
-
-            let body = self.hir.mirror(arm.body.clone());
-            let scope = self.declare_bindings(
-                None,
-                body.span,
-                LintLevel::Inherited,
-                &arm.patterns[0],
-                ArmHasGuard(arm.guard.is_some()),
-                Some((Some(&scrutinee_place), scrutinee_span)),
-            );
-
-            for candidate in candidates {
-                self.bind_and_guard_matched_candidate(
-                    candidate,
-                    arm.guard.clone(),
-                    arm_block,
-                    &fake_borrow_temps,
-                    scrutinee_span,
+            let arm_source_info = self.source_info(arm.span);
+            let region_scope = (arm.scope, arm_source_info);
+            self.in_scope(region_scope, arm.lint_level, |this| {
+                let arm_block = this.cfg.start_new_block();
+
+                let body = this.hir.mirror(arm.body.clone());
+                let scope = this.declare_bindings(
+                    None,
+                    arm.span,
+                    &arm.patterns[0],
+                    ArmHasGuard(arm.guard.is_some()),
+                    Some((Some(&scrutinee_place), scrutinee_span)),
                 );
-            }
 
-            if let Some(source_scope) = scope {
-                self.source_scope = source_scope;
-            }
+                if let Some(source_scope) = scope {
+                    this.source_scope = source_scope;
+                }
 
-            unpack!(arm_block = self.into(destination, arm_block, body));
+                for candidate in candidates {
+                    this.clear_top_scope(arm.scope);
+                    this.bind_and_guard_matched_candidate(
+                        candidate,
+                        arm.guard.clone(),
+                        arm_block,
+                        &fake_borrow_temps,
+                        scrutinee_span,
+                        region_scope,
+                    );
+                }
 
-            arm_block
+                this.into(destination, arm_block, body)
+            })
         }).collect();
 
         // all the arm blocks will rejoin here
@@ -289,7 +292,7 @@ pub fn match_expr(
 
         for arm_block in arm_end_blocks {
             self.cfg.terminate(
-                arm_block,
+                unpack!(arm_block),
                 outer_source_info,
                 TerminatorKind::Goto { target: end_block },
             );
@@ -489,33 +492,20 @@ pub fn declare_bindings(
         &mut self,
         mut visibility_scope: Option<SourceScope>,
         scope_span: Span,
-        lint_level: LintLevel,
         pattern: &Pattern<'tcx>,
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
     ) -> Option<SourceScope> {
-        assert!(
-            !(visibility_scope.is_some() && lint_level.is_explicit()),
-            "can't have both a visibility and a lint scope at the same time"
-        );
-        let mut scope = self.source_scope;
         debug!("declare_bindings: pattern={:?}", pattern);
         self.visit_bindings(
             &pattern,
             UserTypeProjections::none(),
             &mut |this, mutability, name, mode, var, span, ty, user_ty| {
                 if visibility_scope.is_none() {
-                    // If we have lints, create a new source scope
-                    // that marks the lints for the locals. See the comment
-                    // on the `source_info` field for why this is needed.
-                    if lint_level.is_explicit() {
-                        scope = this.new_source_scope(scope_span, lint_level, None);
-                    }
-                visibility_scope = Some(this.new_source_scope(scope_span,
-                                                           LintLevel::Inherited,
-                                                           None));
+                    visibility_scope =
+                        Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
                 }
-                let source_info = SourceInfo { span, scope };
+                let source_info = SourceInfo { span, scope: this.source_scope };
                 let visibility_scope = visibility_scope.unwrap();
                 this.declare_binding(
                     source_info,
@@ -880,7 +870,7 @@ fn match_candidates<'pat>(
             span,
             untested_candidates,
             join_block,
-            &mut None,
+            fake_borrows,
         )
     }
 
@@ -1328,6 +1318,7 @@ fn bind_and_guard_matched_candidate<'pat>(
         arm_block: BasicBlock,
         fake_borrows: &Vec<(&Place<'tcx>, Local)>,
         scrutinee_span: Span,
+        region_scope: (region::Scope, SourceInfo),
     ) {
         debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
 
@@ -1510,17 +1501,40 @@ fn bind_and_guard_matched_candidate<'pat>(
             //
             // and that is clearly not correct.
             let post_guard_block = self.cfg.start_new_block();
+            let otherwise_post_guard_block = self.cfg.start_new_block();
             self.cfg.terminate(
                 block,
                 source_info,
                 TerminatorKind::if_(
                     self.hir.tcx(),
-                    cond,
+                    cond.clone(),
                     post_guard_block,
-                    candidate.otherwise_block.unwrap()
+                    otherwise_post_guard_block,
                 ),
             );
 
+            self.exit_scope(
+                source_info.span,
+                region_scope,
+                otherwise_post_guard_block,
+                candidate.otherwise_block.unwrap(),
+            );
+
+            if let Operand::Copy(cond_place) | Operand::Move(cond_place) = cond {
+                if let Place::Base(PlaceBase::Local(cond_temp)) = cond_place {
+                    // We will call `clear_top_scope` if there's another guard. So
+                    // we have to drop this variable now or it will be "storage
+                    // leaked".
+                    self.pop_variable(
+                        post_guard_block,
+                        region_scope.0,
+                        cond_temp
+                    );
+                } else {
+                    bug!("Expected as_local_operand to produce a temporary");
+                }
+            }
+
             let by_value_bindings = candidate.bindings.iter().filter(|binding| {
                 if let BindingMode::ByValue = binding.binding_mode { true } else { false }
             });
index e46c51535552164ef07f78e4a3bcedbcb7ee6d11..55b5d5d1471ac0ff8907c407f57835134ee368e9 100644 (file)
@@ -20,7 +20,7 @@
 use std::u32;
 use rustc_target::spec::abi::Abi;
 use syntax::attr::{self, UnwindAttr};
-use syntax::symbol::keywords;
+use syntax::symbol::kw;
 use syntax_pos::Span;
 
 use super::lints;
@@ -660,7 +660,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                 ty::UpvarCapture::ByRef(..) => true,
             };
             let mut debuginfo = UpvarDebuginfo {
-                debug_name: keywords::Invalid.name(),
+                debug_name: kw::Invalid,
                 by_ref,
             };
             let mut mutability = Mutability::Not;
@@ -704,13 +704,13 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     let mut block = START_BLOCK;
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
-    unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
+    unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
         if should_abort_on_panic(tcx, fn_def_id, abi) {
             builder.schedule_abort();
         }
 
         let arg_scope_s = (arg_scope, source_info);
-        unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| {
+        unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
             builder.args_and_body(block, &arguments, arg_scope, &body.value)
         }));
         // Attribute epilogue to function's closing brace
@@ -950,10 +950,13 @@ fn args_and_body(&mut self,
                         self.var_indices.insert(var, LocalsForNode::One(local));
                     }
                     _ => {
-                        scope = self.declare_bindings(scope, ast_body.span,
-                                                      LintLevel::Inherited, &pattern,
-                                                      matches::ArmHasGuard(false),
-                                                      Some((Some(&place), span)));
+                        scope = self.declare_bindings(
+                            scope,
+                            ast_body.span,
+                            &pattern,
+                            matches::ArmHasGuard(false),
+                            Some((Some(&place), span)),
+                        );
                         unpack!(block = self.place_into_pattern(block, pattern, &place, false));
                     }
                 }
index 3b11e335fb87f6019d901d259a0d22e15395db50..58339173c9e5d2590e446be852d77d9dbbc22dd0 100644 (file)
 them. Eventually, when we shift to non-lexical lifetimes, there should
 be no need to remember this mapping.
 
-There is one additional wrinkle, actually, that I wanted to hide from
-you but duty compels me to mention. In the course of building
-matches, it sometimes happen that certain code (namely guards) gets
-executed multiple times. This means that the scope lexical scope may
-in fact correspond to multiple, disjoint SEME regions. So in fact our
+### Not so SEME Regions
+
+In the course of building matches, it sometimes happens that certain code
+(namely guards) gets executed multiple times. This means that the scope lexical
+scope may in fact correspond to multiple, disjoint SEME regions. So in fact our
 mapping is from one scope to a vector of SEME regions.
 
+Also in matches, the scopes assigned to arms are not even SEME regions! Each
+arm has a single region with one entry for each pattern. We manually
+manipulate the scheduled drops in this scope to avoid dropping things multiple
+times, although drop elaboration would clean this up for value drops.
+
 ### Drops
 
 The primary purpose for scopes is to insert drops: while building
@@ -282,13 +287,13 @@ pub fn in_breakable_scope<F, R>(&mut self,
 
     pub fn in_opt_scope<F, R>(&mut self,
                               opt_scope: Option<(region::Scope, SourceInfo)>,
-                              mut block: BasicBlock,
                               f: F)
                               -> BlockAnd<R>
         where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
     {
-        debug!("in_opt_scope(opt_scope={:?}, block={:?})", opt_scope, block);
+        debug!("in_opt_scope(opt_scope={:?})", opt_scope);
         if let Some(region_scope) = opt_scope { self.push_scope(region_scope); }
+        let mut block;
         let rv = unpack!(block = f(self));
         if let Some(region_scope) = opt_scope {
             unpack!(block = self.pop_scope(region_scope, block));
@@ -302,12 +307,11 @@ pub fn in_opt_scope<F, R>(&mut self,
     pub fn in_scope<F, R>(&mut self,
                           region_scope: (region::Scope, SourceInfo),
                           lint_level: LintLevel,
-                          mut block: BasicBlock,
                           f: F)
                           -> BlockAnd<R>
         where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
     {
-        debug!("in_scope(region_scope={:?}, block={:?})", region_scope, block);
+        debug!("in_scope(region_scope={:?})", region_scope);
         let source_scope = self.source_scope;
         let tcx = self.hir.tcx();
         if let LintLevel::Explicit(current_hir_id) = lint_level {
@@ -333,6 +337,7 @@ pub fn in_scope<F, R>(&mut self,
             }
         }
         self.push_scope(region_scope);
+        let mut block;
         let rv = unpack!(block = f(self));
         unpack!(block = self.pop_scope(region_scope, block));
         self.source_scope = source_scope;
@@ -730,7 +735,7 @@ pub fn schedule_drop(
             // Note that this code iterates scopes from the inner-most to the outer-most,
             // invalidating caches of each scope visited. This way bare minimum of the
             // caches gets invalidated. i.e., if a new drop is added into the middle scope, the
-            // cache of outer scpoe stays intact.
+            // cache of outer scope stays intact.
             scope.invalidate_cache(!needs_drop, this_scope);
             if this_scope {
                 if let DropKind::Value { .. } = drop_kind {
@@ -872,6 +877,73 @@ pub fn assert(&mut self, block: BasicBlock,
 
         success_block
     }
+
+    // `match` arm scopes
+    // ==================
+    /// Unschedules any drops in the top scope.
+    ///
+    /// This is only needed for `match` arm scopes, because they have one
+    /// entrance per pattern, but only one exit.
+    pub fn clear_top_scope(&mut self, region_scope: region::Scope) {
+        let top_scope = self.scopes.last_mut().unwrap();
+
+        assert_eq!(top_scope.region_scope, region_scope);
+
+        top_scope.drops.clear();
+        top_scope.invalidate_cache(false, true);
+    }
+
+    /// Drops the single variable provided
+    ///
+    /// * The scope must be the top scope.
+    /// * The variable must be in that scope.
+    /// * The variable must be at the top of that scope: it's the next thing
+    ///   scheduled to drop.
+    /// * The drop must be of `DropKind::Storage`.
+    ///
+    /// This is used for the boolean holding the result of the match guard. We
+    /// do this because:
+    ///
+    /// * The boolean is different for each pattern
+    /// * There is only one exit for the arm scope
+    /// * The guard expression scope is too short, it ends just before the
+    ///   boolean is tested.
+    pub fn pop_variable(
+        &mut self,
+        block: BasicBlock,
+        region_scope: region::Scope,
+        variable: Local,
+    ) {
+        let top_scope = self.scopes.last_mut().unwrap();
+
+        assert_eq!(top_scope.region_scope, region_scope);
+
+        let top_drop_data = top_scope.drops.pop().unwrap();
+
+        match top_drop_data.kind {
+            DropKind::Value { .. } => {
+                bug!("Should not be calling pop_top_variable on non-copy type!")
+            }
+            DropKind::Storage => {
+                // Drop the storage for both value and storage drops.
+                // Only temps and vars need their storage dead.
+                match top_drop_data.location {
+                    Place::Base(PlaceBase::Local(index)) => {
+                        let source_info = top_scope.source_info(top_drop_data.span);
+                        assert_eq!(index, variable);
+                        self.cfg.push(block, Statement {
+                            source_info,
+                            kind: StatementKind::StorageDead(index)
+                        });
+                    }
+                    _ => unreachable!(),
+                }
+            }
+        }
+
+        top_scope.invalidate_cache(true, true);
+    }
+
 }
 
 /// Builds drops for pop_scope and exit_scope.
index 4dcfb3f1a7fc32a9d01dda14d6bc64848ab451b3..03d55b84f32e260f38dce78551558c77388c331f 100644 (file)
@@ -11,8 +11,7 @@
 
 use crate::util::elaborate_drops::DropFlagState;
 
-use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex};
-use super::move_paths::{LookupResult, InitKind};
+use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex, InitKind};
 use super::{BitDenotation, BlockSets, InitialFlow};
 
 use super::drop_flag_effects_for_function_entry;
@@ -470,35 +469,13 @@ fn statement_effect(&self,
         sets.gen_all(&init_loc_map[location]);
 
         match stmt.kind {
-            mir::StatementKind::StorageDead(local) |
-            mir::StatementKind::StorageLive(local) => {
-                // End inits for StorageDead and StorageLive, so that an immutable
-                // variable can be reinitialized on the next iteration of the loop.
-                //
-                // FIXME(#46525): We *need* to do this for StorageLive as well as
-                // StorageDead, because lifetimes of match bindings with guards are
-                // weird - i.e., this code
-                //
-                // ```
-                //     fn main() {
-                //         match 0 {
-                //             a | a
-                //             if { println!("a={}", a); false } => {}
-                //             _ => {}
-                //         }
-                //     }
-                // ```
-                //
-                // runs the guard twice, using the same binding for `a`, and only
-                // storagedeads after everything ends, so if we don't regard the
-                // storagelive as killing storage, we would have a multiple assignment
-                // to immutable data error.
-                if let LookupResult::Exact(mpi) =
-                    rev_lookup.find(&mir::Place::Base(mir::PlaceBase::Local(local))) {
-                    debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
-                           stmt, location, &init_path_map[mpi]);
-                    sets.kill_all(&init_path_map[mpi]);
-                }
+            mir::StatementKind::StorageDead(local) => {
+                // End inits for StorageDead, so that an immutable variable can
+                // be reinitialized on the next iteration of the loop.
+                let move_path_index = rev_lookup.find_local(local);
+                debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
+                        stmt, location, &init_path_map[move_path_index]);
+                sets.kill_all(&init_path_map[move_path_index]);
             }
             _ => {}
         }
index 74a4278d5991b1c5f364457d869fe33b4fb91b4d..4807782c66347e55b8321b84b695be61ba6de47e 100644 (file)
@@ -2424,6 +2424,38 @@ const fn foo() -> impl T {
 ```
 "##,
 
+E0729: r##"
+Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler
+since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow
+checker for NLL uncovered some bugs in the old borrow checker, which in some
+cases allowed unsound code to compile, resulting in memory safety issues.
+
+### What do I do?
+
+Change your code so the warning does no longer trigger. For backwards
+compatibility, this unsound code may still compile (with a warning) right now.
+However, at some point in the future, the compiler will no longer accept this
+code and will throw a hard error.
+
+### Shouldn't you fix the old borrow checker?
+
+The old borrow checker has known soundness issues that are basically impossible
+to fix. The new NLL-based borrow checker is the fix.
+
+### Can I turn these warnings into errors by denying a lint?
+
+No.
+
+### When are these warnings going to turn into errors?
+
+No formal timeline for turning the warnings into errors has been set. See
+[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more
+information.
+
+### Why do I get this message with code that doesn't involve borrowing?
+
+There are some known bugs that trigger this message.
+"##,
 }
 
 register_diagnostics! {
index 50140880a368df329bdbf08b35f3cb833cffb9a4..d623f149988c7aed7893e9d1cc9614f7d26c9013 100644 (file)
@@ -879,8 +879,12 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm)
                 _ => None,
             },
         body: arm.body.to_ref(),
-        // BUG: fix this
-        lint_level: LintLevel::Inherited,
+        lint_level: LintLevel::Explicit(arm.hir_id),
+        scope: region::Scope {
+            id: arm.hir_id.local_id,
+            data: region::ScopeData::Node
+        },
+        span: arm.span,
     }
 }
 
index d4f139e103a641a12d665f0e8cf05ec2e96f0255..8e19913f4df26d30ab8611cef310842cce27677f 100644 (file)
@@ -31,15 +31,6 @@ pub enum LintLevel {
     Explicit(hir::HirId)
 }
 
-impl LintLevel {
-    pub fn is_explicit(self) -> bool {
-        match self {
-            LintLevel::Inherited => false,
-            LintLevel::Explicit(_) => true
-        }
-    }
-}
-
 #[derive(Clone, Debug)]
 pub struct Block<'tcx> {
     pub targeted_by_break: bool,
@@ -311,6 +302,8 @@ pub struct Arm<'tcx> {
     pub guard: Option<Guard<'tcx>>,
     pub body: ExprRef<'tcx>,
     pub lint_level: LintLevel,
+    pub scope: region::Scope,
+    pub span: Span,
 }
 
 #[derive(Clone, Debug)]
index 84e2caec68e1ccfb58137f46a390a3674ffab453..12357cb10a991bfae20895b513bfa40ef7bdd0b4 100644 (file)
@@ -930,58 +930,60 @@ fn visit_place(&mut self,
                     context: PlaceContext,
                     location: Location) {
         debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
-        self.super_place(place, context, location);
-        match *place {
-            Place::Base(PlaceBase::Local(_)) => {}
-            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
-                unreachable!()
-            }
-            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
-                if self.tcx
-                       .get_attrs(def_id)
-                       .iter()
-                       .any(|attr| attr.check_name(sym::thread_local)) {
-                    if self.mode != Mode::Fn {
-                        span_err!(self.tcx.sess, self.span, E0625,
-                                  "thread-local statics cannot be \
-                                   accessed at compile-time");
-                    }
-                    return;
+        place.iterate(|place_base, place_projections| {
+            match place_base {
+                PlaceBase::Local(_) => {}
+                PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => {
+                    unreachable!()
                 }
+                PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
+                    if self.tcx
+                           .get_attrs(*def_id)
+                           .iter()
+                           .any(|attr| attr.check_name(sym::thread_local)) {
+                        if self.mode != Mode::Fn {
+                            span_err!(self.tcx.sess, self.span, E0625,
+                                      "thread-local statics cannot be \
+                                       accessed at compile-time");
+                        }
+                        return;
+                    }
 
-                // Only allow statics (not consts) to refer to other statics.
-                if self.mode == Mode::Static || self.mode == Mode::StaticMut {
-                    if self.mode == Mode::Static && context.is_mutating_use() {
-                        // this is not strictly necessary as miri will also bail out
-                        // For interior mutability we can't really catch this statically as that
-                        // goes through raw pointers and intermediate temporaries, so miri has
-                        // to catch this anyway
-                        self.tcx.sess.span_err(
-                            self.span,
-                            "cannot mutate statics in the initializer of another static",
-                        );
+                    // Only allow statics (not consts) to refer to other statics.
+                    if self.mode == Mode::Static || self.mode == Mode::StaticMut {
+                        if self.mode == Mode::Static && context.is_mutating_use() {
+                            // this is not strictly necessary as miri will also bail out
+                            // For interior mutability we can't really catch this statically as that
+                            // goes through raw pointers and intermediate temporaries, so miri has
+                            // to catch this anyway
+                            self.tcx.sess.span_err(
+                                self.span,
+                                "cannot mutate statics in the initializer of another static",
+                            );
+                        }
+                        return;
                     }
-                    return;
-                }
-                unleash_miri!(self);
+                    unleash_miri!(self);
 
-                if self.mode != Mode::Fn {
-                    let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
-                                                   "{}s cannot refer to statics, use \
-                                                    a constant instead", self.mode);
-                    if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                        err.note(
-                            "Static and const variables can refer to other const variables. But a \
-                             const variable cannot refer to a static variable."
-                        );
-                        err.help(
-                            "To fix this, the value can be extracted as a const and then used."
-                        );
+                    if self.mode != Mode::Fn {
+                        let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
+                                                       "{}s cannot refer to statics, use \
+                                                        a constant instead", self.mode);
+                        if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                            err.note(
+                                "Static and const variables can refer to other const variables. \
+                                 But a const variable cannot refer to a static variable."
+                            );
+                            err.help(
+                                "To fix this, the value can be extracted as a const and then used."
+                            );
+                        }
+                        err.emit()
                     }
-                    err.emit()
                 }
             }
-            Place::Projection(ref proj) => {
+
+            for proj in place_projections {
                 match proj.elem {
                     ProjectionElem::Deref => {
                         if context.is_mutating_use() {
@@ -1041,7 +1043,7 @@ fn visit_place(&mut self,
                     }
                 }
             }
-        }
+        });
     }
 
     fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
index 2bea1db841ae918db916e9e2ba15f6f67255ddf9..3091570d14802b48b448f083969b20b964911fdd 100644 (file)
@@ -15,7 +15,7 @@
 use syntax::ast::*;
 use syntax::attr;
 use syntax::source_map::Spanned;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax::ptr::P;
 use syntax::visit::{self, Visitor};
 use syntax::{span_err, struct_span_err, walk_list};
@@ -177,9 +177,9 @@ fn err_handler(&self) -> &errors::Handler {
     }
 
     fn check_lifetime(&self, ident: Ident) {
-        let valid_names = [keywords::UnderscoreLifetime.name(),
-                           keywords::StaticLifetime.name(),
-                           keywords::Invalid.name()];
+        let valid_names = [kw::UnderscoreLifetime,
+                           kw::StaticLifetime,
+                           kw::Invalid];
         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
             self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
         }
index c74314ce0c4b509aea306cc743dc09def8520249..0088c97679c6666f13e1d05731a1cdf2ebfb3779 100644 (file)
@@ -149,7 +149,7 @@ fn visit_stmt(&mut self, s: &'v hir::Stmt) {
     }
 
     fn visit_arm(&mut self, a: &'v hir::Arm) {
-        self.record("Arm", Id::None, a);
+        self.record("Arm", Id::Node(a.hir_id), a);
         hir_visit::walk_arm(self, a)
     }
 
index 680bdcc4bbe9763f687b3c97685198f8705500ff..46cd66fe58546d0ae79df7a3fb0d24f5ef9dee82 100644 (file)
@@ -11,7 +11,7 @@
 use std::path::PathBuf;
 use syntax::ast;
 use syntax::span_err;
-use syntax::symbol::{Symbol, keywords, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax_pos::{Span, DUMMY_SP};
 
 /// Pointer to a registrar function.
@@ -58,7 +58,7 @@ pub fn load_plugins(sess: &Session,
             for plugin in plugins {
                 // plugins must have a name and can't be key = value
                 let name = plugin.name_or_empty();
-                if name != keywords::Invalid.name() && !plugin.is_value_str() {
+                if name != kw::Invalid && !plugin.is_value_str() {
                     let args = plugin.meta_item_list().map(ToOwned::to_owned);
                     loader.load_plugin(plugin.span(), name, args.unwrap_or_default());
                 } else {
index cd21713cddf97364da7657f09c16a375b416f452..65b6a89aa0b4d4225cd98e14e44144f42d73feb3 100644 (file)
 use rustc::ty::subst::InternalSubsts;
 use rustc::util::nodemap::HirIdSet;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::Lrc;
 use syntax::ast::Ident;
 use syntax::attr;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax_pos::Span;
 
 use std::{cmp, fmt, mem};
@@ -67,7 +66,7 @@ fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool {
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
         self.skeleton().visit_trait(trait_ref)
     }
-    fn visit_predicates(&mut self, predicates: Lrc<ty::GenericPredicates<'tcx>>) -> bool {
+    fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool {
         self.skeleton().visit_predicates(predicates)
     }
 }
@@ -89,8 +88,8 @@ fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
         (!self.def_id_visitor.shallow() && substs.visit_with(self))
     }
 
-    fn visit_predicates(&mut self, predicates: Lrc<ty::GenericPredicates<'tcx>>) -> bool {
-        let ty::GenericPredicates { parent: _, predicates } = &*predicates;
+    fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool {
+        let ty::GenericPredicates { parent: _, predicates } = predicates;
         for (predicate, _span) in predicates {
             match predicate {
                 ty::Predicate::Trait(poly_predicate) => {
@@ -844,7 +843,7 @@ fn check_field(&mut self,
                    span: Span, // span of the field pattern, e.g., `x: 0`
                    def: &'tcx ty::AdtDef, // definition of the struct or enum
                    field: &'tcx ty::FieldDef) { // definition of the field
-        let ident = Ident::new(keywords::Invalid.name(), use_ctxt);
+        let ident = Ident::new(kw::Invalid, use_ctxt);
         let current_hir = self.current_item;
         let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1;
         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
@@ -1851,7 +1850,7 @@ fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
 fn privacy_access_levels<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     krate: CrateNum,
-) -> Lrc<AccessLevels> {
+) -> &'tcx AccessLevels {
     assert_eq!(krate, LOCAL_CRATE);
 
     // Build up a set of all exported items in the AST. This is a set of all
@@ -1872,7 +1871,7 @@ fn privacy_access_levels<'tcx>(
     }
     visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
 
-    Lrc::new(visitor.access_levels)
+    tcx.arena.alloc(visitor.access_levels)
 }
 
 fn check_private_in_public<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
index 3b58a99d19fe00b8389af4716511bd535327ec32..8c516a4da4e5fca9b7055c3e0b7f01b3be70e34e 100644 (file)
@@ -37,7 +37,7 @@
 use syntax::parse::token::{self, Token};
 use syntax::span_err;
 use syntax::std_inject::injected_crate_name;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -143,7 +143,7 @@ fn build_reduced_graph_for_use_tree(
             }
             _ => None,
         }.map(|ctxt| Segment::from_ident(Ident::new(
-            keywords::PathRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt)
+            kw::PathRoot, use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt)
         )));
 
         let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
@@ -151,7 +151,7 @@ fn build_reduced_graph_for_use_tree(
 
         let empty_for_self = |prefix: &[Segment]| {
             prefix.is_empty() ||
-            prefix.len() == 1 && prefix[0].ident.name == keywords::PathRoot.name()
+            prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot
         };
         match use_tree.kind {
             ast::UseTreeKind::Simple(rename, ..) => {
@@ -162,7 +162,7 @@ fn build_reduced_graph_for_use_tree(
 
                 if nested {
                     // Correctly handle `self`
-                    if source.ident.name == keywords::SelfLower.name() {
+                    if source.ident.name == kw::SelfLower {
                         type_ns_only = true;
 
                         if empty_for_self(&module_path) {
@@ -183,14 +183,14 @@ fn build_reduced_graph_for_use_tree(
                     }
                 } else {
                     // Disallow `self`
-                    if source.ident.name == keywords::SelfLower.name() {
+                    if source.ident.name == kw::SelfLower {
                         resolve_error(self,
                                       use_tree.span,
                                       ResolutionError::SelfImportsOnlyAllowedWithin);
                     }
 
                     // Disallow `use $crate;`
-                    if source.ident.name == keywords::DollarCrate.name() && module_path.is_empty() {
+                    if source.ident.name == kw::DollarCrate && module_path.is_empty() {
                         let crate_root = self.resolve_crate_root(source.ident);
                         let crate_name = match crate_root.kind {
                             ModuleKind::Def(.., name) => name,
@@ -199,11 +199,11 @@ fn build_reduced_graph_for_use_tree(
                         // HACK(eddyb) unclear how good this is, but keeping `$crate`
                         // in `source` breaks `src/test/compile-fail/import-crate-var.rs`,
                         // while the current crate doesn't have a valid `crate_name`.
-                        if crate_name != keywords::Invalid.name() {
+                        if crate_name != kw::Invalid {
                             // `crate_name` should not be interpreted as relative.
                             module_path.push(Segment {
                                 ident: Ident {
-                                    name: keywords::PathRoot.name(),
+                                    name: kw::PathRoot,
                                     span: source.ident.span,
                                 },
                                 id: Some(self.session.next_node_id()),
@@ -221,7 +221,7 @@ fn build_reduced_graph_for_use_tree(
                     }
                 }
 
-                if ident.name == keywords::Crate.name() {
+                if ident.name == kw::Crate {
                     self.session.span_err(ident.span,
                         "crate root imports need to be explicitly named: \
                          `use crate as name;`");
@@ -276,7 +276,7 @@ fn build_reduced_graph_for_use_tree(
                 // Ensure there is at most one `self` in the list
                 let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
                     if let ast::UseTreeKind::Simple(..) = use_tree.kind {
-                        if use_tree.ident().name == keywords::SelfLower.name() {
+                        if use_tree.ident().name == kw::SelfLower {
                             return Some(use_tree.span);
                         }
                     }
@@ -311,7 +311,7 @@ fn build_reduced_graph_for_use_tree(
                     let new_span = prefix[prefix.len() - 1].ident.span;
                     let tree = ast::UseTree {
                         prefix: ast::Path::from_ident(
-                            Ident::new(keywords::SelfLower.name(), new_span)
+                            Ident::new(kw::SelfLower, new_span)
                         ),
                         kind: ast::UseTreeKind::Simple(
                             Some(Ident::from_str_and_span("__dummy", new_span).gensym()),
@@ -350,7 +350,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
             }
 
             ItemKind::ExternCrate(orig_name) => {
-                let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() {
+                let module = if orig_name.is_none() && ident.name == kw::SelfLower {
                     self.session
                         .struct_span_err(item.span, "`extern crate self;` requires renaming")
                         .span_suggestion(
@@ -361,7 +361,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
                         )
                         .emit();
                     return;
-                } else if orig_name == Some(keywords::SelfLower.name()) {
+                } else if orig_name == Some(kw::SelfLower) {
                     self.graph_root
                 } else {
                     let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
@@ -420,7 +420,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
 
             ItemKind::GlobalAsm(..) => {}
 
-            ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root
+            ItemKind::Mod(..) if ident.name == kw::Invalid => {} // Crate root
 
             ItemKind::Mod(..) => {
                 let def_id = self.definitions.local_def_id(item.id);
@@ -831,7 +831,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>,
                         "an `extern crate` loading macros must be at the crate root");
                 }
                 if let ItemKind::ExternCrate(Some(orig_name)) = item.node {
-                    if orig_name == keywords::SelfLower.name() {
+                    if orig_name == kw::SelfLower {
                         self.session.span_err(attr.span,
                             "`macro_use` is not supported on `extern crate self`");
                     }
index 509aa95bb61dfc38ffff8f817caf5cb2bdaba6d1..8b5e2b86d5ee8025804b1c4b802497e0833759fb 100644 (file)
@@ -7,7 +7,7 @@
 use rustc::session::{Session, config::nightly_options};
 use syntax::ast::{self, Expr, ExprKind, Ident};
 use syntax::ext::base::MacroKind;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::{Symbol, kw};
 use syntax_pos::{BytePos, Span};
 
 type Res = def::Res<ast::NodeId>;
@@ -48,7 +48,7 @@ pub(crate) fn smart_resolve_report_errors(
             let item_span = path.last().unwrap().ident.span;
             let (mod_prefix, mod_str) = if path.len() == 1 {
                 (String::new(), "this scope".to_string())
-            } else if path.len() == 2 && path[0].ident.name == keywords::PathRoot.name() {
+            } else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
                 (String::new(), "the crate root".to_string())
             } else {
                 let mod_path = &path[..path.len() - 1];
@@ -454,13 +454,13 @@ pub(crate) fn make_path_suggestion(
         match (path.get(0), path.get(1)) {
             // `{{root}}::ident::...` on both editions.
             // On 2015 `{{root}}` is usually added implicitly.
-            (Some(fst), Some(snd)) if fst.ident.name == keywords::PathRoot.name() &&
+            (Some(fst), Some(snd)) if fst.ident.name == kw::PathRoot &&
                                       !snd.ident.is_path_segment_keyword() => {}
             // `ident::...` on 2018.
             (Some(fst), _) if fst.ident.span.rust_2018() &&
                               !fst.ident.is_path_segment_keyword() => {
                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
-                path.insert(0, Segment::from_ident(keywords::Invalid.ident()));
+                path.insert(0, Segment::from_ident(Ident::invalid()));
             }
             _ => return None,
         }
@@ -485,7 +485,7 @@ fn make_missing_self_suggestion(
         parent_scope: &ParentScope<'b>,
     ) -> Option<(Vec<Segment>, Vec<String>)> {
         // Replace first ident with `self` and check if that is valid.
-        path[0].ident.name = keywords::SelfLower.name();
+        path[0].ident.name = kw::SelfLower;
         let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
         debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
         if let PathResult::Module(..) = result {
@@ -509,7 +509,7 @@ fn make_missing_crate_suggestion(
         parent_scope: &ParentScope<'b>,
     ) -> Option<(Vec<Segment>, Vec<String>)> {
         // Replace first ident with `crate` and check if that is valid.
-        path[0].ident.name = keywords::Crate.name();
+        path[0].ident.name = kw::Crate;
         let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
         debug!("make_missing_crate_suggestion:  path={:?} result={:?}", path, result);
         if let PathResult::Module(..) = result {
@@ -540,7 +540,7 @@ fn make_missing_super_suggestion(
         parent_scope: &ParentScope<'b>,
     ) -> Option<(Vec<Segment>, Vec<String>)> {
         // Replace first ident with `crate` and check if that is valid.
-        path[0].ident.name = keywords::Super.name();
+        path[0].ident.name = kw::Super;
         let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
         debug!("make_missing_super_suggestion:  path={:?} result={:?}", path, result);
         if let PathResult::Module(..) = result {
index c4a4dd306055bb92db05298eebe2bba46db2ef20..a7097a9475ede1bee0879ad74eb7a80898848adf 100644 (file)
@@ -43,7 +43,7 @@
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::base::MacroKind;
-use syntax::symbol::{Symbol, keywords, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use syntax::visit::{self, FnKind, Visitor};
@@ -820,7 +820,7 @@ fn visit_ty(&mut self, ty: &'tcx Ty) {
                 self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
             }
             TyKind::ImplicitSelf => {
-                let self_ty = keywords::SelfUpper.ident();
+                let self_ty = Ident::with_empty_ctxt(kw::SelfUpper);
                 let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span)
                               .map_or(Res::Err, |d| d.res());
                 self.record_partial_res(ty.id, PartialRes::new(res));
@@ -1817,18 +1817,17 @@ fn resolve_str_path(
         is_value: bool
     ) -> hir::Path {
         let root = if crate_root.is_some() {
-            keywords::PathRoot
+            kw::PathRoot
         } else {
-            keywords::Crate
+            kw::Crate
         };
-        let segments = iter::once(root.ident())
+        let segments = iter::once(Ident::with_empty_ctxt(root))
             .chain(
                 crate_root.into_iter()
                     .chain(components.iter().cloned())
                     .map(Ident::with_empty_ctxt)
             ).map(|i| self.new_ast_path_segment(i)).collect::<Vec<_>>();
 
-
         let path = ast::Path {
             span,
             segments,
@@ -1866,7 +1865,7 @@ pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: b
         let path = if path_str.starts_with("::") {
             ast::Path {
                 span,
-                segments: iter::once(keywords::PathRoot.ident())
+                segments: iter::once(Ident::with_empty_ctxt(kw::PathRoot))
                     .chain({
                         path_str.split("::").skip(1).map(Ident::from_str)
                     })
@@ -1961,7 +1960,7 @@ pub fn new(session: &'a Session,
         let root_module_kind = ModuleKind::Def(
             DefKind::Mod,
             root_def_id,
-            keywords::Invalid.name(),
+            kw::Invalid,
         );
         let graph_root = arenas.alloc_module(ModuleData {
             no_implicit_prelude: attr::contains_name(&krate.attrs, sym::no_implicit_prelude),
@@ -2187,10 +2186,10 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                       path_span: Span)
                                       -> Option<LexicalScopeBinding<'a>> {
         assert!(ns == TypeNS  || ns == ValueNS);
-        if ident.name == keywords::Invalid.name() {
+        if ident.name == kw::Invalid {
             return Some(LexicalScopeBinding::Res(Res::Err));
         }
-        ident.span = if ident.name == keywords::SelfUpper.name() {
+        ident.span = if ident.name == kw::SelfUpper {
             // FIXME(jseyfried) improve `Self` hygiene
             ident.span.with_ctxt(SyntaxContext::empty())
         } else if ns == TypeNS {
@@ -2405,7 +2404,7 @@ fn resolve_ident_in_module_ext(
 
     fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
         let mut ctxt = ident.span.ctxt();
-        let mark = if ident.name == keywords::DollarCrate.name() {
+        let mark = if ident.name == kw::DollarCrate {
             // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
             // we don't want to pretend that the `macro_rules!` definition is in the `macro`
             // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
@@ -2851,7 +2850,7 @@ fn with_self_rib<F>(&mut self, self_res: Res, f: F)
         let mut self_type_rib = Rib::new(NormalRibKind);
 
         // Plain insert (no renaming, since types are not currently hygienic)
-        self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_res);
+        self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
         self.ribs[TypeNS].push(self_type_rib);
         f(self);
         self.ribs[TypeNS].pop();
@@ -2862,7 +2861,7 @@ fn with_self_struct_ctor_rib<F>(&mut self, impl_id: DefId, f: F)
     {
         let self_res = Res::SelfCtor(impl_id);
         let mut self_type_rib = Rib::new(NormalRibKind);
-        self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_res);
+        self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
         self.ribs[ValueNS].push(self_type_rib);
         f(self);
         self.ribs[ValueNS].pop();
@@ -3199,7 +3198,7 @@ fn fresh_binding(&mut self,
             }
             None => {
                 // A completely fresh binding, add to the lists if it's valid.
-                if ident.name != keywords::Invalid.name() {
+                if ident.name != kw::Invalid {
                     bindings.insert(ident, outer_pat_id);
                     self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, res);
                 }
@@ -3494,13 +3493,13 @@ fn type_ascription_suggestion(
     }
 
     fn self_type_is_available(&mut self, span: Span) -> bool {
-        let binding = self.resolve_ident_in_lexical_scope(keywords::SelfUpper.ident(),
+        let binding = self.resolve_ident_in_lexical_scope(Ident::with_empty_ctxt(kw::SelfUpper),
                                                           TypeNS, None, span);
         if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
     }
 
     fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool {
-        let ident = Ident::new(keywords::SelfLower.name(), self_span);
+        let ident = Ident::new(kw::SelfLower, self_span);
         let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span);
         if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
     }
@@ -3657,8 +3656,8 @@ fn resolve_qpath(
         };
 
         if path.len() > 1 && !global_by_default && result.base_res() != Res::Err &&
-           path[0].ident.name != keywords::PathRoot.name() &&
-           path[0].ident.name != keywords::DollarCrate.name() {
+           path[0].ident.name != kw::PathRoot &&
+           path[0].ident.name != kw::DollarCrate {
             let unqualified_result = {
                 match self.resolve_path_without_parent_scope(
                     &[*path.last().unwrap()],
@@ -3739,11 +3738,11 @@ fn resolve_path(
             let name = ident.name;
 
             allow_super &= ns == TypeNS &&
-                (name == keywords::SelfLower.name() ||
-                 name == keywords::Super.name());
+                (name == kw::SelfLower ||
+                 name == kw::Super);
 
             if ns == TypeNS {
-                if allow_super && name == keywords::Super.name() {
+                if allow_super && name == kw::Super {
                     let mut ctxt = ident.span.ctxt().modern();
                     let self_module = match i {
                         0 => Some(self.resolve_self(&mut ctxt, self.current_module)),
@@ -3768,25 +3767,25 @@ fn resolve_path(
                     };
                 }
                 if i == 0 {
-                    if name == keywords::SelfLower.name() {
+                    if name == kw::SelfLower {
                         let mut ctxt = ident.span.ctxt().modern();
                         module = Some(ModuleOrUniformRoot::Module(
                             self.resolve_self(&mut ctxt, self.current_module)));
                         continue;
                     }
-                    if name == keywords::PathRoot.name() && ident.span.rust_2018() {
+                    if name == kw::PathRoot && ident.span.rust_2018() {
                         module = Some(ModuleOrUniformRoot::ExternPrelude);
                         continue;
                     }
-                    if name == keywords::PathRoot.name() &&
+                    if name == kw::PathRoot &&
                        ident.span.rust_2015() && self.session.rust_2018() {
                         // `::a::b` from 2015 macro on 2018 global edition
                         module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
                         continue;
                     }
-                    if name == keywords::PathRoot.name() ||
-                       name == keywords::Crate.name() ||
-                       name == keywords::DollarCrate.name() {
+                    if name == kw::PathRoot ||
+                       name == kw::Crate ||
+                       name == kw::DollarCrate {
                         // `::a::b`, `crate::a::b` or `$crate::a::b`
                         module = Some(ModuleOrUniformRoot::Module(
                             self.resolve_crate_root(ident)));
@@ -3797,12 +3796,12 @@ fn resolve_path(
 
             // Report special messages for path segment keywords in wrong positions.
             if ident.is_path_segment_keyword() && i != 0 {
-                let name_str = if name == keywords::PathRoot.name() {
+                let name_str = if name == kw::PathRoot {
                     "crate root".to_string()
                 } else {
                     format!("`{}`", name)
                 };
-                let label = if i == 1 && path[0].ident.name == keywords::PathRoot.name() {
+                let label = if i == 1 && path[0].ident.name == kw::PathRoot {
                     format!("global paths cannot start with {}", name_str)
                 } else {
                     format!("{} in paths can only be used in start position", name_str)
@@ -3971,13 +3970,13 @@ fn lint_if_path_starts_with_module(
 
         // We're only interested in `use` paths which should start with
         // `{{root}}` currently.
-        if first_name != keywords::PathRoot.name() {
+        if first_name != kw::PathRoot {
             return
         }
 
         match path.get(1) {
             // If this import looks like `crate::...` it's already good
-            Some(Segment { ident, .. }) if ident.name == keywords::Crate.name() => return,
+            Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
             // Otherwise go below to see if it's an extern crate
             Some(_) => {}
             // If the path has length one (and it's `PathRoot` most likely)
@@ -4670,7 +4669,7 @@ fn lookup_import_candidates_from_module<FilterFn>(&mut self,
     {
         let mut candidates = Vec::new();
         let mut seen_modules = FxHashSet::default();
-        let not_local_module = crate_name != keywords::Crate.ident();
+        let not_local_module = crate_name.name != kw::Crate;
         let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
 
         while let Some((in_module,
@@ -4764,7 +4763,8 @@ fn lookup_import_candidates<FilterFn>(&mut self,
         where FilterFn: Fn(Res) -> bool
     {
         let mut suggestions = self.lookup_import_candidates_from_module(
-            lookup_ident, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn);
+            lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn
+        );
 
         if lookup_ident.span.rust_2018() {
             let extern_prelude_names = self.extern_prelude.clone();
@@ -4883,7 +4883,7 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                 } else {
                     let ctxt = ident.span.ctxt();
                     Some(Segment::from_ident(Ident::new(
-                        keywords::PathRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt)
+                        kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt)
                     )))
                 };
 
@@ -5352,17 +5352,17 @@ fn extern_prelude_get(&mut self, ident: Ident, speculative: bool)
 }
 
 fn is_self_type(path: &[Segment], namespace: Namespace) -> bool {
-    namespace == TypeNS && path.len() == 1 && path[0].ident.name == keywords::SelfUpper.name()
+    namespace == TypeNS && path.len() == 1 && path[0].ident.name == kw::SelfUpper
 }
 
 fn is_self_value(path: &[Segment], namespace: Namespace) -> bool {
-    namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfLower.name()
+    namespace == ValueNS && path.len() == 1 && path[0].ident.name == kw::SelfLower
 }
 
 fn names_to_string(idents: &[Ident]) -> String {
     let mut result = String::new();
     for (i, ident) in idents.iter()
-                            .filter(|ident| ident.name != keywords::PathRoot.name())
+                            .filter(|ident| ident.name != kw::PathRoot)
                             .enumerate() {
         if i > 0 {
             result.push_str("::");
index d07f7b65275f19f3ac3f6e80083dd49b2d89d276..9bb607a2cc28f54c7e9c5204e1cb6ede42071ac4 100644 (file)
@@ -22,7 +22,7 @@
 use syntax::feature_gate::{
     feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES,
 };
-use syntax::symbol::{Symbol, keywords, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax::visit::Visitor;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{Span, DUMMY_SP};
@@ -137,10 +137,10 @@ struct ResolveDollarCrates<'a, 'b: 'a> {
         }
         impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
             fn visit_ident(&mut self, ident: Ident) {
-                if ident.name == keywords::DollarCrate.name() {
+                if ident.name == kw::DollarCrate {
                     let name = match self.resolver.resolve_crate_root(ident).kind {
-                        ModuleKind::Def(.., name) if name != keywords::Invalid.name() => name,
-                        _ => keywords::Crate.name(),
+                        ModuleKind::Def(.., name) if name != kw::Invalid => name,
+                        _ => kw::Crate,
                     };
                     ident.span.ctxt().set_dollar_crate_name(name);
                 }
@@ -415,7 +415,7 @@ pub fn resolve_macro_to_res_inner(
         if kind == MacroKind::Bang && path.len() == 1 &&
            path[0].ident.span.ctxt().outer().expn_info()
                .map_or(false, |info| info.local_inner_macros) {
-            let root = Ident::new(keywords::DollarCrate.name(), path[0].ident.span);
+            let root = Ident::new(kw::DollarCrate, path[0].ident.span);
             path.insert(0, Segment::from_ident(root));
         }
 
@@ -613,7 +613,7 @@ struct Flags: u8 {
                     _ => Err(Determinacy::Determined),
                 }
                 WhereToResolve::CrateRoot => {
-                    let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
+                    let root_ident = Ident::new(kw::PathRoot, orig_ident.span);
                     let root_module = self.resolve_crate_root(root_ident);
                     let binding = self.resolve_ident_in_module_ext(
                         ModuleOrUniformRoot::Module(root_module),
index 3a6a8b56ff35d875b695f8d2c644ddaec78be745..c0ff7b310b5815e0a6d9767f63b5e02e91cf6137 100644 (file)
@@ -29,7 +29,7 @@
 use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::{struct_span_err, unwrap_or};
 use syntax_pos::{MultiSpan, Span};
@@ -217,15 +217,15 @@ fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
                     parent_scope.expect("no parent scope for a single-segment import");
 
                 if ns == TypeNS {
-                    if ident.name == keywords::Crate.name() ||
-                        ident.name == keywords::DollarCrate.name() {
+                    if ident.name == kw::Crate ||
+                        ident.name == kw::DollarCrate {
                         let module = self.resolve_crate_root(ident);
                         let binding = (module, ty::Visibility::Public,
                                         module.span, Mark::root())
                                         .to_name_binding(self.arenas);
                         return Ok(binding);
-                    } else if ident.name == keywords::Super.name() ||
-                                ident.name == keywords::SelfLower.name() {
+                    } else if ident.name == kw::Super ||
+                                ident.name == kw::SelfLower {
                         // FIXME: Implement these with renaming requirements so that e.g.
                         // `use super;` doesn't work, but `use super as name;` does.
                         // Fall through here to get an error from `early_resolve_...`.
@@ -707,7 +707,7 @@ pub fn finalize_imports(&mut self) {
                 has_errors = true;
 
                 if let SingleImport { source, ref source_bindings, .. } = import.subclass {
-                    if source.name == keywords::SelfLower.name() {
+                    if source.name == kw::SelfLower {
                         // Silence `unresolved import` error if E0429 is already emitted
                         if let Err(Determined) = source_bindings.value_ns.get() {
                             continue;
@@ -992,7 +992,7 @@ fn finalize_import(
                     // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
                     // 2 segments, so the `resolve_path` above won't trigger it.
                     let mut full_path = directive.module_path.clone();
-                    full_path.push(Segment::from_ident(keywords::Invalid.ident()));
+                    full_path.push(Segment::from_ident(Ident::invalid()));
                     self.lint_if_path_starts_with_module(
                         directive.crate_lint(),
                         &full_path,
@@ -1484,8 +1484,8 @@ fn import_path_to_string(names: &[Ident],
                          subclass: &ImportDirectiveSubclass<'_>,
                          span: Span) -> String {
     let pos = names.iter()
-        .position(|p| span == p.span && p.name != keywords::PathRoot.name());
-    let global = !names.is_empty() && names[0].name == keywords::PathRoot.name();
+        .position(|p| span == p.span && p.name != kw::PathRoot);
+    let global = !names.is_empty() && names[0].name == kw::PathRoot;
     if let Some(pos) = pos {
         let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
         names_to_string(names)
index d34f5633946bfa281773da81d21cab2b44013bcc..55471dbc00be5c75a3dfbdbd8bd3b8ba8966078f 100644 (file)
@@ -24,7 +24,6 @@
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
-use rustc_data_structures::sync::Lrc;
 
 use std::cell::Cell;
 use std::default::Default;
@@ -110,8 +109,8 @@ pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
         let mut result = Vec::with_capacity(self.tcx.crates().len());
 
         for &n in self.tcx.crates().iter() {
-            let span = match *self.tcx.extern_crate(n.as_def_id()) {
-                Some(ExternCrate { span, .. }) => span,
+            let span = match self.tcx.extern_crate(n.as_def_id()) {
+                Some(&ExternCrate { span, .. }) => span,
                 None => {
                     debug!("Skipping crate {}, no data", n);
                     continue;
@@ -1120,7 +1119,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
         // fallback in case the access levels couldn't have been correctly computed.
         let access_levels = match tcx.sess.compile_status() {
             Ok(..) => tcx.privacy_access_levels(LOCAL_CRATE),
-            Err(..) => Lrc::new(AccessLevels::default()),
+            Err(..) => tcx.arena.alloc(AccessLevels::default()),
         };
 
         let save_ctxt = SaveContext {
index 4110a55840196e950e694b40e9f07b2bba74231b..3a2b0178ce4d099c525ea7457ed1bc3bc7bb5737 100644 (file)
@@ -17,7 +17,6 @@
 use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
 use rustc::ty::wf::object_region_bounds;
 use rustc::mir::interpret::ConstValue;
-use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi;
 use crate::require_c_abi_if_c_variadic;
 use smallvec::SmallVec;
@@ -46,7 +45,7 @@ pub trait AstConv<'gcx, 'tcx> {
     /// Returns the set of bounds in scope for the type parameter with
     /// the given id.
     fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
-                                 -> Lrc<ty::GenericPredicates<'tcx>>;
+                                 -> &'tcx ty::GenericPredicates<'tcx>;
 
     /// What lifetime should we use when a lifetime is omitted (and not elided)?
     fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>)
index a69f639e8941f51d3aca9290fd553f7b7e27551b..e4b431e6e68f17bc653196b4818d043680b3d13c 100644 (file)
@@ -540,7 +540,7 @@ fn borrow_pat_suggestion(
                         err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
                     }
                 }
-                hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
+                hir::Node::Arm(_) |
                 hir::Node::Pat(_) => {
                     // rely on match ergonomics or it might be nested `&&pat`
                     if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
@@ -781,14 +781,17 @@ fn if_fallback_coercion(
     fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
         use hir::Node::{Block, Item, Local};
 
-        let node = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_node_by_hir_id(
-            self.tcx.hir().get_parent_node_by_hir_id(hir_id),
-        ));
+        let hir = self.tcx.hir();
+        let arm_id = hir.get_parent_node_by_hir_id(hir_id);
+        let match_id = hir.get_parent_node_by_hir_id(arm_id);
+        let containing_id = hir.get_parent_node_by_hir_id(match_id);
+
+        let node = hir.get_by_hir_id(containing_id);
         if let Block(block) = node {
             // check that the body's parent is an fn
-            let parent = self.tcx.hir().get_by_hir_id(
-                self.tcx.hir().get_parent_node_by_hir_id(
-                    self.tcx.hir().get_parent_node_by_hir_id(block.hir_id),
+            let parent = hir.get_by_hir_id(
+                hir.get_parent_node_by_hir_id(
+                    hir.get_parent_node_by_hir_id(block.hir_id),
                 ),
             );
             if let (Some(expr), Item(hir::Item {
index 77d2ffab8efb4e1bb32c8b9a64f52afe2c9b10f8..dfe21edee41f3fb629f05580f2b477971f21a1c5 100644 (file)
@@ -6,7 +6,6 @@
 use crate::namespace::Namespace;
 use crate::util::nodemap::FxHashSet;
 use errors::{Applicability, DiagnosticBuilder};
-use rustc_data_structures::sync::Lrc;
 use rustc::hir::{self, ExprKind, Node, QPath};
 use rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
@@ -844,7 +843,7 @@ fn handle_external_res(tcx: TyCtxt<'_, '_, '_>,
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
     providers.all_traits = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
-        Lrc::new(compute_all_traits(tcx))
+        &tcx.arena.alloc(compute_all_traits(tcx))[..]
     }
 }
 
index 362b6f0504d99aed306f7bba354acad944a04182..655bf5722ae5af7eb2959a3790d34286178343ff 100644 (file)
@@ -97,7 +97,6 @@
 use rustc::infer::{self, InferCtxt, InferOk, InferResult};
 use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi::Abi;
 use rustc::infer::opaque_types::OpaqueTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::ptr::P;
 use syntax::source_map::{DUMMY_SP, original_sp};
-use syntax::symbol::{Symbol, LocalInternedString, keywords, sym};
+use syntax::symbol::{Symbol, LocalInternedString, kw, sym};
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use std::cell::{Cell, RefCell, Ref, RefMut};
@@ -808,8 +807,8 @@ fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 fn used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 def_id: DefId)
-                                -> Lrc<DefIdSet> {
-    tcx.typeck_tables_of(def_id).used_trait_imports.clone()
+                                -> &'tcx DefIdSet {
+    &*tcx.typeck_tables_of(def_id).used_trait_imports
 }
 
 fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -1907,7 +1906,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
-                                 -> Lrc<ty::GenericPredicates<'tcx>>
+                                 -> &'tcx ty::GenericPredicates<'tcx>
     {
         let tcx = self.tcx;
         let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -1915,7 +1914,7 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
         let item_def_id = tcx.hir().local_def_id_from_hir_id(item_id);
         let generics = tcx.generics_of(item_def_id);
         let index = generics.param_def_id_to_index[&def_id];
-        Lrc::new(ty::GenericPredicates {
+        tcx.arena.alloc(ty::GenericPredicates {
             parent: None,
             predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| {
                 match predicate {
@@ -3290,7 +3289,7 @@ fn check_method_call(&self,
                 Ok(method)
             }
             Err(error) => {
-                if segment.ident.name != keywords::Invalid.name() {
+                if segment.ident.name != kw::Invalid {
                     self.report_method_error(span,
                                              rcvr_t,
                                              segment.ident,
@@ -3402,7 +3401,7 @@ fn check_field(&self,
             }
             err.emit();
             field_ty
-        } else if field.name == keywords::Invalid.name() {
+        } else if field.name == kw::Invalid {
             self.tcx().types.err
         } else if self.method_exists(field, expr_t, expr.hir_id, true) {
             let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0615,
@@ -4672,7 +4671,7 @@ pub fn resolve_ty_and_res_ufcs<'b>(&self,
                 method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
                 _ => Err(ErrorReported),
             };
-            if item_name.name != keywords::Invalid.name() {
+            if item_name.name != kw::Invalid {
                 self.report_method_error(
                     span,
                     ty,
index d167c7fcafbe4807ce8f7a0bf7bb44623e14c730..644d95963e652cdf5a882fbf05675178dafaec9c 100644 (file)
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
 
-use rustc_data_structures::sync::Lrc;
 use syntax::ast;
 use syntax_pos::Span;
 
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
 pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       crate_num: CrateNum)
-                                      -> Lrc<CrateInherentImpls> {
+                                      -> &'tcx CrateInherentImpls {
     assert_eq!(crate_num, LOCAL_CRATE);
 
     let krate = tcx.hir().krate();
@@ -29,13 +28,13 @@ pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         impls_map: Default::default(),
     };
     krate.visit_all_item_likes(&mut collect);
-    Lrc::new(collect.impls_map)
+    tcx.arena.alloc(collect.impls_map)
 }
 
 /// On-demand query: yields a vector of the inherent impls for a specific type.
 pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 ty_def_id: DefId)
-                                -> Lrc<Vec<DefId>> {
+                                -> &'tcx [DefId] {
     assert!(ty_def_id.is_local());
 
     // NB. Until we adopt the red-green dep-tracking algorithm (see
@@ -53,15 +52,11 @@ pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     //
     // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4
 
-    thread_local! {
-        static EMPTY_DEF_ID_VEC: Lrc<Vec<DefId>> = Lrc::new(vec![])
-    }
-
     let result = tcx.dep_graph.with_ignore(|| {
         let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
         match crate_map.inherent_impls.get(&ty_def_id) {
-            Some(v) => v.clone(),
-            None => EMPTY_DEF_ID_VEC.with(|v| v.clone())
+            Some(v) => &v[..],
+            None => &[],
         }
     });
 
@@ -289,13 +284,8 @@ fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
             // type def ID, if there is a base type for this implementation and
             // the implementation does not have any associated traits.
             let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
-            let mut rc_vec = self.impls_map.inherent_impls
-                                           .entry(def_id)
-                                           .or_default();
-
-            // At this point, there should not be any clones of the
-            // `Lrc`, so we can still safely push into it in place:
-            Lrc::get_mut(&mut rc_vec).unwrap().push(impl_def_id);
+            let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
+            vec.push(impl_def_id);
         } else {
             struct_span_err!(self.tcx.sess,
                              item.span,
index 7adf86a99bd438765fbbeb46aa455668071cac8e..45380d757b97d77d981c89366f7c20d090cff79b 100644 (file)
@@ -31,7 +31,6 @@
 use rustc::ty::{ReprOptions, ToPredicate};
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi;
 
 use syntax::ast;
@@ -39,7 +38,7 @@
 use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used};
 use syntax::source_map::Spanned;
 use syntax::feature_gate;
-use syntax::symbol::{InternedString, keywords, Symbol, sym};
+use syntax::symbol::{InternedString, kw, Symbol, sym};
 use syntax_pos::{Span, DUMMY_SP};
 
 use rustc::hir::def::{CtorKind, Res, DefKind};
@@ -178,7 +177,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
     }
 
     fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
-                                 -> Lrc<ty::GenericPredicates<'tcx>> {
+                                 -> &'tcx ty::GenericPredicates<'tcx> {
         self.tcx
             .at(span)
             .type_param_predicates((self.item_def_id, def_id))
@@ -243,7 +242,7 @@ fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
 fn type_param_predicates<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     (item_def_id, def_id): (DefId, DefId),
-) -> Lrc<ty::GenericPredicates<'tcx>> {
+) -> &'tcx ty::GenericPredicates<'tcx> {
     use rustc::hir::*;
 
     // In the AST, bounds can derive from two places. Either
@@ -264,16 +263,11 @@ fn type_param_predicates<'a, 'tcx>(
         tcx.generics_of(item_def_id).parent
     };
 
-    let mut result = parent.map_or_else(
-        || Lrc::new(ty::GenericPredicates {
-            parent: None,
-            predicates: vec![],
-        }),
-        |parent| {
-            let icx = ItemCtxt::new(tcx, parent);
-            icx.get_type_parameter_bounds(DUMMY_SP, def_id)
-        },
-    );
+    let result = parent.map_or(&tcx.common.empty_predicates, |parent| {
+        let icx = ItemCtxt::new(tcx, parent);
+        icx.get_type_parameter_bounds(DUMMY_SP, def_id)
+    });
+    let mut extend = None;
 
     let item_hir_id = tcx.hir().as_local_hir_id(item_def_id).unwrap();
     let ast_generics = match tcx.hir().get_by_hir_id(item_hir_id) {
@@ -298,9 +292,7 @@ fn type_param_predicates<'a, 'tcx>(
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_hir_id {
                         let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
-                        Lrc::make_mut(&mut result)
-                            .predicates
-                            .push((identity_trait_ref.to_predicate(), item.span));
+                        extend = Some((identity_trait_ref.to_predicate(), item.span));
                     }
                     generics
                 }
@@ -317,11 +309,12 @@ fn type_param_predicates<'a, 'tcx>(
     };
 
     let icx = ItemCtxt::new(tcx, item_def_id);
-    Lrc::make_mut(&mut result)
-        .predicates
-        .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty,
-            OnlySelfBounds(true)));
-    result
+    let mut result = (*result).clone();
+    result.predicates.extend(extend.into_iter());
+    result.predicates
+          .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty,
+                  OnlySelfBounds(true)));
+    tcx.arena.alloc(result)
 }
 
 impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
@@ -690,7 +683,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
 fn super_predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     trait_def_id: DefId,
-) -> Lrc<ty::GenericPredicates<'tcx>> {
+) -> &'tcx ty::GenericPredicates<'tcx> {
     debug!("super_predicates(trait_def_id={:?})", trait_def_id);
     let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id).unwrap();
 
@@ -734,7 +727,7 @@ fn super_predicates_of<'a, 'tcx>(
         }
     }
 
-    Lrc::new(ty::GenericPredicates {
+    tcx.arena.alloc(ty::GenericPredicates {
         parent: None,
         predicates: superbounds,
     })
@@ -939,7 +932,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
 
                     opt_self = Some(ty::GenericParamDef {
                         index: 0,
-                        name: keywords::SelfUpper.name().as_interned_str(),
+                        name: kw::SelfUpper.as_interned_str(),
                         def_id: tcx.hir().local_def_id_from_hir_id(param_id),
                         pure_wrt_drop: false,
                         kind: ty::GenericParamDefKind::Type {
@@ -1008,7 +1001,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
                         synthetic,
                         ..
                     } => {
-                        if param.name.ident().name == keywords::SelfUpper.name() {
+                        if param.name.ident().name == kw::SelfUpper {
                             span_bug!(
                                 param.span,
                                 "`Self` should not be the name of a regular parameter"
@@ -1038,7 +1031,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
                         }
                     }
                     GenericParamKind::Const { .. } => {
-                        if param.name.ident().name == keywords::SelfUpper.name() {
+                        if param.name.ident().name == kw::SelfUpper {
                             span_bug!(
                                 param.span,
                                 "`Self` should not be the name of a regular parameter",
@@ -1842,7 +1835,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
 fn predicates_defined_on<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> Lrc<ty::GenericPredicates<'tcx>> {
+) -> &'tcx ty::GenericPredicates<'tcx> {
     debug!("predicates_defined_on({:?})", def_id);
     let mut result = tcx.explicit_predicates_of(def_id);
     debug!(
@@ -1858,9 +1851,9 @@ fn predicates_defined_on<'a, 'tcx>(
             def_id,
             inferred_outlives,
         );
-        Lrc::make_mut(&mut result)
-            .predicates
-            .extend(inferred_outlives.iter().map(|&p| (p, span)));
+        let mut predicates = (*result).clone();
+        predicates.predicates.extend(inferred_outlives.iter().map(|&p| (p, span)));
+        result = tcx.arena.alloc(predicates);
     }
     debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
     result
@@ -1872,7 +1865,7 @@ fn predicates_defined_on<'a, 'tcx>(
 fn predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> Lrc<ty::GenericPredicates<'tcx>> {
+) -> &'tcx ty::GenericPredicates<'tcx> {
     let mut result = tcx.predicates_defined_on(def_id);
 
     if tcx.is_trait(def_id) {
@@ -1889,9 +1882,9 @@ fn predicates_of<'a, 'tcx>(
         // used, and adding the predicate into this list ensures
         // that this is done.
         let span = tcx.def_span(def_id);
-        Lrc::make_mut(&mut result)
-            .predicates
-            .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span));
+        let mut predicates = (*result).clone();
+        predicates.predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span));
+        result = tcx.arena.alloc(predicates);
     }
     debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
     result
@@ -1902,7 +1895,7 @@ fn predicates_of<'a, 'tcx>(
 fn explicit_predicates_of<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> Lrc<ty::GenericPredicates<'tcx>> {
+) -> &'tcx ty::GenericPredicates<'tcx> {
     use rustc::hir::*;
     use rustc_data_structures::fx::FxHashSet;
 
@@ -2017,7 +2010,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
 
                     if impl_trait_fn.is_some() {
                         // impl Trait
-                        return Lrc::new(ty::GenericPredicates {
+                        return tcx.arena.alloc(ty::GenericPredicates {
                             parent: None,
                             predicates: bounds.predicates(tcx, opaque_ty),
                         });
@@ -2228,7 +2221,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
         );
     }
 
-    let result = Lrc::new(ty::GenericPredicates {
+    let result = tcx.arena.alloc(ty::GenericPredicates {
         parent: generics.parent,
         predicates,
     });
index a6b5b99982ec6b5ba8a4cb72b36446268a17999c..57787a75e4aefd683a7a6320aac19899215b4756 100644 (file)
@@ -4,7 +4,6 @@
 use rustc::ty::query::Providers;
 use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, CratePredicatesMap, TyCtxt};
-use rustc_data_structures::sync::Lrc;
 use syntax::symbol::sym;
 
 mod explicit;
@@ -74,7 +73,7 @@ fn inferred_outlives_of<'a, 'tcx>(
 fn inferred_outlives_crate<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     crate_num: CrateNum,
-) -> Lrc<CratePredicatesMap<'tcx>> {
+) -> &'tcx CratePredicatesMap<'tcx> {
     assert_eq!(crate_num, LOCAL_CRATE);
 
     // Compute a map from each struct/enum/union S to the **explicit**
@@ -120,7 +119,7 @@ fn inferred_outlives_crate<'tcx>(
             (def_id, &*predicates)
         }).collect();
 
-    Lrc::new(ty::CratePredicatesMap {
+    tcx.arena.alloc(ty::CratePredicatesMap {
         predicates,
     })
 }
index 88ee1d79f5435dd165bc30e1402a1c191f5915fa..47c4a9b39c865e024dc91be4c9984783f85ec1db 100644 (file)
@@ -9,7 +9,6 @@
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ty::{self, CrateVariancesMap, TyCtxt};
 use rustc::ty::query::Providers;
-use rustc_data_structures::sync::Lrc;
 
 /// Defines the `TermsContext` basically houses an arena where we can
 /// allocate terms.
@@ -36,12 +35,12 @@ pub fn provide(providers: &mut Providers<'_>) {
 }
 
 fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
-                             -> Lrc<CrateVariancesMap<'tcx>> {
+                             -> &'tcx CrateVariancesMap<'tcx> {
     assert_eq!(crate_num, LOCAL_CRATE);
     let mut arena = arena::TypedArena::default();
     let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena);
     let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
-    Lrc::new(solve::solve_constraints(constraints_cx))
+    tcx.arena.alloc(solve::solve_constraints(constraints_cx))
 }
 
 fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
index 11e8192521d79901d131832bf575f83964fb90f9..8e2460a14b87a7e6d62c9e82540f5294d1094c16 100644 (file)
@@ -104,8 +104,10 @@ pub fn get_auto_trait_impls(
                     // Instead, we generate `impl !Send for Foo<T>`, which better
                     // expresses the fact that `Foo<T>` never implements `Send`,
                     // regardless of the choice of `T`.
-                    let params = (self.cx.tcx.generics_of(param_env_def_id), &Default::default())
-                        .clean(self.cx).params;
+                    let params = (
+                        self.cx.tcx.generics_of(param_env_def_id),
+                        &&self.cx.tcx.common.empty_predicates,
+                    ).clean(self.cx).params;
 
                     Generics {
                         params,
index 6d03a5ad63bbbb237b960a16d94b795b59cf81ac..9c3f522d8470fcbd69fe30dc66d8d840a80b5104 100644 (file)
@@ -10,7 +10,6 @@
 mod blanket_impl;
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi::Abi;
 use rustc_typeck::hir_ty_to_ty;
 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
@@ -31,8 +30,7 @@
 use syntax::ext::base::MacroKind;
 use syntax::source_map::{dummy_spanned, Spanned};
 use syntax::ptr::P;
-use syntax::symbol::keywords::{self, Keyword};
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax::symbol::InternedString;
 use syntax_pos::{self, Pos, FileName};
 
@@ -43,7 +41,6 @@
 use std::{mem, slice, vec};
 use std::iter::{FromIterator, once};
 use std::rc::Rc;
-use std::str::FromStr;
 use std::cell::RefCell;
 use std::sync::Arc;
 use std::u32;
@@ -309,10 +306,9 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
                 for attr in attrs.lists(sym::doc) {
                     if let Some(v) = attr.value_str() {
                         if attr.check_name(sym::keyword) {
-                            keyword = Keyword::from_str(&v.as_str()).ok()
-                                                                    .map(|x| x.name().to_string());
-                            if keyword.is_some() {
-                                break
+                            if v.is_doc_keyword() {
+                                keyword = Some(v.to_string());
+                                break;
                             }
                             // FIXME: should warn on unknown keywords?
                         }
@@ -1690,7 +1686,7 @@ fn is_impl_trait(param: &hir::GenericParam) -> bool {
 }
 
 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
-                                    &'a Lrc<ty::GenericPredicates<'tcx>>) {
+                                    &'a &'tcx ty::GenericPredicates<'tcx>) {
     fn clean(&self, cx: &DocContext<'_>) -> Generics {
         use self::WherePredicate as WP;
 
@@ -1702,7 +1698,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
         let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind {
             ty::GenericParamDefKind::Lifetime => None,
             ty::GenericParamDefKind::Type { .. } => {
-                if param.name.as_symbol() == keywords::SelfUpper.name() {
+                if param.name.as_symbol() == kw::SelfUpper {
                     assert_eq!(param.index, 0);
                     return None;
                 }
@@ -3596,7 +3592,7 @@ fn qpath_to_string(p: &hir::QPath) -> String {
         if i > 0 {
             s.push_str("::");
         }
-        if seg.ident.name != keywords::PathRoot.name() {
+        if seg.ident.name != kw::PathRoot {
             s.push_str(&*seg.ident.as_str());
         }
     }
@@ -4176,7 +4172,7 @@ fn resolve_type(cx: &DocContext<'_>,
             hir::Float(float_ty) => return Primitive(float_ty.into()),
         },
         Res::SelfTy(..) if path.segments.len() == 1 => {
-            return Generic(keywords::SelfUpper.name().to_string());
+            return Generic(kw::SelfUpper.to_string());
         }
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
             return Generic(format!("{:#}", path));
@@ -4437,7 +4433,7 @@ pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[Symbol]) -> Option<DefId> {
         loop {
             let segment = path_it.next()?;
 
-            for item in mem::replace(&mut items, Lrc::new(vec![])).iter() {
+            for item in mem::replace(&mut items, &[]).iter() {
                 if item.ident.name == *segment {
                     if path_it.peek().is_none() {
                         return match item.res {
index 5bb06516ac49e81ebaf917d4ea9b9dcb8fd6a407..932419c78f22c1f03d6d09828e53e51d5e39b966 100644 (file)
@@ -15,6 +15,7 @@
 use syntax::parse::lexer::{self, TokenAndSpan};
 use syntax::parse::token;
 use syntax::parse;
+use syntax::symbol::{kw, sym};
 use syntax_pos::{Span, FileName};
 
 /// Highlights `src`, returning the HTML output.
@@ -309,32 +310,31 @@ fn write_token<W: Writer>(&mut self,
                 }
             }
 
-            token::Literal(lit, _suf) => {
-                match lit {
+            token::Literal(lit) => {
+                match lit.kind {
                     // Text literals.
-                    token::Byte(..) | token::Char(..) | token::Err(..) |
-                        token::ByteStr(..) | token::ByteStrRaw(..) |
-                        token::Str_(..) | token::StrRaw(..) => Class::String,
+                    token::Byte | token::Char | token::Err |
+                    token::ByteStr | token::ByteStrRaw(..) |
+                    token::Str | token::StrRaw(..) => Class::String,
 
                     // Number literals.
-                    token::Integer(..) | token::Float(..) => Class::Number,
+                    token::Integer | token::Float => Class::Number,
 
-                    token::Bool(..) => panic!("literal token contains `Lit::Bool`"),
+                    token::Bool => panic!("literal token contains `Lit::Bool`"),
                 }
             }
 
             // Keywords are also included in the identifier set.
             token::Ident(ident, is_raw) => {
-                match &*ident.as_str() {
-                    "ref" | "mut" if !is_raw => Class::RefKeyWord,
+                match ident.name {
+                    kw::Ref | kw::Mut if !is_raw => Class::RefKeyWord,
 
-                    "self" | "Self" => Class::Self_,
-                    "false" | "true" if !is_raw => Class::Bool,
+                    kw::SelfLower | kw::SelfUpper => Class::Self_,
+                    kw::False | kw::True if !is_raw => Class::Bool,
 
-                    "Option" | "Result" => Class::PreludeTy,
-                    "Some" | "None" | "Ok" | "Err" => Class::PreludeVal,
+                    sym::Option | sym::Result => Class::PreludeTy,
+                    sym::Some | sym::None | sym::Ok | sym::Err => Class::PreludeVal,
 
-                    "$crate" => Class::KeyWord,
                     _ if tas.tok.is_reserved_ident() => Class::KeyWord,
 
                     _ => {
index 55e8b39974e09be7611e658533fab45cae204b55..c4c1170e539ae6c213f5a52a9a6f13971f4c3f04 100644 (file)
@@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
 core = { path = "../libcore" }
 libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.14" }
+compiler_builtins = { version = "0.1.15" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
 hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] }
@@ -49,12 +49,12 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 cc = "1.0"
 
 [features]
-default = ["compiler_builtins_c", "std_detect_file_io", "std_detect_dlsym_getauxval"]
+default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
 
 backtrace = ["backtrace-sys"]
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
-compiler_builtins_c = ["alloc/compiler-builtins-c"]
+compiler-builtins-c = ["alloc/compiler-builtins-c"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 
 # Make panics and failed asserts immediately abort without formatting any message
index 260624a8bd8594945fde8d6923159bad3b31c7dc..9058ea93d6de077d2717173df417931ac68c364e 100644 (file)
@@ -746,10 +746,6 @@ fn next(&mut self) -> Option<String> {
         self.inner.next().map(|s| s.into_string().unwrap())
     }
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-    #[inline]
-    fn last(mut self) -> Option<String> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -785,8 +781,6 @@ impl Iterator for ArgsOs {
     type Item = OsString;
     fn next(&mut self) -> Option<OsString> { self.inner.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-    #[inline]
-    fn last(mut self) -> Option<OsString> { self.next_back() }
 }
 
 #[stable(feature = "env", since = "1.0.0")]
index 59f9e439add244a4955c74191188b02d15740582..126bc3754dabcac134e18c713c3d967878439aa3 100644 (file)
@@ -888,11 +888,6 @@ impl<'a> Iterator for Iter<'a> {
     fn next(&mut self) -> Option<&'a OsStr> {
         self.inner.next().map(Component::as_os_str)
     }
-
-    #[inline]
-    fn last(mut self) -> Option<&'a OsStr> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -956,11 +951,6 @@ fn next(&mut self) -> Option<Component<'a>> {
         }
         None
     }
-
-    #[inline]
-    fn last(mut self) -> Option<Self::Item> {
-        self.next_back()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 6ba947d4598b1da1163214923bbf24dbacc854c8..3b4de56f2c9b7602c3f5699a2a9fa00456ff3735 100644 (file)
@@ -35,8 +35,6 @@ impl Iterator for Args {
     type Item = OsString;
     fn next(&mut self) -> Option<OsString> { self.iter.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-    #[inline]
-    fn last(mut self) -> Option<OsString> { self.next_back() }
 }
 
 impl ExactSizeIterator for Args {
index 6766099c1ece13d05520f6f5ba04ed1c453f7adc..b3c77b869956364326312711471bff4e66fa2556 100644 (file)
@@ -37,10 +37,6 @@ fn next(&mut self) -> Option<OsString> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
-    #[inline]
-    fn last(mut self) -> Option<OsString> {
-        self.next_back()
-    }
 }
 
 impl ExactSizeIterator for Args {
index 744d7ec59d3a3e76303da40a4589bf099af936d1..b04bb484eedb9499cf453c344749251be4fca405 100644 (file)
@@ -181,8 +181,6 @@ impl Iterator for Args {
     type Item = OsString;
     fn next(&mut self) -> Option<OsString> { self.parsed_args_list.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.parsed_args_list.size_hint() }
-    #[inline]
-    fn last(mut self) -> Option<OsString> { self.next_back() }
 }
 
 impl DoubleEndedIterator for Args {
index da45bc1d9f5c5cfa87a506c864a92cde2b0598b0..84ef0468cac7a420db1f694a6535b00c20cdcb6e 100644 (file)
@@ -10,7 +10,7 @@
 use crate::print::pprust;
 use crate::ptr::P;
 use crate::source_map::{dummy_spanned, respan, Spanned};
-use crate::symbol::{keywords, Symbol};
+use crate::symbol::{kw, Symbol};
 use crate::tokenstream::TokenStream;
 use crate::ThinVec;
 
@@ -65,7 +65,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 pub struct Path {
     pub span: Span,
     /// The segments in the path: the things separated by `::`.
-    /// Global paths begin with `keywords::PathRoot`.
+    /// Global paths begin with `kw::PathRoot`.
     pub segments: Vec<PathSegment>,
 }
 
@@ -100,7 +100,7 @@ pub fn from_ident(ident: Ident) -> Path {
     }
 
     pub fn is_global(&self) -> bool {
-        !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name()
+        !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
     }
 }
 
@@ -128,7 +128,7 @@ pub fn from_ident(ident: Ident) -> Self {
         PathSegment { ident, id: DUMMY_NODE_ID, args: None }
     }
     pub fn path_root(span: Span) -> Self {
-        PathSegment::from_ident(Ident::new(keywords::PathRoot.name(), span))
+        PathSegment::from_ident(Ident::new(kw::PathRoot, span))
     }
 }
 
@@ -908,6 +908,7 @@ pub struct Arm {
     pub pats: Vec<P<Pat>>,
     pub guard: Option<Guard>,
     pub body: P<Expr>,
+    pub span: Span,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -1346,8 +1347,6 @@ pub enum StrStyle {
 pub struct Lit {
     /// The original literal token as written in source code.
     pub token: token::Lit,
-    /// The original literal suffix as written in source code.
-    pub suffix: Option<Symbol>,
     /// The "semantic" representation of the literal lowered from the original tokens.
     /// Strings are unescaped, hexadecimal forms are eliminated, etc.
     /// FIXME: Remove this and only create the semantic representation during lowering to HIR.
@@ -1782,7 +1781,7 @@ pub enum SelfKind {
 impl Arg {
     pub fn to_self(&self) -> Option<ExplicitSelf> {
         if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node {
-            if ident.name == keywords::SelfLower.name() {
+            if ident.name == kw::SelfLower {
                 return match self.ty.node {
                     TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
                     TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.node.is_implicit_self() => {
@@ -1800,7 +1799,7 @@ pub fn to_self(&self) -> Option<ExplicitSelf> {
 
     pub fn is_self(&self) -> bool {
         if let PatKind::Ident(_, ident, _) = self.pat.node {
-            ident.name == keywords::SelfLower.name()
+            ident.name == kw::SelfLower
         } else {
             false
         }
index 592b40df1764e36c8fec5a757481480bcbb1b5f2..2f75a8c9db57e453f9165f5bb5819aef15c06791 100644 (file)
@@ -22,7 +22,7 @@
 use crate::parse::{self, ParseSess, PResult};
 use crate::parse::token::{self, Token};
 use crate::ptr::P;
-use crate::symbol::{keywords, Symbol, sym};
+use crate::symbol::{sym, Symbol};
 use crate::ThinVec;
 use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
 use crate::GLOBALS;
@@ -90,7 +90,7 @@ pub fn ident(&self) -> Option<Ident> {
         self.meta_item().and_then(|meta_item| meta_item.ident())
     }
     pub fn name_or_empty(&self) -> Symbol {
-        self.ident().unwrap_or(keywords::Invalid.ident()).name
+        self.ident().unwrap_or(Ident::invalid()).name
     }
 
     /// Gets the string value if self is a MetaItem and the MetaItem is a
@@ -168,7 +168,7 @@ pub fn ident(&self) -> Option<Ident> {
         }
     }
     pub fn name_or_empty(&self) -> Symbol {
-        self.ident().unwrap_or(keywords::Invalid.ident()).name
+        self.ident().unwrap_or(Ident::invalid()).name
     }
 
     pub fn value_str(&self) -> Option<Symbol> {
@@ -206,7 +206,7 @@ pub fn ident(&self) -> Option<Ident> {
         }
     }
     pub fn name_or_empty(&self) -> Symbol {
-        self.ident().unwrap_or(keywords::Invalid.ident()).name
+        self.ident().unwrap_or(Ident::invalid()).name
     }
 
     // #[attribute(name = "value")]
@@ -554,7 +554,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItemKind>
             Some(TokenTree::Token(_, token::Eq)) => {
                 tokens.next();
                 return if let Some(TokenTree::Token(span, token)) = tokens.next() {
-                    Lit::from_token(&token, span, None).map(MetaItemKind::NameValue)
+                    Lit::from_token(&token, span).ok().map(MetaItemKind::NameValue)
                 } else {
                     None
                 };
@@ -599,7 +599,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
         where I: Iterator<Item = TokenTree>,
     {
         if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() {
-            if let Some(lit) = Lit::from_token(&token, span, None) {
+            if let Ok(lit) = Lit::from_token(&token, span) {
                 tokens.next();
                 return Some(NestedMetaItem::Literal(lit));
             }
index c988dc61bec449034082097b18c8ab4e7582a311..0c57c23b2b5c4102e61a83e5be5f4e99fafb46b4 100644 (file)
@@ -7,7 +7,7 @@
 use crate::ext::build::AstBuilder;
 use crate::parse::token;
 use crate::ptr::P;
-use crate::symbol::keywords;
+use crate::symbol::kw;
 use crate::tokenstream::{TokenTree};
 
 use smallvec::smallvec;
@@ -77,8 +77,8 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>,
         },
         (3, Some(&TokenTree::Token(_, token::Ident(ref code, _))),
             Some(&TokenTree::Token(_, token::Comma)),
-            Some(&TokenTree::Token(_, token::Literal(token::StrRaw(description, _), None)))) => {
-            (code, Some(description))
+            Some(&TokenTree::Token(_, token::Literal(token::Lit { symbol, .. })))) => {
+            (code, Some(symbol))
         }
         _ => unreachable!()
     };
@@ -185,7 +185,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>,
             (descriptions.len(), ecx.expr_vec(span, descriptions))
         });
 
-    let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident());
+    let static_ = ecx.lifetime(span, Ident::with_empty_ctxt(kw::StaticLifetime));
     let ty_str = ecx.ty_rptr(
         span,
         ecx.ty_ident(span, ecx.ident_of("str")),
index 489fac4f1ca4c642d8a5c290d3e86391abc8afef..f1a20d54065743fd4de8578406d75aa0f6b64662 100644 (file)
@@ -10,7 +10,7 @@
 use crate::parse::{self, parser, DirectoryOwnership};
 use crate::parse::token;
 use crate::ptr::P;
-use crate::symbol::{keywords, Ident, Symbol, sym};
+use crate::symbol::{kw, sym, Ident, Symbol};
 use crate::ThinVec;
 use crate::tokenstream::{self, TokenStream};
 
@@ -971,7 +971,7 @@ pub fn ident_of(&self, st: &str) -> ast::Ident {
     }
     pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
         let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark);
-        iter::once(Ident::new(keywords::DollarCrate.name(), def_site))
+        iter::once(Ident::new(kw::DollarCrate, def_site))
             .chain(components.iter().map(|s| self.ident_of(s)))
             .collect()
     }
index d24106f697e19f1470fd4a6adecfad08c73191b6..ad8fb12deb7f6b34cd33954514ccc0b8a3a277da 100644 (file)
@@ -3,7 +3,7 @@
 use crate::source_map::{dummy_spanned, respan, Spanned};
 use crate::ext::base::ExtCtxt;
 use crate::ptr::P;
-use crate::symbol::{Symbol, keywords};
+use crate::symbol::{Symbol, kw};
 use crate::ThinVec;
 
 use rustc_target::spec::abi::Abi;
@@ -628,7 +628,7 @@ fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> {
         self.expr_path(self.path_ident(span, id))
     }
     fn expr_self(&self, span: Span) -> P<ast::Expr> {
-        self.expr_ident(span, keywords::SelfLower.ident())
+        self.expr_ident(span, Ident::with_empty_ctxt(kw::SelfLower))
     }
 
     fn expr_binary(&self, sp: Span, op: ast::BinOpKind,
@@ -890,12 +890,13 @@ fn pat_err(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
         self.pat_tuple_struct(span, path, vec![pat])
     }
 
-    fn arm(&self, _span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm {
+    fn arm(&self, span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm {
         ast::Arm {
             attrs: vec![],
             pats,
             guard: None,
             body: expr,
+            span,
         }
     }
 
@@ -1175,7 +1176,7 @@ fn item_use(&self, sp: Span,
                 vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item> {
         P(ast::Item {
             id: ast::DUMMY_NODE_ID,
-            ident: keywords::Invalid.ident(),
+            ident: Ident::invalid(),
             attrs: vec![],
             node: ast::ItemKind::Use(vp),
             vis,
index 478ae4de82b74958eb23ed5942171a7a25c47e76..fbe052252a1140de41ec7e91b974a28b91c2d293 100644 (file)
@@ -14,7 +14,7 @@
 use crate::parse::parser::Parser;
 use crate::ptr::P;
 use crate::symbol::Symbol;
-use crate::symbol::{keywords, sym};
+use crate::symbol::{kw, sym};
 use crate::tokenstream::{TokenStream, TokenTree};
 use crate::visit::{self, Visitor};
 use crate::util::map_in_place::MapInPlace;
@@ -198,7 +198,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
         if i != 0 {
             path_str.push_str("::");
         }
-        if segment.ident.name != keywords::PathRoot.name() {
+        if segment.ident.name != kw::PathRoot {
             path_str.push_str(&segment.ident.as_str())
         }
     }
@@ -271,7 +271,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             attrs: krate.attrs,
             span: krate.span,
             node: ast::ItemKind::Mod(krate.module),
-            ident: keywords::Invalid.ident(),
+            ident: Ident::invalid(),
             id: ast::DUMMY_NODE_ID,
             vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
             tokens: None,
@@ -708,7 +708,7 @@ fn expand_bang_invoc(&mut self,
         };
         let path = &mac.node.path;
 
-        let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
+        let ident = ident.unwrap_or_else(|| Ident::invalid());
         let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
                                           def_site_span: Option<Span>,
                                           allow_internal_unstable,
@@ -736,7 +736,7 @@ fn expand_bang_invoc(&mut self,
                 }
             }
 
-            if ident.name != keywords::Invalid.name() {
+            if ident.name != kw::Invalid {
                 let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
                 this.cx.span_err(path.span, &msg);
                 this.cx.trace_macros_diag();
@@ -792,7 +792,7 @@ fn expand_bang_invoc(&mut self,
             }
 
             IdentTT { ref expander, span: tt_span, ref allow_internal_unstable } => {
-                if ident.name == keywords::Invalid.name() {
+                if ident.name == kw::Invalid {
                     self.cx.span_err(path.span,
                                     &format!("macro {}! expects an ident argument", path));
                     self.cx.trace_macros_diag();
@@ -828,7 +828,7 @@ fn expand_bang_invoc(&mut self,
             }
 
             SyntaxExtension::ProcMacro { ref expander, ref allow_internal_unstable, edition } => {
-                if ident.name != keywords::Invalid.name() {
+                if ident.name != kw::Invalid {
                     let msg =
                         format!("macro {}! expects no ident argument, given '{}'", path, ident);
                     self.cx.span_err(path.span, &msg);
@@ -929,7 +929,7 @@ fn expand_derive_invoc(&mut self,
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = span.with_ctxt(self.cx.backtrace());
                 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
-                    path: Path::from_ident(keywords::Invalid.ident()),
+                    path: Path::from_ident(Ident::invalid()),
                     span: DUMMY_SP,
                     node: ast::MetaItemKind::Word,
                 };
@@ -1338,7 +1338,7 @@ fn visit_block(&mut self, block: &mut P<Block>) {
                 })
             }
             ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
-                if item.ident == keywords::Invalid.ident() {
+                if item.ident == Ident::invalid() {
                     return noop_flat_map_item(item, self);
                 }
 
index f5e18e98436e6e1b222ca0eabca59fb3e3074afb..8f24d11cfd5b0696da080a9cd55211c757086f6c 100644 (file)
@@ -6,7 +6,6 @@
 use crate::tokenstream::TokenStream;
 use crate::mut_visit::*;
 use crate::ptr::P;
-use crate::symbol::keywords;
 use crate::ThinVec;
 
 use smallvec::{smallvec, SmallVec};
@@ -22,7 +21,7 @@ fn mac_placeholder() -> ast::Mac {
         })
     }
 
-    let ident = keywords::Invalid.ident();
+    let ident = ast::Ident::invalid();
     let attrs = Vec::new();
     let generics = ast::Generics::default();
     let vis = dummy_spanned(ast::VisibilityKind::Inherited);
index 084a69f4cda0f97b6ec56ae08cbb6b82a348ff12..fa1f85c0e7b572a3f4cd903c7bec7acb95afea40 100644 (file)
@@ -80,7 +80,7 @@
 use crate::parse::parser::{Parser, PathStyle};
 use crate::parse::token::{self, DocComment, Nonterminal, Token};
 use crate::print::pprust;
-use crate::symbol::keywords;
+use crate::symbol::kw;
 use crate::tokenstream::{DelimSpan, TokenStream};
 
 use errors::FatalError;
@@ -382,7 +382,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
             TokenTree::Delimited(_, ref delim) => for next_m in &delim.tts {
                 n_rec(sess, next_m, res.by_ref(), ret_val)?;
             },
-            TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => {
+            TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
                 if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
                     return Err((span, "missing fragment specifier".to_string()));
                 }
@@ -587,7 +587,7 @@ fn inner_parse_loop<'root, 'tt>(
                 }
 
                 // We need to match a metavar (but the identifier is invalid)... this is an error
-                TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => {
+                TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
                     if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
                         return Error(span, "missing fragment specifier".to_string());
                     }
@@ -802,7 +802,7 @@ pub fn parse(
 /// We prohibit passing `_` to macros expecting `ident` for now.
 fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
     match *token {
-        token::Ident(ident, is_raw) if ident.name != keywords::Underscore.name() =>
+        token::Ident(ident, is_raw) if ident.name != kw::Underscore =>
             Some((ident, is_raw)),
         _ => None,
     }
index 672b7b4285522b1a13ba1911510257d0f80db99a..37c49112dcaaceb22dcd42b1841620734fc2435c 100644 (file)
@@ -13,7 +13,7 @@
 use crate::parse::parser::Parser;
 use crate::parse::token::{self, NtTT};
 use crate::parse::token::Token::*;
-use crate::symbol::{Symbol, keywords, sym};
+use crate::symbol::{Symbol, kw, sym};
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
 
 use errors::FatalError;
@@ -1046,8 +1046,8 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
                 match *tok {
                     TokenTree::Token(_, ref tok) => match *tok {
                         FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes,
-                        Ident(i, false) if i.name == keywords::If.name() ||
-                                           i.name == keywords::In.name() => IsInFollow::Yes,
+                        Ident(i, false) if i.name == kw::If ||
+                                           i.name == kw::In => IsInFollow::Yes,
                         _ => IsInFollow::No(tokens),
                     },
                     _ => IsInFollow::No(tokens),
@@ -1064,8 +1064,8 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
                         OpenDelim(token::DelimToken::Bracket) |
                         Comma | FatArrow | Colon | Eq | Gt | BinOp(token::Shr) | Semi |
                         BinOp(token::Or) => IsInFollow::Yes,
-                        Ident(i, false) if i.name == keywords::As.name() ||
-                                           i.name == keywords::Where.name() => IsInFollow::Yes,
+                        Ident(i, false) if i.name == kw::As ||
+                                           i.name == kw::Where => IsInFollow::Yes,
                         _ => IsInFollow::No(tokens),
                     },
                     TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::block =>
@@ -1092,7 +1092,7 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
                 match *tok {
                     TokenTree::Token(_, ref tok) => match *tok {
                         Comma => IsInFollow::Yes,
-                        Ident(i, is_raw) if is_raw || i.name != keywords::Priv.name() =>
+                        Ident(i, is_raw) if is_raw || i.name != kw::Priv =>
                             IsInFollow::Yes,
                         ref tok => if tok.can_begin_type() {
                             IsInFollow::Yes
@@ -1107,7 +1107,7 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
                     _ => IsInFollow::No(tokens),
                 }
             },
-            "" => IsInFollow::Yes, // keywords::Invalid
+            "" => IsInFollow::Yes, // kw::Invalid
             _ => IsInFollow::Invalid(format!("invalid fragment specifier `{}`", frag),
                                      VALID_FRAGMENT_NAMES_MSG),
         }
index ed8395f11ad5089c3557ea964ff748e81c280631..a029c6546595217abe0855f1f74ebb06fd5c2995 100644 (file)
@@ -6,7 +6,7 @@
 use crate::print::pprust;
 use crate::tokenstream::{self, DelimSpan};
 use crate::ast;
-use crate::symbol::keywords;
+use crate::symbol::kw;
 
 use syntax_pos::{edition::Edition, BytePos, Span};
 
@@ -228,7 +228,7 @@ pub fn parse(
                 result.push(TokenTree::MetaVarDecl(
                     span,
                     ident,
-                    keywords::Invalid.ident(),
+                    ast::Ident::invalid(),
                 ));
             }
 
@@ -319,8 +319,8 @@ fn parse_tree<I>(
             Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => {
                 let (ident, is_raw) = token.ident().unwrap();
                 let span = ident_span.with_lo(span.lo());
-                if ident.name == keywords::Crate.name() && !is_raw {
-                    let ident = ast::Ident::new(keywords::DollarCrate.name(), ident.span);
+                if ident.name == kw::Crate && !is_raw {
+                    let ident = ast::Ident::new(kw::DollarCrate, ident.span);
                     TokenTree::Token(span, token::Ident(ident, is_raw))
                 } else {
                     TokenTree::MetaVar(span, ident)
@@ -334,7 +334,7 @@ fn parse_tree<I>(
                     pprust::token_to_string(&tok)
                 );
                 sess.span_diagnostic.span_err(span, &msg);
-                TokenTree::MetaVar(span, keywords::Invalid.ident())
+                TokenTree::MetaVar(span, ast::Ident::invalid())
             }
 
             // There are no more tokens. Just return the `$` we already have.
index e3586c1854c1775b083dea9015106be62b7c7506..e6b49e61937d6aae3e96670b44fd4e72213f2b02 100644 (file)
@@ -170,9 +170,11 @@ pub fn transcribe(
                     }
 
                     LockstepIterSize::Contradiction(ref msg) => {
-                        // This should never happen because the macro parser should generate
-                        // properly-sized matches for all meta-vars.
-                        cx.span_bug(seq.span(), &msg[..]);
+                        // FIXME: this really ought to be caught at macro definition time... It
+                        // happens when two meta-variables are used in the same repetition in a
+                        // sequence, but they come from different sequence matchers and repeat
+                        // different amounts.
+                        cx.span_fatal(seq.span(), &msg[..]);
                     }
 
                     LockstepIterSize::Constraint(len, _) => {
@@ -187,9 +189,10 @@ pub fn transcribe(
                         // Is the repetition empty?
                         if len == 0 {
                             if seq.op == quoted::KleeneOp::OneOrMore {
-                                // This should be impossible because the macro parser would not
-                                // match the given macro arm.
-                                cx.span_bug(sp.entire(), "this must repeat at least once");
+                                // FIXME: this really ought to be caught at macro definition
+                                // time... It happens when the Kleene operator in the matcher and
+                                // the body for the same meta-variable do not match.
+                                cx.span_fatal(sp.entire(), "this must repeat at least once");
                             }
                         } else {
                             // 0 is the initial counter (we have done 0 repretitions so far). `len`
@@ -327,8 +330,7 @@ fn with(self, other: LockstepIterSize) -> LockstepIterSize {
                 LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self,
                 LockstepIterSize::Constraint(r_len, r_id) => {
                     let msg = format!(
-                        "inconsistent lockstep iteration: \
-                         '{}' has {} items, but '{}' has {}",
+                        "meta-variable `{}` repeats {} times, but `{}` repeats {} times",
                         l_id, l_len, r_id, r_len
                     );
                     LockstepIterSize::Contradiction(msg)
index 5b1a9bb739ff8346ec9e889b313d0bebf67129e2..0f1bf436eca1a39acb14fe7762c7a61673010d8e 100644 (file)
@@ -22,7 +22,7 @@
 use crate::edition::{ALL_EDITIONS, Edition};
 use crate::visit::{self, FnKind, Visitor};
 use crate::parse::{token, ParseSess};
-use crate::symbol::{Symbol, keywords, sym};
+use crate::symbol::{Symbol, kw, sym};
 use crate::tokenstream::TokenTree;
 
 use errors::{DiagnosticBuilder, Handler};
@@ -1134,6 +1134,13 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
             is just used to enable niche optimizations in libcore \
             and will never be stable",
         cfg_fn!(rustc_attrs))),
+    (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word),
+    Gated(Stability::Unstable,
+        sym::rustc_attrs,
+        "the `#[rustc_nonnull_optimization_guaranteed]` attribute \
+            is just used to enable niche optimizations in libcore \
+            and will never be stable",
+        cfg_fn!(rustc_attrs))),
     (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable,
                                     sym::rustc_attrs,
                                     "the `#[rustc_regions]` attribute \
@@ -1948,7 +1955,7 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
     fn visit_item(&mut self, i: &'a ast::Item) {
         match i.node {
             ast::ItemKind::Const(_,_) => {
-                if i.ident.name == keywords::Underscore.name() {
+                if i.ident.name == kw::Underscore {
                     gate_feature_post!(&self, underscore_const_names, i.span,
                                         "naming constants with `_` is unstable");
                 }
index 2dd2ecb749300ec19853d138e18710a9f919663c..767ab74355e66213ff8c27fbec2ba22be41f7302 100644 (file)
@@ -92,8 +92,8 @@ fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
         }
     }
 
-    fn emit_artifact_notification(&mut self, path: &Path) {
-        let data = ArtifactNotification { artifact: path };
+    fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) {
+        let data = ArtifactNotification { artifact: path, emit: artifact_type };
         let result = if self.pretty {
             writeln!(&mut self.dst, "{}", as_pretty_json(&data))
         } else {
@@ -185,6 +185,8 @@ struct DiagnosticCode {
 struct ArtifactNotification<'a> {
     /// The path of the artifact.
     artifact: &'a Path,
+    /// What kind of artifact we're emitting.
+    emit: &'a str,
 }
 
 impl Diagnostic {
index 8fdd15a029f13808d002543c65656ee71884040c..e743248ef4b59057a10b5c3b7b2150098b58e7b2 100644 (file)
@@ -11,7 +11,6 @@
 use crate::source_map::{Spanned, respan};
 use crate::parse::token::{self, Token};
 use crate::ptr::P;
-use crate::symbol::keywords;
 use crate::ThinVec;
 use crate::tokenstream::*;
 use crate::util::map_in_place::MapInPlace;
@@ -392,11 +391,15 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_arm<T: MutVisitor>(Arm { attrs, pats, guard, body }: &mut Arm, vis: &mut T) {
+pub fn noop_visit_arm<T: MutVisitor>(
+    Arm { attrs, pats, guard, body, span }: &mut Arm,
+    vis: &mut T,
+) {
     visit_attrs(attrs, vis);
     visit_vec(pats, |pat| vis.visit_pat(pat));
     visit_opt(guard, |guard| vis.visit_guard(guard));
     vis.visit_expr(body);
+    vis.visit_span(span);
 }
 
 pub fn noop_visit_guard<T: MutVisitor>(g: &mut Guard, vis: &mut T) {
@@ -977,7 +980,7 @@ pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod,
 pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
     visit_clobber(krate, |Crate { module, attrs, span }| {
         let item = P(Item {
-            ident: keywords::Invalid.ident(),
+            ident: Ident::invalid(),
             attrs,
             id: DUMMY_NODE_ID,
             vis: respan(span.shrink_to_lo(), VisibilityKind::Public),
index 1a2393be806d55d037f2faef1ef558bcb0fe142b..d48fcbbd6720d96e4b27581e7e0d69e4af5544d9 100644 (file)
@@ -6,7 +6,7 @@
 use crate::parse::Parser;
 use crate::print::pprust;
 use crate::ptr::P;
-use crate::symbol::keywords;
+use crate::symbol::kw;
 use crate::ThinVec;
 use errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
@@ -405,7 +405,7 @@ impl<'a> Parser<'a> {
 
     /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
     crate fn eat_bad_pub(&mut self) {
-        if self.token.is_keyword(keywords::Pub) {
+        if self.token.is_keyword(kw::Pub) {
             match self.parse_visibility(false) {
                 Ok(vis) => {
                     self.diagnostic()
index c97d804076157e039d827e66c61acd6a9f22adf0..deb76d6d70a33f319d49ff15897cbfdcd4715d5c 100644 (file)
@@ -1,5 +1,6 @@
 use crate::ast::{self, Ident};
-use crate::parse::{token, ParseSess};
+use crate::parse::ParseSess;
+use crate::parse::token::{self, Token};
 use crate::symbol::Symbol;
 use crate::parse::unescape;
 use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char};
@@ -21,7 +22,7 @@
 
 #[derive(Clone, Debug)]
 pub struct TokenAndSpan {
-    pub tok: token::Token,
+    pub tok: Token,
     pub sp: Span,
 }
 
@@ -55,7 +56,7 @@ pub struct StringReader<'a> {
     /// Stop reading src at this index.
     crate end_src_index: usize,
     // cached:
-    peek_tok: token::Token,
+    peek_tok: Token,
     peek_span: Span,
     peek_span_src_raw: Span,
     fatal_errs: Vec<DiagnosticBuilder<'a>>,
@@ -726,7 +727,7 @@ fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
     }
 
     /// Lex a LIT_INTEGER or a LIT_FLOAT
-    fn scan_number(&mut self, c: char) -> token::Lit {
+    fn scan_number(&mut self, c: char) -> (token::LitKind, Symbol) {
         let mut base = 10;
         let start_bpos = self.pos;
         self.bump();
@@ -753,7 +754,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
                 }
                 _ => {
                     // just a 0
-                    return token::Integer(self.name_from(start_bpos));
+                    return (token::Integer, self.name_from(start_bpos));
                 }
             }
         } else if c.is_digit(10) {
@@ -765,7 +766,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
         if num_digits == 0 {
             self.err_span_(start_bpos, self.pos, "no valid digits found for number");
 
-            return token::Integer(Symbol::intern("0"));
+            return (token::Integer, Symbol::intern("0"));
         }
 
         // might be a float, but don't be greedy if this is actually an
@@ -783,17 +784,17 @@ fn scan_number(&mut self, c: char) -> token::Lit {
             let pos = self.pos;
             self.check_float_base(start_bpos, pos, base);
 
-            token::Float(self.name_from(start_bpos))
+            (token::Float, self.name_from(start_bpos))
         } else {
             // it might be a float if it has an exponent
             if self.ch_is('e') || self.ch_is('E') {
                 self.scan_float_exponent();
                 let pos = self.pos;
                 self.check_float_base(start_bpos, pos, base);
-                return token::Float(self.name_from(start_bpos));
+                return (token::Float, self.name_from(start_bpos));
             }
             // but we certainly have an integer!
-            token::Integer(self.name_from(start_bpos))
+            (token::Integer, self.name_from(start_bpos))
         }
     }
 
@@ -846,7 +847,7 @@ fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: us
         }
     }
 
-    fn binop(&mut self, op: token::BinOpToken) -> token::Token {
+    fn binop(&mut self, op: token::BinOpToken) -> Token {
         self.bump();
         if self.ch_is('=') {
             self.bump();
@@ -858,7 +859,7 @@ fn binop(&mut self, op: token::BinOpToken) -> token::Token {
 
     /// Returns the next token from the string, advances the input past that
     /// token, and updates the interner
-    fn next_token_inner(&mut self) -> Result<token::Token, ()> {
+    fn next_token_inner(&mut self) -> Result<Token, ()> {
         let c = self.ch;
 
         if ident_start(c) {
@@ -912,10 +913,10 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
         }
 
         if is_dec_digit(c) {
-            let num = self.scan_number(c.unwrap());
+            let (kind, symbol) = self.scan_number(c.unwrap());
             let suffix = self.scan_optional_raw_name();
-            debug!("next_token_inner: scanned number {:?}, {:?}", num, suffix);
-            return Ok(token::Literal(num, suffix));
+            debug!("next_token_inner: scanned number {:?}, {:?}, {:?}", kind, symbol, suffix);
+            return Ok(Token::lit(kind, symbol, suffix));
         }
 
         match c.expect("next_token_inner called at EOF") {
@@ -1073,10 +1074,10 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     // lifetimes shouldn't end with a single quote
                     // if we find one, then this is an invalid character literal
                     if self.ch_is('\'') {
-                        let id = self.name_from(start);
+                        let symbol = self.name_from(start);
                         self.bump();
                         self.validate_char_escape(start_with_quote);
-                        return Ok(token::Literal(token::Char(id), None))
+                        return Ok(Token::lit(token::Char, symbol, None));
                     }
 
                     // Include the leading `'` in the real identifier, for macro
@@ -1098,43 +1099,43 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     return Ok(token::Lifetime(ident));
                 }
                 let msg = "unterminated character literal";
-                let id = self.scan_single_quoted_string(start_with_quote, msg);
+                let symbol = self.scan_single_quoted_string(start_with_quote, msg);
                 self.validate_char_escape(start_with_quote);
                 let suffix = self.scan_optional_raw_name();
-                Ok(token::Literal(token::Char(id), suffix))
+                Ok(Token::lit(token::Char, symbol, suffix))
             }
             'b' => {
                 self.bump();
-                let lit = match self.ch {
+                let (kind, symbol) = match self.ch {
                     Some('\'') => {
                         let start_with_quote = self.pos;
                         self.bump();
                         let msg = "unterminated byte constant";
-                        let id = self.scan_single_quoted_string(start_with_quote, msg);
+                        let symbol = self.scan_single_quoted_string(start_with_quote, msg);
                         self.validate_byte_escape(start_with_quote);
-                        token::Byte(id)
+                        (token::Byte, symbol)
                     },
                     Some('"') => {
                         let start_with_quote = self.pos;
                         let msg = "unterminated double quote byte string";
-                        let id = self.scan_double_quoted_string(msg);
+                        let symbol = self.scan_double_quoted_string(msg);
                         self.validate_byte_str_escape(start_with_quote);
-                        token::ByteStr(id)
+                        (token::ByteStr, symbol)
                     },
                     Some('r') => self.scan_raw_byte_string(),
                     _ => unreachable!(),  // Should have been a token::Ident above.
                 };
                 let suffix = self.scan_optional_raw_name();
 
-                Ok(token::Literal(lit, suffix))
+                Ok(Token::lit(kind, symbol, suffix))
             }
             '"' => {
                 let start_with_quote = self.pos;
                 let msg = "unterminated double quote string";
-                let id = self.scan_double_quoted_string(msg);
+                let symbol = self.scan_double_quoted_string(msg);
                 self.validate_str_escape(start_with_quote);
                 let suffix = self.scan_optional_raw_name();
-                Ok(token::Literal(token::Str_(id), suffix))
+                Ok(Token::lit(token::Str, symbol, suffix))
             }
             'r' => {
                 let start_bpos = self.pos;
@@ -1205,14 +1206,14 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 }
 
                 self.bump();
-                let id = if valid {
+                let symbol = if valid {
                     self.name_from_to(content_start_bpos, content_end_bpos)
                 } else {
                     Symbol::intern("??")
                 };
                 let suffix = self.scan_optional_raw_name();
 
-                Ok(token::Literal(token::StrRaw(id, hash_count), suffix))
+                Ok(Token::lit(token::StrRaw(hash_count), symbol, suffix))
             }
             '-' => {
                 if self.nextch_is('>') {
@@ -1366,7 +1367,7 @@ fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> ast::Name {
         id
     }
 
-    fn scan_raw_byte_string(&mut self) -> token::Lit {
+    fn scan_raw_byte_string(&mut self) -> (token::LitKind, Symbol) {
         let start_bpos = self.pos;
         self.bump();
         let mut hash_count = 0;
@@ -1423,7 +1424,7 @@ fn scan_raw_byte_string(&mut self) -> token::Lit {
 
         self.bump();
 
-        token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), hash_count)
+        (token::ByteStrRaw(hash_count), self.name_from_to(content_start_bpos, content_end_bpos))
     }
 
     fn validate_char_escape(&self, start_with_quote: BytePos) {
@@ -1637,15 +1638,19 @@ fn t1() {
 
     // check that the given reader produces the desired stream
     // of tokens (stop checking after exhausting the expected vec)
-    fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec<token::Token>) {
+    fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec<Token>) {
         for expected_tok in &expected {
             assert_eq!(&string_reader.next_token().tok, expected_tok);
         }
     }
 
     // make the identifier by looking up the string in the interner
-    fn mk_ident(id: &str) -> token::Token {
-        token::Token::from_ast_ident(Ident::from_str(id))
+    fn mk_ident(id: &str) -> Token {
+        Token::from_ast_ident(Ident::from_str(id))
+    }
+
+    fn mk_lit(kind: token::LitKind, symbol: &str, suffix: Option<&str>) -> Token {
+        Token::lit(kind, Symbol::intern(symbol), suffix.map(Symbol::intern))
     }
 
     #[test]
@@ -1694,7 +1699,7 @@ fn character_a() {
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let sh = mk_sess(sm.clone());
             assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token().tok,
-                    token::Literal(token::Char(Symbol::intern("a")), None));
+                       mk_lit(token::Char, "a", None));
         })
     }
 
@@ -1704,7 +1709,7 @@ fn character_space() {
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let sh = mk_sess(sm.clone());
             assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token().tok,
-                    token::Literal(token::Char(Symbol::intern(" ")), None));
+                       mk_lit(token::Char, " ", None));
         })
     }
 
@@ -1714,7 +1719,7 @@ fn character_escaped() {
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let sh = mk_sess(sm.clone());
             assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token().tok,
-                    token::Literal(token::Char(Symbol::intern("\\n")), None));
+                       mk_lit(token::Char, "\\n", None));
         })
     }
 
@@ -1724,7 +1729,7 @@ fn lifetime_name() {
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let sh = mk_sess(sm.clone());
             assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token().tok,
-                    token::Lifetime(Ident::from_str("'abc")));
+                       token::Lifetime(Ident::from_str("'abc")));
         })
     }
 
@@ -1733,10 +1738,8 @@ fn raw_string() {
         with_default_globals(|| {
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let sh = mk_sess(sm.clone());
-            assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string())
-                        .next_token()
-                        .tok,
-                    token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None));
+            assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token().tok,
+                       mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None));
         })
     }
 
@@ -1748,18 +1751,16 @@ fn literal_suffixes() {
             macro_rules! test {
                 ($input: expr, $tok_type: ident, $tok_contents: expr) => {{
                     assert_eq!(setup(&sm, &sh, format!("{}suffix", $input)).next_token().tok,
-                            token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
-                                            Some(Symbol::intern("suffix"))));
+                               mk_lit(token::$tok_type, $tok_contents, Some("suffix")));
                     // with a whitespace separator:
                     assert_eq!(setup(&sm, &sh, format!("{} suffix", $input)).next_token().tok,
-                            token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
-                                            None));
+                               mk_lit(token::$tok_type, $tok_contents, None));
                 }}
             }
 
             test!("'a'", Char, "a");
             test!("b'a'", Byte, "a");
-            test!("\"a\"", Str_, "a");
+            test!("\"a\"", Str, "a");
             test!("b\"a\"", ByteStr, "a");
             test!("1234", Integer, "1234");
             test!("0b101", Integer, "0b101");
@@ -1768,14 +1769,11 @@ macro_rules! test {
             test!("1.0e10", Float, "1.0e10");
 
             assert_eq!(setup(&sm, &sh, "2us".to_string()).next_token().tok,
-                    token::Literal(token::Integer(Symbol::intern("2")),
-                                    Some(Symbol::intern("us"))));
+                       mk_lit(token::Integer, "2", Some("us")));
             assert_eq!(setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok,
-                    token::Literal(token::StrRaw(Symbol::intern("raw"), 3),
-                                    Some(Symbol::intern("suffix"))));
+                       mk_lit(token::StrRaw(3), "raw", Some("suffix")));
             assert_eq!(setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok,
-                    token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3),
-                                    Some(Symbol::intern("suffix"))));
+                       mk_lit(token::ByteStrRaw(3), "raw", Some("suffix")));
         })
     }
 
@@ -1796,8 +1794,7 @@ fn nested_block_comments() {
                 token::Comment => {}
                 _ => panic!("expected a comment!"),
             }
-            assert_eq!(lexer.next_token().tok,
-                    token::Literal(token::Char(Symbol::intern("a")), None));
+            assert_eq!(lexer.next_token().tok, mk_lit(token::Char, "a", None));
         })
     }
 
index 53195421ddceeb90f3cb4b25a14a0fab54aa9683..0305b1f59b94652e4f1027bdd10af7c85fbf4d1d 100644 (file)
@@ -6,7 +6,7 @@
 use crate::parse::token::{self, Token};
 use crate::parse::unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte};
 use crate::print::pprust;
-use crate::symbol::{keywords, Symbol};
+use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{TokenStream, TokenTree};
 
 use errors::{Applicability, Handler};
 
 use std::ascii;
 
-macro_rules! err {
-    ($opt_diag:expr, |$span:ident, $diag:ident| $($body:tt)*) => {
-        match $opt_diag {
-            Some(($span, $diag)) => { $($body)* }
-            None => return None,
+crate enum LitError {
+    NotLiteral,
+    LexerError,
+    InvalidSuffix,
+    InvalidIntSuffix,
+    InvalidFloatSuffix,
+    NonDecimalFloat(u32),
+    IntTooLarge,
+}
+
+impl LitError {
+    fn report(&self, diag: &Handler, lit: token::Lit, span: Span) {
+        let token::Lit { kind, suffix, .. } = lit;
+        match *self {
+            // `NotLiteral` is not an error by itself, so we don't report
+            // it and give the parser opportunity to try something else.
+            LitError::NotLiteral => {}
+            // `LexerError` *is* an error, but it was already reported
+            // by lexer, so here we don't report it the second time.
+            LitError::LexerError => {}
+            LitError::InvalidSuffix => {
+                expect_no_suffix(
+                    diag, span, &format!("{} {} literal", kind.article(), kind.descr()), suffix
+                );
+            }
+            LitError::InvalidIntSuffix => {
+                let suf = suffix.expect("suffix error with no suffix").as_str();
+                if looks_like_width_suffix(&['i', 'u'], &suf) {
+                    // If it looks like a width, try to be helpful.
+                    let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
+                    diag.struct_span_err(span, &msg)
+                        .help("valid widths are 8, 16, 32, 64 and 128")
+                        .emit();
+                } else {
+                    let msg = format!("invalid suffix `{}` for integer literal", suf);
+                    diag.struct_span_err(span, &msg)
+                        .span_label(span, format!("invalid suffix `{}`", suf))
+                        .help("the suffix must be one of the integral types (`u32`, `isize`, etc)")
+                        .emit();
+                }
+            }
+            LitError::InvalidFloatSuffix => {
+                let suf = suffix.expect("suffix error with no suffix").as_str();
+                if looks_like_width_suffix(&['f'], &suf) {
+                    // If it looks like a width, try to be helpful.
+                    let msg = format!("invalid width `{}` for float literal", &suf[1..]);
+                    diag.struct_span_err(span, &msg)
+                        .help("valid widths are 32 and 64")
+                        .emit();
+                } else {
+                    let msg = format!("invalid suffix `{}` for float literal", suf);
+                    diag.struct_span_err(span, &msg)
+                        .span_label(span, format!("invalid suffix `{}`", suf))
+                        .help("valid suffixes are `f32` and `f64`")
+                        .emit();
+                }
+            }
+            LitError::NonDecimalFloat(base) => {
+                let descr = match base {
+                    16 => "hexadecimal",
+                    8 => "octal",
+                    2 => "binary",
+                    _ => unreachable!(),
+                };
+                diag.struct_span_err(span, &format!("{} float literal is not supported", descr))
+                    .span_label(span, "not supported")
+                    .emit();
+            }
+            LitError::IntTooLarge => {
+                diag.struct_span_err(span, "integer literal is too large")
+                    .emit();
+            }
         }
     }
 }
 
 impl LitKind {
-    /// Converts literal token with a suffix into a semantic literal.
-    /// Works speculatively and may return `None` if diagnostic handler is not passed.
-    /// If diagnostic handler is passed, always returns `Some`,
-    /// possibly after reporting non-fatal errors and recovery.
-    fn from_lit_token(
-        lit: token::Lit,
-        suf: Option<Symbol>,
-        diag: Option<(Span, &Handler)>
-    ) -> Option<LitKind> {
-        if suf.is_some() && !lit.may_have_suffix() {
-            err!(diag, |span, diag| {
-                expect_no_suffix(span, diag, &format!("a {}", lit.literal_name()), suf)
-            });
+    /// Converts literal token into a semantic literal.
+    fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
+        let token::Lit { kind, symbol, suffix } = lit;
+        if suffix.is_some() && !kind.may_have_suffix() {
+            return Err(LitError::InvalidSuffix);
         }
 
-        Some(match lit {
-            token::Bool(i) => {
-                assert!(i == keywords::True.name() || i == keywords::False.name());
-                LitKind::Bool(i == keywords::True.name())
+        Ok(match kind {
+            token::Bool => {
+                assert!(symbol == kw::True || symbol == kw::False);
+                LitKind::Bool(symbol == kw::True)
             }
-            token::Byte(i) => {
-                match unescape_byte(&i.as_str()) {
-                    Ok(c) => LitKind::Byte(c),
-                    Err(_) => LitKind::Err(i),
-                }
-            },
-            token::Char(i) => {
-                match unescape_char(&i.as_str()) {
-                    Ok(c) => LitKind::Char(c),
-                    Err(_) => LitKind::Err(i),
-                }
-            },
-            token::Err(i) => LitKind::Err(i),
+            token::Byte => return unescape_byte(&symbol.as_str())
+                .map(LitKind::Byte).map_err(|_| LitError::LexerError),
+            token::Char => return unescape_char(&symbol.as_str())
+                .map(LitKind::Char).map_err(|_| LitError::LexerError),
 
             // There are some valid suffixes for integer and float literals,
             // so all the handling is done internally.
-            token::Integer(s) => return integer_lit(&s.as_str(), suf, diag),
-            token::Float(s) => return float_lit(&s.as_str(), suf, diag),
+            token::Integer => return integer_lit(symbol, suffix),
+            token::Float => return float_lit(symbol, suffix),
 
-            token::Str_(mut sym) => {
+            token::Str => {
                 // If there are no characters requiring special treatment we can
-                // reuse the symbol from the Token. Otherwise, we must generate a
+                // reuse the symbol from the token. Otherwise, we must generate a
                 // new symbol because the string in the LitKind is different to the
-                // string in the Token.
-                let mut has_error = false;
-                let s = &sym.as_str();
-                if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') {
+                // string in the token.
+                let s = symbol.as_str();
+                let symbol = if s.contains(&['\\', '\r'][..]) {
                     let mut buf = String::with_capacity(s.len());
-                    unescape_str(s, &mut |_, unescaped_char| {
+                    let mut error = Ok(());
+                    unescape_str(&s, &mut |_, unescaped_char| {
                         match unescaped_char {
                             Ok(c) => buf.push(c),
-                            Err(_) => has_error = true,
+                            Err(_) => error = Err(LitError::LexerError),
                         }
                     });
-                    if has_error {
-                        return Some(LitKind::Err(sym));
-                    }
-                    sym = Symbol::intern(&buf)
-                }
-
-                LitKind::Str(sym, ast::StrStyle::Cooked)
+                    error?;
+                    Symbol::intern(&buf)
+                } else {
+                    symbol
+                };
+                LitKind::Str(symbol, ast::StrStyle::Cooked)
             }
-            token::StrRaw(mut sym, n) => {
+            token::StrRaw(n) => {
                 // Ditto.
-                let s = &sym.as_str();
-                if s.contains('\r') {
-                    sym = Symbol::intern(&raw_str_lit(s));
-                }
-                LitKind::Str(sym, ast::StrStyle::Raw(n))
+                let s = symbol.as_str();
+                let symbol = if s.contains('\r') {
+                    Symbol::intern(&raw_str_lit(&s))
+                } else {
+                    symbol
+                };
+                LitKind::Str(symbol, ast::StrStyle::Raw(n))
             }
-            token::ByteStr(i) => {
-                let s = &i.as_str();
+            token::ByteStr => {
+                let s = symbol.as_str();
                 let mut buf = Vec::with_capacity(s.len());
-                let mut has_error = false;
-                unescape_byte_str(s, &mut |_, unescaped_byte| {
+                let mut error = Ok(());
+                unescape_byte_str(&s, &mut |_, unescaped_byte| {
                     match unescaped_byte {
                         Ok(c) => buf.push(c),
-                        Err(_) => has_error = true,
+                        Err(_) => error = Err(LitError::LexerError),
                     }
                 });
-                if has_error {
-                    return Some(LitKind::Err(i));
-                }
+                error?;
                 buf.shrink_to_fit();
                 LitKind::ByteStr(Lrc::new(buf))
             }
-            token::ByteStrRaw(i, _) => {
-                LitKind::ByteStr(Lrc::new(i.to_string().into_bytes()))
-            }
+            token::ByteStrRaw(_) => LitKind::ByteStr(Lrc::new(symbol.to_string().into_bytes())),
+            token::Err => LitKind::Err(symbol),
         })
     }
 
     /// Attempts to recover a token from semantic literal.
     /// This function is used when the original token doesn't exist (e.g. the literal is created
     /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
-    pub fn to_lit_token(&self) -> (token::Lit, Option<Symbol>) {
-        match *self {
+    pub fn to_lit_token(&self) -> token::Lit {
+        let (kind, symbol, suffix) = match *self {
             LitKind::Str(string, ast::StrStyle::Cooked) => {
                 let escaped = string.as_str().escape_default().to_string();
-                (token::Lit::Str_(Symbol::intern(&escaped)), None)
+                (token::Str, Symbol::intern(&escaped), None)
             }
             LitKind::Str(string, ast::StrStyle::Raw(n)) => {
-                (token::Lit::StrRaw(string, n), None)
+                (token::StrRaw(n), string, None)
             }
             LitKind::ByteStr(ref bytes) => {
                 let string = bytes.iter().cloned().flat_map(ascii::escape_default)
                     .map(Into::<char>::into).collect::<String>();
-                (token::Lit::ByteStr(Symbol::intern(&string)), None)
+                (token::ByteStr, Symbol::intern(&string), None)
             }
             LitKind::Byte(byte) => {
                 let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
-                (token::Lit::Byte(Symbol::intern(&string)), None)
+                (token::Byte, Symbol::intern(&string), None)
             }
             LitKind::Char(ch) => {
                 let string: String = ch.escape_default().map(Into::<char>::into).collect();
-                (token::Lit::Char(Symbol::intern(&string)), None)
+                (token::Char, Symbol::intern(&string), None)
             }
             LitKind::Int(n, ty) => {
                 let suffix = match ty {
@@ -149,65 +197,66 @@ pub fn to_lit_token(&self) -> (token::Lit, Option<Symbol>) {
                     ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())),
                     ast::LitIntType::Unsuffixed => None,
                 };
-                (token::Lit::Integer(Symbol::intern(&n.to_string())), suffix)
+                (token::Integer, Symbol::intern(&n.to_string()), suffix)
             }
             LitKind::Float(symbol, ty) => {
-                (token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string())))
+                (token::Float, symbol, Some(Symbol::intern(ty.ty_to_string())))
+            }
+            LitKind::FloatUnsuffixed(symbol) => {
+                (token::Float, symbol, None)
             }
-            LitKind::FloatUnsuffixed(symbol) => (token::Lit::Float(symbol), None),
             LitKind::Bool(value) => {
-                let kw = if value { keywords::True } else { keywords::False };
-                (token::Lit::Bool(kw.name()), None)
+                let symbol = if value { kw::True } else { kw::False };
+                (token::Bool, symbol, None)
             }
-            LitKind::Err(val) => (token::Lit::Err(val), None),
-        }
+            LitKind::Err(symbol) => {
+                (token::Err, symbol, None)
+            }
+        };
+
+        token::Lit::new(kind, symbol, suffix)
     }
 }
 
 impl Lit {
-    /// Converts literal token with a suffix into an AST literal.
-    /// Works speculatively and may return `None` if diagnostic handler is not passed.
-    /// If diagnostic handler is passed, may return `Some`,
-    /// possibly after reporting non-fatal errors and recovery, or `None` for irrecoverable errors.
-    crate fn from_token(
-        token: &token::Token,
-        span: Span,
-        diag: Option<(Span, &Handler)>,
-    ) -> Option<Lit> {
-        let (token, suffix) = match *token {
-            token::Ident(ident, false) if ident.name == keywords::True.name() ||
-                                          ident.name == keywords::False.name() =>
-                (token::Bool(ident.name), None),
-            token::Literal(token, suffix) =>
-                (token, suffix),
+    /// Converts literal token into an AST literal.
+    fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
+        Ok(Lit { token, node: LitKind::from_lit_token(token)?, span })
+    }
+
+    /// Converts arbitrary token into an AST literal.
+    crate fn from_token(token: &Token, span: Span) -> Result<Lit, LitError> {
+        let lit = match *token {
+            token::Ident(ident, false) if ident.name == kw::True || ident.name == kw::False =>
+                token::Lit::new(token::Bool, ident.name, None),
+            token::Literal(lit) =>
+                lit,
             token::Interpolated(ref nt) => {
                 if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
                     if let ast::ExprKind::Lit(lit) = &expr.node {
-                        return Some(lit.clone());
+                        return Ok(lit.clone());
                     }
                 }
-                return None;
+                return Err(LitError::NotLiteral);
             }
-            _ => return None,
+            _ => return Err(LitError::NotLiteral)
         };
 
-        let node = LitKind::from_lit_token(token, suffix, diag)?;
-        Some(Lit { node, token, suffix, span })
+        Lit::from_lit_token(lit, span)
     }
 
     /// Attempts to recover an AST literal from semantic literal.
     /// This function is used when the original token doesn't exist (e.g. the literal is created
     /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
     pub fn from_lit_kind(node: LitKind, span: Span) -> Lit {
-        let (token, suffix) = node.to_lit_token();
-        Lit { node, token, suffix, span }
+        Lit { token: node.to_lit_token(), node, span }
     }
 
     /// Losslessly convert an AST literal into a token stream.
     crate fn tokens(&self) -> TokenStream {
-        let token = match self.token {
-            token::Bool(symbol) => Token::Ident(Ident::with_empty_ctxt(symbol), false),
-            token => Token::Literal(token, self.suffix),
+        let token = match self.token.kind {
+            token::Bool => token::Ident(Ident::new(self.token.symbol, self.span), false),
+            _ => token::Literal(self.token),
         };
         TokenTree::Token(self.span, token).into()
     }
@@ -216,24 +265,22 @@ pub fn from_lit_kind(node: LitKind, span: Span) -> Lit {
 impl<'a> Parser<'a> {
     /// Matches `lit = true | false | token_lit`.
     crate fn parse_lit(&mut self) -> PResult<'a, Lit> {
-        let diag = Some((self.span, &self.sess.span_diagnostic));
-        if let Some(lit) = Lit::from_token(&self.token, self.span, diag) {
-            self.bump();
-            return Ok(lit);
-        } else if self.token == token::Dot {
-            // Recover `.4` as `0.4`.
-            let recovered = self.look_ahead(1, |t| {
-                if let token::Literal(token::Integer(val), suf) = *t {
+        let mut recovered = None;
+        if self.token == token::Dot {
+            // Attempt to recover `.4` as `0.4`.
+            recovered = self.look_ahead(1, |t| {
+                if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = *t {
                     let next_span = self.look_ahead_span(1);
                     if self.span.hi() == next_span.lo() {
-                        let sym = String::from("0.") + &val.as_str();
-                        let token = token::Literal(token::Float(Symbol::intern(&sym)), suf);
+                        let s = String::from("0.") + &symbol.as_str();
+                        let token = Token::lit(token::Float, Symbol::intern(&s), suffix);
                         return Some((token, self.span.to(next_span)));
                     }
                 }
                 None
             });
-            if let Some((token, span)) = recovered {
+            if let Some((ref token, span)) = recovered {
+                self.bump();
                 self.diagnostic()
                     .struct_span_err(span, "float literals must have an integer part")
                     .span_suggestion(
@@ -243,63 +290,68 @@ impl<'a> Parser<'a> {
                         Applicability::MachineApplicable,
                     )
                     .emit();
-                let diag = Some((span, &self.sess.span_diagnostic));
-                if let Some(lit) = Lit::from_token(&token, span, diag) {
-                    self.bump();
-                    self.bump();
-                    return Ok(lit);
-                }
             }
         }
 
-        Err(self.span_fatal(self.span, &format!("unexpected token: {}", self.this_token_descr())))
-    }
-}
+        let (token, span) = recovered.as_ref().map_or((&self.token, self.span),
+                                                      |(token, span)| (token, *span));
 
-crate fn expect_no_suffix(sp: Span, diag: &Handler, kind: &str, suffix: Option<ast::Name>) {
-    match suffix {
-        None => {/* everything ok */}
-        Some(suf) => {
-            let text = suf.as_str();
-            if text.is_empty() {
-                diag.span_bug(sp, "found empty literal suffix in Some")
+        match Lit::from_token(token, span) {
+            Ok(lit) => {
+                self.bump();
+                Ok(lit)
+            }
+            Err(LitError::NotLiteral) => {
+                let msg = format!("unexpected token: {}", self.this_token_descr());
+                Err(self.span_fatal(span, &msg))
+            }
+            Err(err) => {
+                let lit = token.expect_lit();
+                self.bump();
+                err.report(&self.sess.span_diagnostic, lit, span);
+                let lit = token::Lit::new(token::Err, lit.symbol, lit.suffix);
+                Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
             }
-            let mut err = if kind == "a tuple index" &&
-                ["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str())
-            {
-                // #59553: warn instead of reject out of hand to allow the fix to percolate
-                // through the ecosystem when people fix their macros
-                let mut err = diag.struct_span_warn(
-                    sp,
-                    &format!("suffixes on {} are invalid", kind),
-                );
-                err.note(&format!(
-                    "`{}` is *temporarily* accepted on tuple index fields as it was \
-                        incorrectly accepted on stable for a few releases",
-                    text,
-                ));
-                err.help(
-                    "on proc macros, you'll want to use `syn::Index::from` or \
-                        `proc_macro::Literal::*_unsuffixed` for code that will desugar \
-                        to tuple field access",
-                );
-                err.note(
-                    "for more context, see https://github.com/rust-lang/rust/issues/60210",
-                );
-                err
-            } else {
-                diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
-            };
-            err.span_label(sp, format!("invalid suffix `{}`", text));
-            err.emit();
         }
     }
 }
 
+crate fn expect_no_suffix(diag: &Handler, sp: Span, kind: &str, suffix: Option<Symbol>) {
+    if let Some(suf) = suffix {
+        let mut err = if kind == "a tuple index" &&
+                         [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) {
+            // #59553: warn instead of reject out of hand to allow the fix to percolate
+            // through the ecosystem when people fix their macros
+            let mut err = diag.struct_span_warn(
+                sp,
+                &format!("suffixes on {} are invalid", kind),
+            );
+            err.note(&format!(
+                "`{}` is *temporarily* accepted on tuple index fields as it was \
+                    incorrectly accepted on stable for a few releases",
+                suf,
+            ));
+            err.help(
+                "on proc macros, you'll want to use `syn::Index::from` or \
+                    `proc_macro::Literal::*_unsuffixed` for code that will desugar \
+                    to tuple field access",
+            );
+            err.note(
+                "for more context, see https://github.com/rust-lang/rust/issues/60210",
+            );
+            err
+        } else {
+            diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
+        };
+        err.span_label(sp, format!("invalid suffix `{}`", suf));
+        err.emit();
+    }
+}
+
 /// Parses a string representing a raw string literal into its final form. The
 /// only operation this does is convert embedded CRLF into a single LF.
 fn raw_str_lit(lit: &str) -> String {
-    debug!("raw_str_lit: given {}", lit.escape_default());
+    debug!("raw_str_lit: {:?}", lit);
     let mut res = String::with_capacity(lit.len());
 
     let mut chars = lit.chars().peekable();
@@ -319,169 +371,87 @@ fn raw_str_lit(lit: &str) -> String {
     res
 }
 
-// check if `s` looks like i32 or u1234 etc.
+// Checks if `s` looks like i32 or u1234 etc.
 fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
-    s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
+    s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
 }
 
-fn filtered_float_lit(data: Symbol, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
-                      -> Option<LitKind> {
-    debug!("filtered_float_lit: {}, {:?}", data, suffix);
-    let suffix = match suffix {
-        Some(suffix) => suffix,
-        None => return Some(LitKind::FloatUnsuffixed(data)),
-    };
-
-    Some(match &*suffix.as_str() {
-        "f32" => LitKind::Float(data, ast::FloatTy::F32),
-        "f64" => LitKind::Float(data, ast::FloatTy::F64),
-        suf => {
-            err!(diag, |span, diag| {
-                if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) {
-                    // if it looks like a width, lets try to be helpful.
-                    let msg = format!("invalid width `{}` for float literal", &suf[1..]);
-                    diag.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit()
-                } else {
-                    let msg = format!("invalid suffix `{}` for float literal", suf);
-                    diag.struct_span_err(span, &msg)
-                        .span_label(span, format!("invalid suffix `{}`", suf))
-                        .help("valid suffixes are `f32` and `f64`")
-                        .emit();
-                }
-            });
+fn strip_underscores(symbol: Symbol) -> Symbol {
+    // Do not allocate a new string unless necessary.
+    let s = symbol.as_str();
+    if s.contains('_') {
+        let mut s = s.to_string();
+        s.retain(|c| c != '_');
+        return Symbol::intern(&s);
+    }
+    symbol
+}
 
-            LitKind::FloatUnsuffixed(data)
+fn filtered_float_lit(symbol: Symbol, suffix: Option<Symbol>, base: u32)
+                      -> Result<LitKind, LitError> {
+    debug!("filtered_float_lit: {:?}, {:?}, {:?}", symbol, suffix, base);
+    if base != 10 {
+        return Err(LitError::NonDecimalFloat(base));
+    }
+    Ok(match suffix {
+        Some(suf) => match suf {
+            sym::f32 => LitKind::Float(symbol, ast::FloatTy::F32),
+            sym::f64 => LitKind::Float(symbol, ast::FloatTy::F64),
+            _ => return Err(LitError::InvalidFloatSuffix),
         }
+        None => LitKind::FloatUnsuffixed(symbol)
     })
 }
-fn float_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
-                 -> Option<LitKind> {
-    debug!("float_lit: {:?}, {:?}", s, suffix);
-    // FIXME #2252: bounds checking float literals is deferred until trans
-
-    // Strip underscores without allocating a new String unless necessary.
-    let s2;
-    let s = if s.chars().any(|c| c == '_') {
-        s2 = s.chars().filter(|&c| c != '_').collect::<String>();
-        &s2
-    } else {
-        s
-    };
 
-    filtered_float_lit(Symbol::intern(s), suffix, diag)
+fn float_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
+    debug!("float_lit: {:?}, {:?}", symbol, suffix);
+    filtered_float_lit(strip_underscores(symbol), suffix, 10)
 }
 
-fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
-                   -> Option<LitKind> {
-    // s can only be ascii, byte indexing is fine
-
-    // Strip underscores without allocating a new String unless necessary.
-    let s2;
-    let mut s = if s.chars().any(|c| c == '_') {
-        s2 = s.chars().filter(|&c| c != '_').collect::<String>();
-        &s2
-    } else {
-        s
-    };
-
-    debug!("integer_lit: {}, {:?}", s, suffix);
+fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
+    debug!("integer_lit: {:?}, {:?}", symbol, suffix);
+    let symbol = strip_underscores(symbol);
+    let s = symbol.as_str();
 
     let mut base = 10;
-    let orig = s;
-    let mut ty = ast::LitIntType::Unsuffixed;
-
-    if s.starts_with('0') && s.len() > 1 {
+    if s.len() > 1 && s.as_bytes()[0] == b'0' {
         match s.as_bytes()[1] {
             b'x' => base = 16,
             b'o' => base = 8,
             b'b' => base = 2,
-            _ => { }
+            _ => {}
         }
     }
 
-    // 1f64 and 2f32 etc. are valid float literals.
-    if let Some(suf) = suffix {
-        if looks_like_width_suffix(&['f'], &suf.as_str()) {
-            let err = match base {
-                16 => Some("hexadecimal float literal is not supported"),
-                8 => Some("octal float literal is not supported"),
-                2 => Some("binary float literal is not supported"),
-                _ => None,
-            };
-            if let Some(err) = err {
-                err!(diag, |span, diag| {
-                    diag.struct_span_err(span, err)
-                        .span_label(span, "not supported")
-                        .emit();
-                });
-            }
-            return filtered_float_lit(Symbol::intern(s), Some(suf), diag)
-        }
-    }
-
-    if base != 10 {
-        s = &s[2..];
-    }
-
-    if let Some(suf) = suffix {
-        if suf.as_str().is_empty() {
-            err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some"));
-        }
-        ty = match &*suf.as_str() {
-            "isize" => ast::LitIntType::Signed(ast::IntTy::Isize),
-            "i8"  => ast::LitIntType::Signed(ast::IntTy::I8),
-            "i16" => ast::LitIntType::Signed(ast::IntTy::I16),
-            "i32" => ast::LitIntType::Signed(ast::IntTy::I32),
-            "i64" => ast::LitIntType::Signed(ast::IntTy::I64),
-            "i128" => ast::LitIntType::Signed(ast::IntTy::I128),
-            "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize),
-            "u8"  => ast::LitIntType::Unsigned(ast::UintTy::U8),
-            "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
-            "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
-            "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
-            "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128),
-            suf => {
-                // i<digits> and u<digits> look like widths, so lets
-                // give an error message along those lines
-                err!(diag, |span, diag| {
-                    if looks_like_width_suffix(&['i', 'u'], suf) {
-                        let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
-                        diag.struct_span_err(span, &msg)
-                            .help("valid widths are 8, 16, 32, 64 and 128")
-                            .emit();
-                    } else {
-                        let msg = format!("invalid suffix `{}` for numeric literal", suf);
-                        diag.struct_span_err(span, &msg)
-                            .span_label(span, format!("invalid suffix `{}`", suf))
-                            .help("the suffix must be one of the integral types \
-                                   (`u32`, `isize`, etc)")
-                            .emit();
-                    }
-                });
-
-                ty
-            }
+    let ty = match suffix {
+        Some(suf) => match suf {
+            sym::isize => ast::LitIntType::Signed(ast::IntTy::Isize),
+            sym::i8  => ast::LitIntType::Signed(ast::IntTy::I8),
+            sym::i16 => ast::LitIntType::Signed(ast::IntTy::I16),
+            sym::i32 => ast::LitIntType::Signed(ast::IntTy::I32),
+            sym::i64 => ast::LitIntType::Signed(ast::IntTy::I64),
+            sym::i128 => ast::LitIntType::Signed(ast::IntTy::I128),
+            sym::usize => ast::LitIntType::Unsigned(ast::UintTy::Usize),
+            sym::u8  => ast::LitIntType::Unsigned(ast::UintTy::U8),
+            sym::u16 => ast::LitIntType::Unsigned(ast::UintTy::U16),
+            sym::u32 => ast::LitIntType::Unsigned(ast::UintTy::U32),
+            sym::u64 => ast::LitIntType::Unsigned(ast::UintTy::U64),
+            sym::u128 => ast::LitIntType::Unsigned(ast::UintTy::U128),
+            // `1f64` and `2f32` etc. are valid float literals, and
+            // `fxxx` looks more like an invalid float literal than invalid integer literal.
+            _ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base),
+            _ => return Err(LitError::InvalidIntSuffix),
         }
-    }
-
-    debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \
-           string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix);
-
-    Some(match u128::from_str_radix(s, base) {
-        Ok(r) => LitKind::Int(r, ty),
-        Err(_) => {
-            // small bases are lexed as if they were base 10, e.g, the string
-            // might be `0b10201`. This will cause the conversion above to fail,
-            // but these cases have errors in the lexer: we don't want to emit
-            // two errors, and we especially don't want to emit this error since
-            // it isn't necessarily true.
-            let already_errored = base < 10 &&
-                s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
+        _ => ast::LitIntType::Unsuffixed
+    };
 
-            if !already_errored {
-                err!(diag, |span, diag| diag.span_err(span, "int literal is too large"));
-            }
-            LitKind::Int(0, ty)
-        }
+    let s = &s[if base != 10 { 2 } else { 0 } ..];
+    u128::from_str_radix(s, base).map(|i| LitKind::Int(i, ty)).map_err(|_| {
+        // Small bases are lexed as if they were base 10, e.g, the string
+        // might be `0b10201`. This will cause the conversion above to fail,
+        // but these kinds of errors are already reported by the lexer.
+        let from_lexer =
+            base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
+        if from_lexer { LitError::LexerError } else { LitError::IntTooLarge }
     })
 }
index 24d120376def15092077d3b91594222bbcc8491d..ae3665c834bd3e9c0b949a5281d3f4ff9eac5d34 100644 (file)
@@ -46,7 +46,7 @@
 use crate::parse::PResult;
 use crate::ThinVec;
 use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
-use crate::symbol::{keywords, sym, Symbol};
+use crate::symbol::{kw, sym, Symbol};
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
 use rustc_target::spec::abi::{self, Abi};
@@ -352,10 +352,12 @@ fn next_desugared(&mut self) -> TokenAndSpan {
         let body = TokenTree::Delimited(
             delim_span,
             token::Bracket,
-            [TokenTree::Token(sp, token::Ident(ast::Ident::with_empty_ctxt(sym::doc), false)),
-             TokenTree::Token(sp, token::Eq),
-             TokenTree::Token(sp, token::Literal(
-                token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))
+            [
+                TokenTree::Token(sp, token::Ident(ast::Ident::with_empty_ctxt(sym::doc), false)),
+                TokenTree::Token(sp, token::Eq),
+                TokenTree::Token(sp, token::Token::lit(
+                    token::StrRaw(num_of_hashes), Symbol::intern(&stripped), None
+                )),
             ]
             .iter().cloned().collect::<TokenStream>().into(),
         );
@@ -379,7 +381,7 @@ fn next_desugared(&mut self) -> TokenAndSpan {
 #[derive(Clone, PartialEq)]
 crate enum TokenType {
     Token(token::Token),
-    Keyword(keywords::Keyword),
+    Keyword(Symbol),
     Operator,
     Lifetime,
     Ident,
@@ -392,7 +394,7 @@ impl TokenType {
     crate fn to_string(&self) -> String {
         match *self {
             TokenType::Token(ref t) => format!("`{}`", pprust::token_to_string(t)),
-            TokenType::Keyword(kw) => format!("`{}`", kw.name()),
+            TokenType::Keyword(kw) => format!("`{}`", kw),
             TokenType::Operator => "an operator".to_string(),
             TokenType::Lifetime => "lifetime".to_string(),
             TokenType::Ident => "identifier".to_string(),
@@ -510,7 +512,7 @@ fn from(expr: P<Expr>) -> Self {
 
 /// Creates a placeholder argument.
 fn dummy_arg(span: Span) -> Arg {
-    let ident = Ident::new(keywords::Invalid.name(), span);
+    let ident = Ident::new(kw::Invalid, span);
     let pat = P(Pat {
         id: ast::DUMMY_NODE_ID,
         node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
@@ -771,15 +773,15 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
                 TokenType::Token(token::Semi) => true, // we expect a `;` here
                 _ => false,
             }) && ( // a `;` would be expected before the current keyword
-                self.token.is_keyword(keywords::Break) ||
-                self.token.is_keyword(keywords::Continue) ||
-                self.token.is_keyword(keywords::For) ||
-                self.token.is_keyword(keywords::If) ||
-                self.token.is_keyword(keywords::Let) ||
-                self.token.is_keyword(keywords::Loop) ||
-                self.token.is_keyword(keywords::Match) ||
-                self.token.is_keyword(keywords::Return) ||
-                self.token.is_keyword(keywords::While)
+                self.token.is_keyword(kw::Break) ||
+                self.token.is_keyword(kw::Continue) ||
+                self.token.is_keyword(kw::For) ||
+                self.token.is_keyword(kw::If) ||
+                self.token.is_keyword(kw::Let) ||
+                self.token.is_keyword(kw::Loop) ||
+                self.token.is_keyword(kw::Match) ||
+                self.token.is_keyword(kw::Return) ||
+                self.token.is_keyword(kw::While)
             );
             let cm = self.sess.source_map();
             match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
@@ -913,14 +915,14 @@ pub fn eat(&mut self, tok: &token::Token) -> bool {
         is_present
     }
 
-    fn check_keyword(&mut self, kw: keywords::Keyword) -> bool {
+    fn check_keyword(&mut self, kw: Symbol) -> bool {
         self.expected_tokens.push(TokenType::Keyword(kw));
         self.token.is_keyword(kw)
     }
 
     /// If the next token is the given keyword, eats it and returns
     /// `true`. Otherwise, returns `false`.
-    pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool {
+    pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
         if self.check_keyword(kw) {
             self.bump();
             true
@@ -929,7 +931,7 @@ pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool {
         }
     }
 
-    fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool {
+    fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
         if self.token.is_keyword(kw) {
             self.bump();
             true
@@ -941,7 +943,7 @@ fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool {
     /// If the given word is not a keyword, signals an error.
     /// If the next token is not the given word, signals an error.
     /// Otherwise, eats it.
-    fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, ()> {
+    fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> {
         if !self.eat_keyword(kw) {
             self.unexpected()
         } else {
@@ -1054,7 +1056,7 @@ fn expect_or(&mut self) -> PResult<'a, ()> {
     }
 
     fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) {
-        literal::expect_no_suffix(sp, &self.sess.span_diagnostic, kind, suffix)
+        literal::expect_no_suffix(&self.sess.span_diagnostic, sp, kind, suffix)
     }
 
     /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single
@@ -1375,9 +1377,9 @@ fn cancel(&self, err: &mut DiagnosticBuilder<'_>) {
 
     /// Is the current token one of the keywords that signals a bare function type?
     fn token_is_bare_fn_keyword(&mut self) -> bool {
-        self.check_keyword(keywords::Fn) ||
-            self.check_keyword(keywords::Unsafe) ||
-            self.check_keyword(keywords::Extern)
+        self.check_keyword(kw::Fn) ||
+            self.check_keyword(kw::Unsafe) ||
+            self.check_keyword(kw::Extern)
     }
 
     /// Parses a `TyKind::BareFn` type.
@@ -1395,13 +1397,13 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a,
         */
 
         let unsafety = self.parse_unsafety();
-        let abi = if self.eat_keyword(keywords::Extern) {
+        let abi = if self.eat_keyword(kw::Extern) {
             self.parse_opt_abi()?.unwrap_or(Abi::C)
         } else {
             Abi::Rust
         };
 
-        self.expect_keyword(keywords::Fn)?;
+        self.expect_keyword(kw::Fn)?;
         let (inputs, c_variadic) = self.parse_fn_args(false, true)?;
         let ret_ty = self.parse_ret_ty(false)?;
         let decl = P(FnDecl {
@@ -1419,7 +1421,7 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a,
 
     /// Parses asyncness: `async` or nothing.
     fn parse_asyncness(&mut self) -> IsAsync {
-        if self.eat_keyword(keywords::Async) {
+        if self.eat_keyword(kw::Async) {
             IsAsync::Async {
                 closure_id: ast::DUMMY_NODE_ID,
                 return_impl_trait_id: ast::DUMMY_NODE_ID,
@@ -1432,7 +1434,7 @@ fn parse_asyncness(&mut self) -> IsAsync {
 
     /// Parses unsafety: `unsafe` or nothing.
     fn parse_unsafety(&mut self) -> Unsafety {
-        if self.eat_keyword(keywords::Unsafe) {
+        if self.eat_keyword(kw::Unsafe) {
             Unsafety::Unsafe
         } else {
             Unsafety::Normal
@@ -1462,10 +1464,10 @@ fn parse_trait_item_(&mut self,
                          mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
         let lo = self.span;
         self.eat_bad_pub();
-        let (name, node, generics) = if self.eat_keyword(keywords::Type) {
+        let (name, node, generics) = if self.eat_keyword(kw::Type) {
             self.parse_trait_item_assoc_ty()?
         } else if self.is_const_item() {
-            self.expect_keyword(keywords::Const)?;
+            self.expect_keyword(kw::Const)?;
             let ident = self.parse_ident()?;
             self.expect(&token::Colon)?;
             let ty = self.parse_ty()?;
@@ -1480,7 +1482,7 @@ fn parse_trait_item_(&mut self,
             (ident, TraitItemKind::Const(ty, default), ast::Generics::default())
         } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
             // trait item macro.
-            (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
+            (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
         } else {
             let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
 
@@ -1654,7 +1656,7 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
             // Reference
             self.expect_and()?;
             self.parse_borrowed_pointee()?
-        } else if self.eat_keyword_noexpect(keywords::Typeof) {
+        } else if self.eat_keyword_noexpect(kw::Typeof) {
             // `typeof(EXPR)`
             // In order to not be ambiguous, the type must be surrounded by parens.
             self.expect(&token::OpenDelim(token::Paren))?;
@@ -1664,13 +1666,13 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
             };
             self.expect(&token::CloseDelim(token::Paren))?;
             TyKind::Typeof(e)
-        } else if self.eat_keyword(keywords::Underscore) {
+        } else if self.eat_keyword(kw::Underscore) {
             // A type to be inferred `_`
             TyKind::Infer
         } else if self.token_is_bare_fn_keyword() {
             // Function pointer type
             self.parse_ty_bare_fn(Vec::new())?
-        } else if self.check_keyword(keywords::For) {
+        } else if self.check_keyword(kw::For) {
             // Function pointer type or bound list (trait object type) starting with a poly-trait.
             //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
             //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
@@ -1683,12 +1685,12 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
                 let parse_plus = allow_plus && self.check_plus();
                 self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
             }
-        } else if self.eat_keyword(keywords::Impl) {
+        } else if self.eat_keyword(kw::Impl) {
             // Always parse bounds greedily for better error recovery.
             let bounds = self.parse_generic_bounds(None)?;
             impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
             TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
-        } else if self.check_keyword(keywords::Dyn) &&
+        } else if self.check_keyword(kw::Dyn) &&
                   (self.span.rust_2018() ||
                    self.look_ahead(1, |t| t.can_begin_bound() &&
                                           !can_continue_type_after_non_fn_ident(t))) {
@@ -1766,9 +1768,9 @@ fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
     }
 
     fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
-        let mutbl = if self.eat_keyword(keywords::Mut) {
+        let mutbl = if self.eat_keyword(kw::Mut) {
             Mutability::Mutable
-        } else if self.eat_keyword(keywords::Const) {
+        } else if self.eat_keyword(kw::Const) {
             Mutability::Immutable
         } else {
             let span = self.prev_span;
@@ -1790,7 +1792,7 @@ fn is_named_argument(&self) -> bool {
                 _ => 0,
             }
             token::BinOp(token::And) | token::AndAnd => 1,
-            _ if self.token.is_keyword(keywords::Mut) => 1,
+            _ if self.token.is_keyword(kw::Mut) => 1,
             _ => 0,
         };
 
@@ -1891,7 +1893,7 @@ fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool,
             }
             match ty {
                 Ok(ty) => {
-                    let ident = Ident::new(keywords::Invalid.name(), self.prev_span);
+                    let ident = Ident::new(kw::Invalid, self.prev_span);
                     let pat = P(Pat {
                         id: ast::DUMMY_NODE_ID,
                         node: PatKind::Ident(
@@ -2006,7 +2008,7 @@ fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> {
 
     fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
         match self.token {
-            token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
+            token::Ident(ident, false) if ident.name == kw::Underscore => {
                 let span = self.span;
                 self.bump();
                 Ok(Ident::new(ident.name, span))
@@ -2034,7 +2036,7 @@ fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> {
         // above). `path_span` has the span of that path, or an empty
         // span in the case of something like `<T>::Bar`.
         let (mut path, path_span);
-        if self.eat_keyword(keywords::As) {
+        if self.eat_keyword(kw::As) {
             let path_lo = self.span;
             path = self.parse_path(PathStyle::Type)?;
             path_span = path_lo.to(self.prev_span);
@@ -2233,7 +2235,7 @@ fn eat_label(&mut self) -> Option<Label> {
 
     /// Parses mutability (`mut` or nothing).
     fn parse_mutability(&mut self) -> Mutability {
-        if self.eat_keyword(keywords::Mut) {
+        if self.eat_keyword(kw::Mut) {
             Mutability::Mutable
         } else {
             Mutability::Immutable
@@ -2241,10 +2243,10 @@ fn parse_mutability(&mut self) -> Mutability {
     }
 
     fn parse_field_name(&mut self) -> PResult<'a, Ident> {
-        if let token::Literal(token::Integer(name), suffix) = self.token {
+        if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token {
             self.expect_no_suffix(self.span, "a tuple index", suffix);
             self.bump();
-            Ok(Ident::new(name, self.prev_span))
+            Ok(Ident::new(symbol, self.prev_span))
         } else {
             self.parse_ident_common(false)
         }
@@ -2465,37 +2467,37 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     hi = path.span;
                     return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
                 }
-                if self.span.rust_2018() && self.check_keyword(keywords::Async) {
+                if self.span.rust_2018() && self.check_keyword(kw::Async) {
                     return if self.is_async_block() { // check for `async {` and `async move {`
                         self.parse_async_block(attrs)
                     } else {
                         self.parse_lambda_expr(attrs)
                     };
                 }
-                if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) {
+                if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
                     return self.parse_lambda_expr(attrs);
                 }
-                if self.eat_keyword(keywords::If) {
+                if self.eat_keyword(kw::If) {
                     return self.parse_if_expr(attrs);
                 }
-                if self.eat_keyword(keywords::For) {
+                if self.eat_keyword(kw::For) {
                     let lo = self.prev_span;
                     return self.parse_for_expr(None, lo, attrs);
                 }
-                if self.eat_keyword(keywords::While) {
+                if self.eat_keyword(kw::While) {
                     let lo = self.prev_span;
                     return self.parse_while_expr(None, lo, attrs);
                 }
                 if let Some(label) = self.eat_label() {
                     let lo = label.ident.span;
                     self.expect(&token::Colon)?;
-                    if self.eat_keyword(keywords::While) {
+                    if self.eat_keyword(kw::While) {
                         return self.parse_while_expr(Some(label), lo, attrs)
                     }
-                    if self.eat_keyword(keywords::For) {
+                    if self.eat_keyword(kw::For) {
                         return self.parse_for_expr(Some(label), lo, attrs)
                     }
-                    if self.eat_keyword(keywords::Loop) {
+                    if self.eat_keyword(kw::Loop) {
                         return self.parse_loop_expr(Some(label), lo, attrs)
                     }
                     if self.token == token::OpenDelim(token::Brace) {
@@ -2509,24 +2511,24 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     err.span_label(self.span, msg);
                     return Err(err);
                 }
-                if self.eat_keyword(keywords::Loop) {
+                if self.eat_keyword(kw::Loop) {
                     let lo = self.prev_span;
                     return self.parse_loop_expr(None, lo, attrs);
                 }
-                if self.eat_keyword(keywords::Continue) {
+                if self.eat_keyword(kw::Continue) {
                     let label = self.eat_label();
                     let ex = ExprKind::Continue(label);
                     let hi = self.prev_span;
                     return Ok(self.mk_expr(lo.to(hi), ex, attrs));
                 }
-                if self.eat_keyword(keywords::Match) {
+                if self.eat_keyword(kw::Match) {
                     let match_sp = self.prev_span;
                     return self.parse_match_expr(attrs).map_err(|mut err| {
                         err.span_label(match_sp, "while parsing this match expression");
                         err
                     });
                 }
-                if self.eat_keyword(keywords::Unsafe) {
+                if self.eat_keyword(kw::Unsafe) {
                     return self.parse_block_expr(
                         None,
                         lo,
@@ -2540,10 +2542,10 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 }
                 if self.is_try_block() {
                     let lo = self.span;
-                    assert!(self.eat_keyword(keywords::Try));
+                    assert!(self.eat_keyword(kw::Try));
                     return self.parse_try_block(lo, attrs);
                 }
-                if self.eat_keyword(keywords::Return) {
+                if self.eat_keyword(kw::Return) {
                     if self.token.can_begin_expr() {
                         let e = self.parse_expr()?;
                         hi = e.span;
@@ -2551,7 +2553,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     } else {
                         ex = ExprKind::Ret(None);
                     }
-                } else if self.eat_keyword(keywords::Break) {
+                } else if self.eat_keyword(kw::Break) {
                     let label = self.eat_label();
                     let e = if self.token.can_begin_expr()
                                && !(self.token == token::OpenDelim(token::Brace)
@@ -2563,7 +2565,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     };
                     ex = ExprKind::Break(label, e);
                     hi = self.prev_span;
-                } else if self.eat_keyword(keywords::Yield) {
+                } else if self.eat_keyword(kw::Yield) {
                     if self.token.can_begin_expr() {
                         let e = self.parse_expr()?;
                         hi = e.span;
@@ -2571,14 +2573,14 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     } else {
                         ex = ExprKind::Yield(None);
                     }
-                } else if self.token.is_keyword(keywords::Let) {
+                } else if self.token.is_keyword(kw::Let) {
                     // Catch this syntax error here, instead of in `parse_ident`, so
                     // that we can explicitly mention that let is not to be used as an expression
                     let mut db = self.fatal("expected expression, found statement (`let`)");
                     db.span_label(self.span, "expected expression");
                     db.note("variable declaration using `let` is a statement");
                     return Err(db);
-                } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) {
+                } else if self.span.rust_2018() && self.eat_keyword(kw::Await) {
                     let (await_hi, e_kind) = self.parse_await_macro_or_alt(lo, self.prev_span)?;
                     hi = await_hi;
                     ex = e_kind;
@@ -2879,7 +2881,7 @@ fn parse_dot_or_call_expr_with(&mut self,
 
     // Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        if self.span.rust_2018() && self.eat_keyword(keywords::Await) {
+        if self.span.rust_2018() && self.eat_keyword(kw::Await) {
             let span = lo.to(self.prev_span);
             let await_expr = self.mk_expr(
                 span,
@@ -3045,19 +3047,19 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
                     token::Ident(..) => {
                         e = self.parse_dot_suffix(e, lo)?;
                     }
-                    token::Literal(token::Integer(name), suffix) => {
+                    token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
                         let span = self.span;
                         self.bump();
-                        let field = ExprKind::Field(e, Ident::new(name, span));
+                        let field = ExprKind::Field(e, Ident::new(symbol, span));
                         e = self.mk_expr(lo.to(span), field, ThinVec::new());
 
                         self.expect_no_suffix(span, "a tuple index", suffix);
                     }
-                    token::Literal(token::Float(n), _suf) => {
+                    token::Literal(token::Lit { kind: token::Float, symbol, .. }) => {
                       self.bump();
-                      let fstr = n.as_str();
-                      let mut err = self.diagnostic()
-                          .struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n));
+                      let fstr = symbol.as_str();
+                      let msg = format!("unexpected token: `{}`", symbol);
+                      let mut err = self.diagnostic().struct_span_err(self.prev_span, &msg);
                       err.span_label(self.prev_span, "unexpected token");
                       if fstr.chars().all(|x| "0123456789.".contains(x)) {
                           let float = match fstr.parse::<f64>().ok() {
@@ -3250,7 +3252,7 @@ fn parse_prefix_expr(&mut self,
                 let (span, e) = self.interpolated_or_expr_span(e)?;
                 (lo.to(span), ExprKind::AddrOf(m, e))
             }
-            token::Ident(..) if self.token.is_keyword(keywords::In) => {
+            token::Ident(..) if self.token.is_keyword(kw::In) => {
                 self.bump();
                 let place = self.parse_expr_res(
                     Restrictions::NO_STRUCT_LITERAL,
@@ -3261,7 +3263,7 @@ fn parse_prefix_expr(&mut self,
                 let blk_expr = self.mk_expr(span, ExprKind::Block(blk, None), ThinVec::new());
                 (lo.to(span), ExprKind::ObsoleteInPlace(place, blk_expr))
             }
-            token::Ident(..) if self.token.is_keyword(keywords::Box) => {
+            token::Ident(..) if self.token.is_keyword(kw::Box) => {
                 self.bump();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
@@ -3683,7 +3685,7 @@ fn is_at_start_of_range_notation_rhs(&self) -> bool {
 
     /// Parses an `if` or `if let` expression (`if` token already eaten).
     fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
-        if self.check_keyword(keywords::Let) {
+        if self.check_keyword(kw::Let) {
             return self.parse_if_let_expr(attrs);
         }
         let lo = self.prev_span;
@@ -3693,7 +3695,7 @@ fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         // verify that the last statement is either an implicit return (no `;`) or an explicit
         // return. This won't catch blocks with an explicit `return`, but that would be caught by
         // the dead code lint.
-        if self.eat_keyword(keywords::Else) || !cond.returns() {
+        if self.eat_keyword(kw::Else) || !cond.returns() {
             let sp = self.sess.source_map().next_point(lo);
             let mut err = self.diagnostic()
                 .struct_span_err(sp, "missing condition for `if` statemement");
@@ -3709,7 +3711,7 @@ fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         })?;
         let mut els: Option<P<Expr>> = None;
         let mut hi = thn.span;
-        if self.eat_keyword(keywords::Else) {
+        if self.eat_keyword(kw::Else) {
             let elexpr = self.parse_else_expr()?;
             hi = elexpr.span;
             els = Some(elexpr);
@@ -3721,12 +3723,12 @@ fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
     fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>)
                              -> PResult<'a, P<Expr>> {
         let lo = self.prev_span;
-        self.expect_keyword(keywords::Let)?;
+        self.expect_keyword(kw::Let)?;
         let pats = self.parse_pats()?;
         self.expect(&token::Eq)?;
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
         let thn = self.parse_block()?;
-        let (hi, els) = if self.eat_keyword(keywords::Else) {
+        let (hi, els) = if self.eat_keyword(kw::Else) {
             let expr = self.parse_else_expr()?;
             (expr.span, Some(expr))
         } else {
@@ -3741,7 +3743,7 @@ fn parse_lambda_expr(&mut self,
                              -> PResult<'a, P<Expr>>
     {
         let lo = self.span;
-        let movability = if self.eat_keyword(keywords::Static) {
+        let movability = if self.eat_keyword(kw::Static) {
             Movability::Static
         } else {
             Movability::Movable
@@ -3751,7 +3753,7 @@ fn parse_lambda_expr(&mut self,
         } else {
             IsAsync::NotAsync
         };
-        let capture_clause = if self.eat_keyword(keywords::Move) {
+        let capture_clause = if self.eat_keyword(kw::Move) {
             CaptureBy::Value
         } else {
             CaptureBy::Ref
@@ -3779,7 +3781,7 @@ fn parse_lambda_expr(&mut self,
 
     // `else` token already eaten
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
-        if self.eat_keyword(keywords::If) {
+        if self.eat_keyword(kw::If) {
             return self.parse_if_expr(ThinVec::new());
         } else {
             let blk = self.parse_block()?;
@@ -3794,7 +3796,7 @@ fn parse_for_expr(&mut self, opt_label: Option<Label>,
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
         let pat = self.parse_top_level_pat()?;
-        if !self.eat_keyword(keywords::In) {
+        if !self.eat_keyword(kw::In) {
             let in_span = self.prev_span.between(self.span);
             let mut err = self.sess.span_diagnostic
                 .struct_span_err(in_span, "missing `in` in `for` loop");
@@ -3806,7 +3808,7 @@ fn parse_for_expr(&mut self, opt_label: Option<Label>,
             err.emit();
         }
         let in_span = self.prev_span;
-        if self.eat_keyword(keywords::In) {
+        if self.eat_keyword(kw::In) {
             // a common typo: `for _ in in bar {}`
             let mut err = self.sess.span_diagnostic.struct_span_err(
                 self.prev_span,
@@ -3835,7 +3837,7 @@ fn parse_for_expr(&mut self, opt_label: Option<Label>,
     fn parse_while_expr(&mut self, opt_label: Option<Label>,
                             span_lo: Span,
                             mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
-        if self.token.is_keyword(keywords::Let) {
+        if self.token.is_keyword(kw::Let) {
             return self.parse_while_let_expr(opt_label, span_lo, attrs);
         }
         let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@@ -3849,7 +3851,7 @@ fn parse_while_expr(&mut self, opt_label: Option<Label>,
     fn parse_while_let_expr(&mut self, opt_label: Option<Label>,
                                 span_lo: Span,
                                 mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
-        self.expect_keyword(keywords::Let)?;
+        self.expect_keyword(kw::Let)?;
         let pats = self.parse_pats()?;
         self.expect(&token::Eq)?;
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@@ -3874,8 +3876,8 @@ pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
         -> PResult<'a, P<Expr>>
     {
         let span_lo = self.span;
-        self.expect_keyword(keywords::Async)?;
-        let capture_clause = if self.eat_keyword(keywords::Move) {
+        self.expect_keyword(kw::Async)?;
+        let capture_clause = if self.eat_keyword(kw::Move) {
             CaptureBy::Value
         } else {
             CaptureBy::Ref
@@ -3893,7 +3895,7 @@ fn parse_try_block(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
     {
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
-        if self.eat_keyword(keywords::Catch) {
+        if self.eat_keyword(kw::Catch) {
             let mut error = self.struct_span_err(self.prev_span,
                                                  "keyword `catch` cannot follow a `try` block");
             error.help("try using `match` on the result of the `try` block instead");
@@ -3946,8 +3948,9 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<E
 
     crate fn parse_arm(&mut self) -> PResult<'a, Arm> {
         let attrs = self.parse_outer_attributes()?;
+        let lo = self.span;
         let pats = self.parse_pats()?;
-        let guard = if self.eat_keyword(keywords::If) {
+        let guard = if self.eat_keyword(kw::If) {
             Some(Guard::If(self.parse_expr()?))
         } else {
             None
@@ -3965,6 +3968,8 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<E
         let require_comma = classify::expr_requires_semi_to_be_stmt(&expr)
             && self.token != token::CloseDelim(token::Brace);
 
+        let hi = self.span;
+
         if require_comma {
             let cm = self.sess.source_map();
             self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])
@@ -4008,6 +4013,7 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<E
             pats,
             guard,
             body: expr,
+            span: lo.to(hi),
         })
     }
 
@@ -4211,10 +4217,10 @@ fn parse_pat_field(
             (pat, fieldname, false)
         } else {
             // Parsing a pattern of the form "(box) (ref) (mut) fieldname"
-            let is_box = self.eat_keyword(keywords::Box);
+            let is_box = self.eat_keyword(kw::Box);
             let boxed_span = self.span;
-            let is_ref = self.eat_keyword(keywords::Ref);
-            let is_mut = self.eat_keyword(keywords::Mut);
+            let is_ref = self.eat_keyword(kw::Ref);
+            let is_mut = self.eat_keyword(kw::Mut);
             let fieldname = self.parse_ident()?;
             hi = self.prev_span;
 
@@ -4493,13 +4499,13 @@ fn parse_pat_with_range_pat(
                 pat = PatKind::Slice(before, slice, after);
             }
             // At this point, token != &, &&, (, [
-            _ => if self.eat_keyword(keywords::Underscore) {
+            _ => if self.eat_keyword(kw::Underscore) {
                 // Parse _
                 pat = PatKind::Wild;
-            } else if self.eat_keyword(keywords::Mut) {
+            } else if self.eat_keyword(kw::Mut) {
                 // Parse mut ident @ pat / mut ref ident @ pat
                 let mutref_span = self.prev_span.to(self.span);
-                let binding_mode = if self.eat_keyword(keywords::Ref) {
+                let binding_mode = if self.eat_keyword(kw::Ref) {
                     self.diagnostic()
                         .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
                         .span_suggestion(
@@ -4513,11 +4519,11 @@ fn parse_pat_with_range_pat(
                     BindingMode::ByValue(Mutability::Mutable)
                 };
                 pat = self.parse_pat_ident(binding_mode)?;
-            } else if self.eat_keyword(keywords::Ref) {
+            } else if self.eat_keyword(kw::Ref) {
                 // Parse ref ident @ pat / ref mut ident @ pat
                 let mutbl = self.parse_mutability();
                 pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?;
-            } else if self.eat_keyword(keywords::Box) {
+            } else if self.eat_keyword(kw::Box) {
                 // Parse box pat
                 let subpat = self.parse_pat_with_range_pat(false, None)?;
                 pat = PatKind::Box(subpat);
@@ -4816,10 +4822,10 @@ fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> {
     }
 
     fn is_async_block(&self) -> bool {
-        self.token.is_keyword(keywords::Async) &&
+        self.token.is_keyword(kw::Async) &&
         (
             ( // `async move {`
-                self.look_ahead(1, |t| t.is_keyword(keywords::Move)) &&
+                self.look_ahead(1, |t| t.is_keyword(kw::Move)) &&
                 self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))
             ) || ( // `async {`
                 self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace))
@@ -4828,19 +4834,19 @@ fn is_async_block(&self) -> bool {
     }
 
     fn is_async_fn(&self) -> bool {
-        self.token.is_keyword(keywords::Async) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+        self.token.is_keyword(kw::Async) &&
+            self.look_ahead(1, |t| t.is_keyword(kw::Fn))
     }
 
     fn is_do_catch_block(&self) -> bool {
-        self.token.is_keyword(keywords::Do) &&
-        self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
+        self.token.is_keyword(kw::Do) &&
+        self.look_ahead(1, |t| t.is_keyword(kw::Catch)) &&
         self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
         !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
     }
 
     fn is_try_block(&self) -> bool {
-        self.token.is_keyword(keywords::Try) &&
+        self.token.is_keyword(kw::Try) &&
         self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
         self.span.rust_2018() &&
         // prevent `while try {} {}`, `if try {} {} else {}`, etc.
@@ -4848,34 +4854,34 @@ fn is_try_block(&self) -> bool {
     }
 
     fn is_union_item(&self) -> bool {
-        self.token.is_keyword(keywords::Union) &&
+        self.token.is_keyword(kw::Union) &&
         self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
     fn is_crate_vis(&self) -> bool {
-        self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
+        self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
     }
 
     fn is_existential_type_decl(&self) -> bool {
-        self.token.is_keyword(keywords::Existential) &&
-        self.look_ahead(1, |t| t.is_keyword(keywords::Type))
+        self.token.is_keyword(kw::Existential) &&
+        self.look_ahead(1, |t| t.is_keyword(kw::Type))
     }
 
     fn is_auto_trait_item(&self) -> bool {
         // auto trait
-        (self.token.is_keyword(keywords::Auto)
-            && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+        (self.token.is_keyword(kw::Auto)
+            && self.look_ahead(1, |t| t.is_keyword(kw::Trait)))
         || // unsafe auto trait
-        (self.token.is_keyword(keywords::Unsafe) &&
-         self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) &&
-         self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
+        (self.token.is_keyword(kw::Unsafe) &&
+         self.look_ahead(1, |t| t.is_keyword(kw::Auto)) &&
+         self.look_ahead(2, |t| t.is_keyword(kw::Trait)))
     }
 
     fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
                      -> PResult<'a, Option<P<Item>>> {
         let token_lo = self.span;
         let (ident, def) = match self.token {
-            token::Ident(ident, false) if ident.name == keywords::Macro.name() => {
+            token::Ident(ident, false) if ident.name == kw::Macro => {
                 self.bump();
                 let ident = self.parse_ident()?;
                 let tokens = if self.check(&token::OpenDelim(token::Brace)) {
@@ -4933,7 +4939,7 @@ fn parse_stmt_without_recovery(&mut self,
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span;
 
-        Ok(Some(if self.eat_keyword(keywords::Let) {
+        Ok(Some(if self.eat_keyword(kw::Let) {
             Stmt {
                 id: ast::DUMMY_NODE_ID,
                 node: StmtKind::Local(self.parse_local(attrs.into())?),
@@ -4986,7 +4992,7 @@ fn parse_stmt_without_recovery(&mut self,
 
             // it's a macro invocation
             let id = match self.token {
-                token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier
+                token::OpenDelim(_) => Ident::invalid(), // no special identifier
                 _ => self.parse_ident()?,
             };
 
@@ -4998,7 +5004,7 @@ fn parse_stmt_without_recovery(&mut self,
                 _ => {
                     // we only expect an ident if we didn't parse one
                     // above.
-                    let ident_str = if id.name == keywords::Invalid.name() {
+                    let ident_str = if id.name == kw::Invalid {
                         "identifier, "
                     } else {
                         ""
@@ -5021,7 +5027,7 @@ fn parse_stmt_without_recovery(&mut self,
                 MacStmtStyle::NoBraces
             };
 
-            if id.name == keywords::Invalid.name() {
+            if id.name == kw::Invalid {
                 let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
                 let node = if delim == MacDelimiter::Brace ||
                               self.token == token::Semi || self.token == token::Eof {
@@ -5139,7 +5145,7 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
             let tok = self.this_token_descr();
             let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
             let do_not_suggest_help =
-                self.token.is_keyword(keywords::In) || self.token == token::Colon;
+                self.token.is_keyword(kw::In) || self.token == token::Colon;
 
             if self.token.is_ident_named("and") {
                 e.span_suggestion_short(
@@ -5332,7 +5338,7 @@ fn parse_generic_bounds_common(&mut self,
             let is_bound_start = self.check_path() || self.check_lifetime() ||
                                  self.check(&token::Not) || // used for error reporting only
                                  self.check(&token::Question) ||
-                                 self.check_keyword(keywords::For) ||
+                                 self.check_keyword(kw::For) ||
                                  self.check(&token::OpenDelim(token::Paren));
             if is_bound_start {
                 let lo = self.span;
@@ -5510,7 +5516,7 @@ fn parse_trait_item_assoc_ty(&mut self)
     }
 
     fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
-        self.expect_keyword(keywords::Const)?;
+        self.expect_keyword(kw::Const)?;
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
@@ -5547,7 +5553,7 @@ fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a,
                     bounds,
                     kind: ast::GenericParamKind::Lifetime,
                 });
-            } else if self.check_keyword(keywords::Const) {
+            } else if self.check_keyword(kw::Const) {
                 // Parse const parameter.
                 params.push(self.parse_const_param(attrs)?);
             } else if self.check_ident() {
@@ -5851,7 +5857,7 @@ fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
             span: syntax_pos::DUMMY_SP,
         };
 
-        if !self.eat_keyword(keywords::Where) {
+        if !self.eat_keyword(kw::Where) {
             return Ok(where_clause);
         }
         let lo = self.prev_span;
@@ -6017,7 +6023,7 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
             _ => unreachable!()
         };
         let isolated_self = |this: &mut Self, n| {
-            this.look_ahead(n, |t| t.is_keyword(keywords::SelfLower)) &&
+            this.look_ahead(n, |t| t.is_keyword(kw::SelfLower)) &&
             this.look_ahead(n + 1, |t| t != &token::ModSep)
         };
 
@@ -6035,7 +6041,7 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
                 (if isolated_self(self, 1) {
                     self.bump();
                     SelfKind::Region(None, Mutability::Immutable)
-                } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
+                } else if self.look_ahead(1, |t| t.is_keyword(kw::Mut)) &&
                           isolated_self(self, 2) {
                     self.bump();
                     self.bump();
@@ -6046,7 +6052,7 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
                     let lt = self.expect_lifetime();
                     SelfKind::Region(Some(lt), Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
-                          self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
+                          self.look_ahead(2, |t| t.is_keyword(kw::Mut)) &&
                           isolated_self(self, 3) {
                     self.bump();
                     let lt = self.expect_lifetime();
@@ -6093,7 +6099,7 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
                     } else {
                         SelfKind::Value(Mutability::Immutable)
                     }, eself_ident, eself_hi)
-                } else if self.token.is_keyword(keywords::Mut) &&
+                } else if self.token.is_keyword(kw::Mut) &&
                           isolated_self(self, 1) {
                     // mut self
                     // mut self: TYPE
@@ -6224,9 +6230,9 @@ fn parse_item_fn(&mut self,
     /// Returns `true` if we are looking at `const ID`
     /// (returns `false` for things like `const fn`, etc.).
     fn is_const_item(&self) -> bool {
-        self.token.is_keyword(keywords::Const) &&
-            !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) &&
-            !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe))
+        self.token.is_keyword(kw::Const) &&
+            !self.look_ahead(1, |t| t.is_keyword(kw::Fn)) &&
+            !self.look_ahead(1, |t| t.is_keyword(kw::Unsafe))
     }
 
     /// Parses all the "front matter" for a `fn` declaration, up to
@@ -6245,7 +6251,7 @@ fn parse_fn_front_matter(&mut self)
             Abi
         )>
     {
-        let is_const_fn = self.eat_keyword(keywords::Const);
+        let is_const_fn = self.eat_keyword(kw::Const);
         let const_span = self.prev_span;
         let unsafety = self.parse_unsafety();
         let asyncness = self.parse_asyncness();
@@ -6253,14 +6259,14 @@ fn parse_fn_front_matter(&mut self)
         let (constness, unsafety, abi) = if is_const_fn {
             (respan(const_span, Constness::Const), unsafety, Abi::Rust)
         } else {
-            let abi = if self.eat_keyword(keywords::Extern) {
+            let abi = if self.eat_keyword(kw::Extern) {
                 self.parse_opt_abi()?.unwrap_or(Abi::C)
             } else {
                 Abi::Rust
             };
             (respan(self.prev_span, Constness::NotConst), unsafety, abi)
         };
-        if !self.eat_keyword(keywords::Fn) {
+        if !self.eat_keyword(kw::Fn) {
             // It is possible for `expect_one_of` to recover given the contents of
             // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
             // account for this.
@@ -6304,7 +6310,7 @@ fn parse_impl_item_(&mut self,
         } else if self.is_const_item() {
             // This parses the grammar:
             //     ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
-            self.expect_keyword(keywords::Const)?;
+            self.expect_keyword(kw::Const)?;
             let name = self.parse_ident()?;
             self.expect(&token::Colon)?;
             let typ = self.parse_ty()?;
@@ -6394,7 +6400,7 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
         // code copied from parse_macro_use_or_failure... abstraction!
         if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
             // method macro
-            Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
+            Ok((Ident::invalid(), vec![], ast::Generics::default(),
                 ast::ImplItemKind::Macro(mac)))
         } else {
             let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
@@ -6502,7 +6508,7 @@ fn choose_generics_over_qpath(&self) -> bool {
              self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
                 self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
                                        t == &token::Colon || t == &token::Eq) ||
-             self.look_ahead(1, |t| t.is_keyword(keywords::Const)))
+             self.look_ahead(1, |t| t.is_keyword(kw::Const)))
     }
 
     fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
@@ -6552,8 +6558,8 @@ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
         };
 
         // Parse both types and traits as a type, then reinterpret if necessary.
-        let err_path = |span| ast::Path::from_ident(Ident::new(keywords::Invalid.name(), span));
-        let ty_first = if self.token.is_keyword(keywords::For) &&
+        let err_path = |span| ast::Path::from_ident(Ident::new(kw::Invalid, span));
+        let ty_first = if self.token.is_keyword(kw::For) &&
                           self.look_ahead(1, |t| t != &token::Lt) {
             let span = self.prev_span.between(self.span);
             self.struct_span_err(span, "missing trait in a trait impl").emit();
@@ -6563,7 +6569,7 @@ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
         };
 
         // If `for` is missing we try to recover.
-        let has_for = self.eat_keyword(keywords::For);
+        let has_for = self.eat_keyword(kw::For);
         let missing_for_span = self.prev_span.between(self.span);
 
         let ty_second = if self.token == token::DotDot {
@@ -6614,11 +6620,11 @@ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
             }
         };
 
-        Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
+        Ok((Ident::invalid(), item_kind, Some(attrs)))
     }
 
     fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
-        if self.eat_keyword(keywords::For) {
+        if self.eat_keyword(kw::For) {
             self.expect_lt()?;
             let params = self.parse_generic_params()?;
             self.expect_gt()?;
@@ -6650,7 +6656,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
         // Otherwise if we look ahead and see a paren we parse a tuple-style
         // struct.
 
-        let vdata = if self.token.is_keyword(keywords::Where) {
+        let vdata = if self.token.is_keyword(kw::Where) {
             generics.where_clause = self.parse_where_clause()?;
             if self.eat(&token::Semi) {
                 // If we see a: `struct Foo<T> where T: Copy;` style decl.
@@ -6692,7 +6698,7 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
 
         let mut generics = self.parse_generics()?;
 
-        let vdata = if self.token.is_keyword(keywords::Where) {
+        let vdata = if self.token.is_keyword(kw::Where) {
             generics.where_clause = self.parse_where_clause()?;
             let (fields, recovered) = self.parse_record_struct_body()?;
             VariantData::Struct(fields, recovered)
@@ -6844,13 +6850,13 @@ fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
     pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
         maybe_whole!(self, NtVis, |x| x);
 
-        self.expected_tokens.push(TokenType::Keyword(keywords::Crate));
+        self.expected_tokens.push(TokenType::Keyword(kw::Crate));
         if self.is_crate_vis() {
             self.bump(); // `crate`
             return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate)));
         }
 
-        if !self.eat_keyword(keywords::Pub) {
+        if !self.eat_keyword(kw::Pub) {
             // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
             // keyword to grab a span from for inherited visibility; an empty span at the
             // beginning of the current token would seem to be the "Schelling span".
@@ -6863,7 +6869,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
             // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
             // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
             // by the following tokens.
-            if self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) &&
+            if self.look_ahead(1, |t| t.is_keyword(kw::Crate)) &&
                 self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
             {
                 // `pub(crate)`
@@ -6875,7 +6881,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                     VisibilityKind::Crate(CrateSugar::PubCrate),
                 );
                 return Ok(vis)
-            } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) {
+            } else if self.look_ahead(1, |t| t.is_keyword(kw::In)) {
                 // `pub(in path)`
                 self.bump(); // `(`
                 self.bump(); // `in`
@@ -6887,8 +6893,8 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                 });
                 return Ok(vis)
             } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
-                      self.look_ahead(1, |t| t.is_keyword(keywords::Super) ||
-                                             t.is_keyword(keywords::SelfLower))
+                      self.look_ahead(1, |t| t.is_keyword(kw::Super) ||
+                                             t.is_keyword(kw::SelfLower))
             {
                 // `pub(self)` or `pub(super)`
                 self.bump(); // `(`
@@ -6926,14 +6932,14 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
     /// Parses defaultness (i.e., `default` or nothing).
     fn parse_defaultness(&mut self) -> Defaultness {
         // `pub` is included for better error messages
-        if self.check_keyword(keywords::Default) &&
-           self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
-                                  t.is_keyword(keywords::Const) ||
-                                  t.is_keyword(keywords::Fn) ||
-                                  t.is_keyword(keywords::Unsafe) ||
-                                  t.is_keyword(keywords::Extern) ||
-                                  t.is_keyword(keywords::Type) ||
-                                  t.is_keyword(keywords::Pub)) {
+        if self.check_keyword(kw::Default) &&
+           self.look_ahead(1, |t| t.is_keyword(kw::Impl) ||
+                                  t.is_keyword(kw::Const) ||
+                                  t.is_keyword(kw::Fn) ||
+                                  t.is_keyword(kw::Unsafe) ||
+                                  t.is_keyword(kw::Extern) ||
+                                  t.is_keyword(kw::Type) ||
+                                  t.is_keyword(kw::Pub)) {
             self.bump(); // `default`
             Defaultness::Default
         } else {
@@ -7257,7 +7263,7 @@ fn eval_src_mod(&mut self,
     /// Parses a function declaration from a foreign module.
     fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
                              -> PResult<'a, ForeignItem> {
-        self.expect_keyword(keywords::Fn)?;
+        self.expect_keyword(kw::Fn)?;
 
         let (ident, mut generics) = self.parse_fn_header()?;
         let decl = self.parse_fn_decl(true)?;
@@ -7297,7 +7303,7 @@ fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: V
     /// Parses a type from a foreign module.
     fn parse_item_foreign_type(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
                              -> PResult<'a, ForeignItem> {
-        self.expect_keyword(keywords::Type)?;
+        self.expect_keyword(kw::Type)?;
 
         let ident = self.parse_ident()?;
         let hi = self.span;
@@ -7316,7 +7322,7 @@ fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> {
         let error_msg = "crate name using dashes are not valid in `extern crate` statements";
         let suggestion_msg = "if the original crate name uses dashes you need to use underscores \
                               in the code";
-        let mut ident = if self.token.is_keyword(keywords::SelfLower) {
+        let mut ident = if self.token.is_keyword(kw::SelfLower) {
             self.parse_path_segment_ident()
         } else {
             self.parse_ident()
@@ -7412,7 +7418,7 @@ fn parse_item_foreign_mod(&mut self,
             abi,
             items: foreign_items
         };
-        let invalid = keywords::Invalid.ident();
+        let invalid = Ident::invalid();
         Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs))
     }
 
@@ -7425,11 +7431,11 @@ fn parse_item_foreign_mod(&mut self,
     fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
         // This parses the grammar:
         //     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
-        if self.check_keyword(keywords::Type) ||
-           self.check_keyword(keywords::Existential) &&
-                self.look_ahead(1, |t| t.is_keyword(keywords::Type)) {
-            let existential = self.eat_keyword(keywords::Existential);
-            assert!(self.eat_keyword(keywords::Type));
+        if self.check_keyword(kw::Type) ||
+           self.check_keyword(kw::Existential) &&
+                self.look_ahead(1, |t| t.is_keyword(kw::Type)) {
+            let existential = self.eat_keyword(kw::Existential);
+            assert!(self.eat_keyword(kw::Type));
             Some(self.parse_existential_or_alias(existential))
         } else {
             None
@@ -7553,11 +7559,12 @@ fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
     /// the `extern` keyword, if one is found.
     fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
         match self.token {
-            token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
+            token::Literal(token::Lit { kind: token::Str, symbol, suffix }) |
+            token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => {
                 let sp = self.span;
-                self.expect_no_suffix(sp, "an ABI spec", suf);
+                self.expect_no_suffix(sp, "an ABI spec", suffix);
                 self.bump();
-                match abi::lookup(&s.as_str()) {
+                match abi::lookup(&symbol.as_str()) {
                     Some(abi) => Ok(Some(abi)),
                     None => {
                         let prev_span = self.prev_span;
@@ -7566,7 +7573,7 @@ fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
                             prev_span,
                             E0703,
                             "invalid ABI: found `{}`",
-                            s);
+                            symbol);
                         err.span_label(prev_span, "invalid ABI");
                         err.help(&format!("valid ABIs: {}", abi::all_names().join(", ")));
                         err.emit();
@@ -7580,10 +7587,10 @@ fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
     }
 
     fn is_static_global(&mut self) -> bool {
-        if self.check_keyword(keywords::Static) {
+        if self.check_keyword(kw::Static) {
             // Check if this could be a closure
             !self.look_ahead(1, |token| {
-                if token.is_keyword(keywords::Move) {
+                if token.is_keyword(kw::Move) {
                     return true;
                 }
                 match *token {
@@ -7653,24 +7660,25 @@ fn parse_item_implementation(
 
         let visibility = self.parse_visibility(false)?;
 
-        if self.eat_keyword(keywords::Use) {
+        if self.eat_keyword(kw::Use) {
             // USE ITEM
             let item_ = ItemKind::Use(P(self.parse_use_tree()?));
             self.expect(&token::Semi)?;
 
             let span = lo.to(self.prev_span);
-            let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs);
+            let item =
+                self.mk_item(span, Ident::invalid(), item_, visibility, attrs);
             return Ok(Some(item));
         }
 
-        if self.eat_keyword(keywords::Extern) {
-            if self.eat_keyword(keywords::Crate) {
+        if self.eat_keyword(kw::Extern) {
+            if self.eat_keyword(kw::Crate) {
                 return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
             }
 
             let opt_abi = self.parse_opt_abi()?;
 
-            if self.eat_keyword(keywords::Fn) {
+            if self.eat_keyword(kw::Fn) {
                 // EXTERN FUNCTION ITEM
                 let fn_span = self.prev_span;
                 let abi = opt_abi.unwrap_or(Abi::C);
@@ -7696,7 +7704,7 @@ fn parse_item_implementation(
         if self.is_static_global() {
             self.bump();
             // STATIC ITEM
-            let m = if self.eat_keyword(keywords::Mut) {
+            let m = if self.eat_keyword(kw::Mut) {
                 Mutability::Mutable
             } else {
                 Mutability::Immutable
@@ -7710,11 +7718,11 @@ fn parse_item_implementation(
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Const) {
+        if self.eat_keyword(kw::Const) {
             let const_span = self.prev_span;
-            if self.check_keyword(keywords::Fn)
-                || (self.check_keyword(keywords::Unsafe)
-                    && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
+            if self.check_keyword(kw::Fn)
+                || (self.check_keyword(kw::Unsafe)
+                    && self.look_ahead(1, |t| t.is_keyword(kw::Fn))) {
                 // CONST FUNCTION ITEM
                 let unsafety = self.parse_unsafety();
                 self.bump();
@@ -7733,7 +7741,7 @@ fn parse_item_implementation(
             }
 
             // CONST ITEM
-            if self.eat_keyword(keywords::Mut) {
+            if self.eat_keyword(kw::Mut) {
                 let prev_span = self.prev_span;
                 let mut err = self.diagnostic()
                     .struct_span_err(prev_span, "const globals cannot be mutable");
@@ -7758,18 +7766,18 @@ fn parse_item_implementation(
 
         // `unsafe async fn` or `async fn`
         if (
-            self.check_keyword(keywords::Unsafe) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Async))
+            self.check_keyword(kw::Unsafe) &&
+            self.look_ahead(1, |t| t.is_keyword(kw::Async))
         ) || (
-            self.check_keyword(keywords::Async) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+            self.check_keyword(kw::Async) &&
+            self.look_ahead(1, |t| t.is_keyword(kw::Fn))
         )
         {
             // ASYNC FUNCTION ITEM
             let unsafety = self.parse_unsafety();
-            self.expect_keyword(keywords::Async)?;
+            self.expect_keyword(kw::Async)?;
             let async_span = self.prev_span;
-            self.expect_keyword(keywords::Fn)?;
+            self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(unsafety,
@@ -7795,17 +7803,17 @@ fn parse_item_implementation(
             }
             return Ok(Some(item));
         }
-        if self.check_keyword(keywords::Unsafe) &&
-            (self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
-            self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
+        if self.check_keyword(kw::Unsafe) &&
+            (self.look_ahead(1, |t| t.is_keyword(kw::Trait)) ||
+            self.look_ahead(1, |t| t.is_keyword(kw::Auto)))
         {
             // UNSAFE TRAIT ITEM
             self.bump(); // `unsafe`
-            let is_auto = if self.eat_keyword(keywords::Trait) {
+            let is_auto = if self.eat_keyword(kw::Trait) {
                 IsAuto::No
             } else {
-                self.expect_keyword(keywords::Auto)?;
-                self.expect_keyword(keywords::Trait)?;
+                self.expect_keyword(kw::Auto)?;
+                self.expect_keyword(kw::Trait)?;
                 IsAuto::Yes
             };
             let (ident, item_, extra_attrs) =
@@ -7818,23 +7826,23 @@ fn parse_item_implementation(
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.check_keyword(keywords::Impl) ||
-           self.check_keyword(keywords::Unsafe) &&
-                self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
-           self.check_keyword(keywords::Default) &&
-                self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
-           self.check_keyword(keywords::Default) &&
-                self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
+        if self.check_keyword(kw::Impl) ||
+           self.check_keyword(kw::Unsafe) &&
+                self.look_ahead(1, |t| t.is_keyword(kw::Impl)) ||
+           self.check_keyword(kw::Default) &&
+                self.look_ahead(1, |t| t.is_keyword(kw::Impl)) ||
+           self.check_keyword(kw::Default) &&
+                self.look_ahead(1, |t| t.is_keyword(kw::Unsafe)) {
             // IMPL ITEM
             let defaultness = self.parse_defaultness();
             let unsafety = self.parse_unsafety();
-            self.expect_keyword(keywords::Impl)?;
+            self.expect_keyword(kw::Impl)?;
             let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
             let span = lo.to(self.prev_span);
             return Ok(Some(self.mk_item(span, ident, item, visibility,
                                         maybe_append(attrs, extra_attrs))));
         }
-        if self.check_keyword(keywords::Fn) {
+        if self.check_keyword(kw::Fn) {
             // FUNCTION ITEM
             self.bump();
             let fn_span = self.prev_span;
@@ -7851,18 +7859,18 @@ fn parse_item_implementation(
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.check_keyword(keywords::Unsafe)
+        if self.check_keyword(kw::Unsafe)
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
             // UNSAFE FUNCTION ITEM
             self.bump(); // `unsafe`
             // `{` is also expected after `unsafe`, in case of error, include it in the diagnostic
             self.check(&token::OpenDelim(token::Brace));
-            let abi = if self.eat_keyword(keywords::Extern) {
+            let abi = if self.eat_keyword(kw::Extern) {
                 self.parse_opt_abi()?.unwrap_or(Abi::C)
             } else {
                 Abi::Rust
             };
-            self.expect_keyword(keywords::Fn)?;
+            self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(Unsafety::Unsafe,
@@ -7877,7 +7885,7 @@ fn parse_item_implementation(
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Mod) {
+        if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
             let (ident, item_, extra_attrs) =
                 self.parse_item_mod(&attrs[..])?;
@@ -7904,7 +7912,7 @@ fn parse_item_implementation(
                                     attrs);
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Enum) {
+        if self.eat_keyword(kw::Enum) {
             // ENUM ITEM
             let (ident, item_, extra_attrs) = self.parse_item_enum()?;
             let prev_span = self.prev_span;
@@ -7915,15 +7923,15 @@ fn parse_item_implementation(
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.check_keyword(keywords::Trait)
-            || (self.check_keyword(keywords::Auto)
-                && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+        if self.check_keyword(kw::Trait)
+            || (self.check_keyword(kw::Auto)
+                && self.look_ahead(1, |t| t.is_keyword(kw::Trait)))
         {
-            let is_auto = if self.eat_keyword(keywords::Trait) {
+            let is_auto = if self.eat_keyword(kw::Trait) {
                 IsAuto::No
             } else {
-                self.expect_keyword(keywords::Auto)?;
-                self.expect_keyword(keywords::Trait)?;
+                self.expect_keyword(kw::Auto)?;
+                self.expect_keyword(kw::Trait)?;
                 IsAuto::Yes
             };
             // TRAIT ITEM
@@ -7937,7 +7945,7 @@ fn parse_item_implementation(
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Struct) {
+        if self.eat_keyword(kw::Struct) {
             // STRUCT ITEM
             let (ident, item_, extra_attrs) = self.parse_item_struct()?;
             let prev_span = self.prev_span;
@@ -8078,8 +8086,8 @@ fn parse_item_implementation(
 
         // FOREIGN STATIC ITEM
         // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
-        if self.check_keyword(keywords::Static) || self.token.is_keyword(keywords::Const) {
-            if self.token.is_keyword(keywords::Const) {
+        if self.check_keyword(kw::Static) || self.token.is_keyword(kw::Const) {
+            if self.token.is_keyword(kw::Const) {
                 self.diagnostic()
                     .struct_span_err(self.span, "extern items cannot be `const`")
                     .span_suggestion(
@@ -8093,11 +8101,11 @@ fn parse_item_implementation(
             return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?);
         }
         // FOREIGN FUNCTION ITEM
-        if self.check_keyword(keywords::Fn) {
+        if self.check_keyword(kw::Fn) {
             return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?);
         }
         // FOREIGN TYPE ITEM
-        if self.check_keyword(keywords::Type) {
+        if self.check_keyword(kw::Type) {
             return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?);
         }
 
@@ -8105,7 +8113,7 @@ fn parse_item_implementation(
             Some(mac) => {
                 Ok(
                     ForeignItem {
-                        ident: keywords::Invalid.ident(),
+                        ident: Ident::invalid(),
                         span: lo.to(self.prev_span),
                         id: ast::DUMMY_NODE_ID,
                         attrs,
@@ -8152,7 +8160,7 @@ fn parse_macro_use_or_failure(
             let id = if self.token.is_ident() {
                 self.parse_ident()?
             } else {
-                keywords::Invalid.ident() // no special identifier
+                Ident::invalid() // no special identifier
             };
             // eat a matched-delimiter token tree:
             let (delim, tts) = self.expect_delimited_token_tree()?;
@@ -8345,7 +8353,7 @@ fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
     }
 
     fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
-        if self.eat_keyword(keywords::As) {
+        if self.eat_keyword(kw::As) {
             self.parse_ident_or_underscore().map(Some)
         } else {
             Ok(None)
@@ -8365,8 +8373,10 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
 
     pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
         let ret = match self.token {
-            token::Literal(token::Str_(s), suf) => (s, ast::StrStyle::Cooked, suf),
-            token::Literal(token::StrRaw(s, n), suf) => (s, ast::StrStyle::Raw(n), suf),
+            token::Literal(token::Lit { kind: token::Str, symbol, suffix }) =>
+                (symbol, ast::StrStyle::Cooked, suffix),
+            token::Literal(token::Lit { kind: token::StrRaw(n), symbol, suffix }) =>
+                (symbol, ast::StrStyle::Raw(n), suffix),
             _ => return None
         };
         self.bump();
index 068fc41c87a0baadcff9b67938019cef4880684b..e5361b2db4e9e4b29cb529257c90b2dcea4d6435 100644 (file)
@@ -1,14 +1,14 @@
 pub use BinOpToken::*;
 pub use Nonterminal::*;
 pub use DelimToken::*;
-pub use Lit::*;
+pub use LitKind::*;
 pub use Token::*;
 
 use crate::ast::{self};
 use crate::parse::ParseSess;
 use crate::print::pprust;
 use crate::ptr::P;
-use crate::symbol::keywords;
+use crate::symbol::kw;
 use crate::syntax::parse::parse_stream_from_source_str;
 use crate::tokenstream::{self, DelimSpan, TokenStream, TokenTree};
 
@@ -59,48 +59,61 @@ pub fn is_empty(self) -> bool {
     }
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum Lit {
-    Bool(ast::Name), // AST only, must never appear in a `Token`
-    Byte(ast::Name),
-    Char(ast::Name),
-    Err(ast::Name),
-    Integer(ast::Name),
-    Float(ast::Name),
-    Str_(ast::Name),
-    StrRaw(ast::Name, u16), /* raw str delimited by n hash symbols */
-    ByteStr(ast::Name),
-    ByteStrRaw(ast::Name, u16), /* raw byte str delimited by n hash symbols */
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+pub enum LitKind {
+    Bool, // AST only, must never appear in a `Token`
+    Byte,
+    Char,
+    Integer,
+    Float,
+    Str,
+    StrRaw(u16), // raw string delimited by `n` hash symbols
+    ByteStr,
+    ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols
+    Err,
 }
 
-#[cfg(target_arch = "x86_64")]
-static_assert_size!(Lit, 8);
+/// A literal token.
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+pub struct Lit {
+    pub kind: LitKind,
+    pub symbol: Symbol,
+    pub suffix: Option<Symbol>,
+}
 
-impl Lit {
-    crate fn literal_name(&self) -> &'static str {
-        match *self {
-            Bool(_) => panic!("literal token contains `Lit::Bool`"),
-            Byte(_) => "byte literal",
-            Char(_) => "char literal",
-            Err(_) => "invalid literal",
-            Integer(_) => "integer literal",
-            Float(_) => "float literal",
-            Str_(_) | StrRaw(..) => "string literal",
-            ByteStr(_) | ByteStrRaw(..) => "byte string literal"
+impl LitKind {
+    /// An English article for the literal token kind.
+    crate fn article(self) -> &'static str {
+        match self {
+            Integer | Err => "an",
+            _ => "a",
         }
     }
 
-    crate fn may_have_suffix(&self) -> bool {
-        match *self {
-            Integer(..) | Float(..) => true,
+    crate fn descr(self) -> &'static str {
+        match self {
+            Bool => panic!("literal token contains `Lit::Bool`"),
+            Byte => "byte",
+            Char => "char",
+            Integer => "integer",
+            Float => "float",
+            Str | StrRaw(..) => "string",
+            ByteStr | ByteStrRaw(..) => "byte string",
+            Err => "error",
+        }
+    }
+
+    crate fn may_have_suffix(self) -> bool {
+        match self {
+            Integer | Float | Err => true,
             _ => false,
         }
     }
+}
 
-    // See comments in `Nonterminal::to_tokenstream` for why we care about
-    // *probably* equal here rather than actual equality
-    fn probably_equal_for_proc_macro(&self, other: &Lit) -> bool {
-        mem::discriminant(self) == mem::discriminant(other)
+impl Lit {
+    pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
+        Lit { kind, symbol, suffix }
     }
 }
 
@@ -110,28 +123,28 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
     !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
-        keywords::Async.name(),
+        kw::Async,
 
         // FIXME: remove when `await!(..)` syntax is removed
         // https://github.com/rust-lang/rust/issues/60610
-        keywords::Await.name(),
-
-        keywords::Do.name(),
-        keywords::Box.name(),
-        keywords::Break.name(),
-        keywords::Continue.name(),
-        keywords::False.name(),
-        keywords::For.name(),
-        keywords::If.name(),
-        keywords::Loop.name(),
-        keywords::Match.name(),
-        keywords::Move.name(),
-        keywords::Return.name(),
-        keywords::True.name(),
-        keywords::Unsafe.name(),
-        keywords::While.name(),
-        keywords::Yield.name(),
-        keywords::Static.name(),
+        kw::Await,
+
+        kw::Do,
+        kw::Box,
+        kw::Break,
+        kw::Continue,
+        kw::False,
+        kw::For,
+        kw::If,
+        kw::Loop,
+        kw::Match,
+        kw::Move,
+        kw::Return,
+        kw::True,
+        kw::Unsafe,
+        kw::While,
+        kw::Yield,
+        kw::Static,
     ].contains(&ident.name)
 }
 
@@ -141,14 +154,14 @@ fn ident_can_begin_type(ident: ast::Ident, is_raw: bool) -> bool {
     !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
-        keywords::Underscore.name(),
-        keywords::For.name(),
-        keywords::Impl.name(),
-        keywords::Fn.name(),
-        keywords::Unsafe.name(),
-        keywords::Extern.name(),
-        keywords::Typeof.name(),
-        keywords::Dyn.name(),
+        kw::Underscore,
+        kw::For,
+        kw::Impl,
+        kw::Fn,
+        kw::Unsafe,
+        kw::Extern,
+        kw::Typeof,
+        kw::Dyn,
     ].contains(&ident.name)
 }
 
@@ -193,7 +206,7 @@ pub enum Token {
     CloseDelim(DelimToken),
 
     /* Literals */
-    Literal(Lit, Option<ast::Name>),
+    Literal(Lit),
 
     /* Name components */
     Ident(ast::Ident, /* is_raw */ bool),
@@ -306,10 +319,14 @@ pub fn can_begin_const_arg(&self) -> bool {
 
     /// Returns `true` if the token can appear at the start of a generic bound.
     crate fn can_begin_bound(&self) -> bool {
-        self.is_path_start() || self.is_lifetime() || self.is_keyword(keywords::For) ||
+        self.is_path_start() || self.is_lifetime() || self.is_keyword(kw::For) ||
         self == &Question || self == &OpenDelim(Paren)
     }
 
+    pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Token {
+        Literal(Lit::new(kind, symbol, suffix))
+    }
+
     /// Returns `true` if the token is any literal
     crate fn is_lit(&self) -> bool {
         match *self {
@@ -318,14 +335,21 @@ pub fn can_begin_const_arg(&self) -> bool {
         }
     }
 
+    crate fn expect_lit(&self) -> Lit {
+        match *self {
+            Literal(lit) => lit,
+            _=> panic!("`expect_lit` called on non-literal"),
+        }
+    }
+
     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
     /// for example a '-42', or one of the boolean idents).
     crate fn can_begin_literal_or_bool(&self) -> bool {
         match *self {
             Literal(..)  => true,
             BinOp(Minus) => true,
-            Ident(ident, false) if ident.name == keywords::True.name() => true,
-            Ident(ident, false) if ident.name == keywords::False.name() => true,
+            Ident(ident, false) if ident.name == kw::True => true,
+            Ident(ident, false) if ident.name == kw::False => true,
             Interpolated(ref nt) => match **nt {
                 NtLiteral(..) => true,
                 _             => false,
@@ -386,8 +410,8 @@ fn is_path(&self) -> bool {
 
     /// Returns `true` if the token is either the `mut` or `const` keyword.
     crate fn is_mutability(&self) -> bool {
-        self.is_keyword(keywords::Mut) ||
-        self.is_keyword(keywords::Const)
+        self.is_keyword(kw::Mut) ||
+        self.is_keyword(kw::Const)
     }
 
     crate fn is_qpath_start(&self) -> bool {
@@ -400,8 +424,8 @@ fn is_path(&self) -> bool {
     }
 
     /// Returns `true` if the token is a given keyword, `kw`.
-    pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
-        self.ident().map(|(ident, is_raw)| ident.name == kw.name() && !is_raw).unwrap_or(false)
+    pub fn is_keyword(&self, kw: Symbol) -> bool {
+        self.ident().map(|(ident, is_raw)| ident.name == kw && !is_raw).unwrap_or(false)
     }
 
     pub fn is_path_segment_keyword(&self) -> bool {
@@ -564,14 +588,12 @@ pub fn is_reserved_ident(&self) -> bool {
             (&DocComment(a), &DocComment(b)) |
             (&Shebang(a), &Shebang(b)) => a == b,
 
+            (&Literal(a), &Literal(b)) => a == b,
+
             (&Lifetime(a), &Lifetime(b)) => a.name == b.name,
             (&Ident(a, b), &Ident(c, d)) => b == d && (a.name == c.name ||
-                                                       a.name == keywords::DollarCrate.name() ||
-                                                       c.name == keywords::DollarCrate.name()),
-
-            (&Literal(ref a, b), &Literal(ref c, d)) => {
-                b == d && a.probably_equal_for_proc_macro(c)
-            }
+                                                       a.name == kw::DollarCrate ||
+                                                       c.name == kw::DollarCrate),
 
             (&Interpolated(_), &Interpolated(_)) => false,
 
index ac240359b56b6f68387852472028a725640997e1..88a5033f3b55f43d7330d06dc42e9f1b7c7e772d 100644 (file)
@@ -13,7 +13,7 @@
 use crate::print::pp::Breaks::{Consistent, Inconsistent};
 use crate::ptr::P;
 use crate::std_inject;
-use crate::symbol::{keywords, sym};
+use crate::symbol::{kw, sym};
 use crate::tokenstream::{self, TokenStream, TokenTree};
 
 use rustc_target::spec::abi::{self, Abi};
@@ -163,22 +163,23 @@ fn binop_to_string(op: BinOpToken) -> &'static str {
     }
 }
 
-pub fn literal_to_string(lit: token::Lit, suffix: Option<ast::Name>) -> String {
-    let mut out = match lit {
-        token::Byte(b)           => format!("b'{}'", b),
-        token::Char(c)           => format!("'{}'", c),
-        token::Err(c)            => format!("'{}'", c),
-        token::Bool(c)           |
-        token::Float(c)          |
-        token::Integer(c)        => c.to_string(),
-        token::Str_(s)           => format!("\"{}\"", s),
-        token::StrRaw(s, n)      => format!("r{delim}\"{string}\"{delim}",
-                                            delim="#".repeat(n as usize),
-                                            string=s),
-        token::ByteStr(v)        => format!("b\"{}\"", v),
-        token::ByteStrRaw(s, n)  => format!("br{delim}\"{string}\"{delim}",
-                                            delim="#".repeat(n as usize),
-                                            string=s),
+pub fn literal_to_string(lit: token::Lit) -> String {
+    let token::Lit { kind, symbol, suffix } = lit;
+    let mut out = match kind {
+        token::Byte          => format!("b'{}'", symbol),
+        token::Char          => format!("'{}'", symbol),
+        token::Bool          |
+        token::Float         |
+        token::Integer       => symbol.to_string(),
+        token::Str           => format!("\"{}\"", symbol),
+        token::StrRaw(n)     => format!("r{delim}\"{string}\"{delim}",
+                                        delim="#".repeat(n as usize),
+                                        string=symbol),
+        token::ByteStr       => format!("b\"{}\"", symbol),
+        token::ByteStrRaw(n) => format!("br{delim}\"{string}\"{delim}",
+                                        delim="#".repeat(n as usize),
+                                        string=symbol),
+        token::Err           => format!("'{}'", symbol),
     };
 
     if let Some(suffix) = suffix {
@@ -231,7 +232,7 @@ pub fn token_to_string(tok: &Token) -> String {
         token::SingleQuote          => "'".to_string(),
 
         /* Literals */
-        token::Literal(lit, suf) => literal_to_string(lit, suf),
+        token::Literal(lit) => literal_to_string(lit),
 
         /* Name components */
         token::Ident(s, false)      => s.to_string(),
@@ -571,7 +572,7 @@ fn next_comment(&mut self) -> Option<comments::Comment> {
 
     fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
         self.maybe_print_comment(lit.span.lo())?;
-        self.writer().word(literal_to_string(lit.token, lit.suffix))
+        self.writer().word(literal_to_string(lit.token))
     }
 
     fn print_string(&mut self, st: &str,
@@ -641,8 +642,8 @@ fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> {
             if i > 0 {
                 self.writer().word("::")?
             }
-            if segment.ident.name != keywords::PathRoot.name() {
-                if segment.ident.name == keywords::DollarCrate.name() {
+            if segment.ident.name != kw::PathRoot {
+                if segment.ident.name == kw::DollarCrate {
                     self.print_dollar_crate(segment.ident)?;
                 } else {
                     self.writer().word(segment.ident.as_str().to_string())?;
@@ -1340,7 +1341,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.s.word(";")?;
             }
             ast::ItemKind::Mac(ref mac) => {
-                if item.ident.name == keywords::Invalid.name() {
+                if item.ident.name == kw::Invalid {
                     self.print_mac(mac)?;
                     match mac.node.delim {
                         MacDelimiter::Brace => {}
@@ -2400,8 +2401,8 @@ fn print_path_segment(&mut self,
                           colons_before_params: bool)
                           -> io::Result<()>
     {
-        if segment.ident.name != keywords::PathRoot.name() {
-            if segment.ident.name == keywords::DollarCrate.name() {
+        if segment.ident.name != kw::PathRoot {
+            if segment.ident.name == kw::DollarCrate {
                 self.print_dollar_crate(segment.ident)?;
             } else {
                 self.print_ident(segment.ident)?;
@@ -2984,7 +2985,7 @@ pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()
                     self.print_explicit_self(&eself)?;
                 } else {
                     let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
-                        ident.name == keywords::Invalid.name()
+                        ident.name == kw::Invalid
                     } else {
                         false
                     };
index e01a3260d4993a5e878ef3bc8e92ca617eb0470b..398705857bb7e91351f2c668fb6867af9438cca6 100644 (file)
@@ -2,7 +2,7 @@
 use crate::attr;
 use crate::edition::Edition;
 use crate::ext::hygiene::{Mark, SyntaxContext};
-use crate::symbol::{Ident, Symbol, keywords, sym};
+use crate::symbol::{Ident, Symbol, kw, sym};
 use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, respan};
 use crate::ptr::P;
 use crate::tokenstream::TokenStream;
@@ -107,7 +107,7 @@ pub fn maybe_inject_crates_ref(
         vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
         node: ast::ItemKind::Use(P(ast::UseTree {
             prefix: ast::Path {
-                segments: iter::once(keywords::PathRoot.ident())
+                segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot))
                     .chain(
                         [name, "prelude", "v1"].iter().cloned()
                             .map(ast::Ident::from_str)
@@ -118,7 +118,7 @@ pub fn maybe_inject_crates_ref(
             span,
         })),
         id: ast::DUMMY_NODE_ID,
-        ident: keywords::Invalid.ident(),
+        ident: ast::Ident::invalid(),
         span,
         tokens: None,
     }));
index 7cd83f3e495be5a1094b2a56f56b79c9124eea9b..d1e11da4e7cc26175b4270c8b9b376db03708f4e 100644 (file)
@@ -29,7 +29,7 @@
 use crate::print::pprust;
 use crate::ast::{self, Ident};
 use crate::ptr::P;
-use crate::symbol::{self, Symbol, keywords, sym};
+use crate::symbol::{self, Symbol, kw, sym};
 use crate::ThinVec;
 
 struct Test {
@@ -100,7 +100,7 @@ fn visit_crate(&mut self, c: &mut ast::Crate) {
 
     fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         let ident = i.ident;
-        if ident.name != keywords::Invalid.name() {
+        if ident.name != kw::Invalid {
             self.cx.path.push(ident);
         }
         debug!("current path: {}", path_name_i(&self.cx.path));
@@ -139,7 +139,7 @@ fn visit_crate(&mut self, c: &mut ast::Crate) {
             }
             item.node = ast::ItemKind::Mod(module);
         }
-        if ident.name != keywords::Invalid.name() {
+        if ident.name != kw::Invalid {
             self.cx.path.pop();
         }
         smallvec![P(item)]
@@ -215,7 +215,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>,
                    tests: Vec<Ident>,
                    tested_submods: Vec<(Ident, Ident)>)
                    -> (P<ast::Item>, Ident) {
-    let super_ = Ident::with_empty_ctxt(keywords::Super.name());
+    let super_ = Ident::with_empty_ctxt(kw::Super);
 
     let items = tests.into_iter().map(|r| {
         cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
index 86e89945afe068cad1b4fef80a6a6f74e0a64871..6789fea28cad6daf1798c2da3e1c31d5e9282931 100644 (file)
@@ -1,5 +1,5 @@
 use crate::parse::token::{Token, BinOpToken};
-use crate::symbol::keywords;
+use crate::symbol::kw;
 use crate::ast::{self, BinOpKind};
 
 /// Associative operator with precedence.
@@ -100,7 +100,7 @@ pub fn from_token(t: &Token) -> Option<AssocOp> {
             // DotDotDot is no longer supported, but we need some way to display the error
             Token::DotDotDot => Some(DotDotEq),
             Token::Colon => Some(Colon),
-            _ if t.is_keyword(keywords::As) => Some(As),
+            _ if t.is_keyword(kw::As) => Some(As),
             _ => None
         }
     }
index cd69733571d5af6a12f4d9b6c8f9ad161e337d44..a11cd9c6f761dbab4b714eb77e5b73f46381c1d8 100644 (file)
@@ -4,7 +4,7 @@
 use syntax::source_map::Spanned;
 use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
+use syntax::parse::token::{self, Token};
 use syntax::parse::parser::Parser;
 use syntax::print::pprust;
 use syntax::ptr::P;
@@ -31,13 +31,10 @@ pub fn expand_assert<'cx>(
         tts: custom_message.unwrap_or_else(|| {
             TokenStream::from(TokenTree::Token(
                 DUMMY_SP,
-                token::Literal(
-                    token::Lit::Str_(Name::intern(&format!(
-                        "assertion failed: {}",
-                        pprust::expr_to_string(&cond_expr).escape_debug()
-                    ))),
-                    None,
-                ),
+                Token::lit(token::Str, Symbol::intern(&format!(
+                    "assertion failed: {}",
+                    pprust::expr_to_string(&cond_expr).escape_debug()
+                )), None),
             ))
         }).into(),
         delim: MacDelimiter::Parenthesis,
@@ -106,7 +103,7 @@ fn parse_assert<'a>(
     //
     // Parse this as an actual message, and suggest inserting a comma. Eventually, this should be
     // turned into an error.
-    let custom_message = if let token::Literal(token::Lit::Str_(_), _) = parser.token {
+    let custom_message = if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token {
         let mut err = cx.struct_span_warn(parser.span, "unexpected string literal");
         let comma_span = cx.source_map().next_point(parser.prev_span);
         err.span_suggestion_short(
index 1b0d572324a7924dada216e2d413e2dfd9aedee6..a39e0a6e9730380e74a890636281fb9a33208ea4 100644 (file)
@@ -7,7 +7,7 @@
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, keywords, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax_pos::Span;
 
 pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>,
@@ -129,7 +129,8 @@ fn process_variant(cx: &mut ExtCtxt<'_>, stmts: &mut Vec<ast::Stmt>, variant: &V
     let mut stmts = Vec::new();
     if is_union {
         // let _: AssertParamIsCopy<Self>;
-        let self_ty = cx.ty_path(cx.path_ident(trait_span, keywords::SelfUpper.ident()));
+        let self_ty =
+            cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_empty_ctxt(kw::SelfUpper)));
         assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy");
     } else {
         match *substr.fields {
index a13dc07085f809403946684e4c03c129fa0858a6..0689eb50f9ca2b65f4c53ec5dfe1f9f3a0bdb88e 100644 (file)
 use syntax::source_map::{self, respan};
 use syntax::util::map_in_place::MapInPlace;
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, keywords, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax::parse::ParseSess;
 use syntax_pos::{DUMMY_SP, Span};
 
@@ -686,7 +686,7 @@ fn create_derived_impl(&self,
         };
 
         cx.item(self.span,
-                keywords::Invalid.ident(),
+                Ident::invalid(),
                 a,
                 ast::ItemKind::Impl(unsafety,
                                     ast::ImplPolarity::Positive,
@@ -929,8 +929,8 @@ fn create_method(&self,
 
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
-                ast::Arg::from_self(explicit_self,
-                                    keywords::SelfLower.ident().with_span_pos(trait_.span))
+                let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span);
+                ast::Arg::from_self(explicit_self, ident)
             });
             let nonself_args = arg_types.into_iter()
                 .map(|(name, ty)| cx.arg(trait_.span, name, ty));
index 100ec0057ee028ddf62a74110e551ce85b58ec05..362ea9ed2291f03d03dba86deacae0e41b0a6098 100644 (file)
@@ -10,7 +10,7 @@
 use syntax::source_map::{respan, DUMMY_SP};
 use syntax::ptr::P;
 use syntax_pos::Span;
-use syntax_pos::symbol::keywords;
+use syntax_pos::symbol::kw;
 
 /// The types of pointers
 #[derive(Clone)]
@@ -86,7 +86,7 @@ pub fn to_path(&self,
             PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()),
             PathKind::Std => {
                 let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark);
-                idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site));
+                idents.insert(0, Ident::new(kw::DollarCrate, def_site));
                 cx.path_all(span, false, idents, params, Vec::new())
             }
         }
index 2127179eecb5aaee64cc80bc76ef0bdb6bf3dce2..72a66ae3845d0c53032a04a0a22364544c611955 100644 (file)
@@ -6,7 +6,7 @@
 use syntax::ast::{self, Ident, GenericArg};
 use syntax::ext::base::{self, *};
 use syntax::ext::build::AstBuilder;
-use syntax::symbol::{keywords, Symbol, sym};
+use syntax::symbol::{kw, sym, Symbol};
 use syntax_pos::Span;
 use syntax::tokenstream;
 
@@ -24,7 +24,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
     let sp = sp.apply_mark(cx.current_expansion.mark);
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
-            let lt = cx.lifetime(sp, keywords::StaticLifetime.ident());
+            let lt = cx.lifetime(sp, Ident::with_empty_ctxt(kw::StaticLifetime));
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&["option", "Option", "None"]),
index 3f2853e4b0e20b3025d411eed2d8ddb8a2ea7ffc..5220143a3cc461b2753d1587b50ccf6ad38e03d4 100644 (file)
@@ -37,7 +37,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
     match parse_global_asm(cx, sp, tts) {
         Ok(Some(global_asm)) => {
             MacEager::items(smallvec![P(ast::Item {
-                ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
+                ident: ast::Ident::invalid(),
                 attrs: Vec::new(),
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ItemKind::GlobalAsm(P(global_asm)),
index a13fe65ca0ddf84435fad0d33d5dfd0e6a5ba189..a485bb19808db2a90a7495f73d7a62332673a607 100644 (file)
@@ -13,7 +13,7 @@
 use syntax::parse::ParseSess;
 use syntax::ptr::P;
 use syntax::symbol::Symbol;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -378,7 +378,7 @@ fn mk_decls(
     let custom_derive = Ident::from_str("custom_derive");
     let attr = Ident::from_str("attr");
     let bang = Ident::from_str("bang");
-    let crate_kw = Ident::with_empty_ctxt(keywords::Crate.name());
+    let crate_kw = Ident::with_empty_ctxt(kw::Crate);
 
     let decls = {
         let local_path = |sp: Span, name| {
index 09dce77579001f5cbb2be5c7cec00dd481e4cc06..beac92894b77ad7b0e803860cf515b6e3bfd21d9 100644 (file)
@@ -14,7 +14,7 @@
 use syntax::parse::{self, token, ParseSess};
 use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 use syntax_pos::hygiene::{SyntaxContext, Transparency};
-use syntax_pos::symbol::{keywords, Symbol};
+use syntax_pos::symbol::{kw, Symbol};
 use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
 
 trait FromInternal<T> {
@@ -142,7 +142,7 @@ macro_rules! op {
             Question => op!('?'),
             SingleQuote => op!('\''),
 
-            Ident(ident, false) if ident.name == keywords::DollarCrate.name() =>
+            Ident(ident, false) if ident.name == kw::DollarCrate =>
                 tt!(Ident::dollar_crate()),
             Ident(ident, is_raw) => tt!(Ident::new(ident.name, is_raw)),
             Lifetime(ident) => {
@@ -150,7 +150,7 @@ macro_rules! op {
                 stack.push(tt!(Ident::new(ident.name, false)));
                 tt!(Punct::new('\'', true))
             }
-            Literal(lit, suffix) => tt!(Literal { lit, suffix }),
+            Literal(lit) => tt!(Literal { lit }),
             DocComment(c) => {
                 let style = comments::doc_comment_style(&c.as_str());
                 let stripped = comments::strip_doc_comment_decoration(&c.as_str());
@@ -161,7 +161,7 @@ macro_rules! op {
                 let stream = vec![
                     Ident(ast::Ident::new(Symbol::intern("doc"), span), false),
                     Eq,
-                    Literal(Lit::Str_(Symbol::intern(&escaped)), None),
+                    Token::lit(token::Str, Symbol::intern(&escaped), None),
                 ]
                 .into_iter()
                 .map(|token| tokenstream::TokenTree::Token(span, token))
@@ -215,31 +215,29 @@ fn to_internal(self) -> TokenStream {
                 return tokenstream::TokenTree::Token(span, token).into();
             }
             TokenTree::Literal(self::Literal {
-                lit: Lit::Integer(ref a),
-                suffix,
+                lit: token::Lit { kind: token::Integer, symbol, suffix },
                 span,
-            }) if a.as_str().starts_with("-") => {
+            }) if symbol.as_str().starts_with("-") => {
                 let minus = BinOp(BinOpToken::Minus);
-                let integer = Symbol::intern(&a.as_str()[1..]);
-                let integer = Literal(Lit::Integer(integer), suffix);
+                let symbol = Symbol::intern(&symbol.as_str()[1..]);
+                let integer = Token::lit(token::Integer, symbol, suffix);
                 let a = tokenstream::TokenTree::Token(span, minus);
                 let b = tokenstream::TokenTree::Token(span, integer);
                 return vec![a, b].into_iter().collect();
             }
             TokenTree::Literal(self::Literal {
-                lit: Lit::Float(ref a),
-                suffix,
+                lit: token::Lit { kind: token::Float, symbol, suffix },
                 span,
-            }) if a.as_str().starts_with("-") => {
+            }) if symbol.as_str().starts_with("-") => {
                 let minus = BinOp(BinOpToken::Minus);
-                let float = Symbol::intern(&a.as_str()[1..]);
-                let float = Literal(Lit::Float(float), suffix);
+                let symbol = Symbol::intern(&symbol.as_str()[1..]);
+                let float = Token::lit(token::Float, symbol, suffix);
                 let a = tokenstream::TokenTree::Token(span, minus);
                 let b = tokenstream::TokenTree::Token(span, float);
                 return vec![a, b].into_iter().collect();
             }
-            TokenTree::Literal(self::Literal { lit, suffix, span }) => {
-                return tokenstream::TokenTree::Token(span, Literal(lit, suffix)).into()
+            TokenTree::Literal(self::Literal { lit, span }) => {
+                return tokenstream::TokenTree::Token(span, Literal(lit)).into()
             }
         };
 
@@ -347,7 +345,7 @@ fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
     }
     fn dollar_crate(span: Span) -> Ident {
         // `$crate` is accepted as an ident only if it comes from the compiler.
-        Ident { sym: keywords::DollarCrate.name(), is_raw: false, span }
+        Ident { sym: kw::DollarCrate, is_raw: false, span }
     }
 }
 
@@ -355,7 +353,6 @@ fn dollar_crate(span: Span) -> Ident {
 #[derive(Clone, Debug)]
 pub struct Literal {
     lit: token::Lit,
-    suffix: Option<Symbol>,
     span: Span,
 }
 
@@ -381,6 +378,13 @@ pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
             call_site: to_span(Transparency::Transparent),
         }
     }
+
+    fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
+        Literal {
+            lit: token::Lit::new(kind, symbol, suffix),
+            span: server::Span::call_site(self),
+        }
+    }
 }
 
 impl server::Types for Rustc<'_> {
@@ -536,59 +540,31 @@ fn debug(&mut self, literal: &Self::Literal) -> String {
         format!("{:?}", literal)
     }
     fn integer(&mut self, n: &str) -> Self::Literal {
-        Literal {
-            lit: token::Lit::Integer(Symbol::intern(n)),
-            suffix: None,
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Integer, Symbol::intern(n), None)
     }
     fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
-        Literal {
-            lit: token::Lit::Integer(Symbol::intern(n)),
-            suffix: Some(Symbol::intern(kind)),
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind)))
     }
     fn float(&mut self, n: &str) -> Self::Literal {
-        Literal {
-            lit: token::Lit::Float(Symbol::intern(n)),
-            suffix: None,
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Float, Symbol::intern(n), None)
     }
     fn f32(&mut self, n: &str) -> Self::Literal {
-        Literal {
-            lit: token::Lit::Float(Symbol::intern(n)),
-            suffix: Some(Symbol::intern("f32")),
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Float, Symbol::intern(n), Some(Symbol::intern("f32")))
     }
     fn f64(&mut self, n: &str) -> Self::Literal {
-        Literal {
-            lit: token::Lit::Float(Symbol::intern(n)),
-            suffix: Some(Symbol::intern("f64")),
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Float, Symbol::intern(n), Some(Symbol::intern("f64")))
     }
     fn string(&mut self, string: &str) -> Self::Literal {
         let mut escaped = String::new();
         for ch in string.chars() {
             escaped.extend(ch.escape_debug());
         }
-        Literal {
-            lit: token::Lit::Str_(Symbol::intern(&escaped)),
-            suffix: None,
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Str, Symbol::intern(&escaped), None)
     }
     fn character(&mut self, ch: char) -> Self::Literal {
         let mut escaped = String::new();
         escaped.extend(ch.escape_unicode());
-        Literal {
-            lit: token::Lit::Char(Symbol::intern(&escaped)),
-            suffix: None,
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::Char, Symbol::intern(&escaped), None)
     }
     fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
         let string = bytes
@@ -597,11 +573,7 @@ fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
             .flat_map(ascii::escape_default)
             .map(Into::<char>::into)
             .collect::<String>();
-        Literal {
-            lit: token::Lit::ByteStr(Symbol::intern(&string)),
-            suffix: None,
-            span: server::Span::call_site(self),
-        }
+        self.lit(token::ByteStr, Symbol::intern(&string), None)
     }
     fn span(&mut self, literal: &Self::Literal) -> Self::Span {
         literal.span
index eca658cb5473e2fb30d3a24ca5c43edda152d2e3..61ef94560ccb95c6b718dd3bcdf3ebc56cc55f4f 100644 (file)
@@ -1,6 +1,6 @@
 use syntax::ext::base::{self, ExtCtxt};
 use syntax::feature_gate;
-use syntax::symbol::{keywords, sym};
+use syntax::symbol::{kw, sym};
 use syntax_pos::Span;
 use syntax::tokenstream::TokenTree;
 
@@ -17,10 +17,10 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt<'_>,
     }
 
     match (tt.len(), tt.first()) {
-        (1, Some(&TokenTree::Token(_, ref tok))) if tok.is_keyword(keywords::True) => {
+        (1, Some(&TokenTree::Token(_, ref tok))) if tok.is_keyword(kw::True) => {
             cx.set_trace_macros(true);
         }
-        (1, Some(&TokenTree::Token(_, ref tok))) if tok.is_keyword(keywords::False) => {
+        (1, Some(&TokenTree::Token(_, ref tok))) if tok.is_keyword(kw::False) => {
             cx.set_trace_macros(false);
         }
         _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
index 6e787c08504f37872cf2203c889f1db72e06879a..e8dcd8171c91fc14b9c518087c6279ac95ecc888 100644 (file)
@@ -8,7 +8,7 @@
 use crate::GLOBALS;
 use crate::Span;
 use crate::edition::Edition;
-use crate::symbol::{keywords, Symbol};
+use crate::symbol::{kw, Symbol};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -192,7 +192,7 @@ impl HygieneData {
                 prev_ctxt: SyntaxContext(0),
                 opaque: SyntaxContext(0),
                 opaque_and_semitransparent: SyntaxContext(0),
-                dollar_crate_name: keywords::DollarCrate.name(),
+                dollar_crate_name: kw::DollarCrate,
             }],
             markings: FxHashMap::default(),
         }
@@ -245,7 +245,7 @@ pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
                 prev_ctxt: SyntaxContext::empty(),
                 opaque: SyntaxContext::empty(),
                 opaque_and_semitransparent: SyntaxContext::empty(),
-                dollar_crate_name: keywords::DollarCrate.name(),
+                dollar_crate_name: kw::DollarCrate,
             });
             SyntaxContext(data.syntax_contexts.len() as u32 - 1)
         })
@@ -312,7 +312,7 @@ fn apply_mark_internal(self, mark: Mark, transparency: Transparency) -> SyntaxCo
                         prev_ctxt,
                         opaque: new_opaque,
                         opaque_and_semitransparent: new_opaque,
-                        dollar_crate_name: keywords::DollarCrate.name(),
+                        dollar_crate_name: kw::DollarCrate,
                     });
                     new_opaque
                 });
@@ -330,7 +330,7 @@ fn apply_mark_internal(self, mark: Mark, transparency: Transparency) -> SyntaxCo
                         prev_ctxt,
                         opaque,
                         opaque_and_semitransparent: new_opaque_and_semitransparent,
-                        dollar_crate_name: keywords::DollarCrate.name(),
+                        dollar_crate_name: kw::DollarCrate,
                     });
                     new_opaque_and_semitransparent
                 });
@@ -346,7 +346,7 @@ fn apply_mark_internal(self, mark: Mark, transparency: Transparency) -> SyntaxCo
                     prev_ctxt,
                     opaque,
                     opaque_and_semitransparent,
-                    dollar_crate_name: keywords::DollarCrate.name(),
+                    dollar_crate_name: kw::DollarCrate,
                 });
                 new_opaque_and_semitransparent_and_transparent
             })
@@ -512,7 +512,7 @@ pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) {
                 &mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name
             );
             assert!(dollar_crate_name == prev_dollar_crate_name ||
-                    prev_dollar_crate_name == keywords::DollarCrate.name(),
+                    prev_dollar_crate_name == kw::DollarCrate,
                     "$crate name is reset for a syntax context");
         })
     }
index 8b07e81e5863790e27daec7e459ffb63e99a4d76..b1e1a056db4adaa736f8cd057adc33bc520c8835 100644 (file)
         extern_prelude,
         extern_types,
         f16c_target_feature,
+        f32,
+        f64,
         feature,
         ffi_returns_twice,
         field_init_shorthand,
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
         rustc_mir,
+        rustc_nonnull_optimization_guaranteed,
         rustc_object_lifetime_default,
         rustc_on_unimplemented,
         rustc_outlives,
@@ -641,6 +644,11 @@ pub const fn with_empty_ctxt(name: Symbol) -> Ident {
         Ident::new(name, DUMMY_SP)
     }
 
+    #[inline]
+    pub fn invalid() -> Ident {
+        Ident::with_empty_ctxt(kw::Invalid)
+    }
+
     /// Maps an interned string to an identifier with an empty syntax context.
     pub fn from_interned_str(string: InternedString) -> Ident {
         Ident::with_empty_ctxt(string.as_symbol())
@@ -692,7 +700,7 @@ pub fn gensym(self) -> Ident {
     /// Transforms an underscore identifier into one with the same name, but
     /// gensymed. Leaves non-underscore identifiers unchanged.
     pub fn gensym_if_underscore(self) -> Ident {
-        if self.name == keywords::Underscore.name() { self.gensym() } else { self }
+        if self.name == kw::Underscore { self.gensym() } else { self }
     }
 
     // WARNING: this function is deprecated and will be removed in the future.
@@ -864,8 +872,8 @@ fn prefill(init: &[&str]) -> Self {
         this.strings.reserve(init.len());
 
         // We can't allocate empty strings in the arena, so handle this here.
-        assert!(keywords::Invalid.name().as_u32() == 0 && init[0].is_empty());
-        this.names.insert("", keywords::Invalid.name());
+        assert!(kw::Invalid.as_u32() == 0 && init[0].is_empty());
+        this.names.insert("", kw::Invalid);
         this.strings.push("");
 
         for string in &init[1..] {
@@ -926,26 +934,9 @@ pub fn get(&self, symbol: Symbol) -> &str {
     }
 }
 
-pub mod keywords {
-    use super::{Symbol, Ident};
-
-    #[derive(Clone, Copy, PartialEq, Eq)]
-    pub struct Keyword {
-        ident: Ident,
-    }
-
-    impl Keyword {
-        #[inline]
-        pub fn ident(self) -> Ident {
-            self.ident
-        }
-
-        #[inline]
-        pub fn name(self) -> Symbol {
-            self.ident.name
-        }
-    }
-
+// This module has a very short name because it's used a lot.
+pub mod kw {
+    use super::Symbol;
     keywords!();
 }
 
@@ -957,11 +948,16 @@ pub mod sym {
 
 impl Symbol {
     fn is_used_keyword_2018(self) -> bool {
-        self == keywords::Dyn.name()
+        self == kw::Dyn
     }
 
     fn is_unused_keyword_2018(self) -> bool {
-        self >= keywords::Async.name() && self <= keywords::Try.name()
+        self >= kw::Async && self <= kw::Try
+    }
+
+    /// Used for sanity checking rustdoc keyword sections.
+    pub fn is_doc_keyword(self) -> bool {
+        self <= kw::Union
     }
 }
 
@@ -969,20 +965,20 @@ impl Ident {
     // Returns `true` for reserved identifiers used internally for elided lifetimes,
     // unnamed method parameters, crate root module, error recovery etc.
     pub fn is_special(self) -> bool {
-        self.name <= keywords::Underscore.name()
+        self.name <= kw::Underscore
     }
 
     /// Returns `true` if the token is a keyword used in the language.
     pub fn is_used_keyword(self) -> bool {
         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
-        self.name >= keywords::As.name() && self.name <= keywords::While.name() ||
+        self.name >= kw::As && self.name <= kw::While ||
         self.name.is_used_keyword_2018() && self.span.rust_2018()
     }
 
     /// Returns `true` if the token is a keyword reserved for possible future use.
     pub fn is_unused_keyword(self) -> bool {
         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
-        self.name >= keywords::Abstract.name() && self.name <= keywords::Yield.name() ||
+        self.name >= kw::Abstract && self.name <= kw::Yield ||
         self.name.is_unused_keyword_2018() && self.span.rust_2018()
     }
 
@@ -993,17 +989,17 @@ pub fn is_reserved(self) -> bool {
 
     /// A keyword or reserved identifier that can be used as a path segment.
     pub fn is_path_segment_keyword(self) -> bool {
-        self.name == keywords::Super.name() ||
-        self.name == keywords::SelfLower.name() ||
-        self.name == keywords::SelfUpper.name() ||
-        self.name == keywords::Crate.name() ||
-        self.name == keywords::PathRoot.name() ||
-        self.name == keywords::DollarCrate.name()
+        self.name == kw::Super ||
+        self.name == kw::SelfLower ||
+        self.name == kw::SelfUpper ||
+        self.name == kw::Crate ||
+        self.name == kw::PathRoot ||
+        self.name == kw::DollarCrate
     }
 
     /// This identifier can be a raw identifier.
     pub fn can_be_raw(self) -> bool {
-        self.name != keywords::Invalid.name() && self.name != keywords::Underscore.name() &&
+        self.name != kw::Invalid && self.name != kw::Underscore &&
         !self.is_path_segment_keyword()
     }
 
@@ -1267,7 +1263,7 @@ fn interner_tests() {
     fn without_first_quote_test() {
         GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
             let i = Ident::from_str("'break");
-            assert_eq!(i.without_first_quote().name, keywords::Break.name());
+            assert_eq!(i.without_first_quote().name, kw::Break);
         });
     }
 }
index 2c5656ae593851d0b2336a727cc14b77a06b8ac0..4efebe31651d5520bcba968878dbb8a4971d2045 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2c5656ae593851d0b2336a727cc14b77a06b8ac0
+Subproject commit 4efebe31651d5520bcba968878dbb8a4971d2045
index 4102eb32580f025143f6e7bd5627790e18e4fc7b..27287d06d54b171b4573b235d1345fb42e6a56c7 100644 (file)
@@ -7,7 +7,6 @@ pub trait T2 { }
 #[cfg(cfail2)]
 pub trait T2: T1 { }
 //[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2`
-//[cfail2]~| ERROR cycle detected when computing the supertraits of `T2`
 
 pub trait T1: T2 { }
 
index d4852db6d475e39736104ebc1de375729077b62e..ee6adfefe3e360b3a0ec00bd878d1fceb2de619e 100644 (file)
@@ -22,13 +22,11 @@ fn drop(&mut self) {
 // END RUST SOURCE
 // START rustc.main.ElaborateDrops.before.mir
 //     let mut _0: ();
+//     let _1: std::boxed::Box<S>;
 //     let mut _2: std::boxed::Box<S>;
 //     let mut _3: ();
 //     let mut _4: std::boxed::Box<S>;
 //     scope 1 {
-//         let _1: std::boxed::Box<S>;
-//     }
-//     scope 2 {
 //     }
 //     bb0: {
 //         StorageLive(_1);
index 023440af0eb10d014549346c9008271b594b7dbe..0b678be2ab3197ea4f8c1b34b6204c546e16f7fa 100644 (file)
@@ -29,27 +29,24 @@ fn other(self, s: Self) {}
 // END RUST SOURCE
 // START rustc.main.ElaborateDrops.after.mir
 //    let mut _0: ();
+//    let _1: ();
 //    let mut _2: S;
 //    let mut _3: S;
 //    let mut _4: S;
 //    let mut _5: bool;
 //    scope 1 {
-//        let _1: ();
-//    }
-//    scope 2 {
 //    }
 //    ...
 //    bb0: {
 // END rustc.main.ElaborateDrops.after.mir
 // START rustc.test.ElaborateDrops.after.mir
 //    let mut _0: ();
+//    let _1: S;
 //    let mut _3: ();
 //    let mut _4: S;
 //    let mut _5: S;
 //    let mut _6: bool;
 //    ...
-//    let _1: S;
-//    ...
 //    let mut _2: S;
 //    ...
 //    bb0: {
index 29446d2ecc23e5d9180ee6f47957cbde30d42977..bf22f00b5055241febebe48805840a533a8cb617 100644 (file)
@@ -18,14 +18,12 @@ fn main() {
 // fn main() -> (){
 //     let mut _0: ();
 //     let mut _1: ();
+//     let _2: i32;
 //     let mut _3: bool;
 //     let mut _4: !;
 //     let mut _5: ();
 //     let mut _6: &i32;
 //     scope 1 {
-//         let _2: i32;
-//     }
-//     scope 2 {
 //     }
 //     bb0: {
 //         goto -> bb1;
@@ -88,7 +86,6 @@ fn main() {
 //         unreachable;
 //     }
 //     bb17: {
-//         StorageDead(_4);
 //         goto -> bb18;
 //     }
 //     bb18: {
diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs
new file mode 100644 (file)
index 0000000..0f026b8
--- /dev/null
@@ -0,0 +1,245 @@
+// Test that StorageDead and Drops are generated properly for bindings in
+// matches:
+// * The MIR should only contain a single drop of `s` and `t`: at the end
+//   of their respective arms.
+// * StorageDead and StorageLive statements are correctly matched up on
+//   non-unwind paths.
+// * The visibility scopes of the match arms should be disjoint, and contain.
+//   all of the bindings for that scope.
+// * No drop flags are used.
+
+#![feature(nll, bind_by_move_pattern_guards)]
+
+fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 {
+    match items {
+        (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1,
+        (true, b, t) | (false, b, t) => 2,
+    }
+}
+
+const CASES: &[(bool, bool, bool, i32)] = &[
+    (false, false, false, 2),
+    (false, false, true, 1),
+    (false, true, false, 1),
+    (false, true, true, 2),
+    (true, false, false, 3),
+    (true, false, true, 3),
+    (true, true, false, 3),
+    (true, true, true, 2),
+];
+
+fn main() {
+    for &(cond, items_1, items_2, result) in CASES {
+        assert_eq!(
+            complicated_match(cond, (items_1, items_2, String::new())),
+            result,
+        );
+    }
+}
+
+// END RUST SOURCE
+// START rustc.complicated_match.SimplifyCfg-initial.after.mir
+// let mut _0: i32;
+// let mut _3: &bool;                   // Temp for fake borrow of `items.0`
+// let mut _4: &bool;                   // Temp for fake borrow of `items.1`
+// let _5: bool;                    // `a` in arm
+// let _6: &bool;                   // `a` in guard
+// let _7: std::string::String;     // `s` in arm
+// let _8: &std::string::String;    // `s` in guard
+// let mut _9: bool;                    // `if cond { return 3 } else { a }`
+// let mut _10: bool;                   // `cond`
+// let mut _11: !;                      // `return 3`
+// let mut _12: bool;                   // `if cond { return 3 } else { a }`
+// let mut _13: bool;                   // `cond`
+// let mut _14: !;                      // `return 3`
+// let _15: bool;                   // `b`
+// let _16: std::string::String;    // `t`
+// scope 1 {
+// }
+// scope 2 {
+// }
+// bb0: {
+//     FakeRead(ForMatchedPlace, _2);
+//     switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb7];
+// }
+// bb1 (cleanup): {
+//     resume;
+// }
+// bb2: {
+//     falseEdges -> [real: bb10, imaginary: bb3];
+// }
+// bb3: {
+//     falseEdges -> [real: bb21, imaginary: bb4];
+// }
+// bb4: {
+//     falseEdges -> [real: bb31, imaginary: bb5];
+// }
+// bb5: {
+//     falseEdges -> [real: bb32, imaginary: bb6];
+// }
+// bb6: {
+//     unreachable;
+// }
+// bb7: {
+//     switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb8];
+// }
+// bb8: {
+//     switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb4];
+// }
+// bb9: {                               // arm 1
+//     _0 = const 1i32;
+//     drop(_7) -> [return: bb29, unwind: bb16];
+// }
+// bb10: {                              // guard - first time
+//     StorageLive(_6);
+//     _6 = &(_2.1: bool);
+//     StorageLive(_8);
+//     _8 = &(_2.2: std::string::String);
+//     _3 = &shallow (_2.0: bool);
+//     _4 = &shallow (_2.1: bool);
+//     StorageLive(_9);
+//     StorageLive(_10);
+//     _10 = _1;
+//     FakeRead(ForMatchedPlace, _10);
+//     switchInt(_10) -> [false: bb12, otherwise: bb11];
+// }
+// bb11: {
+//     falseEdges -> [real: bb14, imaginary: bb12];
+// }
+// bb12: {
+//     falseEdges -> [real: bb18, imaginary: bb13];
+// }
+// bb13: {
+//     unreachable;
+// }
+// bb14: {                              // `return 3` - first time
+//     _0 = const 3i32;
+//     StorageDead(_10);
+//     StorageDead(_9);
+//     StorageDead(_8);
+//     StorageDead(_6);
+//     goto -> bb17;
+// }
+// bb15: {
+//     return;
+// }
+// bb16 (cleanup): {
+//     drop(_2) -> bb1;
+// }
+// bb17: {
+//     drop(_2) -> [return: bb15, unwind: bb1];
+// }
+// bb18: {                              // `else` block - first time
+//     _9 = (*_6);
+//     StorageDead(_10);
+//     FakeRead(ForMatchGuard, _3);
+//     FakeRead(ForMatchGuard, _4);
+//     FakeRead(ForGuardBinding, _6);
+//     FakeRead(ForGuardBinding, _8);
+//     switchInt(move _9) -> [false: bb20, otherwise: bb19];
+// }
+// bb19: {
+//     StorageDead(_9);
+//     StorageLive(_5);
+//     _5 = (_2.1: bool);
+//     StorageLive(_7);
+//     _7 = move (_2.2: std::string::String);
+//     goto -> bb9;
+// }
+// bb20: {                              // guard otherwise case - first time
+//     StorageDead(_9);
+//     StorageDead(_8);
+//     StorageDead(_6);
+//     falseEdges -> [real: bb7, imaginary: bb3];
+// }
+// bb21: {                              // guard - second time
+//     StorageLive(_6);
+//     _6 = &(_2.0: bool);
+//     StorageLive(_8);
+//     _8 = &(_2.2: std::string::String);
+//     _3 = &shallow (_2.0: bool);
+//     _4 = &shallow (_2.1: bool);
+//     StorageLive(_12);
+//     StorageLive(_13);
+//     _13 = _1;
+//     FakeRead(ForMatchedPlace, _13);
+//     switchInt(_13) -> [false: bb23, otherwise: bb22];
+// }
+// bb22: {
+//     falseEdges -> [real: bb25, imaginary: bb23];
+// }
+// bb23: {
+//     falseEdges -> [real: bb26, imaginary: bb24];
+// }
+// bb24: {
+//     unreachable;
+// }
+// bb25: {                              // `return 3` - second time
+//     _0 = const 3i32;
+//     StorageDead(_13);
+//     StorageDead(_12);
+//     StorageDead(_8);
+//     StorageDead(_6);
+//     goto -> bb17;
+// }
+// bb26: {                              // `else` block - second time
+//     _12 = (*_6);
+//     StorageDead(_13);
+//     FakeRead(ForMatchGuard, _3);
+//     FakeRead(ForMatchGuard, _4);
+//     FakeRead(ForGuardBinding, _6);
+//     FakeRead(ForGuardBinding, _8);
+//     switchInt(move _12) -> [false: bb28, otherwise: bb27];
+// }
+// bb27: {                              // Guard otherwise case - second time
+//     StorageDead(_12);
+//     StorageLive(_5);
+//     _5 = (_2.0: bool);
+//     StorageLive(_7);
+//     _7 = move (_2.2: std::string::String);
+//     goto -> bb9;
+// }
+// bb28: {                              // rest of arm 1
+//     StorageDead(_12);
+//     StorageDead(_8);
+//     StorageDead(_6);
+//     falseEdges -> [real: bb8, imaginary: bb4];
+// }
+// bb29: {
+//     StorageDead(_7);
+//     StorageDead(_5);
+//     StorageDead(_8);
+//     StorageDead(_6);
+//     goto -> bb34;
+// }
+// bb30: {                              // arm 2
+//     _0 = const 2i32;
+//     drop(_16) -> [return: bb33, unwind: bb16];
+// }
+// bb31: {                              // bindings for arm 2 - first pattern
+//     StorageLive(_15);
+//     _15 = (_2.1: bool);
+//     StorageLive(_16);
+//     _16 = move (_2.2: std::string::String);
+//     goto -> bb30;
+// }
+// bb32: {                              // bindings for arm 2 - first pattern
+//     StorageLive(_15);
+//     _15 = (_2.1: bool);
+//     StorageLive(_16);
+//     _16 = move (_2.2: std::string::String);
+//     goto -> bb30;
+// }
+// bb33: {                              // rest of arm 2
+//     StorageDead(_16);
+//     StorageDead(_15);
+//     goto -> bb34;
+// }
+// bb34: {                              // end of match
+//     drop(_2) -> [return: bb15, unwind: bb1];
+// }
+// END rustc.complicated_match.SimplifyCfg-initial.after.mir
+// START rustc.complicated_match.ElaborateDrops.after.mir
+// let _16: std::string::String;      // No drop flags, which would come after this.
+// scope 1 {
+// END rustc.complicated_match.ElaborateDrops.after.mir
index 7ac36a22274f33897dfe8e2a827b7c97f373a010..6979924c8cd9083b4986665d81abb6c2df17e97a 100644 (file)
@@ -45,13 +45,13 @@ fn main() {
 //      _2 = std::option::Option::<i32>::Some(const 42i32,);
 //      FakeRead(ForMatchedPlace, _2);
 //      _3 = discriminant(_2);
-//      switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb7];
+//      switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb6];
 //  }
 //  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
-//      falseEdges -> [real: bb8, imaginary: bb3]; //pre_binding1
+//      falseEdges -> [real: bb7, imaginary: bb3]; //pre_binding1
 //  }
 //  bb3: {
 //      falseEdges -> [real: bb11, imaginary: bb4]; //pre_binding2
@@ -62,48 +62,56 @@ fn main() {
 //  bb5: {
 //      unreachable;
 //  }
-//  bb6: { // to pre_binding2
-//      falseEdges -> [real: bb3, imaginary: bb3];
-//  }
-//  bb7: {
+//  bb6: {
 //      unreachable;
 //  }
-//  bb8: { // binding1 and guard
+//  bb7: { // binding1 and guard
 //      StorageLive(_6);
 //      _6 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
 //      _4 = &shallow _2;
 //      StorageLive(_7);
-//      _7 = const guard() -> [return: bb9, unwind: bb1];
+//      _7 = const guard() -> [return: bb8, unwind: bb1];
 //  }
-//  bb9: {
+//  bb8: { // end of guard
 //      FakeRead(ForMatchGuard, _4);
 //      FakeRead(ForGuardBinding, _6);
-//      switchInt(move _7) -> [false: bb6, otherwise: bb10];
+//      switchInt(move _7) -> [false: bb10, otherwise: bb9];
 //  }
-//  bb10: {
+//  bb9: { // arm1
+//      StorageDead(_7);
 //      StorageLive(_5);
 //      _5 = ((_2 as Some).0: i32);
 //      StorageLive(_8);
 //      _8 = _5;
 //      _1 = (const 1i32, move _8);
 //      StorageDead(_8);
+//      StorageDead(_5);
+//      StorageDead(_6);
 //      goto -> bb13;
 //  }
-//  bb11: {
+//  bb10: { // to pre_binding2
+//      StorageDead(_7);
+//      StorageDead(_6);
+//      falseEdges -> [real: bb3, imaginary: bb3];
+//  }
+//  bb11: { // arm2
 //      StorageLive(_9);
 //      _9 = ((_2 as Some).0: i32);
 //      StorageLive(_10);
 //      _10 = _9;
 //      _1 = (const 2i32, move _10);
 //      StorageDead(_10);
+//      StorageDead(_9);
 //      goto -> bb13;
 //  }
-//  bb12: {
+//  bb12: { // arm3
 //      _1 = (const 3i32, const 3i32);
 //      goto -> bb13;
 //  }
 //  bb13: {
-//      ...
+//      StorageDead(_2);
+//      StorageDead(_1);
+//      _0 = ();
 //      return;
 //  }
 // END rustc.full_tested_match.QualifyAndPromoteConstants.after.mir
@@ -114,13 +122,13 @@ fn main() {
 //      _2 = std::option::Option::<i32>::Some(const 42i32,);
 //      FakeRead(ForMatchedPlace, _2);
 //      _3 = discriminant(_2);
-//      switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb7];
+//      switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb6];
 //  }
 //  bb1 (cleanup): {
 //      resume;
 //  }
 //  bb2: {
-//      falseEdges -> [real: bb8, imaginary: bb3];
+//      falseEdges -> [real: bb7, imaginary: bb3];
 //  }
 //  bb3: {
 //      falseEdges -> [real: bb11, imaginary: bb4];
@@ -131,33 +139,38 @@ fn main() {
 //  bb5: {
 //      unreachable;
 //  }
-//  bb6: { // to pre_binding3 (can skip 2 since this is `Some`)
-//      falseEdges -> [real: bb4, imaginary: bb3];
-//  }
-//  bb7: {
+//  bb6: {
 //      unreachable;
 //  }
-//  bb8: { // binding1 and guard
+//  bb7: { // binding1 and guard
 //      StorageLive(_6);
 //      _6 = &((_2 as Some).0: i32);
 //      _4 = &shallow _2;
 //      StorageLive(_7);
-//      _7 = const guard() -> [return: bb9, unwind: bb1];
+//      _7 = const guard() -> [return: bb8, unwind: bb1];
 //  }
-//  bb9: { // end of guard
+//  bb8: { // end of guard
 //      FakeRead(ForMatchGuard, _4);
 //      FakeRead(ForGuardBinding, _6);
-//      switchInt(move _7) -> [false: bb6, otherwise: bb10];
+//      switchInt(move _7) -> [false: bb10, otherwise: bb9];
 //  }
-//  bb10: { // arm1
+//  bb9: { // arm1
+//      StorageDead(_7);
 //      StorageLive(_5);
 //      _5 = ((_2 as Some).0: i32);
 //      StorageLive(_8);
 //      _8 = _5;
 //      _1 = (const 1i32, move _8);
 //      StorageDead(_8);
+//      StorageDead(_5);
+//      StorageDead(_6);
 //      goto -> bb13;
 //  }
+//  bb10: { // to pre_binding3 (can skip 2 since this is `Some`)
+//      StorageDead(_7);
+//      StorageDead(_6);
+//      falseEdges -> [real: bb4, imaginary: bb3];
+//  }
 //  bb11: { // arm2
 //      _1 = (const 3i32, const 3i32);
 //      goto -> bb13;
@@ -169,16 +182,19 @@ fn main() {
 //      _10 = _9;
 //      _1 = (const 2i32, move _10);
 //      StorageDead(_10);
+//      StorageDead(_9);
 //      goto -> bb13;
 //  }
 //  bb13: {
-//      ...
+//      StorageDead(_2);
+//      StorageDead(_1);
+//      _0 = ();
 //      return;
 //  }
 // END rustc.full_tested_match2.QualifyAndPromoteConstants.before.mir
 //
 // START rustc.main.QualifyAndPromoteConstants.before.mir
-// bb0: {
+//  bb0: {
 //     ...
 //      _2 = std::option::Option::<i32>::Some(const 1i32,);
 //      FakeRead(ForMatchedPlace, _2);
@@ -189,13 +205,13 @@ fn main() {
 //      resume;
 //  }
 //  bb2: {
-//      falseEdges -> [real: bb9, imaginary: bb3];
+//      falseEdges -> [real: bb7, imaginary: bb3];
 //  }
 //  bb3: {
-//      falseEdges -> [real: bb12, imaginary: bb4];
+//      falseEdges -> [real: bb11, imaginary: bb4];
 //  }
 //  bb4: {
-//      falseEdges -> [real: bb13, imaginary: bb5];
+//      falseEdges -> [real: bb12, imaginary: bb5];
 //  }
 //  bb5: {
 //      falseEdges -> [real: bb16, imaginary: bb6];
@@ -203,65 +219,79 @@ fn main() {
 //  bb6: {
 //      unreachable;
 //  }
-//  bb7: {
-//      falseEdges -> [real: bb3, imaginary: bb3];
-//  }
-//  bb8: {
-//      falseEdges -> [real: bb5, imaginary: bb5];
-//  }
-//  bb9: { // binding1: Some(w) if guard()
+//  bb7: { // binding1: Some(w) if guard()
 //      StorageLive(_7);
 //      _7 = &((_2 as Some).0: i32);
 //      _5 = &shallow _2;
 //      StorageLive(_8);
-//      _8 = const guard() -> [return: bb10, unwind: bb1];
+//      _8 = const guard() -> [return: bb8, unwind: bb1];
 //  }
-//  bb10: { //end of guard
+//  bb8: { //end of guard1
 //      FakeRead(ForMatchGuard, _5);
 //      FakeRead(ForGuardBinding, _7);
-//      switchInt(move _8) -> [false: bb7, otherwise: bb11];
+//      switchInt(move _8) -> [false: bb10, otherwise: bb9];
 //  }
-//  bb11: { // set up bindings for arm1
+//  bb9: {
+//      StorageDead(_8);
 //      StorageLive(_6);
 //      _6 = ((_2 as Some).0: i32);
 //      _1 = const 1i32;
+//      StorageDead(_6);
+//      StorageDead(_7);
 //      goto -> bb17;
 //  }
-//  bb12: { // binding2 & arm2
+//  bb10: {
+//      StorageDead(_8);
+//      StorageDead(_7);
+//      falseEdges -> [real: bb3, imaginary: bb3];
+//  }
+//  bb11: { // binding2 & arm2
 //      StorageLive(_9);
 //      _9 = _2;
 //      _1 = const 2i32;
+//      StorageDead(_9);
 //      goto -> bb17;
 //  }
-//  bb13: { // binding3: Some(y) if guard2(y)
+//  bb12: { // binding3: Some(y) if guard2(y)
 //      StorageLive(_11);
 //      _11 = &((_2 as Some).0: i32);
 //      _5 = &shallow _2;
 //      StorageLive(_12);
 //      StorageLive(_13);
 //      _13 = (*_11);
-//      _12 = const guard2(move _13) -> [return: bb14, unwind: bb1];
+//      _12 = const guard2(move _13) -> [return: bb13, unwind: bb1];
 //  }
-//  bb14: { // end of guard2
+//  bb13: { // end of guard2
 //      StorageDead(_13);
 //      FakeRead(ForMatchGuard, _5);
 //      FakeRead(ForGuardBinding, _11);
-//      switchInt(move _12) -> [false: bb8, otherwise: bb15];
+//      switchInt(move _12) -> [false: bb15, otherwise: bb14];
 //  }
-//  bb15: { // binding4 & arm4
+//  bb14: { // binding4 & arm4
+//      StorageDead(_12);
 //      StorageLive(_10);
 //      _10 = ((_2 as Some).0: i32);
 //      _1 = const 3i32;
+//      StorageDead(_10);
+//      StorageDead(_11);
 //      goto -> bb17;
 //  }
+//  bb15: {
+//      StorageDead(_12);
+//      StorageDead(_11);
+//      falseEdges -> [real: bb5, imaginary: bb5];
+//  }
 //  bb16: {
 //      StorageLive(_14);
 //      _14 = _2;
 //      _1 = const 4i32;
+//      StorageDead(_14);
 //      goto -> bb17;
 //  }
 //  bb17: {
-//      ...
+//      StorageDead(_2);
+//      StorageDead(_1);
+//      _0 = ();
 //      return;
 //  }
 // END rustc.main.QualifyAndPromoteConstants.before.mir
index a5317f98ef1885df9f20df65aae3a88a0172671d..2ef9520c12c637e54c6bb00191c85d01f950a583 100644 (file)
@@ -20,10 +20,10 @@ fn main() {
 // START rustc.main.SimplifyCfg-initial.after.mir
 //    bb0: {
 //        ...
-//        switchInt(move _4) -> [false: bb7, otherwise: bb8];
+//        switchInt(move _4) -> [false: bb6, otherwise: bb7];
 //    }
 //    bb1: {
-//        falseEdges -> [real: bb12, imaginary: bb2];
+//        falseEdges -> [real: bb10, imaginary: bb2];
 //    }
 //    bb2: {
 //        falseEdges -> [real: bb13, imaginary: bb3];
@@ -38,33 +38,35 @@ fn main() {
 //        unreachable;
 //    }
 //    bb6: {
-//        falseEdges -> [real: bb4, imaginary: bb2];
+//        _6 = Le(const 10i32, _1);
+//        switchInt(move _6) -> [false: bb8, otherwise: bb9];
 //    }
 //    bb7: {
-//        _6 = Le(const 10i32, _1);
-//        switchInt(move _6) -> [false: bb9, otherwise: bb10];
+//        _5 = Lt(_1, const 10i32);
+//        switchInt(move _5) -> [false: bb6, otherwise: bb1];
 //    }
 //    bb8: {
-//        _5 = Lt(_1, const 10i32);
-//        switchInt(move _5) -> [false: bb7, otherwise: bb1];
+//        switchInt(_1) -> [-1i32: bb3, otherwise: bb4];
 //    }
 //    bb9: {
-//        switchInt(_1) -> [-1i32: bb3, otherwise: bb4];
+//        _7 = Le(_1, const 20i32);
+//        switchInt(move _7) -> [false: bb8, otherwise: bb2];
 //    }
 //    bb10: {
-//        _7 = Le(_1, const 20i32);
-//        switchInt(move _7) -> [false: bb9, otherwise: bb2];
+//        _8 = &shallow _1;
+//        StorageLive(_9);
+//        _9 = _2;
+//        FakeRead(ForMatchGuard, _8);
+//        switchInt(move _9) -> [false: bb12, otherwise: bb11];
 //    }
 //    bb11: {
+//        StorageDead(_9);
 //        _3 = const 0i32;
 //        goto -> bb16;
 //    }
 //    bb12: {
-//        _8 = &shallow _1;
-//        StorageLive(_9);
-//        _9 = _2;
-//        FakeRead(ForMatchGuard, _8);
-//        switchInt(move _9) -> [false: bb6, otherwise: bb11];
+//        StorageDead(_9);
+//        falseEdges -> [real: bb4, imaginary: bb2];
 //    }
 //    bb13: {
 //        _3 = const 1i32;
@@ -79,7 +81,6 @@ fn main() {
 //        goto -> bb16;
 //    }
 //    bb16: {
-//        StorageDead(_9);
 //        _0 = ();
 //        StorageDead(_2);
 //        StorageDead(_1);
index 7e8c58e64c28d60d2689682e094f927291c0da75..da73cc96348f059e4c15e29ce839204b2b824ed4 100644 (file)
@@ -18,15 +18,13 @@ fn drop(&mut self) {}
 // START rustc.main.EraseRegions.before.mir
 // fn main() -> () {
 //     let mut _0: ();
+//     let mut _1: Packed;
 //     let mut _2: Aligned;
 //     let mut _3: Droppy;
 //     let mut _4: Aligned;
 //     let mut _5: Droppy;
 //     let mut _6: Aligned;
 //     scope 1 {
-//         let mut _1: Packed;
-//     }
-//     scope 2 {
 //     }
 //
 //     bb0: {
index 8348f9a77467888fe5b7273d7e76790a33f5fad9..6ac9cee79f53a82e53ace7b82f2c3f3a284ac84b 100644 (file)
@@ -19,10 +19,10 @@ fn main() {
 // bb0: {
 //     FakeRead(ForMatchedPlace, _1);
 //     _3 = discriminant(_1);
-//     switchInt(move _3) -> [1isize: bb5, otherwise: bb2];
+//     switchInt(move _3) -> [1isize: bb4, otherwise: bb2];
 // }
 // bb1: {
-//     goto -> bb7;
+//     goto -> bb5;
 // }
 // bb2: {
 //     goto -> bb8;
@@ -31,16 +31,9 @@ fn main() {
 //     unreachable;
 // }
 // bb4: {
-//     goto -> bb2;
-// }
-// bb5: {
 //     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb1, otherwise: bb2];
 // }
-// bb6: {
-//     _0 = const 0i32;
-//     goto -> bb9;
-// }
-// bb7: {
+// bb5: {
 //     _4 = &shallow _1;
 //     _5 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
 //     _6 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
@@ -51,14 +44,22 @@ fn main() {
 //     FakeRead(ForMatchGuard, _5);
 //     FakeRead(ForMatchGuard, _6);
 //     FakeRead(ForMatchGuard, _7);
-//     switchInt(move _8) -> [false: bb4, otherwise: bb6];
+//     switchInt(move _8) -> [false: bb7, otherwise: bb6];
+// }
+// bb6: {
+//     StorageDead(_8);
+//     _0 = const 0i32;
+//     goto -> bb9;
+// }
+// bb7: {
+//     StorageDead(_8);
+//     goto -> bb2;
 // }
 // bb8: {
 //     _0 = const 1i32;
 //     goto -> bb9;
 // }
 // bb9: {
-//     StorageDead(_8);
 //     return;
 // }
 // bb10 (cleanup): {
@@ -70,10 +71,10 @@ fn main() {
 // bb0: {
 //     nop;
 //     _3 = discriminant(_1);
-//     switchInt(move _3) -> [1isize: bb5, otherwise: bb2];
+//     switchInt(move _3) -> [1isize: bb4, otherwise: bb2];
 // }
 // bb1: {
-//     goto -> bb7;
+//     goto -> bb5;
 // }
 // bb2: {
 //     goto -> bb8;
@@ -82,16 +83,9 @@ fn main() {
 //     unreachable;
 // }
 // bb4: {
-//     goto -> bb2;
-// }
-// bb5: {
 //     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb1, otherwise: bb2];
 // }
-// bb6: {
-//     _0 = const 0i32;
-//     goto -> bb9;
-// }
-// bb7: {
+// bb5: {
 //     nop;
 //     nop;
 //     nop;
@@ -102,14 +96,22 @@ fn main() {
 //     nop;
 //     nop;
 //     nop;
-//     switchInt(move _8) -> [false: bb4, otherwise: bb6];
+//     switchInt(move _8) -> [false: bb7, otherwise: bb6];
+// }
+// bb6: {
+//     StorageDead(_8);
+//     _0 = const 0i32;
+//     goto -> bb9;
+// }
+// bb7: {
+//     StorageDead(_8);
+//     goto -> bb2;
 // }
 // bb8: {
 //     _0 = const 1i32;
 //     goto -> bb9;
 // }
 // bb9: {
-//     StorageDead(_8);
 //     return;
 // }
 // bb10 (cleanup): {
index 10f00cf8b0c32869aa294faec4e8f9af3e79c81c..2ed34ecfad2c6317f8f4b9a07db528b963ff26e9 100644 (file)
@@ -182,8 +182,8 @@ fn main() {
 //        _2 = Foo { tup: const "hi", data: move _3 };
 //        _1 = &_2;
 //        _0 = &(*_1);
-//        StorageDead(_1);
 //        StorageDead(_5);
+//        StorageDead(_1);
 //        return;
 //    }
 //}
index 4e43aa96e1d853895e90754a9cd747a36fb83d12..1bab3f01aba04707ecd058eefcd21ba57037afbe 100644 (file)
@@ -47,8 +47,8 @@ fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
     fn provide(&self, providers: &mut Providers) {
         rustc_codegen_utils::symbol_names::provide(providers);
 
-        providers.target_features_whitelist = |_tcx, _cnum| {
-            Default::default() // Just a dummy
+        providers.target_features_whitelist = |tcx, _cnum| {
+            tcx.arena.alloc(Default::default()) // Just a dummy
         };
         providers.is_reachable_non_generic = |_tcx, _defid| true;
         providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs
new file mode 100644 (file)
index 0000000..6acc862
--- /dev/null
@@ -0,0 +1,35 @@
+use std::marker::PhantomData;
+
+pub struct True;
+pub struct False;
+
+pub trait InterfaceType{
+    type Send;
+}
+
+
+pub struct FooInterface<T>(PhantomData<fn()->T>);
+
+impl<T> InterfaceType for FooInterface<T> {
+    type Send=False;
+}
+
+
+pub struct DynTrait<I>{
+    _interface:PhantomData<fn()->I>,
+    _unsync_unsend:PhantomData<::std::rc::Rc<()>>,
+}
+
+unsafe impl<I> Send for DynTrait<I>
+where
+    I:InterfaceType<Send=True>
+{}
+
+// @has issue_60726/struct.IntoIter.html
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
+// IntoIter<T>"
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Sync for \
+// IntoIter<T>"
+pub struct IntoIter<T>{
+    hello:DynTrait<FooInterface<T>>,
+}
index 5e86dcb1232c873a2665f4cd3c5ce4d9b1936d1e..e2d3e417ac3ac8777abf79ae5fe69ddc520ded08 100644 (file)
@@ -12,6 +12,7 @@ LL |     *a += 1;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0503]: cannot use `y` because it was mutably borrowed
   --> $DIR/borrowck-anon-fields-variant.rs:37:7
index fb42e5fbca8a883eefbbfcb1c4c75bd30d71b4de..14b9b50f0c32a6352eeed0c16209e1aabf13411c 100644 (file)
@@ -341,6 +341,7 @@ LL |             drop(x);
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:227:33
@@ -355,6 +356,7 @@ LL |             drop(x);
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-describe-lvalue.rs:282:22
index 8dba34bd8086bb3d8393c5c644bdeaec5f9905c5..461fb7d11a58aa4f4f986b11607ec1c659190331 100644 (file)
@@ -6,4 +6,5 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
index 8dba34bd8086bb3d8393c5c644bdeaec5f9905c5..461fb7d11a58aa4f4f986b11607ec1c659190331 100644 (file)
@@ -6,4 +6,5 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
index d12d751d89b766983824be81dbac8c8421095419..ac6bed6137fa304577dd009cb862b0e3cf908be8 100644 (file)
@@ -28,6 +28,7 @@ LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0510]: cannot mutably borrow `x` in match guard
   --> $DIR/borrowck-mutate-in-guard.rs:15:33
@@ -40,6 +41,7 @@ LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to 3 previous errors
 
index 20433bbf8b5c764afecdaab642654234d7d29dd1..2ca76667bd118fb5c1bc2a95c329ad4d347594d4 100644 (file)
@@ -21,6 +21,7 @@ LL |     a + b
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0381]: use of possibly uninitialized variable: `b`
   --> $DIR/const_let_refutable.rs:4:9
@@ -30,6 +31,7 @@ LL |     a + b
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to 2 previous errors
 
index 7af379924608ff4d15f603b248deb08179cae9c4..93b57bc24a82f0cbba7ed9527b7c44a4771860d4 100644 (file)
@@ -297,6 +297,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:144:41
index b6445329db383e7dcfd28088b43b9a575a1a2f56..9ded93c16727ba5e881e22f37e1e56ffafc360e5 100644 (file)
@@ -27,6 +27,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to 2 previous errors
 
index 336b67852cd015da6e839d3b2478622ae2490f46..d3609acfdff63edd44e05599669eeb292e2083d2 100644 (file)
@@ -16,7 +16,6 @@ struct A<T>
     where T : Trait,
           T : Add<T::Item>
     //~^ ERROR cycle detected
-    //~| ERROR associated type `Item` not found for `T`
 {
     data: T
 }
index e5a5e2897cd0a101ec195127bb66a324858d7763..59815138e2e36f32853b6a2cdfdb3960ee77ba61 100644 (file)
@@ -11,13 +11,6 @@ note: cycle used when processing `A`
 LL |           T : Add<T::Item>
    |                   ^^^^^^^
 
-error[E0220]: associated type `Item` not found for `T`
-  --> $DIR/cycle-projection-based-on-where-clause.rs:17:19
-   |
-LL |           T : Add<T::Item>
-   |                   ^^^^^^^ associated type `Item` not found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0220, E0391.
-For more information about an error, try `rustc --explain E0220`.
+For more information about this error, try `rustc --explain E0391`.
index 347d9aeac2307934edfa68d619a7157452aa78c0..5547631a4b0229e9b2b5310ebc16e316c9106140 100644 (file)
@@ -1 +1 @@
-{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"}
+{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta","emit":"metadata"}
index 56c977181ff515a8a97bd7f56a22fdee4bd1eb96..260d41b8f15cc090902f2a39d22af5c1525ed2c9 100644 (file)
@@ -1 +1 @@
-{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"}
+{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"}
index 6608ad763b2e94c5f7bfcd90f3ebac419768c0ea..9911dd4683b6664a69b47d9e7b3a85fb6eb96194 100644 (file)
@@ -19,6 +19,7 @@ LL |     u
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
index ac21241b3038607f8ed6556bfffafa7008a0c292..37542d52dc2ce10dbe8dcf474f42e7497b0c34f6 100644 (file)
@@ -11,6 +11,7 @@ LL |     m;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/feature-gate-nll.rs:10:1
index f7ff3eb3ac9ff7bf2dac3680d4aef78337c68263..9f5c92349e06f25bb9e77e1c50426002d7e590a2 100644 (file)
@@ -4,5 +4,6 @@
 
 #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
 #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
 
 fn main() {}
index 882feb87f42e805c7496ba2b9a81203475e710d5..ed98484e13c4a53813a0d204f33dd866b2dc3d90 100644 (file)
@@ -16,6 +16,15 @@ LL | #[rustc_error]
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
+  --> $DIR/feature-gate-rustc-attrs-1.rs:7:1
+   |
+LL | #[rustc_nonnull_optimization_guaranteed]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 0f44a0f170f84939675a23af97d34b5f68839509..7b11d85ead8749fe86741c4ed9a3577e9c174e0a 100644 (file)
@@ -12,6 +12,7 @@ LL |         println!("y={}", y);
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
index 36551e7014f10cd4df110ad7bda21c3e9002eb8a..1500bc831528a599dcbd72bc45dbe8bc9d6c3616 100644 (file)
@@ -1,6 +1,5 @@
 trait T : Iterator<Item=Self::Item>
 //~^ ERROR cycle detected
-//~| ERROR associated type `Item` not found for `Self`
 {}
 
 fn main() {}
index 3b5dd975ce9e92540e9086709e8cc157c02d1129..d64636310a3687344adff5d67cd2482889abe8ae 100644 (file)
@@ -3,7 +3,6 @@ error[E0391]: cycle detected when computing the supertraits of `T`
    |
 LL | / trait T : Iterator<Item=Self::Item>
 LL | |
-LL | |
 LL | | {}
    | |__^
    |
@@ -13,17 +12,9 @@ note: cycle used when collecting item types in top-level module
    |
 LL | / trait T : Iterator<Item=Self::Item>
 LL | |
-LL | |
 LL | | {}
    | |__^
 
-error[E0220]: associated type `Item` not found for `Self`
-  --> $DIR/issue-20772.rs:1:25
-   |
-LL | trait T : Iterator<Item=Self::Item>
-   |                         ^^^^^^^^^^ associated type `Item` not found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0220, E0391.
-For more information about an error, try `rustc --explain E0220`.
+For more information about this error, try `rustc --explain E0391`.
index 9d153696b885e2f11dbf46a29b84004828a7039f..258e362d1317c5ee38b7f0bb66d1320182fac0d7 100644 (file)
@@ -5,6 +5,5 @@ trait Trait {
 
 fn foo<T: Trait<A = T::B>>() { }
 //~^ ERROR cycle detected
-//~| ERROR associated type `B` not found for `T`
 
 fn main() { }
index 6841fe85dd79298bf2a4085124db989c3d3e99f8..00d9a3c46a723a5b98a5975da6bda4a3e7f08fbf 100644 (file)
@@ -11,13 +11,6 @@ note: cycle used when processing `foo`
 LL | fn foo<T: Trait<A = T::B>>() { }
    |                     ^^^^
 
-error[E0220]: associated type `B` not found for `T`
-  --> $DIR/issue-21177.rs:6:21
-   |
-LL | fn foo<T: Trait<A = T::B>>() { }
-   |                     ^^^^ associated type `B` not found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0220, E0391.
-For more information about an error, try `rustc --explain E0220`.
+For more information about this error, try `rustc --explain E0391`.
index e17c5eea2a4454e7df41607bbed1a4edc7027c9d..da75f330798865ff2190f84c6009ff253716ee8e 100644 (file)
@@ -1,5 +1,4 @@
 const A: i32 = B; //~ ERROR cycle detected
-//~^ ERROR cycle detected
 
 const B: i32 = A;
 
index 94624640809b77c5b6e0baed5c84bec7bd2f18b7..a7d643987f710293fc124fff8c16d8949a41709a 100644 (file)
@@ -10,36 +10,18 @@ note: ...which requires checking which parts of `A` are promotable to static...
 LL | const A: i32 = B;
    |                ^
 note: ...which requires const checking if rvalue is promotable to static `B`...
-  --> $DIR/issue-23302-3.rs:4:1
+  --> $DIR/issue-23302-3.rs:3:1
    |
 LL | const B: i32 = A;
    | ^^^^^^^^^^^^^^^^^
 note: ...which requires checking which parts of `B` are promotable to static...
-  --> $DIR/issue-23302-3.rs:4:16
+  --> $DIR/issue-23302-3.rs:3:16
    |
 LL | const B: i32 = A;
    |                ^
    = note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle
    = note: cycle used when running analysis passes on this crate
 
-error[E0391]: cycle detected when processing `A`
-  --> $DIR/issue-23302-3.rs:1:16
-   |
-LL | const A: i32 = B;
-   |                ^
-   |
-note: ...which requires processing `B`...
-  --> $DIR/issue-23302-3.rs:4:16
-   |
-LL | const B: i32 = A;
-   |                ^
-   = note: ...which again requires processing `A`, completing the cycle
-note: cycle used when processing `A`
-  --> $DIR/issue-23302-3.rs:1:1
-   |
-LL | const A: i32 = B;
-   | ^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0391`.
index 17d1c48d075460b3ec368e72ef9a16922d726ab9..28aaa2a797e056262772e32e0a1aa527460c4807 100644 (file)
@@ -10,6 +10,7 @@ LL |         &mut x
    = note: ...therefore, they cannot allow references to captured variables to escape
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-40510-1.rs:20:1
index 692aa1053779ac586e5ec470064c6b18bd9b9ff9..f00690efc312cff1fe54c06f34ed52523ed8f867 100644 (file)
@@ -12,6 +12,7 @@ LL | |         }
    = note: ...therefore, they cannot allow references to captured variables to escape
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-40510-3.rs:22:1
index 8cc9f1eb2a6388c4e3a729347f1e037a08447f95..479b724ad18f153411b4e9888f5d0cd7f62f4e2a 100644 (file)
@@ -11,6 +11,7 @@ LL | }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0713]: borrow may still be in use when destructor runs
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5
@@ -25,6 +26,7 @@ LL | }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0713]: borrow may still be in use when destructor runs
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
@@ -39,6 +41,7 @@ LL | }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1
index c66ee69cb2bdb595de3d748384088004948bf771..d5f1af88e133a002acc3de6855887de669f1bdcc 100644 (file)
@@ -15,6 +15,7 @@ LL | |         }
    = note: ...therefore, they cannot allow references to captured variables to escape
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-49824.rs:6:1
index f347c2761c32208aa18879c7bc84c06a92096f25..d3e11d2f7ed6478ef826d3f72dec65f0746396ce 100644 (file)
@@ -1,6 +1,8 @@
 #![deny(improper_ctypes)]
 #![allow(dead_code)]
 
+use std::num;
+
 enum Z { }
 enum U { A }
 enum B { C, D }
@@ -15,14 +17,39 @@ enum U8 { A, B, C }
 #[repr(isize)]
 enum Isize { A, B, C }
 
+#[repr(transparent)]
+struct Transparent<T>(T, std::marker::PhantomData<Z>);
+
+struct Rust<T>(T);
+
 extern {
    fn zf(x: Z);
    fn uf(x: U); //~ ERROR enum has no representation hint
    fn bf(x: B); //~ ERROR enum has no representation hint
    fn tf(x: T); //~ ERROR enum has no representation hint
-   fn reprc(x: ReprC);
-   fn u8(x: U8);
-   fn isize(x: Isize);
+   fn repr_c(x: ReprC);
+   fn repr_u8(x: U8);
+   fn repr_isize(x: Isize);
+   fn option_ref(x: Option<&'static u8>);
+   fn option_fn(x: Option<extern "C" fn()>);
+   fn nonnull(x: Option<std::ptr::NonNull<u8>>);
+   fn nonzero_u8(x: Option<num::NonZeroU8>);
+   fn nonzero_u16(x: Option<num::NonZeroU16>);
+   fn nonzero_u32(x: Option<num::NonZeroU32>);
+   fn nonzero_u64(x: Option<num::NonZeroU64>);
+   fn nonzero_u128(x: Option<num::NonZeroU128>);
+   //~^ ERROR 128-bit integers don't currently have a known stable ABI
+   fn nonzero_usize(x: Option<num::NonZeroUsize>);
+   fn nonzero_i8(x: Option<num::NonZeroI8>);
+   fn nonzero_i16(x: Option<num::NonZeroI16>);
+   fn nonzero_i32(x: Option<num::NonZeroI32>);
+   fn nonzero_i64(x: Option<num::NonZeroI64>);
+   fn nonzero_i128(x: Option<num::NonZeroI128>);
+   //~^ ERROR 128-bit integers don't currently have a known stable ABI
+   fn nonzero_isize(x: Option<num::NonZeroIsize>);
+   fn repr_transparent(x: Option<Transparent<num::NonZeroU8>>);
+   fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
+   fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
 }
 
 pub fn main() { }
index 92f76cfc38a72df8ef52997f577bb0149998d102..6b807f48aaa82576ff092c38d8e555889404cdc1 100644 (file)
@@ -1,5 +1,5 @@
 error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:20:13
+  --> $DIR/lint-ctypes-enum.rs:27:13
    |
 LL |    fn uf(x: U);
    |             ^
@@ -11,36 +11,64 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
    = help: consider adding a #[repr(...)] attribute to this enum
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:5:1
+  --> $DIR/lint-ctypes-enum.rs:7:1
    |
 LL | enum U { A }
    | ^^^^^^^^^^^^
 
 error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:21:13
+  --> $DIR/lint-ctypes-enum.rs:28:13
    |
 LL |    fn bf(x: B);
    |             ^
    |
    = help: consider adding a #[repr(...)] attribute to this enum
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:6:1
+  --> $DIR/lint-ctypes-enum.rs:8:1
    |
 LL | enum B { C, D }
    | ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:22:13
+  --> $DIR/lint-ctypes-enum.rs:29:13
    |
 LL |    fn tf(x: T);
    |             ^
    |
    = help: consider adding a #[repr(...)] attribute to this enum
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:7:1
+  --> $DIR/lint-ctypes-enum.rs:9:1
    |
 LL | enum T { E, F, G }
    | ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes-enum.rs:40:23
+   |
+LL |    fn nonzero_u128(x: Option<num::NonZeroU128>);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes-enum.rs:47:23
+   |
+LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:51:20
+   |
+LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(...)] attribute to this enum
+
+error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:52:20
+   |
+LL |    fn no_result(x: Result<(), num::NonZeroI32>);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(...)] attribute to this enum
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/lint/lint-match-arms.rs b/src/test/ui/lint/lint-match-arms.rs
new file mode 100644 (file)
index 0000000..2c471a6
--- /dev/null
@@ -0,0 +1,18 @@
+fn deny_on_arm() {
+    match 0 {
+        #[deny(unused_variables)]
+        //~^ NOTE lint level defined here
+        y => (),
+        //~^ ERROR unused variable
+    }
+}
+
+#[deny(unused_variables)]
+fn allow_on_arm() {
+    match 0 {
+        #[allow(unused_variables)]
+        y => (), // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-match-arms.stderr b/src/test/ui/lint/lint-match-arms.stderr
new file mode 100644 (file)
index 0000000..e4e3ada
--- /dev/null
@@ -0,0 +1,14 @@
+error: unused variable: `y`
+  --> $DIR/lint-match-arms.rs:5:9
+   |
+LL |         y => (),
+   |         ^ help: consider prefixing with an underscore: `_y`
+   |
+note: lint level defined here
+  --> $DIR/lint-match-arms.rs:3:16
+   |
+LL |         #[deny(unused_variables)]
+   |                ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index da0236ac450705418031a3cec5a8faa37337eb97..78609a6e24b5eefd783900ca4485d0d4e01c43ed 100644 (file)
@@ -105,6 +105,14 @@ fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
       _ => {}
     }
 
+    // Attribute should be respected on match arms
+    match 0 {
+        #[allow(unused_mut)]
+        mut x => {
+            let mut y = 1;
+        },
+    }
+
     let x = |mut y: isize| y = 32;
     fn nothing(mut foo: isize) { foo = 37; }
 
index e41d8f8ac74083ce9f88a9d84f39d01b25a89477..1a175c9683ec729642b81dae0050c1299e65a14c 100644 (file)
@@ -133,7 +133,7 @@ LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
    |                    help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:130:9
+  --> $DIR/lint-unused-mut-variables.rs:138:9
    |
 LL |     let mut b = vec![2];
    |         ----^
@@ -141,7 +141,7 @@ LL |     let mut b = vec![2];
    |         help: remove this `mut`
    |
 note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:126:8
+  --> $DIR/lint-unused-mut-variables.rs:134:8
    |
 LL | #[deny(unused_mut)]
    |        ^^^^^^^^^^
diff --git a/src/test/ui/macros/issue-61033-1.rs b/src/test/ui/macros/issue-61033-1.rs
new file mode 100644 (file)
index 0000000..8f85dec
--- /dev/null
@@ -0,0 +1,9 @@
+// Regression test for issue #61033.
+
+macro_rules! test1 {
+    ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ERROR this must repeat at least once
+}
+
+fn main() {
+    test1!(x,);
+}
diff --git a/src/test/ui/macros/issue-61033-1.stderr b/src/test/ui/macros/issue-61033-1.stderr
new file mode 100644 (file)
index 0000000..f3c68f4
--- /dev/null
@@ -0,0 +1,8 @@
+error: this must repeat at least once
+  --> $DIR/issue-61033-1.rs:4:34
+   |
+LL |     ($x:ident, $($tt:tt)*) => { $($tt)+ }
+   |                                  ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-61033-2.rs b/src/test/ui/macros/issue-61033-2.rs
new file mode 100644 (file)
index 0000000..0799be1
--- /dev/null
@@ -0,0 +1,19 @@
+// Regression test for issue #61033.
+
+macro_rules! test2 {
+    (
+        $(* $id1:ident)*
+        $(+ $id2:ident)*
+    ) => {
+        $( //~ERROR meta-variable `id1` repeats 2 times
+            $id1 + $id2 // $id1 and $id2 may repeat different numbers of times
+        )*
+    }
+}
+
+fn main() {
+    test2! {
+        * a * b
+        + a + b + c
+    }
+}
diff --git a/src/test/ui/macros/issue-61033-2.stderr b/src/test/ui/macros/issue-61033-2.stderr
new file mode 100644 (file)
index 0000000..bf50291
--- /dev/null
@@ -0,0 +1,11 @@
+error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times
+  --> $DIR/issue-61033-2.rs:8:10
+   |
+LL |           $(
+   |  __________^
+LL | |             $id1 + $id2 // $id1 and $id2 may repeat different numbers of times
+LL | |         )*
+   | |_________^
+
+error: aborting due to previous error
+
index 9d1e8d071f061f1615d9580703860210fb9f4dbc..ccfe60e964b2e9b1c056a65fa0e92aa44c6d4bef 100644 (file)
@@ -1,4 +1,4 @@
-error: invalid suffix `is` for numeric literal
+error: invalid suffix `is` for integer literal
   --> $DIR/old-suffixes-are-really-forbidden.rs:2:13
    |
 LL |     let a = 1_is;
@@ -6,7 +6,7 @@ LL |     let a = 1_is;
    |
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
-error: invalid suffix `us` for numeric literal
+error: invalid suffix `us` for integer literal
   --> $DIR/old-suffixes-are-really-forbidden.rs:3:13
    |
 LL |     let b = 2_us;
index 75bed3088587ca3b4a577498d9d4fefc187c5275..151c6e1527ff566aa23bd7fda87327591c8ed65e 100644 (file)
@@ -22,8 +22,8 @@ fn main() {
     1234f1024; //~ ERROR invalid width `1024` for float literal
     1234.5f1024; //~ ERROR invalid width `1024` for float literal
 
-    1234suffix; //~ ERROR invalid suffix `suffix` for numeric literal
-    0b101suffix; //~ ERROR invalid suffix `suffix` for numeric literal
+    1234suffix; //~ ERROR invalid suffix `suffix` for integer literal
+    0b101suffix; //~ ERROR invalid suffix `suffix` for integer literal
     1.0suffix; //~ ERROR invalid suffix `suffix` for float literal
     1.0e10suffix; //~ ERROR invalid suffix `suffix` for float literal
 }
index de194f4820de0e0ec47459d30a1cdda4aa72651e..e53b1498332d113f351f3d75c242fecb320358cc 100644 (file)
@@ -78,7 +78,7 @@ LL |     1234.5f1024;
    |
    = help: valid widths are 32 and 64
 
-error: invalid suffix `suffix` for numeric literal
+error: invalid suffix `suffix` for integer literal
   --> $DIR/bad-lit-suffixes.rs:25:5
    |
 LL |     1234suffix;
@@ -86,7 +86,7 @@ LL |     1234suffix;
    |
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
-error: invalid suffix `suffix` for numeric literal
+error: invalid suffix `suffix` for integer literal
   --> $DIR/bad-lit-suffixes.rs:26:5
    |
 LL |     0b101suffix;
index 206242c3c7fa6861853dc193c20e6f3ef554d9c8..666ca9350597674a8d631b8bab35eb5d75111985 100644 (file)
@@ -2,6 +2,6 @@
 
 fn main() {
     9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
-    //~^ ERROR int literal is too large
+    //~^ ERROR integer literal is too large
         ; // the span shouldn't point to this.
 }
index d7774c333c29a6a2f4ab785c60f6e4408b0b426b..7cae85fc9fe6d433731e5f6f702a1fbe06ed15da 100644 (file)
@@ -1,4 +1,4 @@
-error: int literal is too large
+error: integer literal is too large
   --> $DIR/int-literal-too-large-span.rs:4:5
    |
 LL |     9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
index 303b902c499043d959c3f70b5fbced8c9a901adc..3c239c73b9d708bb44c82331d0fe9a16e650107f 100644 (file)
@@ -1,4 +1,4 @@
 fn main() {
     let __isize = 340282366920938463463374607431768211456; // 2^128
-    //~^ ERROR int literal is too large
+    //~^ ERROR integer literal is too large
 }
index bc48853b380e6fe00e984d76c6297d51edf12134..de579c3c134e511d8a7e5e1bc6b8409591303d7f 100644 (file)
@@ -1,4 +1,4 @@
-error: int literal is too large
+error: integer literal is too large
   --> $DIR/issue-5544-a.rs:2:19
    |
 LL |     let __isize = 340282366920938463463374607431768211456; // 2^128
index fa40f15dedb5c3a48abcb7160327c83b8123a6c3..93f2ff271364e0c935034c038c7121600fc48c0c 100644 (file)
@@ -1,4 +1,4 @@
 fn main() {
     let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff;
-    //~^ ERROR int literal is too large
+    //~^ ERROR integer literal is too large
 }
index 3f15c0c0d755c9051dae36b787d545f76f9af58c..7df212dedfede1fb6dd496297eb0713a47ebfac4 100644 (file)
@@ -1,4 +1,4 @@
-error: int literal is too large
+error: integer literal is too large
   --> $DIR/issue-5544-b.rs:2:19
    |
 LL |     let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff;
index 9496ad305fc2ca453ded7c397a8fdd5b20d5d797..67134c14cded3688ae0659e6bdd877cba7a37d3f 100644 (file)
@@ -13,8 +13,10 @@ fn main() {
     0o; //~ ERROR: no valid digits
     1e+; //~ ERROR: expected at least one digit in exponent
     0x539.0; //~ ERROR: hexadecimal float literal is not supported
-    9900000000000000000000000000999999999999999999999999999999; //~ ERROR: int literal is too large
-    9900000000000000000000000000999999999999999999999999999999; //~ ERROR: int literal is too large
+    9900000000000000000000000000999999999999999999999999999999;
+    //~^ ERROR: integer literal is too large
+    9900000000000000000000000000999999999999999999999999999999;
+    //~^ ERROR: integer literal is too large
     0x; //~ ERROR: no valid digits
     0xu32; //~ ERROR: no valid digits
     0ou32; //~ ERROR: no valid digits
index 466d7af1bda4773390e9bc363d505084b037321c..6d6cd3cc17129928db8b97a97233823bb2151ea6 100644 (file)
@@ -65,43 +65,43 @@ LL |     0x539.0;
    |     ^^^^^^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:18:5
+  --> $DIR/lex-bad-numeric-literals.rs:20:5
    |
 LL |     0x;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:19:5
+  --> $DIR/lex-bad-numeric-literals.rs:21:5
    |
 LL |     0xu32;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:20:5
+  --> $DIR/lex-bad-numeric-literals.rs:22:5
    |
 LL |     0ou32;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:21:5
+  --> $DIR/lex-bad-numeric-literals.rs:23:5
    |
 LL |     0bu32;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:22:5
+  --> $DIR/lex-bad-numeric-literals.rs:24:5
    |
 LL |     0b;
    |     ^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:24:5
+  --> $DIR/lex-bad-numeric-literals.rs:26:5
    |
 LL |     0o123.456;
    |     ^^^^^^^^^
 
 error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:26:5
+  --> $DIR/lex-bad-numeric-literals.rs:28:5
    |
 LL |     0b111.101;
    |     ^^^^^^^^^
@@ -112,26 +112,26 @@ error: octal float literal is not supported
 LL |     0o2f32;
    |     ^^^^^^ not supported
 
-error: int literal is too large
+error: integer literal is too large
   --> $DIR/lex-bad-numeric-literals.rs:16:5
    |
 LL |     9900000000000000000000000000999999999999999999999999999999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: int literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:17:5
+error: integer literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:18:5
    |
 LL |     9900000000000000000000000000999999999999999999999999999999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:23:5
+  --> $DIR/lex-bad-numeric-literals.rs:25:5
    |
 LL |     0o123f64;
    |     ^^^^^^^^ not supported
 
 error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:25:5
+  --> $DIR/lex-bad-numeric-literals.rs:27:5
    |
 LL |     0b101f64;
    |     ^^^^^^^^ not supported
index a42d2cbc442f0c89b6bed838cd662825cc84ddbc..052cb4934f503ce3de402d5e088645b79e8d3728 100644 (file)
@@ -4,5 +4,5 @@ fn main() {
     0b101.010;
     //~^ ERROR binary float literal is not supported
     0b101p4f64;
-    //~^ ERROR invalid suffix `p4f64` for numeric literal
+    //~^ ERROR invalid suffix `p4f64` for integer literal
 }
index 21f415bcfb0003b22a24dbf8684d7cfdb53489c1..65b129b5827ceffbc18c7b38f1728270eb7f97cf 100644 (file)
@@ -10,7 +10,7 @@ error: binary float literal is not supported
 LL |     0b101010f64;
    |     ^^^^^^^^^^^ not supported
 
-error: invalid suffix `p4f64` for numeric literal
+error: invalid suffix `p4f64` for integer literal
   --> $DIR/no-binary-float-literal.rs:6:5
    |
 LL |     0b101p4f64;
index 3a2cffcbf45f08284b8778ccd5e4f8803c269d9b..70452a930ee70ec8af606d70fc453cf999addd48 100644 (file)
@@ -18,6 +18,7 @@ LL |             **z = None;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
index 940ab94a6133233a3ec252989a177d81143506b2..9203f893fdbf777bd4d2278d3265e4dc04c06517 100644 (file)
@@ -12,6 +12,7 @@ LL |     x
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
index bba5b0c74d988159794b59a123be18035490e72f..6869109e67fc06c4deba374cfefc7b91c92781eb 100644 (file)
@@ -20,6 +20,7 @@ LL | static C: &u32 = &A;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
   --> $DIR/thread-local-in-ctfe.rs:15:16
@@ -43,6 +44,7 @@ LL | const E: &u32 = &A;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
   --> $DIR/thread-local-in-ctfe.rs:25:5
index 60a609acaed3bf2b3ec6ab995bccf0f03bc26060..a8eeb7cdb135da1cd582c6093c1739732727a4a2 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 60a609acaed3bf2b3ec6ab995bccf0f03bc26060
+Subproject commit a8eeb7cdb135da1cd582c6093c1739732727a4a2