about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Cargo.lock18
-rw-r--r--src/bootstrap/builder.rs4
-rw-r--r--src/bootstrap/doc.rs1
-rw-r--r--src/bootstrap/test.rs1
-rw-r--r--src/doc/index.md4
-rw-r--r--src/doc/rustc/.gitignore1
-rw-r--r--src/doc/rustc/book.toml5
-rw-r--r--src/doc/rustc/src/SUMMARY.md16
-rw-r--r--src/doc/rustc/src/codegen-options/index.md209
-rw-r--r--src/doc/rustc/src/command-line-arguments.md116
-rw-r--r--src/doc/rustc/src/contributing.md6
-rw-r--r--src/doc/rustc/src/lints/groups.md29
-rw-r--r--src/doc/rustc/src/lints/index.md28
-rw-r--r--src/doc/rustc/src/lints/levels.md252
-rw-r--r--src/doc/rustc/src/lints/listing/allowed-by-default.md453
-rw-r--r--src/doc/rustc/src/lints/listing/deny-by-default.md241
-rw-r--r--src/doc/rustc/src/lints/listing/index.md5
-rw-r--r--src/doc/rustc/src/lints/listing/warn-by-default.md1039
-rw-r--r--src/doc/rustc/src/targets/built-in.md10
-rw-r--r--src/doc/rustc/src/targets/custom.md17
-rw-r--r--src/doc/rustc/src/targets/index.md13
-rw-r--r--src/doc/rustc/src/what-is-rustc.md68
-rw-r--r--src/liballoc/alloc.rs14
-rw-r--r--src/liballoc/arc.rs5
-rw-r--r--src/liballoc/boxed.rs1
-rw-r--r--src/liballoc/rc.rs5
-rw-r--r--src/libcore/cmp.rs12
-rw-r--r--src/libcore/fmt/mod.rs2
-rw-r--r--src/libcore/ops/arith.rs6
-rw-r--r--src/libcore/ops/bit.rs16
-rw-r--r--src/libcore/ops/deref.rs4
-rw-r--r--src/libcore/ops/range.rs6
-rw-r--r--src/libcore/ptr.rs1
-rw-r--r--src/libproc_macro/lib.rs2
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/hir/check_attr.rs15
-rw-r--r--src/librustc/hir/lowering.rs20
-rw-r--r--src/librustc/hir/map/def_collector.rs33
-rw-r--r--src/librustc/hir/map/definitions.rs6
-rw-r--r--src/librustc/ich/impls_syntax.rs28
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs12
-rw-r--r--src/librustc/infer/mod.rs6
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/traits/coherence.rs5
-rw-r--r--src/librustc/traits/error_reporting.rs19
-rw-r--r--src/librustc/traits/fulfill.rs2
-rw-r--r--src/librustc/traits/mod.rs19
-rw-r--r--src/librustc/traits/on_unimplemented.rs6
-rw-r--r--src/librustc/traits/query/evaluate_obligation.rs70
-rw-r--r--src/librustc/traits/query/mod.rs4
-rw-r--r--src/librustc/traits/select.rs243
-rw-r--r--src/librustc/traits/structural_impls.rs1
-rw-r--r--src/librustc/ty/context.rs14
-rw-r--r--src/librustc/ty/fold.rs8
-rw-r--r--src/librustc/ty/item_path.rs11
-rw-r--r--src/librustc/ty/maps/config.rs39
-rw-r--r--src/librustc/ty/maps/job.rs5
-rw-r--r--src/librustc/ty/maps/keys.rs12
-rw-r--r--src/librustc/ty/maps/mod.rs15
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs21
-rw-r--r--src/librustc/ty/maps/plumbing.rs939
-rw-r--r--src/librustc/ty/maps/values.rs2
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc/ty/sty.rs8
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc/util/common.rs8
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/librustc_data_structures/lazy_btree_map.rs108
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_driver/lib.rs3
-rw-r--r--src/librustc_driver/profile/trace.rs2
-rw-r--r--src/librustc_driver/test.rs4
-rw-r--r--src/librustc_incremental/assert_module_sources.rs2
-rw-r--r--src/librustc_lint/unused.rs42
-rw-r--r--src/librustc_metadata/cstore_impl.rs4
-rw-r--r--src/librustc_metadata/decoder.rs16
-rw-r--r--src/librustc_mir/borrow_check/mod.rs40
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs70
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/interpret/const_eval.rs2
-rw-r--r--src/librustc_mir/interpret/eval_context.rs7
-rw-r--r--src/librustc_mir/interpret/memory.rs6
-rw-r--r--src/librustc_mir/interpret/place.rs4
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/monomorphize/item.rs2
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs14
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs12
-rw-r--r--src/librustc_mir/transform/inline.rs67
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs34
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/librustc_resolve/macros.rs3
-rw-r--r--src/librustc_target/abi/mod.rs19
-rw-r--r--src/librustc_target/lib.rs1
-rw-r--r--src/librustc_traits/evaluate_obligation.rs35
-rw-r--r--src/librustc_traits/lib.rs2
-rw-r--r--src/librustc_trans/abi.rs22
-rw-r--r--src/librustc_trans/allocator.rs4
-rw-r--r--src/librustc_trans/attributes.rs30
-rw-r--r--src/librustc_trans/back/linker.rs6
-rw-r--r--src/librustc_trans/back/symbol_export.rs2
-rw-r--r--src/librustc_trans/back/write.rs31
-rw-r--r--src/librustc_trans/base.rs2
-rw-r--r--src/librustc_trans/callee.rs2
-rw-r--r--src/librustc_trans/common.rs6
-rw-r--r--src/librustc_trans/consts.rs2
-rw-r--r--src/librustc_trans/context.rs6
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs2
-rw-r--r--src/librustc_trans/debuginfo/mod.rs2
-rw-r--r--src/librustc_trans/debuginfo/namespace.rs2
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs4
-rw-r--r--src/librustc_trans/intrinsic.rs2
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/mir/block.rs6
-rw-r--r--src/librustc_trans/mir/place.rs23
-rw-r--r--src/librustc_trans/mir/rvalue.rs10
-rw-r--r--src/librustc_trans/trans_item.rs2
-rw-r--r--src/librustc_trans_utils/symbol_names.rs6
-rw-r--r--src/librustc_typeck/astconv.rs4
-rw-r--r--src/librustc_typeck/check/autoderef.rs4
-rw-r--r--src/librustc_typeck/check/compare_method.rs3
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/mod.rs3
-rw-r--r--src/librustc_typeck/check/method/probe.rs4
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/collect.rs18
-rw-r--r--src/librustc_typeck/lib.rs3
-rw-r--r--src/librustdoc/clean/auto_trait.rs4
-rw-r--r--src/librustdoc/clean/mod.rs12
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/render.rs2
-rw-r--r--src/librustdoc/html/static/main.js88
-rw-r--r--src/librustdoc/lib.rs3
-rw-r--r--src/libsyntax/feature_gate.rs9
-rw-r--r--src/libsyntax/parse/token.rs3
-rw-r--r--src/libsyntax_pos/hygiene.rs43
-rw-r--r--src/libsyntax_pos/lib.rs6
-rw-r--r--src/libsyntax_pos/symbol.rs192
-rw-r--r--src/stage0.txt2
-rw-r--r--src/test/codegen/call-metadata.rs29
-rw-r--r--src/test/codegen/target-feature-on-functions.rs19
-rw-r--r--src/test/compile-fail/attr-usage-inline.rs2
-rw-r--r--src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs2
-rw-r--r--src/test/compile-fail/extern-macro.rs2
-rw-r--r--src/test/compile-fail/impl-trait/impl-generic-mismatch.rs11
-rw-r--r--src/test/compile-fail/impl-trait/where-allowed.rs1
-rw-r--r--src/test/compile-fail/issue-23080-2.rs3
-rw-r--r--src/test/compile-fail/issue-31769.rs2
-rw-r--r--src/test/compile-fail/issue-43988.rs6
-rw-r--r--src/test/compile-fail/macros-nonfatal-errors.rs1
-rw-r--r--src/test/compile-fail/mir_check_cast_unsize.rs1
-rw-r--r--src/test/compile-fail/privacy/associated-item-privacy-inherent.rs1
-rw-r--r--src/test/compile-fail/privacy/associated-item-privacy-trait.rs1
-rw-r--r--src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs1
-rw-r--r--src/test/compile-fail/private-inferred-type-3.rs1
-rw-r--r--src/test/compile-fail/private-inferred-type.rs1
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-struct.rs1
-rw-r--r--src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs2
-rw-r--r--src/test/run-pass-fulldeps/macro-quote-test.rs2
-rw-r--r--src/test/run-pass/dyn-trait.rs2
-rw-r--r--src/test/run-pass/hygiene/issue-47311.rs2
-rw-r--r--src/test/run-pass/hygiene/issue-47312.rs2
-rw-r--r--src/test/run-pass/hygiene/legacy_interaction.rs2
-rw-r--r--src/test/run-pass/hygiene/lexical.rs2
-rw-r--r--src/test/run-pass/hygiene/wrap_unhygienic_example.rs2
-rw-r--r--src/test/run-pass/hygiene/xcrate.rs2
-rw-r--r--src/test/run-pass/issue-47703-tuple.rs (renamed from src/test/ui/feature-gate-dyn-trait.rs)13
-rw-r--r--src/test/run-pass/issue-49632.rs17
-rw-r--r--src/test/run-pass/nll/issue-48623-closure.rs24
-rw-r--r--src/test/run-pass/nll/issue-48623-generator.rs25
-rw-r--r--src/test/run-pass/paths-in-macro-invocations.rs2
-rw-r--r--src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs2
-rw-r--r--src/test/ui/error-codes/E0518.stderr8
-rw-r--r--src/test/ui/feature-gate-dyn-trait.stderr11
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.rs10
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr26
-rw-r--r--src/test/ui/generator/yield-while-iterating.nll.stderr32
-rw-r--r--src/test/ui/hygiene/fields.rs2
-rw-r--r--src/test/ui/hygiene/globs.rs2
-rw-r--r--src/test/ui/hygiene/impl_items.rs2
-rw-r--r--src/test/ui/hygiene/intercrate.rs2
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.rs2
-rw-r--r--src/test/ui/hygiene/privacy.rs2
-rw-r--r--src/test/ui/hygiene/trait_items.rs2
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr2
-rw-r--r--src/test/ui/impl_trait_projections.rs2
-rw-r--r--src/test/ui/impl_trait_projections.stderr10
-rw-r--r--src/test/ui/imports/macro-paths.rs2
-rw-r--r--src/test/ui/imports/shadow_builtin_macros.rs2
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr4
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.rs1
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr6
-rw-r--r--src/test/ui/lifetime_starts_expressions.rs23
-rw-r--r--src/test/ui/lifetime_starts_expressions.stderr14
-rw-r--r--src/test/ui/lint/must-use-ops.rs52
-rw-r--r--src/test/ui/lint/must-use-ops.stderr132
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.rs6
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr17
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr24
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr34
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr32
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr20
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr48
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr16
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr12
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr24
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr2
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn.stderr8
-rw-r--r--src/test/ui/raw-literal-keywords.rs1
-rw-r--r--src/test/ui/raw-literal-keywords.stderr6
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs2
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr4
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr10
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.rs2
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr8
-rw-r--r--src/tools/compiletest/src/runtest.rs2
232 files changed, 4778 insertions, 1372 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index e14b9da9713..a6f78a7e6b4 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1325,16 +1325,16 @@ dependencies = [
 
 [[package]]
 name = "parking_lot"
-version = "0.5.4"
+version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1755,8 +1755,8 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1896,8 +1896,8 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3096,8 +3096,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
-"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
-"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
+"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
+"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
 "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b9c82127342..08bb8ab4815 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -323,7 +323,7 @@ impl<'a> Builder<'a> {
                 test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
                 test::RunMakeFullDeps,
                 test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
-                test::TheBook, test::UnstableBook,
+                test::TheBook, test::UnstableBook, test::RustcBook,
                 test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
                 // Run run-make last, since these won't pass without make on Windows
                 test::RunMake, test::RustdocUi),
@@ -331,7 +331,7 @@ impl<'a> Builder<'a> {
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc,
                 doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample,
-                doc::CargoBook),
+                doc::RustcBook, doc::CargoBook),
             Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc,
                 dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src,
                 dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended,
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index ae22260c564..16f4b29dcce 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -71,6 +71,7 @@ book!(
     Nomicon, "src/doc/nomicon", "nomicon";
     Reference, "src/doc/reference", "reference";
     Rustdoc, "src/doc/rustdoc", "rustdoc";
+    RustcBook, "src/doc/rustc", "rustc";
     RustByExample, "src/doc/rust-by-example", "rust-by-example";
 );
 
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 08bbd68c756..e8c40dfdb0a 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1212,6 +1212,7 @@ test_book!(
     Nomicon, "src/doc/nomicon", "nomicon", default=false;
     Reference, "src/doc/reference", "reference", default=false;
     RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
+    RustcBook, "src/doc/rustc", "rustc", default=true;
     RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
     TheBook, "src/doc/book", "book", default=false;
     UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
diff --git a/src/doc/index.md b/src/doc/index.md
index 2ea889da1fd..3a4f51069fc 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -43,6 +43,10 @@ Rust's standard library has [extensive API documentation](std/index.html),
 with explanations of how to use various things, as well as example code for
 accomplishing various tasks.
 
+## The Rustc Book
+
+[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
+
 ## The Cargo Book
 
 [The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager.
diff --git a/src/doc/rustc/.gitignore b/src/doc/rustc/.gitignore
new file mode 100644
index 00000000000..7585238efed
--- /dev/null
+++ b/src/doc/rustc/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
new file mode 100644
index 00000000000..8adc05c5137
--- /dev/null
+++ b/src/doc/rustc/book.toml
@@ -0,0 +1,5 @@
+[book]
+authors = ["The Rust Project Developers"]
+multilingual = false
+src = "src"
+title = "The rustc book"
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
new file mode 100644
index 00000000000..e4c0939fd46
--- /dev/null
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -0,0 +1,16 @@
+# The Rustc Book
+
+- [What is rustc?](what-is-rustc.md)
+- [Command-line arguments](command-line-arguments.md)
+- [Lints](lints/index.md)
+    - [Lint levels](lints/levels.md)
+    - [Lint Groups](lints/groups.md)
+    - [Lint listing](lints/listing/index.md)
+        - [Allowed-by-default lints](lints/listing/allowed-by-default.md)
+        - [Warn-by-default lints](lints/listing/warn-by-default.md)
+        - [Deny-by-default lints](lints/listing/deny-by-default.md)
+- [Codegen options](codegen-options/index.md)
+- [Targets](targets/index.md)
+    - [Built-in Targets](targets/built-in.md)
+    - [Custom Targets](targets/custom.md)
+- [Contributing to `rustc`](contributing.md)
\ No newline at end of file
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
new file mode 100644
index 00000000000..eff09428902
--- /dev/null
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -0,0 +1,209 @@
+# Codegen options
+
+All of these options are passed to `rustc` via the `-C` flag, short for "codegen." You can see
+a version of this list for your exact compiler by running `rustc -C help`.
+
+## ar
+
+This option is deprecated and does nothing.
+
+## linker
+
+This flag lets you control which linker `rustc` invokes to link your code.
+
+## link-arg=val
+
+This flag lets you append a single extra argument to the linker invocation.
+
+"Append" is significant; you can pass this flag multiple times to add multiple arguments.
+
+## link-args
+
+This flag lets you append multiple extra arguments to the linker invocation. The
+options should be separated by spaces.
+
+## link-dead-code
+
+Normally, the linker will remove dead code. This flag disables this behavior.
+
+An example of when this flag might be useful is when trying to construct code coverage
+metrics.
+
+## lto
+
+This flag instructs LLVM to use [link time
+optimizations](https://llvm.org/docs/LinkTimeOptimization.html).
+
+It takes one of two values, `thin` and `fat`. 'thin' LTO [is a new feature of
+LLVM](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html),
+'fat' referring to the classic version of LTO.
+
+## target-cpu
+
+This instructs `rustc` to generate code specifically for a particular processor.
+
+You can run `rustc --print target-cpus` to see the valid options to pass
+here. Additionally, `native` can be passed to use the processor of the host
+machine.
+
+## target-feature
+
+Individual targets will support different features; this flag lets you control
+enabling or disabling a feature.
+
+To see the valid options and an example of use, run `rustc --print
+target-features`.
+
+## passes
+
+This flag can be used to add extra LLVM passes to the compilation.
+
+The list must be separated by spaces.
+
+## llvm-args
+
+This flag can be used to pass a list of arguments directly to LLVM.
+
+The list must be separated by spaces.
+
+## save-temps
+
+`rustc` will generate temporary files during compilation; normally it will
+delete them after it's done with its work. This option will cause them to be
+preserved instead of removed.
+
+## rpath
+
+This option allows you to set the value of
+[`rpath`](https://en.wikipedia.org/wiki/Rpath).
+
+## overflow-checks
+
+This flag allows you to control the behavior of integer overflow. This flag
+can be passed many options:
+
+* To turn overflow checks on: `y`, `yes`, or `on`.
+* To turn overflow checks off: `n`, `no`, or `off`.
+
+## no-prepopulate-passes
+
+The pass manager comes pre-populated with a list of passes; this flag
+ensures that list is empty.
+
+## no-vectorize-loops
+
+By default, `rustc` will attempt to [vectorize
+loops](https://llvm.org/docs/Vectorizers.html#the-loop-vectorizer). This
+flag will turn that behavior off.
+
+## no-vectorize-slp
+
+By default, `rustc` will attempt to vectorize loops using [superword-level
+parallelism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This
+flag will turn that behavior off.
+
+## soft-float
+
+This option will make `rustc` generate code using "soft floats." By default,
+a lot of hardware supports floating point instructions, and so the code generated
+will take advantage of this. "soft floats" emulate floating point instructions
+in software.
+
+## prefer-dynamic
+
+By default, `rustc` prefers to statically link dependencies. This option will
+make it use dynamic linking instead.
+
+## no-integrated-as
+
+LLVM comes with an internal assembler; this option will let you use an
+external assembler instead.
+
+## no-redzone
+
+This flag allows you to disable [the
+red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). This flag can
+be passed many options:
+
+* To enable the red zone: `y`, `yes`, or `on`.
+* To disable it: `n`, `no`, or `off`.
+
+## relocation-model
+
+This option lets you choose which relocation model to use.
+
+To find the valid options for this flag, run `rustc --print relocation-models`.
+
+## code-model=val
+
+This option lets you choose which code model to use.
+
+To find the valid options for this flag, run `rustc --print code-models`.
+
+## metadata
+
+This option allows you to control the metadata used for symbol mangling.
+
+## extra-filename
+
+This option allows you to put extra data in each output filename.
+
+## codegen-units
+
+This flag lets you control how many threads are used when doing
+code generation.
+
+Increasing paralellism may speed up compile times, but may also
+produce slower code.
+
+## remark
+
+This flag lets you print remarks for these optimization passes.
+
+The list of passes should be separated by spaces.
+
+`all` will remark on every pass.
+
+## no-stack-check
+
+This option is deprecated and does nothing.
+
+## debuginfo
+
+This flag lets you control debug information:
+
+* `0`: no debug info at all
+* `1`: line tables only
+* `2`: full debug info
+
+## opt-level
+
+This flag lets you control the optimization level.
+
+* `0`: no optimizations
+* `1`: basic optimizations
+* `2`: some optimizations
+* `3`: all optimizations
+* `s`: optimize for binary size
+* `z`: optimize for binary size, but also turn off loop vectorization.
+
+## debug-assertions
+
+This flag lets you turn `cfg(debug_assertions)` on or off.
+
+## inline-threshold
+
+This option lets you set the threshold for inlining a function.
+
+The default is 225.
+
+## panic
+
+This option lets you control what happens when the code panics.
+
+* `abort`: terminate the process upon panic
+* `unwind`: unwind the stack upon panic
+
+## incremental
+
+This flag allows you to enable incremental compilation.
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
new file mode 100644
index 00000000000..e2b001832fe
--- /dev/null
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -0,0 +1,116 @@
+# Command-line arguments
+
+Here's a list of command-line arguments to `rustc` and what they do.
+
+## `-h`/`--help`: get help
+
+This flag will print out help information for `rustc`.
+
+## `--cfg`: configure the compilation environment
+
+This flag can turn on or off various `#[cfg]` settings.
+
+## `-L`: add a directory to the library search path
+
+When looking for external crates, a directory passed to this flag will be searched.
+
+## `-l`: link the generated crate to a native library
+
+This flag allows you to specify linking to a specific native library when building
+a crate.
+
+## `--crate-type`: a list of types of crates for the compiler to emit
+
+This instructs `rustc` on which crate type to build.
+
+## `--crate-name`: specify the name of the crate being built
+
+This informs `rustc` of the name of your crate.
+
+## `--emit`: emit output other than a crate
+
+Instead of producing a crate, this flag can print out things like the assembly or LLVM-IR.
+
+## `--print`: print compiler information
+
+This flag prints out various information about the compiler.
+
+## `-g`: include debug information
+
+A synonym for `-C debug-level=2`.
+
+## `-O`: optimize your code
+
+A synonym for `-C opt-level=2`.
+
+## `-o`: filename of the output
+
+This flag controls the output filename.
+
+## `--out-dir`: directory to write the output in
+
+The outputted crate will be written to this directory.
+
+## `--explain`: provide a detailed explanation of an error message
+
+Each error of `rustc`'s comes with an error code; this will print
+out a longer explanation of a given error.
+
+## `--test`: build a test harness
+
+When compiling this crate, `rustc` will ignore your `main` function
+and instead produce a test harness.
+
+## `--target`: select a target triple to build
+
+This controls which [target](targets/index.html) to produce.
+
+## `-W`: set lint warnings
+
+This flag will set which lints should be set to the [warn level](lints/levels.html#warn).
+
+## `-A`: set lint allowed
+
+This flag will set which lints should be set to the [allow level](lints/levels.html#allow).
+
+## `-D`: set lint denied
+
+This flag will set which lints should be set to the [deny level](lints/levels.html#deny).
+
+## `-F`: set lint forbidden
+
+This flag will set which lints should be set to the [forbid level](lints/levels.html#forbid).
+
+## `--cap-lints`: set the most restrictive lint level
+
+This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-lints).
+
+## `-C`/`--codegen`: code generation options
+
+This flag will allow you to set [codegen options](codegen-options/index.html).
+
+## `-V`/`--version`: print a version
+
+This flag will print out `rustc`'s version.
+
+## `-v`/`--verbose`: use verbose output
+
+This flag, when combined with other flags, makes them produce extra output.
+
+## `--extern`: specify where an external library is located
+
+This flag allows you to pass the name and location of an external crate that will
+be linked into the crate you're buildling.
+
+## `--sysroot`: Override the system root
+
+The "sysroot" is where `rustc` looks for the crates that come with the Rust
+distribution; this flag allows that to be overridden.
+
+## `--error-format`: control how errors are produced
+
+This flag lets you control the format of errors.
+
+## `--color`: configure coloring of output
+
+This flag lets you control color settings of the output.
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
new file mode 100644
index 00000000000..fcb8e6b27db
--- /dev/null
+++ b/src/doc/rustc/src/contributing.md
@@ -0,0 +1,6 @@
+# Contributing to rustc
+
+We'd love to have your help improving `rustc`! To that end, we've written [a
+whole book](https://rust-lang-nursery.github.io/rustc-guide/) on its
+internals, how it works, and how to get started working on it. To learn
+more, you'll want to check that out.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md
new file mode 100644
index 00000000000..46b717f3387
--- /dev/null
+++ b/src/doc/rustc/src/lints/groups.md
@@ -0,0 +1,29 @@
+# Lint Groups
+
+`rustc` has the concept of a "lint group", where you can toggle several warnings
+through one name.
+
+For example, the `nonstandard-style` lint sets `non-camel-case-types`,
+`non-snake-case`, and `non-upper-case-globals` all at once. So these are
+equivalent:
+
+```bash
+$ rustc -D nonstandard-style
+$ rustc -D non-camel-case-types -D non-snake-case -D non-upper-case-globals
+```
+
+Here's a list of each lint group, and the lints that they are made up of:
+
+| group               | description                                                   | lints                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
+|---------------------|---------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| nonstandard-style   | Violation of standard naming conventions                      | non-camel-case-types, non-snake-case, non-upper-case-globals                                                                                                                                                                                                                                                                                                                                                                                                                           |
+| warnings            | all lints that would be issuing warnings                      | all lints that would be issuing warnings                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+| edition-2018        | Lints that will be turned into errors in Rust 2018            | tyvar-behind-raw-pointer                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+| rust-2018-idioms    | Lints to nudge you toward idiomatic features of Rust 2018     | bare-trait-object, unreachable-pub                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+| unused              | These lints detect things being declared but not used         | unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comment, unused-extern-crates, unused-features, unused-parens                                                                                                                                                                                    |
+| future-incompatible | Lints that detect code that has future-compatibility problems | private-in-public, pub-use-of-private-extern-crate, patterns-in-fns-without-body, safe-extern-statics, invalid-type-param-default, legacy-directory-ownership, legacy-imports, legacy-constructor-visibility, missing-fragment-specifier, illegal-floating-point-literal-pattern, anonymous-parameters, parenthesized-params-in-types-and-modules, late-bound-lifetime-arguments, safe-packed-borrows, incoherent-fundamental-impls, tyvar-behind-raw-pointer, unstable-name-collision |
+
+Additionally, there's a `bad-style` lint group that's a deprecated alias for `nonstandard-style`.
+
+Finally, you can also see the table above by invoking `rustc -W help`. This will give you the exact values for the specific
+compiler you have installed.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md
new file mode 100644
index 00000000000..bf345a24389
--- /dev/null
+++ b/src/doc/rustc/src/lints/index.md
@@ -0,0 +1,28 @@
+# Lints
+
+In software, a "lint" is a tool used to help improve your source code. The
+Rust compiler contains a number of lints, and when it compiles your code, it will
+also run the lints. These lints may produce a warning, an error, or nothing at all,
+depending on how you've configured things.
+
+Here's a small example:
+
+```bash
+$ cat main.rs
+fn main() {
+    let x = 5;
+}
+> rustc main.rs
+warning: unused variable: `x`
+ --> main.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^
+  |
+  = note: #[warn(unused_variables)] on by default
+  = note: to avoid this warning, consider using `_x` instead
+```
+
+This is the `unused_variables` lint, and it tells you that you've introduced
+a variable that you don't use in your code. That's not *wrong*, so it's not
+an error, but it might be a bug, so you get a warning.
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
new file mode 100644
index 00000000000..19bb6707d22
--- /dev/null
+++ b/src/doc/rustc/src/lints/levels.md
@@ -0,0 +1,252 @@
+# Lint levels
+
+In `rustc`, lints are divided into four *levels*:
+
+1. allow
+2. warn
+3. deny
+4. forbid
+
+Each lint has a default level (explained in the lint listing later in this
+chapter), and the compiler has a default warning level. First, let's explain
+what these levels mean, and then we'll talk about configuration.
+
+## allow
+
+These lints exist, but by default, do nothing. For example, consider this
+source:
+
+```rust
+pub fn foo() {}
+```
+
+Compiling this file produces no warnings:
+
+```bash
+$ rustc lib.rs --crate-type=lib
+$
+```
+
+But this code violates the `missing_docs` lint.
+
+These lints exist mostly to be manually turned on via configuration, as we'll
+talk about later in this section.
+
+## warn
+
+The 'warn' lint level will produce a warning if you violate the lint. For example,
+this code runs afoul of the `unused_variable` lint:
+
+```rust
+pub fn foo() {
+    let x = 5;
+}
+```
+
+This will produce this warning:
+
+```console
+$ rustc lib.rs --crate-type=lib
+warning: unused variable: `x`
+ --> lib.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^
+  |
+  = note: #[warn(unused_variables)] on by default
+  = note: to avoid this warning, consider using `_x` instead
+```
+
+## deny
+
+A 'deny' lint produces an error if you violate it. For example, this code
+runs into the `exceeding_bitshifts` lint.
+
+```rust,ignore
+fn main() {
+    100u8 << 10;
+}
+```
+
+```bash
+> rustc main.rs
+error: bitshift exceeds the type's number of bits
+ --> main.rs:2:13
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^
+  |
+  = note: #[deny(exceeding_bitshifts)] on by default
+```
+
+What's the difference between an error from a lint and a regular old error?
+Lints are configurable via levels, so in a similar way to 'allow' lints,
+warnings that are 'deny' by default let you allow them. Similarly, you may
+wish to set up a lint that is `warn` by default to produce an error instead.
+This lint level gives you that.
+
+## forbid
+
+'forbid' is a special lint level that's stronger than 'deny'. It's the same
+as 'deny' in that a lint at this level will produce an error, but unlike the
+'deny' level, the 'forbid' level can not be overridden to be anything lower
+than an error.
+
+## Configuring warning levels
+
+Remember our `missing_docs` example from the 'allow' lint level?
+
+```bash
+$ cat lib.rs
+pub fn foo() {}
+$ rustc lib.rs --crate-type=lib
+$
+```
+
+We can configure this lint to operate at a higher level, both with
+compiler flags, as well as with an attribute in the source code.
+
+You can also "cap" lints so that the compiler can choose to ignore
+certain lint levels. We'll talk about that last.
+
+### Via compiler flag
+
+The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints
+into allowed, warning, deny, or forbid levels, like this:
+
+```bash
+$ rustc lib.rs --crate-type=lib -W missing-docs
+warning: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+  |
+  = note: requested on the command line with `-W missing-docs`
+
+warning: missing documentation for a function
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+> rustc lib.rs --crate-type=lib -D missing-docs
+error: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+  |
+  = note: requested on the command line with `-D missing-docs`
+
+error: missing documentation for a function
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+```
+
+You can also pass each flag more than once for changing multiple lints:
+
+```bash
+rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables
+```
+
+And of course, you can mix these four flags together:
+
+```bash
+rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
+```
+
+### Via an attribute
+
+You can also modify the lint level with a crate-wide attribute:
+
+```bash
+> cat lib.rs
+#![warn(missing_docs)]
+
+pub fn foo() {}
+$ rustc lib.rs --crate-type=lib
+warning: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | / #![warn(missing_docs)]
+2 | |
+3 | | pub fn foo() {}
+  | |_______________^
+  |
+note: lint level defined here
+ --> lib.rs:1:9
+  |
+1 | #![warn(missing_docs)]
+  |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+ --> lib.rs:3:1
+  |
+3 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+```
+
+All four, `warn`, `allow`, `deny`, and `forbid` all work this way.
+
+You can also pass in multiple lints per attribute:
+
+```rust
+#![warn(missing_docs, unused_variables)]
+
+pub fn foo() {}
+```
+
+And use multiple attributes together:
+
+```rust
+#![warn(missing_docs)]
+#![deny(unused_variables)]
+
+pub fn foo() {}
+```
+
+### Capping lints
+
+`rustc` supports a flag, `--cap-lints LEVEL` that sets the "lint cap level."
+This is the maximum level for all lints. So for example, if we take our
+code sample from the "deny" lint level above:
+
+```rust,ignore
+fn main() {
+    100u8 << 10;
+}
+```
+
+And we compile it, capping lints to warn:
+
+```bash
+$ rustc lib.rs --cap-lints warn
+warning: bitshift exceeds the type's number of bits
+ --> lib.rs:2:5
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^
+  |
+  = note: #[warn(exceeding_bitshifts)] on by default
+
+warning: this expression will panic at run-time
+ --> lib.rs:2:5
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^ attempt to shift left with overflow
+```
+
+It now only warns, rather than errors. We can go further and allow all lints:
+
+```bash
+$ rustc lib.rs --cap-lints allow
+$
+```
+
+This feature is used heavily by Cargo; it will pass `--cap-lints allow` when
+compiling your dependencies, so that if they have any warnings, they do not
+pollute the output of your build.
diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md
new file mode 100644
index 00000000000..e1a3f96a6fe
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md
@@ -0,0 +1,453 @@
+# Allowed-by-default lints
+
+These lints are all set to the 'allow' level by default. As such, they won't show up
+unless you set them to a higher lint level with a flag or attribute.
+
+## anonymous-parameters
+
+This lint detects anonymous parameters. Some example code that triggers this lint:
+
+```rust
+trait Foo {
+    fn foo(usize);
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: use of deprecated anonymous parameter
+ --> src/lib.rs:5:11
+  |
+5 |     fn foo(usize);
+  |           ^
+  |
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+```
+
+This syntax is mostly a historical accident, and can be worked around quite
+easily:
+
+```rust
+trait Foo {
+    fn foo(_: usize);
+}
+```
+
+## bare-trait-object
+
+This lint suggests using `dyn Trait` for trait objects. Some example code
+that triggers this lint:
+
+```rust
+#![feature(dyn_trait)]
+
+trait Trait { }
+
+fn takes_trait_object(_: Box<Trait>) {
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trait objects without an explicit `dyn` are deprecated
+ --> src/lib.rs:7:30
+  |
+7 | fn takes_trait_object(_: Box<Trait>) {
+  |                              ^^^^^ help: use `dyn`: `dyn Trait`
+  |
+```
+
+To fix it, do as the help message suggests:
+
+```rust
+#![feature(dyn_trait)]
+#![deny(bare_trait_object)]
+
+trait Trait { }
+
+fn takes_trait_object(_: Box<dyn Trait>) {
+}
+```
+
+## box-pointers
+
+This lints use of the Box type. Some example code that triggers this lint:
+
+```rust
+struct Foo {
+    x: Box<isize>,
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type uses owned (Box type) pointers: std::boxed::Box<isize>
+ --> src/lib.rs:6:5
+  |
+6 |     x: Box<isize> //~ ERROR type uses owned
+  |     ^^^^^^^^^^^^^
+  |
+```
+
+This lint is mostly historical, and not particularly useful. `Box<T>` used to
+be built into the language, and the only way to do heap allocation. Today's
+Rust can call into other allocators, etc.
+
+## elided-lifetime-in-path
+
+This lint detects the use of hidden lifetime parameters. Some example code
+that triggers this lint:
+
+```rust
+struct Foo<'a> {
+    x: &'a u32
+}
+
+fn foo(x: &Foo) {
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: hidden lifetime parameters are deprecated, try `Foo<'_>`
+ --> src/lib.rs:5:12
+  |
+5 | fn foo(x: &Foo) {
+  |            ^^^
+  |
+```
+
+Lifetime elision elides this lifetime, but that is being deprecated.
+
+## missing-copy-implementations
+
+This lint detects potentially-forgotten implementations of `Copy`. Some
+example code that triggers this lint:
+
+```rust
+pub struct Foo {
+    pub field: i32
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type could implement `Copy`; consider adding `impl Copy`
+ --> src/main.rs:3:1
+  |
+3 | / pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy`
+4 | |     pub field: i32
+5 | | }
+  | |_^
+  |
+```
+
+You can fix the lint by deriving `Copy`.
+
+This lint is set to 'allow' because this code isn't bad; it's common to write
+newtypes like this specifically so that a `Copy` type is no longer `Copy`.
+
+## missing-debug-implementations
+
+This lint detects missing implementations of `fmt::Debug`. Some example code
+that triggers this lint:
+
+```rust
+pub struct Foo;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
+ --> src/main.rs:3:1
+  |
+3 | pub struct Foo;
+  | ^^^^^^^^^^^^^^^
+  |
+```
+
+You can fix the lint by deriving `Debug`.
+
+## missing-docs
+
+This lint detects missing documentation for public items. Some example code
+that triggers this lint:
+
+```rust
+pub fn foo() {}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: missing documentation for crate
+ --> src/main.rs:1:1
+  |
+1 | / #![deny(missing_docs)]
+2 | |
+3 | | pub fn foo() {}
+4 | |
+5 | | fn main() {}
+  | |____________^
+  |
+
+error: missing documentation for a function
+ --> src/main.rs:3:1
+  |
+3 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+
+```
+
+To fix the lint, add documentation to all items.
+
+## single-use-lifetime
+
+This lint detects lifetimes that are only used once. Some example code that
+triggers this lint:
+
+```rust
+struct Foo<'x> {
+    x: &'x u32
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: lifetime name `'x` only used once
+ --> src/main.rs:3:12
+  |
+3 | struct Foo<'x> {
+  |            ^^
+  |
+```
+
+## trivial-casts
+
+This lint detects trivial casts which could be removed. Some example code
+that triggers this lint:
+
+```rust
+let x: &u32 = &42;
+let _ = x as *const u32;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trivial cast: `&u32` as `*const u32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
+ --> src/main.rs:5:13
+  |
+5 |     let _ = x as *const u32;
+  |             ^^^^^^^^^^^^^^^
+  |
+note: lint level defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(trivial_casts)]
+  |         ^^^^^^^^^^^^^
+```
+
+## trivial-numeric-casts
+
+This lint detects trivial casts of numeric types which could be removed. Some
+example code that triggers this lint:
+
+```rust
+let x = 42i32 as i32;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trivial numeric cast: `i32` as `i32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
+ --> src/main.rs:4:13
+  |
+4 |     let x = 42i32 as i32;
+  |             ^^^^^^^^^^^^
+  |
+```
+
+## unreachable-pub
+
+This lint triggers for `pub` items not reachable from the crate root. Some
+example code that triggers this lint:
+
+```rust
+mod foo {
+    pub mod bar {
+        
+    }
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unreachable `pub` item
+ --> src/main.rs:4:5
+  |
+4 |     pub mod bar {
+  |     ---^^^^^^^^
+  |     |
+  |     help: consider restricting its visibility: `pub(crate)`
+  |
+```
+
+## unsafe-code
+
+This lint catches usage of `unsafe` code. Some example code that triggers this lint:
+
+```rust
+fn main() {
+    unsafe {
+
+    }
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: usage of an `unsafe` block
+ --> src/main.rs:4:5
+  |
+4 | /     unsafe {
+5 | |         
+6 | |     }
+  | |_____^
+  |
+```
+
+## unstable-features
+
+This lint is deprecated and no longer used.
+
+## unused-extern-crates
+
+This lint guards against `extern crate` items that are never used. Some
+example code that triggers this lint:
+
+```rust,ignore
+extern crate semver;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused extern crate
+ --> src/main.rs:3:1
+  |
+3 | extern crate semver;
+  | ^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-import-braces
+
+This lint catches unnecessary braces around an imported item. Some example
+code that triggers this lint:
+
+```rust
+use test::{A};
+
+pub mod test {
+    pub struct A;
+}
+# fn main() {}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: braces around A is unnecessary
+ --> src/main.rs:3:1
+  |
+3 | use test::{A};
+  | ^^^^^^^^^^^^^^
+  |
+```
+
+To fix it, `use test::A;`
+
+## unused-qualifications
+
+This lint detects unnecessarily qualified names. Some example code that triggers this lint:
+
+```rust
+mod foo {
+    pub fn bar() {}
+}
+
+fn main() {
+    use foo::bar;
+    foo::bar();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unnecessary qualification
+ --> src/main.rs:9:5
+  |
+9 |     foo::bar();
+  |     ^^^^^^^^
+  |
+```
+
+You can call `bar()` directly, without the `foo::`.
+
+## unused-results
+
+This lint checks for the unused result of an expression in a statement. Some
+example code that triggers this lint:
+
+```rust,no_run
+fn foo<T>() -> T { panic!() }
+
+fn main() {
+    foo::<usize>();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused result
+ --> src/main.rs:6:5
+  |
+6 |     foo::<usize>();
+  |     ^^^^^^^^^^^^^^^
+  |
+```
+
+## variant-size-differences
+
+This lint detects enums with widely varying variant sizes. Some example code that triggers this lint:
+
+```rust
+enum En {
+    V0(u8),
+    VBig([u8; 1024]),
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: enum variant is more than three times larger (1024 bytes) than the next largest
+ --> src/main.rs:5:5
+  |
+5 |     VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+  |     ^^^^^^^^^^^^^^^^
+  |
+```
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
new file mode 100644
index 00000000000..e7ec6af8be1
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -0,0 +1,241 @@
+# Deny-by-default lints
+
+These lints are all set to the 'deny' level by default.
+
+## exceeding-bitshifts
+
+This lint detects that a shift exceeds the type's number of bits. Some
+example code that triggers this lint:
+
+```rust,ignore
+1_i32 << 32;
+```
+
+This will produce:
+
+```text
+error: bitshift exceeds the type's number of bits
+ --> src/main.rs:2:5
+  |
+2 |     1_i32 << 32;
+  |     ^^^^^^^^^^^
+  |
+```
+
+## invalid-type-param-default
+
+This lint detects type parameter default erroneously allowed in invalid location. Some
+example code that triggers this lint:
+
+```rust,ignore
+fn foo<T=i32>(t: T) {}
+```
+
+This will produce:
+
+```text
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+ --> src/main.rs:4:8
+  |
+4 | fn foo<T=i32>(t: T) {}
+  |        ^
+  |
+  = note: #[deny(invalid_type_param_default)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+```
+
+## legacy-constructor-visibility
+
+[RFC 1506](https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md) modified some
+visibility rules, and changed the visibility of struct constructors. Some
+example code that triggers this lint:
+
+```rust,ignore
+mod m {
+    pub struct S(u8);
+    
+    fn f() {
+        // this is trying to use S from the 'use' line, but becuase the `u8` is
+        // not pub, it is private
+        ::S;
+    }
+}
+
+use m::S;
+```
+
+This will produce:
+
+```text
+error: private struct constructors are not usable through re-exports in outer modules
+ --> src/main.rs:5:9
+  |
+5 |         ::S;
+  |         ^^^
+  |
+  = note: #[deny(legacy_constructor_visibility)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #39207 <https://github.com/rust-lang/rust/issues/39207>
+```
+
+
+## legacy-directory-ownership
+
+The legacy_directory_ownership warning is issued when
+
+* There is a non-inline module with a #[path] attribute (e.g. #[path = "foo.rs"] mod bar;),
+* The module's file ("foo.rs" in the above example) is not named "mod.rs", and
+* The module's file contains a non-inline child module without a #[path] attribute.
+
+The warning can be fixed by renaming the parent module to "mod.rs" and moving
+it into its own directory if appropriate.
+
+## legacy-imports
+
+This lint detects names that resolve to ambiguous glob imports. Some example
+code that triggers this lint:
+
+```rust,ignore
+pub struct Foo;
+
+mod bar {
+    struct Foo;
+
+    mod baz {
+        use *;
+        use bar::*;
+        fn f(_: Foo) {}
+    }
+}
+```
+
+This will produce:
+
+```text
+error: `Foo` is ambiguous
+ --> src/main.rs:9:17
+  |
+7 |         use *;
+  |             - `Foo` could refer to the name imported here
+8 |         use bar::*;
+  |             ------ `Foo` could also refer to the name imported here
+9 |         fn f(_: Foo) {}
+  |                 ^^^
+  |
+  = note: #[deny(legacy_imports)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #38260 <https://github.com/rust-lang/rust/issues/38260>
+```
+
+
+## missing-fragment-specifier
+
+The missing_fragment_specifier warning is issued when an unused pattern in a
+`macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not
+followed by a fragment specifier (e.g. `:expr`).
+
+This warning can always be fixed by removing the unused pattern in the
+`macro_rules!` macro definition.
+
+## mutable-transmutes
+
+This lint catches transmuting from `&T` to `&mut T` becuase it is undefined
+behavior. Some example code that triggers this lint:
+
+```rust,ignore
+unsafe {
+    let y = std::mem::transmute::<&i32, &mut i32>(&5);
+}
+```
+
+This will produce:
+
+```text
+error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
+ --> src/main.rs:3:17
+  |
+3 |         let y = std::mem::transmute::<&i32, &mut i32>(&5);
+  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+
+## no-mangle-const-items
+
+This lint detects any `const` items with the `#[no_mangle]` attribute.
+Constants do not have their symbols exported, and therefore, this probably
+means you meant to use a `static`, not a `const`. Some example code that
+triggers this lint:
+
+```rust,ignore
+#[no_mangle]
+const FOO: i32 = 5;
+```
+
+This will produce:
+
+```text
+error: const items should never be #[no_mangle]
+ --> src/main.rs:3:1
+  |
+3 | const FOO: i32 = 5;
+  | -----^^^^^^^^^^^^^^
+  | |
+  | help: try a static value: `pub static`
+  |
+```
+
+## parenthesized-params-in-types-and-modules
+
+This lint detects incorrect parentheses. Some example code that triggers this
+lint:
+
+```rust,ignore
+let x = 5 as usize();
+```
+
+This will produce:
+
+```text
+error: parenthesized parameters may only be used with a trait
+ --> src/main.rs:2:21
+  |
+2 |   let x = 5 as usize();
+  |                     ^^
+  |
+  = note: #[deny(parenthesized_params_in_types_and_modules)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+```
+
+To fix it, remove the `()`s.
+
+## pub-use-of-private-extern-crate
+
+This lint detects a specific situation of re-exporting a private `extern crate`;
+
+## safe-extern-statics
+
+In older versions of Rust, there was a soundness issue where `extern static`s were allowed
+to be accessed in safe code. This lint now catches and denies this kind of code.
+
+## unknown-crate-types
+
+This lint detects an unknown crate type found in a `#[crate_type]` directive. Some
+example code that triggers this lint:
+
+```rust,ignore
+#![crate_type="lol"]
+```
+
+This will produce:
+
+```text
+error: invalid `crate_type` value
+ --> src/lib.rs:1:1
+  |
+1 | #![crate_type="lol"]
+  | ^^^^^^^^^^^^^^^^^^^^
+  |
+```
diff --git a/src/doc/rustc/src/lints/listing/index.md b/src/doc/rustc/src/lints/listing/index.md
new file mode 100644
index 00000000000..18cd2fe32a3
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/index.md
@@ -0,0 +1,5 @@
+# Lint listing
+
+This section lists out all of the lints, grouped by their default lint levels.
+
+You can also see this list by running `rustc -W help`.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
new file mode 100644
index 00000000000..1171f75caa1
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -0,0 +1,1039 @@
+# Warn-by-default lints
+
+These lints are all set to the 'warn' level by default.
+
+## const-err
+
+This lint detects an erroneous expression while doing constant evaluation. Some
+example code that triggers this lint:
+
+```rust,ignore
+let b = 200u8 + 200u8;
+```
+
+This will produce:
+
+```text
+warning: attempt to add with overflow
+ --> src/main.rs:2:9
+  |
+2 | let b = 200u8 + 200u8;
+  |         ^^^^^^^^^^^^^
+  |
+```
+
+## dead-code
+
+This lint detects detect unused, unexported items. Some
+example code that triggers this lint:
+
+```rust
+fn foo() {}
+```
+
+This will produce:
+
+```text
+warning: function is never used: `foo`
+ --> src/lib.rs:2:1
+  |
+2 | fn foo() {}
+  | ^^^^^^^^
+  |
+```
+
+## deprecated
+
+This lint detects detects use of deprecated items. Some
+example code that triggers this lint:
+
+```rust
+#[deprecated]
+fn foo() {}
+
+fn bar() {
+    foo();
+}
+```
+
+This will produce:
+
+```text
+warning: use of deprecated item 'foo'
+ --> src/lib.rs:7:5
+  |
+7 |     foo();
+  |     ^^^
+  |
+```
+
+## illegal-floating-point-literal-pattern
+
+This lint detects floating-point literals used in patterns. Some example code
+that triggers this lint:
+
+```rust
+let x = 42.0;
+
+match x {
+    5.0 => {},
+    _ => {},
+}
+```
+
+This will produce:
+
+```text
+warning: floating-point literals cannot be used in patterns
+ --> src/main.rs:4:9
+  |
+4 |         5.0 => {},
+  |         ^^^
+  |
+  = note: #[warn(illegal_floating_point_literal_pattern)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+```
+
+## improper-ctypes
+
+This lint detects proper use of libc types in foreign modules. Some
+example code that triggers this lint:
+
+```rust
+extern "C" {
+    static STATIC: String;
+}
+```
+
+This will produce:
+
+```text
+warning: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
+ --> src/main.rs:2:20
+  |
+2 |     static STATIC: String;
+  |                    ^^^^^^
+  |
+```
+
+## incoherent-fundamental-impls
+
+This lint detects potentially-conflicting impls that were erroneously allowed. Some
+example code that triggers this lint:
+
+```rust
+pub trait Trait1<X> {
+    type Output;
+}
+
+pub trait Trait2<X> {}
+
+pub struct A;
+
+impl<X, T> Trait1<X> for T where T: Trait2<X> {
+    type Output = ();
+}
+
+impl<X> Trait1<Box<X>> for A {
+    type Output = i32;
+}
+```
+
+This will produce:
+
+```text
+warning: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
+  --> src/main.rs:13:1
+   |
+9  | impl<X, T> Trait1<X> for T where T: Trait2<X> {
+   | --------------------------------------------- first implementation here
+...
+13 | impl<X> Trait1<Box<X>> for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
+   |
+   = note: #[warn(incoherent_fundamental_impls)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
+   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
+```
+
+## late-bound-lifetime-arguments
+
+This lint detects detects generic lifetime arguments in path segments with
+late bound lifetime parameters. Some example code that triggers this lint:
+
+```rust
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+}
+
+fn main() {
+    S.late::<'static>(&0, &0);
+}
+```
+
+This will produce:
+
+```text
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> src/main.rs:8:14
+  |
+4 |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+  |             -- the late bound lifetime parameter is introduced here
+...
+8 |     S.late::<'static>(&0, &0);
+  |              ^^^^^^^
+  |
+  = note: #[warn(late_bound_lifetime_arguments)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+```
+
+## non-camel-case-types
+
+This lint detects types, variants, traits and type parameters that don't have
+camel case names. Some example code that triggers this lint:
+
+```rust
+struct s;
+```
+
+This will produce:
+
+```text
+warning: type `s` should have a camel case name such as `S`
+ --> src/main.rs:1:1
+  |
+1 | struct s;
+  | ^^^^^^^^^
+  |
+```
+
+## non-shorthand-field-patterns
+
+This lint detects using `Struct { x: x }` instead of `Struct { x }` in a pattern. Some
+example code that triggers this lint:
+
+```rust
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+
+fn main() {
+    let p = Point {
+        x: 5,
+        y: 5,
+    };
+
+    match p {
+        Point { x: x, y: y } => (),
+    }
+}
+```
+
+This will produce:
+
+```text
+warning: the `x:` in this pattern is redundant
+  --> src/main.rs:14:17
+   |
+14 |         Point { x: x, y: y } => (),
+   |                 --^^
+   |                 |
+   |                 help: remove this
+   |
+
+warning: the `y:` in this pattern is redundant
+  --> src/main.rs:14:23
+   |
+14 |         Point { x: x, y: y } => (),
+   |                       --^^
+   |                       |
+   |                       help: remove this
+
+```
+
+## non-snake-case
+
+This lint detects variables, methods, functions, lifetime parameters and
+modules that don't have snake case names. Some example code that triggers
+this lint:
+
+```rust
+let X = 5;
+```
+
+This will produce:
+
+```text
+warning: variable `X` should have a snake case name such as `x`
+ --> src/main.rs:2:9
+  |
+2 |     let X = 5;
+  |         ^
+  |
+```
+
+## non-upper-case-globals
+
+This lint detects static constants that don't have uppercase identifiers.
+Some example code that triggers this lint:
+
+```rust
+static x: i32 = 5;
+```
+
+This will produce:
+
+```text
+warning: static variable `x` should have an upper case name such as `X`
+ --> src/main.rs:1:1
+  |
+1 | static x: i32 = 5;
+  | ^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## no-mangle-generic-items
+
+This lint detects generic items must be mangled. Some
+example code that triggers this lint:
+
+```rust
+#[no_mangle]
+fn foo<T>(t: T) {
+
+}
+```
+
+This will produce:
+
+```text
+warning: functions generic over types must be mangled
+ --> src/main.rs:2:1
+  |
+1 |   #[no_mangle]
+  |   ------------ help: remove this attribute
+2 | / fn foo<T>(t: T) {
+3 | |     
+4 | | }
+  | |_^
+  |
+```
+
+## overflowing-literals
+
+This lint detects literal out of range for its type. Some
+example code that triggers this lint:
+
+```rust
+let x: u8 = 1000;
+```
+
+This will produce:
+
+```text
+warning: literal out of range for u8
+ --> src/main.rs:2:17
+  |
+2 |     let x: u8 = 1000;
+  |                 ^^^^
+  |
+```
+
+## path-statements
+
+This lint detects path statements with no effect. Some example code that
+triggers this lint:
+
+```rust
+let x = 42;
+
+x;
+```
+
+This will produce:
+
+```text
+warning: path statement with no effect
+ --> src/main.rs:3:5
+  |
+3 |     x;
+  |     ^^
+  |
+```
+
+## patterns-in-fns-without-body
+
+This lint detects patterns in functions without body were that were
+previously erroneously allowed. Some example code that triggers this lint:
+
+```rust
+trait Trait {
+    fn foo(mut arg: u8);
+}
+```
+
+This will produce:
+
+```text
+warning: patterns aren't allowed in methods without bodies
+ --> src/main.rs:2:12
+  |
+2 |     fn foo(mut arg: u8);
+  |            ^^^^^^^
+  |
+  = note: #[warn(patterns_in_fns_without_body)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
+```
+
+To fix this, remove the pattern; it can be used in the implementation without
+being used in the definition. That is:
+
+```rust
+trait Trait {
+    fn foo(arg: u8);
+}
+
+impl Trait for i32 {
+    fn foo(mut arg: u8) {
+
+    }
+}
+```
+
+## plugin-as-library
+
+This lint detects when compiler plugins are used as ordinary library in
+non-plugin crate. Some example code that triggers this lint:
+
+```rust,ignore
+#![feature(plugin)]
+#![plugin(macro_crate_test)]
+
+extern crate macro_crate_test;
+```
+
+## private-in-public
+
+This lint detects detect private items in public interfaces not caught by the old implementation. Some
+example code that triggers this lint:
+
+```rust,ignore
+pub trait Trait {
+    type A;
+}
+
+pub struct S;
+
+mod foo {
+    struct Z;
+
+    impl ::Trait for ::S {
+        type A = Z;
+    }
+}
+# fn main() {}
+```
+
+This will produce:
+
+```text
+error[E0446]: private type `foo::Z` in public interface
+  --> src/main.rs:11:9
+   |
+11 |         type A = Z;
+   |         ^^^^^^^^^^^ can't leak private type
+```
+
+## private-no-mangle-fns
+
+This lint detects functions marked `#[no_mangle]` that are also private.
+Given that private functions aren't exposed publicly, and `#[no_mangle]`
+controls the public symbol, this combination is erroneous. Some example code
+that triggers this lint:
+
+```rust
+#[no_mangle]
+fn foo() {}
+```
+
+This will produce:
+
+```text
+warning: function is marked #[no_mangle], but not exported
+ --> src/main.rs:2:1
+  |
+2 | fn foo() {}
+  | -^^^^^^^^^^
+  | |
+  | help: try making it public: `pub`
+  |
+```
+
+To fix this, either make it public or remove the `#[no_mangle]`.
+
+## private-no-mangle-statics
+
+This lint detects any statics marked `#[no_mangle]` that are private.
+Given that private statics aren't exposed publicly, and `#[no_mangle]`
+controls the public symbol, this combination is erroneous. Some example code
+that triggers this lint:
+
+```rust
+#[no_mangle]
+static X: i32 = 4;
+```
+
+This will produce:
+
+```text
+warning: static is marked #[no_mangle], but not exported
+ --> src/main.rs:2:1
+  |
+2 | static X: i32 = 4;
+  | -^^^^^^^^^^^^^^^^^
+  | |
+  | help: try making it public: `pub`
+  |
+```
+
+To fix this, either make it public or remove the `#[no_mangle]`.
+
+## renamed-and-removed-lints
+
+This lint detects lints that have been renamed or removed. Some
+example code that triggers this lint:
+
+```rust
+#![deny(raw_pointer_derive)]
+```
+
+This will produce:
+
+```text
+warning: lint raw_pointer_derive has been removed: using derive with raw pointers is ok
+ --> src/main.rs:1:9
+  |
+1 | #![deny(raw_pointer_derive)]
+  |         ^^^^^^^^^^^^^^^^^^
+  |
+```
+
+To fix this, either remove the lint or use the new name.
+
+## safe-packed-borrows
+
+This lint detects borrowing a field in the interior of a packed structure
+with alignment other than 1. Some example code that triggers this lint:
+
+```rust
+#[repr(packed)]
+pub struct Unaligned<T>(pub T);
+
+pub struct Foo {
+    start: u8,
+    data: Unaligned<u32>,
+}
+
+fn main() {
+    let x = Foo { start: 0, data: Unaligned(1) };
+    let y = &x.data.0;
+}
+```
+
+This will produce:
+
+```text
+warning: borrow of packed field requires unsafe function or block (error E0133)
+  --> src/main.rs:11:13
+   |
+11 |     let y = &x.data.0; 
+   |             ^^^^^^^^^
+   |
+   = note: #[warn(safe_packed_borrows)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+```
+
+## stable-features
+
+This lint detects a `#[feature]` attribute that's since been made stable. Some
+example code that triggers this lint:
+
+```rust
+#![feature(test_accepted_feature)]
+```
+
+This will produce:
+
+```text
+warning: this feature has been stable since 1.0.0. Attribute no longer needed
+ --> src/main.rs:1:12
+  |
+1 | #![feature(test_accepted_feature)]
+  |            ^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+To fix, simply remove the `#![feature]` attribute, as it's no longer needed.
+
+## type-alias-bounds
+
+This lint detects bounds in type aliases. These are not currently enforced.
+Some example code that triggers this lint:
+
+```rust
+type SendVec<T: Send> = Vec<T>;
+```
+
+This will produce:
+
+```text
+warning: type alias is never used: `SendVec`
+ --> src/main.rs:1:1
+  |
+1 | type SendVec<T: Send> = Vec<T>;
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## tyvar-behind-raw-pointer
+
+This lint detects raw pointer to an inference variable. Some
+example code that triggers this lint:
+
+```rust
+let data = std::ptr::null();
+let _ = &data as *const *const ();
+
+if data.is_null() {}
+```
+
+This will produce:
+
+```text
+warning: type annotations needed
+ --> src/main.rs:4:13
+  |
+4 |     if data.is_null() {}
+  |             ^^^^^^^
+  |
+  = note: #[warn(tyvar_behind_raw_pointer)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+  = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+```
+
+## unconditional-recursion
+
+This lint detects functions that cannot return without calling themselves.
+Some example code that triggers this lint:
+
+```rust
+fn foo() {
+    foo();
+}
+```
+
+This will produce:
+
+```text
+warning: function cannot return without recurring
+ --> src/main.rs:1:1
+  |
+1 | fn foo() {
+  | ^^^^^^^^ cannot return without recurring
+2 |     foo();
+  |     ----- recursive call site
+  |
+```
+
+## unions-with-drop-fields
+
+This lint detects use of unions that contain fields with possibly non-trivial drop code. Some
+example code that triggers this lint:
+
+```rust
+#![feature(untagged_unions)]
+
+union U {
+    s: String,
+}
+```
+
+This will produce:
+
+```text
+warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
+ --> src/main.rs:4:5
+  |
+4 |     s: String,
+  |     ^^^^^^^^^
+  |
+```
+
+## unknown-lints
+
+This lint detects unrecognized lint attribute. Some
+example code that triggers this lint:
+
+```rust,ignore
+#[allow(not_a_real_lint)]
+```
+
+This will produce:
+
+```text
+warning: unknown lint: `not_a_real_lint`
+ --> src/main.rs:1:10
+  |
+1 | #![allow(not_a_real_lint)]
+  |          ^^^^^^^^^^^^^^^
+  |
+```
+
+## unreachable-code
+
+This lint detects detects unreachable code paths. Some example code that
+triggers this lint:
+
+```rust,no_run
+panic!("we never go past here!");
+
+let x = 5;
+```
+
+This will produce:
+
+```text
+warning: unreachable statement
+ --> src/main.rs:4:5
+  |
+4 |     let x = 5;
+  |     ^^^^^^^^^^
+  |
+```
+
+## unreachable-patterns
+
+This lint detects detects unreachable patterns. Some
+example code that triggers this lint:
+
+```rust
+let x = 5;
+match x {
+    y => (),
+    5 => (),
+}
+```
+
+This will produce:
+
+```text
+warning: unreachable pattern
+ --> src/main.rs:5:5
+  |
+5 |     5 => (),
+  |     ^
+  |
+```
+
+The `y` pattern will always match, so the five is impossible to reach.
+Remember, match arms match in order, you probably wanted to put the `5` case
+above the `y` case.
+
+## unstable-name-collision
+
+This lint detects that you've used a name that the standard library plans to
+add in the future, which means that your code may fail to compile without
+additional type annotations in the future. Either rename, or add those
+annotations now.
+
+## unused-allocation
+
+This lint detects detects unnecessary allocations that can be eliminated.
+
+## unused-assignments
+
+This lint detects detect assignments that will never be read. Some
+example code that triggers this lint:
+
+```rust
+let mut x = 5;
+x = 6;
+```
+
+This will produce:
+
+```text
+warning: value assigned to `x` is never read
+ --> src/main.rs:4:5
+  |
+4 |     x = 6;
+  |     ^
+  |
+```
+
+## unused-attributes
+
+This lint detects detects attributes that were not used by the compiler. Some
+example code that triggers this lint:
+
+```rust
+#![feature(custom_attribute)]
+
+#![mutable_doc]
+```
+
+This will produce:
+
+```text
+warning: unused attribute
+ --> src/main.rs:4:1
+  |
+4 | #![mutable_doc]
+  | ^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-comparisons
+
+This lint detects comparisons made useless by limits of the types involved. Some
+example code that triggers this lint:
+
+```rust
+fn foo(x: u8) {
+    x >= 0;
+}
+```
+
+This will produce:
+
+```text
+warning: comparison is useless due to type limits
+ --> src/main.rs:6:5
+  |
+6 |     x >= 0;
+  |     ^^^^^^
+  |
+```
+
+## unused-doc-comment
+
+This lint detects detects doc comments that aren't used by rustdoc. Some
+example code that triggers this lint:
+
+```rust
+/// docs for x
+let x = 12;
+```
+
+This will produce:
+
+```text
+warning: doc comment not used by rustdoc
+ --> src/main.rs:2:5
+  |
+2 |     /// docs for x
+  |     ^^^^^^^^^^^^^^
+  |
+```
+
+## unused-features
+
+This lint detects unused or unknown features found in crate-level #[feature] directives.
+To fix this, simply remove the feature flag.
+
+## unused-imports
+
+This lint detects imports that are never used. Some
+example code that triggers this lint:
+
+```rust
+use std::collections::HashMap;
+```
+
+This will produce:
+
+```text
+warning: unused import: `std::collections::HashMap`
+ --> src/main.rs:1:5
+  |
+1 | use std::collections::HashMap;
+  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-macros
+
+This lint detects detects macros that were not used. Some example code that
+triggers this lint:
+
+```rust
+macro_rules! unused {
+    () => {};
+}
+
+fn main() {
+}
+```
+
+This will produce:
+
+```text
+warning: unused macro definition
+ --> src/main.rs:1:1
+  |
+1 | / macro_rules! unused {
+2 | |     () => {};
+3 | | }
+  | |_^
+  |
+```
+
+## unused-must-use
+
+This lint detects unused result of a type flagged as #[must_use]. Some
+example code that triggers this lint:
+
+```rust
+fn returns_result() -> Result<(), ()> {
+    Ok(())
+}
+
+fn main() {
+    returns_result();
+}
+```
+
+This will produce:
+
+```text
+warning: unused `std::result::Result` which must be used
+ --> src/main.rs:6:5
+  |
+6 |     returns_result();
+  |     ^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-mut
+
+This lint detects detect mut variables which don't need to be mutable. Some
+example code that triggers this lint:
+
+```rust
+let mut x = 5;
+```
+
+This will produce:
+
+```text
+warning: variable does not need to be mutable
+ --> src/main.rs:2:9
+  |
+2 |     let mut x = 5;
+  |         ----^
+  |         |
+  |         help: remove this `mut`
+  |
+```
+
+## unused-parens
+
+This lint detects `if`, `match`, `while` and `return` with parentheses; they
+do not need them. Some example code that triggers this lint:
+
+```rust
+if(true) {}
+```
+
+This will produce:
+
+```text
+warning: unnecessary parentheses around `if` condition
+ --> src/main.rs:2:7
+  |
+2 |     if(true) {}
+  |       ^^^^^^ help: remove these parentheses
+  |
+```
+
+## unused-unsafe
+
+This lint detects unnecessary use of an `unsafe` block. Some
+example code that triggers this lint:
+
+```rust
+unsafe {}
+```
+
+This will produce:
+
+```text
+warning: unnecessary `unsafe` block
+ --> src/main.rs:2:5
+  |
+2 |     unsafe {}
+  |     ^^^^^^ unnecessary `unsafe` block
+  |
+```
+
+## unused-variables
+
+This lint detects detect variables which are not used in any way. Some
+example code that triggers this lint:
+
+```rust
+let x = 5;
+```
+
+This will produce:
+
+```text
+warning: unused variable: `x`
+ --> src/main.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^ help: consider using `_x` instead
+  |
+```
+
+## warnings
+
+This lint is a bit special; by changing its level, you change every other warning
+that would produce a warning to whatever value you'd like:
+
+```rust
+#![deny(warnings)]
+```
+
+As such, you won't ever trigger this lint in your code directly.
+
+## while-true
+
+This lint detects `while true { }`. Some example code that triggers this
+lint:
+
+```rust,no_run
+while true {
+
+}
+```
+
+This will produce:
+
+```text
+warning: denote infinite loops with `loop { ... }`
+ --> src/main.rs:2:5
+  |
+2 |     while true {
+  |     ^^^^^^^^^^ help: use `loop`
+  |
+```
diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
new file mode 100644
index 00000000000..8620346e5b7
--- /dev/null
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -0,0 +1,10 @@
+# Built-in Targets
+
+`rustc` ships with the ability to compile to many targets automatically, we
+call these "built-in" targets, and they generally correspond to targets that
+the team is supporting directly.
+
+To see the list of built-in targets, you can run `rustc --print target-list`,
+or look at [the API
+docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/#modules).
+Each module there defines a builder for a particular target.
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md
new file mode 100644
index 00000000000..0691afc60ea
--- /dev/null
+++ b/src/doc/rustc/src/targets/custom.md
@@ -0,0 +1,17 @@
+# Custom Targets
+
+If you'd like to build for a target that is not yet supported by `rustc`, you can use a
+"custom target specification" to define a target. These target specification files
+are JSON. To see the JSON for the host target, you can run:
+
+```bash
+$ rustc +nightly -Z unstable-options --print target-spec-json
+```
+
+To see it for a different target, add the `--target` flag:
+
+```bash
+$ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json
+```
+
+To use a custom target, see [`xargo`](https://github.com/japaric/xargo).
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
new file mode 100644
index 00000000000..07e3a79471f
--- /dev/null
+++ b/src/doc/rustc/src/targets/index.md
@@ -0,0 +1,13 @@
+# Targets
+
+`rustc` is a cross-compiler by default. This means that you can use any compiler to build for any
+architecture. The list of *targets* are the possible architectures that you can build for.
+
+To see all the options that you can set with a target, see the docs
+[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html).
+
+To compile to a particular target, use the `--target` flag:
+
+```bash
+$ rustc src/main.rs --target=wasm32-unknown-unknown
+```
diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md
new file mode 100644
index 00000000000..bed1b71c24e
--- /dev/null
+++ b/src/doc/rustc/src/what-is-rustc.md
@@ -0,0 +1,68 @@
+# What is rustc?
+
+Welcome to "The rustc book"! `rustc` is the compiler for the Rust programming
+language, provided by the project itself. Compilers take your source code and
+produce binary code, either as a library or executable.
+
+Most Rust programmers don't invoke `rustc` directly, but instead do it through
+[Cargo](../cargo/index.html). It's all in service of `rustc` though! If you
+want to see how Cargo calls `rustc`, you can
+
+```bash
+$ cargo build --verbose
+```
+
+And it will print out each `rustc` invocation. This book can help you
+understand what each of these options does. Additionally, while most
+Rustaceans use Cargo, not all do: sometimes they integrate `rustc` into other
+build systems. This book should provide a guide to all of the options you'd
+need to do so.
+
+## Basic usage
+
+Let's say you've got a little hello world program in a file `hello.rs`:
+
+```rust
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+To turn this source code into an executable, you can use `rustc`:
+
+```bash
+$ rustc hello.rs
+$ ./hello # on a *NIX
+$ .\hello.exe # on Windows
+```
+
+Note that we only ever pass `rustc` the *crate root*, not every file we wish
+to compile. For example, if we had a `main.rs` that looked like this:
+
+```rust,ignore
+mod foo;
+
+fn main() {
+    foo::hello();
+}
+```
+
+And a `foo.rs` that had this:
+
+```rust,ignore
+fn hello() {
+    println!("Hello, world!");
+}
+```
+
+To compile this, we'd run this command:
+
+```bash
+$ rustc main.rs
+```
+
+No need to tell `rustc` about `foo.rs`; the `mod` statements give it
+everything that it needs. This is different than how you would use a C
+compiler, where you invoke the compiler on each file, and then link
+everything together. In other words, the *crate* is a translation unit, not a
+particular module.
\ No newline at end of file
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index c0372d24ed5..f59c9f7fd61 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -16,7 +16,7 @@
             issue = "32838")]
 
 use core::intrinsics::{min_align_of_val, size_of_val};
-use core::ptr::NonNull;
+use core::ptr::{NonNull, Unique};
 use core::usize;
 
 #[doc(inline)]
@@ -152,9 +152,17 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
     }
 }
 
-#[cfg_attr(not(test), lang = "box_free")]
+#[cfg(stage0)]
+#[lang = "box_free"]
+#[inline]
+unsafe fn old_box_free<T: ?Sized>(ptr: *mut T) {
+    box_free(Unique::new_unchecked(ptr))
+}
+
+#[cfg_attr(not(any(test, stage0)), lang = "box_free")]
 #[inline]
-pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
+    let ptr = ptr.as_ptr();
     let size = size_of_val(&*ptr);
     let align = min_align_of_val(&*ptr);
     // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index e52a0216dd3..d0950bff9ce 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -566,7 +566,8 @@ impl<T: ?Sized> Arc<T> {
 
     fn from_box(v: Box<T>) -> Arc<T> {
         unsafe {
-            let bptr = Box::into_raw(v);
+            let box_unique = Box::into_unique(v);
+            let bptr = box_unique.as_ptr();
 
             let value_size = size_of_val(&*bptr);
             let ptr = Self::allocate_for_ptr(bptr);
@@ -578,7 +579,7 @@ impl<T: ?Sized> Arc<T> {
                 value_size);
 
             // Free the allocation without dropping its contents
-            box_free(bptr);
+            box_free(box_unique);
 
             Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 5ebd2cc6146..1b4f86dcfac 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -184,6 +184,7 @@ impl<T: ?Sized> Box<T> {
 
     #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
     #[inline]
+    #[doc(hidden)]
     pub fn into_unique(b: Box<T>) -> Unique<T> {
         let unique = b.0;
         mem::forget(b);
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 8fb8e111754..d0188c6e828 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -681,7 +681,8 @@ impl<T: ?Sized> Rc<T> {
 
     fn from_box(v: Box<T>) -> Rc<T> {
         unsafe {
-            let bptr = Box::into_raw(v);
+            let box_unique = Box::into_unique(v);
+            let bptr = box_unique.as_ptr();
 
             let value_size = size_of_val(&*bptr);
             let ptr = Self::allocate_for_ptr(bptr);
@@ -693,7 +694,7 @@ impl<T: ?Sized> Rc<T> {
                 value_size);
 
             // Free the allocation without dropping its contents
-            box_free(bptr);
+            box_free(box_unique);
 
             Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index c91aa06609d..13e838773a5 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -106,6 +106,8 @@ use self::Ordering::*;
 /// ```
 #[lang = "eq"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
@@ -160,6 +162,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
 /// }
 /// impl Eq for Book {}
 /// ```
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Eq: PartialEq<Self> {
     // this method is used solely by #[deriving] to assert
@@ -428,6 +432,10 @@ impl<T: Ord> Ord for Reverse<T> {
 /// }
 /// ```
 #[lang = "ord"]
+#[doc(alias = "<")]
+#[doc(alias = ">")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an `Ordering` between `self` and `other`.
@@ -599,6 +607,10 @@ impl PartialOrd for Ordering {
 /// ```
 #[lang = "partial_ord"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = ">")]
+#[doc(alias = "<")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values if one exists.
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index a8430f14410..99e3012c9bf 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -547,6 +547,7 @@ impl<'a> Display for Arguments<'a> {
     message="`{Self}` doesn't implement `{Debug}`",
     label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`",
 )]
+#[doc(alias = "{:?}")]
 #[lang = "debug_trait"]
 pub trait Debug {
     /// Formats the value using the given formatter.
@@ -612,6 +613,7 @@ pub trait Debug {
     label="`{Self}` cannot be formatted with the default formatter; \
            try using `:?` instead if you are using a format string",
 )]
+#[doc(alias = "{}")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Display {
     /// Formats the value using the given formatter.
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index a1f6030428f..a1bc5463f73 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -94,6 +94,7 @@ pub trait Add<RHS=Self> {
     type Output;
 
     /// Performs the `+` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn add(self, rhs: RHS) -> Self::Output;
 }
@@ -191,6 +192,7 @@ pub trait Sub<RHS=Self> {
     type Output;
 
     /// Performs the `-` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn sub(self, rhs: RHS) -> Self::Output;
 }
@@ -310,6 +312,7 @@ pub trait Mul<RHS=Self> {
     type Output;
 
     /// Performs the `*` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn mul(self, rhs: RHS) -> Self::Output;
 }
@@ -433,6 +436,7 @@ pub trait Div<RHS=Self> {
     type Output;
 
     /// Performs the `/` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn div(self, rhs: RHS) -> Self::Output;
 }
@@ -517,6 +521,7 @@ pub trait Rem<RHS=Self> {
     type Output = Self;
 
     /// Performs the `%` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn rem(self, rhs: RHS) -> Self::Output;
 }
@@ -601,6 +606,7 @@ pub trait Neg {
     type Output;
 
     /// Performs the unary `-` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn neg(self) -> Self::Output;
 }
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
index 81c4455cef4..3900f365b0a 100644
--- a/src/libcore/ops/bit.rs
+++ b/src/libcore/ops/bit.rs
@@ -46,6 +46,7 @@ pub trait Not {
     type Output;
 
     /// Performs the unary `!` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn not(self) -> Self::Output;
 }
@@ -119,6 +120,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 & bv2, expected);
 /// ```
 #[lang = "bitand"]
+#[doc(alias = "&")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
                          label="no implementation for `{Self} & {RHS}`")]
@@ -128,6 +130,7 @@ pub trait BitAnd<RHS=Self> {
     type Output;
 
     /// Performs the `&` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitand(self, rhs: RHS) -> Self::Output;
 }
@@ -201,6 +204,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 | bv2, expected);
 /// ```
 #[lang = "bitor"]
+#[doc(alias = "|")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
                          label="no implementation for `{Self} | {RHS}`")]
@@ -210,6 +214,7 @@ pub trait BitOr<RHS=Self> {
     type Output;
 
     /// Performs the `|` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitor(self, rhs: RHS) -> Self::Output;
 }
@@ -286,6 +291,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 ^ bv2, expected);
 /// ```
 #[lang = "bitxor"]
+#[doc(alias = "^")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
                          label="no implementation for `{Self} ^ {RHS}`")]
@@ -295,6 +301,7 @@ pub trait BitXor<RHS=Self> {
     type Output;
 
     /// Performs the `^` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitxor(self, rhs: RHS) -> Self::Output;
 }
@@ -372,6 +379,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
 /// ```
 #[lang = "shl"]
+#[doc(alias = "<<")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
                          label="no implementation for `{Self} << {RHS}`")]
@@ -381,6 +389,7 @@ pub trait Shl<RHS=Self> {
     type Output;
 
     /// Performs the `<<` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn shl(self, rhs: RHS) -> Self::Output;
 }
@@ -479,6 +488,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 ///            SpinVector { vec: vec![3, 4, 0, 1, 2] });
 /// ```
 #[lang = "shr"]
+#[doc(alias = ">>")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
                          label="no implementation for `{Self} >> {RHS}`")]
@@ -488,6 +498,7 @@ pub trait Shr<RHS=Self> {
     type Output;
 
     /// Performs the `>>` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn shr(self, rhs: RHS) -> Self::Output;
 }
@@ -593,6 +604,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// assert_eq!(bv, expected);
 /// ```
 #[lang = "bitand_assign"]
+#[doc(alias = "&=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
                          label="no implementation for `{Self} &= {Rhs}`")]
@@ -641,6 +653,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
 /// ```
 #[lang = "bitor_assign"]
+#[doc(alias = "|=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
                          label="no implementation for `{Self} |= {Rhs}`")]
@@ -689,6 +702,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
 /// ```
 #[lang = "bitxor_assign"]
+#[doc(alias = "^=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
                          label="no implementation for `{Self} ^= {Rhs}`")]
@@ -735,6 +749,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(scalar, Scalar(16));
 /// ```
 #[lang = "shl_assign"]
+#[doc(alias = "<<=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
                          label="no implementation for `{Self} <<= {Rhs}`")]
@@ -802,6 +817,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// assert_eq!(scalar, Scalar(4));
 /// ```
 #[lang = "shr_assign"]
+#[doc(alias = ">>=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
                          label="no implementation for `{Self} >>= {Rhs}`")]
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index 4ce0740130b..54eecc82e19 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -68,6 +68,8 @@
 /// assert_eq!('a', *x);
 /// ```
 #[lang = "deref"]
+#[doc(alias = "*")]
+#[doc(alias = "&*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
     /// The resulting type after dereferencing.
@@ -75,6 +77,7 @@ pub trait Deref {
     type Target: ?Sized;
 
     /// Dereferences the value.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn deref(&self) -> &Self::Target;
 }
@@ -162,6 +165,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
 /// assert_eq!('b', *x);
 /// ```
 #[lang = "deref_mut"]
+#[doc(alias = "*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait DerefMut: Deref {
     /// Mutably dereferences the value.
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 6f3e3b50885..d70f7ae66f9 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -45,6 +45,7 @@ use fmt;
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFull;
@@ -74,6 +75,7 @@ impl fmt::Debug for RangeFull {
 /// assert_eq!(arr[1.. ], [     'b', 'c', 'd']);
 /// assert_eq!(arr[1..3], [     'b', 'c'     ]);  // Range
 /// ```
+#[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
@@ -175,6 +177,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
 /// ```
 ///
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
+#[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
@@ -256,6 +259,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeTo<Idx> {
@@ -323,6 +327,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// assert_eq!(arr[ ..=2], [0,1,2  ]);
 /// assert_eq!(arr[1..=2], [  1,2  ]);  // RangeInclusive
 /// ```
+#[doc(alias = "..=")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
@@ -449,6 +454,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..=")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeToInclusive<Idx> {
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 74bb264cc67..c61bdfc9c4f 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2513,6 +2513,7 @@ impl<T: ?Sized> PartialOrd for *mut T {
            reason = "use NonNull instead and consider PhantomData<T> \
                      (if you also use #[may_dangle]), Send, and/or Sync")]
 #[allow(deprecated)]
+#[doc(hidden)]
 pub struct Unique<T: ?Sized> {
     pointer: NonZero<*const T>,
     // NOTE: this marker has no consequences for variance, but is necessary
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index e171216523a..f51dbc3772f 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -270,7 +270,7 @@ impl Span {
     /// `self` was generated from, if any.
     #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn parent(&self) -> Option<Span> {
-        self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site))
+        self.0.parent().map(Span)
     }
 
     /// The span for the origin source code that `self` was generated from. If
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 18bf54297af..e4f432e7caf 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -70,7 +70,8 @@ use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use std::fmt;
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{CanonicalProjectionGoal,
+                    CanonicalTyGoal, CanonicalPredicateGoal};
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
 use ty::subst::Substs;
 
@@ -643,6 +644,7 @@ define_dep_nodes!( <'tcx>
     [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
     [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
     [] DropckOutlives(CanonicalTyGoal<'tcx>),
+    [] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
 
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 956cd17f38f..19f8d15662d 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -30,6 +30,7 @@ enum Target {
     ForeignMod,
     Expression,
     Statement,
+    Closure,
     Other,
 }
 
@@ -103,14 +104,14 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
         self.check_repr(item, target);
     }
 
-    /// Check if an `#[inline]` is applied to a function.
+    /// Check if an `#[inline]` is applied to a function or a closure.
     fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) {
-        if target != Target::Fn {
+        if target != Target::Fn && target != Target::Closure {
             struct_span_err!(self.tcx.sess,
                              attr.span,
                              E0518,
-                             "attribute should be applied to function")
-                .span_label(*span, "not a function")
+                             "attribute should be applied to function or closure")
+                .span_label(*span, "not a function or closure")
                 .emit();
         }
     }
@@ -286,9 +287,13 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     }
 
     fn check_expr_attributes(&self, expr: &hir::Expr) {
+        let target = match expr.node {
+            hir::ExprClosure(..) => Target::Closure,
+            _ => Target::Expression,
+        };
         for attr in expr.attrs.iter() {
             if attr.check_name("inline") {
-                self.check_inline(attr, &expr.span, Target::Expression);
+                self.check_inline(attr, &expr.span, target);
             }
             if attr.check_name("repr") {
                 self.emit_repr_error(
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 4023521147e..e4b9fc1385d 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -655,7 +655,7 @@ impl<'a> LoweringContext<'a> {
                 self.resolver.definitions().create_def_with_parent(
                     parent_id.index,
                     def_node_id,
-                    DefPathData::LifetimeDef(str_name),
+                    DefPathData::LifetimeDef(str_name.as_interned_str()),
                     DefIndexAddressSpace::High,
                     Mark::root(),
                     span,
@@ -1302,7 +1302,7 @@ impl<'a> LoweringContext<'a> {
                     self.context.resolver.definitions().create_def_with_parent(
                         self.parent,
                         def_node_id,
-                        DefPathData::LifetimeDef(name.name().as_str()),
+                        DefPathData::LifetimeDef(name.name().as_interned_str()),
                         DefIndexAddressSpace::High,
                         Mark::root(),
                         lifetime.span,
@@ -4107,15 +4107,13 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) {
-        if self.sess.features_untracked().dyn_trait {
-            self.sess.buffer_lint_with_diagnostic(
-                builtin::BARE_TRAIT_OBJECT,
-                id,
-                span,
-                "trait objects without an explicit `dyn` are deprecated",
-                builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
-            )
-        }
+        self.sess.buffer_lint_with_diagnostic(
+            builtin::BARE_TRAIT_OBJECT,
+            id,
+            span,
+            "trait objects without an explicit `dyn` are deprecated",
+            builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
+        )
     }
 
     fn wrap_in_try_constructor(
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bfe21549e45..ebd8e623582 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -107,18 +107,18 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         // information we encapsulate into
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
-            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()),
+            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
             ItemKind::TraitAlias(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.name.as_str()),
+                DefPathData::TypeNs(i.ident.name.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
-            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.name.as_str()),
-            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
+                DefPathData::ValueNs(i.ident.name.as_interned_str()),
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
@@ -133,7 +133,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.ident.name.as_str()),
+                                            DefPathData::EnumVariant(v.node.ident
+                                                                      .name.as_interned_str()),
                                             REGULAR_SPACE,
                                             v.span);
                         this.with_parent(variant_def_index, |this| {
@@ -141,7 +142,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                                 let name = field.ident.map(|ident| ident.name)
                                     .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                                 this.create_def(field.id,
-                                                DefPathData::Field(name.as_str()),
+                                                DefPathData::Field(name.as_interned_str()),
                                                 REGULAR_SPACE,
                                                 field.span);
                             }
@@ -165,7 +166,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                         let name = field.ident.map(|ident| ident.name)
                             .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                         this.create_def(field.id,
-                                        DefPathData::Field(name.as_str()),
+                                        DefPathData::Field(name.as_interned_str()),
                                         REGULAR_SPACE,
                                         field.span);
                     }
@@ -187,7 +188,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         }
 
         let def = self.create_def(foreign_item.id,
-                                  DefPathData::ValueNs(foreign_item.ident.name.as_str()),
+                                  DefPathData::ValueNs(foreign_item.ident.name.as_interned_str()),
                                   REGULAR_SPACE,
                                   foreign_item.span);
 
@@ -201,7 +202,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             GenericParam::Lifetime(ref lifetime_def) => {
                 self.create_def(
                     lifetime_def.lifetime.id,
-                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_str()),
+                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()),
                     REGULAR_SPACE,
                     lifetime_def.lifetime.ident.span
                 );
@@ -209,7 +210,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             GenericParam::Type(ref ty_param) => {
                 self.create_def(
                     ty_param.id,
-                    DefPathData::TypeParam(ty_param.ident.name.as_str()),
+                    DefPathData::TypeParam(ty_param.ident.name.as_interned_str()),
                     REGULAR_SPACE,
                     ty_param.ident.span
                 );
@@ -222,8 +223,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name.as_str()),
-            TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()),
+                DefPathData::ValueNs(ti.ident.name.as_interned_str()),
+            TraitItemKind::Type(..) => {
+                DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str())
+            },
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
         };
 
@@ -240,8 +243,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.name.as_str()),
-            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()),
+                DefPathData::ValueNs(ii.ident.name.as_interned_str()),
+            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
         };
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 12f146ef491..616dc22486d 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -701,7 +701,7 @@ impl DefPathData {
             Typeof => "{{typeof}}",
         };
 
-        Symbol::intern(s).as_str()
+        Symbol::intern(s).as_interned_str()
     }
 
     pub fn to_string(&self) -> String {
@@ -731,7 +731,7 @@ macro_rules! define_global_metadata_kind {
                     definitions.create_def_with_parent(
                         CRATE_DEF_INDEX,
                         ast::DUMMY_NODE_ID,
-                        DefPathData::GlobalMetaData(instance.name().as_str()),
+                        DefPathData::GlobalMetaData(instance.name().as_interned_str()),
                         GLOBAL_MD_ADDRESS_SPACE,
                         Mark::root(),
                         DUMMY_SP
@@ -746,7 +746,7 @@ macro_rules! define_global_metadata_kind {
                 let def_key = DefKey {
                     parent: Some(CRATE_DEF_INDEX),
                     disambiguated_data: DisambiguatedDefPathData {
-                        data: DefPathData::GlobalMetaData(self.name().as_str()),
+                        data: DefPathData::GlobalMetaData(self.name().as_interned_str()),
                         disambiguator: 0,
                     }
                 };
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index d7e16ab3620..c1e86473996 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -19,7 +19,7 @@ use std::mem;
 use syntax::ast;
 use syntax::feature_gate;
 use syntax::parse::token;
-use syntax::symbol::InternedString;
+use syntax::symbol::{InternedString, LocalInternedString};
 use syntax::tokenstream;
 use syntax_pos::FileMap;
 
@@ -34,8 +34,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        let s: &str = &**self;
-        s.hash_stable(hcx, hasher);
+        self.with(|s| s.hash_stable(hcx, hasher))
     }
 }
 
@@ -50,6 +49,27 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
     }
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let s: &str = &**self;
+        s.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
+    type KeyType = LocalInternedString;
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          _: &StableHashingContext<'a>)
+                          -> LocalInternedString {
+        self.clone()
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -66,7 +86,7 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
     fn to_stable_hash_key(&self,
                           _: &StableHashingContext<'a>)
                           -> InternedString {
-        self.as_str()
+        self.as_interned_str()
     }
 }
 
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index c23836071ff..c35cdf91fe7 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -19,7 +19,7 @@ use super::{CombinedSnapshot,
 use super::combine::CombineFields;
 use super::region_constraints::{TaintDirections};
 
-use std::collections::BTreeMap;
+use rustc_data_structures::lazy_btree_map::LazyBTreeMap;
 use ty::{self, TyCtxt, Binder, TypeFoldable};
 use ty::error::TypeError;
 use ty::relate::{Relate, RelateResult, TypeRelation};
@@ -247,7 +247,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                              snapshot: &CombinedSnapshot<'a, 'tcx>,
                                              debruijn: ty::DebruijnIndex,
                                              new_vars: &[ty::RegionVid],
-                                             a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+                                             a_map: &LazyBTreeMap<ty::BoundRegion,
+                                                                  ty::Region<'tcx>>,
                                              r0: ty::Region<'tcx>)
                                              -> ty::Region<'tcx> {
             // Regions that pre-dated the LUB computation stay as they are.
@@ -343,7 +344,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                              snapshot: &CombinedSnapshot<'a, 'tcx>,
                                              debruijn: ty::DebruijnIndex,
                                              new_vars: &[ty::RegionVid],
-                                             a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+                                             a_map: &LazyBTreeMap<ty::BoundRegion,
+                                                                  ty::Region<'tcx>>,
                                              a_vars: &[ty::RegionVid],
                                              b_vars: &[ty::RegionVid],
                                              r0: ty::Region<'tcx>)
@@ -412,7 +414,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
 
         fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                       span: Span,
-                                      a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+                                      a_map: &LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
                                       r: ty::Region<'tcx>) -> ty::Region<'tcx>
         {
             for (a_br, a_r) in a_map {
@@ -435,7 +437,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
 }
 
 fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>,
-                           map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+                           map: &LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
                            -> Vec<ty::RegionVid> {
     map.iter()
        .map(|(_, &r)| match *r {
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 40cc43c3ca6..553926dba8f 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -28,9 +28,9 @@ use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::TypeFoldable;
 use ty::relate::RelateResult;
 use traits::{self, ObligationCause, PredicateObligations};
+use rustc_data_structures::lazy_btree_map::LazyBTreeMap;
 use rustc_data_structures::unify as ut;
 use std::cell::{Cell, RefCell, Ref, RefMut};
-use std::collections::BTreeMap;
 use std::fmt;
 use syntax::ast;
 use errors::DiagnosticBuilder;
@@ -187,7 +187,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
 /// region that each late-bound region was replaced with.
-pub type SkolemizationMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
+pub type SkolemizationMap<'tcx> = LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
 
 /// See `error_reporting` module for more details
 #[derive(Clone, Debug)]
@@ -1216,7 +1216,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         span: Span,
         lbrct: LateBoundRegionConversionTime,
         value: &ty::Binder<T>)
-        -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+        -> (T, LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where T : TypeFoldable<'tcx>
     {
         self.tcx.replace_late_bound_regions(
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index f85d0a9bf0c..24892dfcc8f 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -45,8 +45,8 @@
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
-#![feature(dyn_trait)]
 #![feature(entry_or_default)]
+#![cfg_attr(stage0, feature(dyn_trait))]
 #![feature(from_ref)]
 #![feature(fs_read_write)]
 #![cfg_attr(windows, feature(libc))]
@@ -58,6 +58,7 @@
 #![feature(nonzero)]
 #![feature(proc_macro_internals)]
 #![feature(quote)]
+#![feature(optin_builtin_traits)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 31f8af1f968..5a626e7b82c 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -154,7 +154,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
                                            recursion_depth: 0,
                                            predicate: p })
                      .chain(obligations)
-                     .find(|o| !selcx.evaluate_obligation(o));
+                     .find(|o| !selcx.predicate_may_hold_fatal(o));
+    // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
+    // to the canonical trait query form, `infcx.predicate_may_hold`, once
+    // the new system supports intercrate mode (which coherence needs).
 
     if let Some(failing_obligation) = opt_failing_obligation {
         debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 33abc0c7e15..047d4bb8930 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -24,6 +24,7 @@ use super::{
     SelectionContext,
     SelectionError,
     ObjectSafetyViolation,
+    Overflow,
 };
 
 use errors::DiagnosticBuilder;
@@ -659,8 +660,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                 predicate: ty::Predicate::Trait(predicate),
                                 .. obligation.clone()
                             };
-                            let mut selcx = SelectionContext::new(self);
-                            if selcx.evaluate_obligation(&unit_obligation) {
+                            if self.predicate_may_hold(&unit_obligation) {
                                 err.note("the trait is implemented for `()`. \
                                          Possibly this error has been caused by changes to \
                                          Rust's type-inference algorithm \
@@ -830,6 +830,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 }
                 err.struct_error(self.tcx, span, "constant expression")
             }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
         };
         self.note_obligation_cause(&mut err, obligation);
         err.emit();
@@ -872,7 +876,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 .count();
 
             let mut trait_type = trait_ref.self_ty();
-            let mut selcx = SelectionContext::new(self);
 
             for refs_remaining in 0..refs_number {
                 if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) =
@@ -886,7 +889,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                          obligation.param_env,
                                                          new_trait_ref.to_predicate());
 
-                    if selcx.evaluate_obligation(&new_obligation) {
+                    if self.predicate_may_hold(&new_obligation) {
                         let sp = self.tcx.sess.codemap()
                             .span_take_while(span, |c| c.is_whitespace() || *c == '&');
 
@@ -976,6 +979,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                      ArgKind::Arg(format!("{}", field.name), "_".to_string())
                  }).collect::<Vec<_>>())
             }
+            hir::map::NodeStructCtor(ref variant_data) => {
+                (self.tcx.sess.codemap().def_span(self.tcx.hir.span(variant_data.id())),
+                 variant_data.fields()
+                    .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned()))
+                    .collect())
+            }
             _ => panic!("non-FnLike node found: {:?}", node),
         }
     }
@@ -1322,7 +1331,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 cleaned_pred.to_predicate()
             );
 
-            selcx.evaluate_obligation(&obligation)
+            self.predicate_may_hold(&obligation)
         })
     }
 
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 5ec2e32b6a4..6e201507181 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -333,7 +333,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
             if data.is_global() {
                 // no type variables present, can use evaluation for better caching.
                 // FIXME: consider caching errors too.
-                if selcx.evaluate_obligation_conservatively(&obligation) {
+                if selcx.infcx().predicate_must_hold(&obligation) {
                     debug!("selecting trait `{:?}` at depth {} evaluated to holds",
                            data, obligation.recursion_depth);
                     return Ok(Some(vec![]))
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 728d9f1a027..dd5208e908e 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -41,7 +41,7 @@ pub use self::object_safety::ObjectSafetyViolation;
 pub use self::object_safety::MethodViolationCode;
 pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
-pub use self::select::IntercrateAmbiguityCause;
+pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::{SpecializesCache, find_associated_item};
 pub use self::engine::TraitEngine;
@@ -74,6 +74,19 @@ pub enum IntercrateMode {
     Fixed
 }
 
+// The mode that trait queries run in
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum TraitQueryMode {
+    // Standard/un-canonicalized queries get accurate
+    // spans etc. passed in and hence can do reasonable
+    // error reporting on their own.
+    Standard,
+    // Canonicalized queries get dummy spans and hence
+    // must generally propagate errors to
+    // pre-canonicalization callsites.
+    Canonical,
+}
+
 /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for
 /// which the vtable must be found.  The process of finding a vtable is
 /// called "resolving" the `Obligation`. This process consists of
@@ -349,6 +362,7 @@ pub enum SelectionError<'tcx> {
                                 ty::error::TypeError<'tcx>),
     TraitNotObjectSafe(DefId),
     ConstEvalFailure(ConstEvalErr<'tcx>),
+    Overflow,
 }
 
 pub struct FulfillmentError<'tcx> {
@@ -550,8 +564,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
         predicate: trait_ref.to_predicate(),
     };
 
-    let result = SelectionContext::new(infcx)
-        .evaluate_obligation_conservatively(&obligation);
+    let result = infcx.predicate_must_hold(&obligation);
     debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
            ty, infcx.tcx.item_path_str(def_id), result);
 
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 405dafdff2b..d1fd70ae02d 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -18,10 +18,10 @@ use util::nodemap::FxHashMap;
 use syntax::ast::{MetaItem, NestedMetaItem};
 use syntax::attr;
 use syntax_pos::Span;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::LocalInternedString;
 
 #[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(InternedString);
+pub struct OnUnimplementedFormatString(LocalInternedString);
 
 #[derive(Debug)]
 pub struct OnUnimplementedDirective {
@@ -225,7 +225,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
 impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
     pub fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                      trait_def_id: DefId,
-                     from: InternedString,
+                     from: LocalInternedString,
                      err_sp: Span)
                      -> Result<Self, ErrorReported>
     {
diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs
new file mode 100644
index 00000000000..4e028cac49a
--- /dev/null
+++ b/src/librustc/traits/query/evaluate_obligation.rs
@@ -0,0 +1,70 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use infer::InferCtxt;
+use infer::canonical::{Canonical, Canonicalize};
+use traits::{EvaluationResult, PredicateObligation, SelectionContext,
+             TraitQueryMode, OverflowError};
+use traits::query::CanonicalPredicateGoal;
+use ty::{ParamEnvAnd, Predicate, TyCtxt};
+
+impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
+    /// Evaluates whether the predicate can be satisfied (by any means)
+    /// in the given `ParamEnv`.
+    pub fn predicate_may_hold(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        self.evaluate_obligation(obligation).may_apply()
+    }
+
+    /// Evaluates whether the predicate can be satisfied in the given
+    /// `ParamEnv`, and returns `false` if not certain. However, this is
+    /// not entirely accurate if inference variables are involved.
+    pub fn predicate_must_hold(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk
+    }
+
+    // Helper function that canonicalizes and runs the query, as well as handles
+    // overflow.
+    fn evaluate_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> EvaluationResult {
+        let (c_pred, _) =
+            self.canonicalize_query(&obligation.param_env.and(obligation.predicate));
+        // Run canonical query. If overflow occurs, rerun from scratch but this time
+        // in standard trait query mode so that overflow is handled appropriately
+        // within `SelectionContext`.
+        match self.tcx.global_tcx().evaluate_obligation(c_pred) {
+            Ok(result) => result,
+            Err(OverflowError) => {
+                let mut selcx =
+                    SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
+                selcx.evaluate_obligation_recursively(obligation)
+                     .expect("Overflow should be caught earlier in standard query mode")
+            }
+        }
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for ParamEnvAnd<'tcx, Predicate<'tcx>> {
+    type Canonicalized = CanonicalPredicateGoal<'gcx>;
+
+    fn intern(
+        _gcx: TyCtxt<'_, 'gcx, 'gcx>,
+        value: Canonical<'gcx, Self::Lifted>,
+    ) -> Self::Canonicalized {
+        value
+    }
+}
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs
index f1f9256f825..096633ddab2 100644
--- a/src/librustc/traits/query/mod.rs
+++ b/src/librustc/traits/query/mod.rs
@@ -19,6 +19,7 @@ use infer::canonical::Canonical;
 use ty::{self, Ty};
 
 pub mod dropck_outlives;
+pub mod evaluate_obligation;
 pub mod normalize;
 pub mod normalize_erasing_regions;
 
@@ -27,6 +28,9 @@ pub type CanonicalProjectionGoal<'tcx> =
 
 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
 
+pub type CanonicalPredicateGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct NoSolution;
 
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index f43f5cf3e3f..4ba3655bb64 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -17,12 +17,12 @@ use self::EvaluationResult::*;
 
 use super::coherence::{self, Conflict};
 use super::DerivedObligationCause;
-use super::IntercrateMode;
+use super::{IntercrateMode, TraitQueryMode};
 use super::project;
 use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey};
 use super::{PredicateObligation, TraitObligation, ObligationCause};
 use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
-use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
+use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch, Overflow};
 use super::{ObjectCastObligation, Obligation};
 use super::TraitNotObjectSafe;
 use super::Selection;
@@ -87,7 +87,12 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     /// Controls whether or not to filter out negative impls when selecting.
     /// This is used in librustdoc to distinguish between the lack of an impl
     /// and a negative impl
-    allow_negative_impls: bool
+    allow_negative_impls: bool,
+
+    /// The mode that trait queries run in, which informs our error handling
+    /// policy. In essence, canonicalized queries need their errors propagated
+    /// rather than immediately reported because we do not have accurate spans.
+    query_mode: TraitQueryMode,
 }
 
 #[derive(Clone, Debug)]
@@ -319,7 +324,7 @@ enum BuiltinImplConditions<'tcx> {
 ///     all the "potential success" candidates can potentially succeed,
 ///     so they are no-ops when unioned with a definite error, and within
 ///     the categories it's easy to see that the unions are correct.
-enum EvaluationResult {
+pub enum EvaluationResult {
     /// Evaluation successful
     EvaluatedToOk,
     /// Evaluation is known to be ambiguous - it *might* hold for some
@@ -385,7 +390,7 @@ enum EvaluationResult {
 }
 
 impl EvaluationResult {
-    fn may_apply(self) -> bool {
+    pub fn may_apply(self) -> bool {
         match self {
             EvaluatedToOk |
             EvaluatedToAmbig |
@@ -408,6 +413,26 @@ impl EvaluationResult {
     }
 }
 
+impl_stable_hash_for!(enum self::EvaluationResult {
+    EvaluatedToOk,
+    EvaluatedToAmbig,
+    EvaluatedToUnknown,
+    EvaluatedToRecur,
+    EvaluatedToErr
+});
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+/// Indicates that trait evaluation caused overflow.
+pub struct OverflowError;
+
+impl_stable_hash_for!(struct OverflowError { });
+
+impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
+    fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
+        SelectionError::Overflow
+    }
+}
+
 #[derive(Clone)]
 pub struct EvaluationCache<'tcx> {
     hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>
@@ -421,6 +446,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             intercrate: None,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
+            query_mode: TraitQueryMode::Standard,
         }
     }
 
@@ -433,6 +459,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             intercrate: Some(mode),
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
+            query_mode: TraitQueryMode::Standard,
         }
     }
 
@@ -445,6 +472,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             intercrate: None,
             intercrate_ambiguity_causes: None,
             allow_negative_impls,
+            query_mode: TraitQueryMode::Standard,
+        }
+    }
+
+    pub fn with_query_mode(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+                           query_mode: TraitQueryMode) -> SelectionContext<'cx, 'gcx, 'tcx> {
+        debug!("with_query_mode({:?})", query_mode);
+        SelectionContext {
+            infcx,
+            freshener: infcx.freshener(),
+            intercrate: None,
+            intercrate_ambiguity_causes: None,
+            allow_negative_impls: false,
+            query_mode,
         }
     }
 
@@ -528,12 +569,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         assert!(!obligation.predicate.has_escaping_regions());
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
-        let ret = match self.candidate_from_obligation(&stack)? {
-            None => None,
-            Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?)
+
+        let candidate = match self.candidate_from_obligation(&stack) {
+            Err(SelectionError::Overflow) => {
+                // In standard mode, overflow must have been caught and reported
+                // earlier.
+                assert!(self.query_mode == TraitQueryMode::Canonical);
+                return Err(SelectionError::Overflow);
+            },
+            Err(e) => { return Err(e); },
+            Ok(None) => { return Ok(None); },
+            Ok(Some(candidate)) => candidate
         };
 
-        Ok(ret)
+        match self.confirm_candidate(obligation, candidate) {
+            Err(SelectionError::Overflow) => {
+                assert!(self.query_mode == TraitQueryMode::Canonical);
+                return Err(SelectionError::Overflow);
+            },
+            Err(e) => Err(e),
+            Ok(candidate) => Ok(Some(candidate))
+        }
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -547,32 +603,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     // we can be sure it does not.
 
     /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
-    pub fn evaluate_obligation(&mut self,
-                               obligation: &PredicateObligation<'tcx>)
-                               -> bool
+    pub fn predicate_may_hold_fatal(&mut self,
+                                    obligation: &PredicateObligation<'tcx>)
+                                    -> bool
     {
-        debug!("evaluate_obligation({:?})",
+        debug!("predicate_may_hold_fatal({:?})",
                obligation);
 
-        self.probe(|this, _| {
-            this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
-                .may_apply()
-        })
+        // This fatal query is a stopgap that should only be used in standard mode,
+        // where we do not expect overflow to be propagated.
+        assert!(self.query_mode == TraitQueryMode::Standard);
+
+        self.evaluate_obligation_recursively(obligation)
+            .expect("Overflow should be caught earlier in standard query mode")
+            .may_apply()
     }
 
-    /// Evaluates whether the obligation `obligation` can be satisfied,
-    /// and returns `false` if not certain. However, this is not entirely
-    /// accurate if inference variables are involved.
-    pub fn evaluate_obligation_conservatively(&mut self,
-                                              obligation: &PredicateObligation<'tcx>)
-                                              -> bool
+    /// Evaluates whether the obligation `obligation` can be satisfied and returns
+    /// an `EvaluationResult`.
+    pub fn evaluate_obligation_recursively(&mut self,
+                                           obligation: &PredicateObligation<'tcx>)
+                                           -> Result<EvaluationResult, OverflowError>
     {
-        debug!("evaluate_obligation_conservatively({:?})",
-               obligation);
-
         self.probe(|this, _| {
             this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
-                == EvaluatedToOk
         })
     }
 
@@ -582,29 +636,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
                                                 stack: TraitObligationStackList<'o, 'tcx>,
                                                 predicates: I)
-                                                -> EvaluationResult
+                                                -> Result<EvaluationResult, OverflowError>
         where I : IntoIterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
     {
         let mut result = EvaluatedToOk;
         for obligation in predicates {
-            let eval = self.evaluate_predicate_recursively(stack, obligation);
+            let eval = self.evaluate_predicate_recursively(stack, obligation)?;
             debug!("evaluate_predicate_recursively({:?}) = {:?}",
                    obligation, eval);
             if let EvaluatedToErr = eval {
                 // fast-path - EvaluatedToErr is the top of the lattice,
                 // so we don't need to look on the other predicates.
-                return EvaluatedToErr;
+                return Ok(EvaluatedToErr);
             } else {
                 result = cmp::max(result, eval);
             }
         }
-        result
+        Ok(result)
     }
 
     fn evaluate_predicate_recursively<'o>(&mut self,
                                           previous_stack: TraitObligationStackList<'o, 'tcx>,
                                           obligation: &PredicateObligation<'tcx>)
-                                           -> EvaluationResult
+                                           -> Result<EvaluationResult, OverflowError>
     {
         debug!("evaluate_predicate_recursively({:?})",
                obligation);
@@ -620,11 +674,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 // does this code ever run?
                 match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
                     Some(Ok(InferOk { obligations, .. })) => {
-                        self.evaluate_predicates_recursively(previous_stack, &obligations);
-                        EvaluatedToOk
+                        self.evaluate_predicates_recursively(previous_stack, &obligations)
                     },
-                    Some(Err(_)) => EvaluatedToErr,
-                    None => EvaluatedToAmbig,
+                    Some(Err(_)) => Ok(EvaluatedToErr),
+                    None => Ok(EvaluatedToAmbig),
                 }
             }
 
@@ -636,21 +689,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     Some(obligations) =>
                         self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
                     None =>
-                        EvaluatedToAmbig,
+                        Ok(EvaluatedToAmbig),
                 }
             }
 
             ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
                 // we do not consider region relationships when
                 // evaluating trait matches
-                EvaluatedToOk
+                Ok(EvaluatedToOk)
             }
 
             ty::Predicate::ObjectSafe(trait_def_id) => {
                 if self.tcx().is_object_safe(trait_def_id) {
-                    EvaluatedToOk
+                    Ok(EvaluatedToOk)
                 } else {
-                    EvaluatedToErr
+                    Ok(EvaluatedToErr)
                 }
             }
 
@@ -668,10 +721,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         result
                     }
                     Ok(None) => {
-                        EvaluatedToAmbig
+                        Ok(EvaluatedToAmbig)
                     }
                     Err(_) => {
-                        EvaluatedToErr
+                        Ok(EvaluatedToErr)
                     }
                 }
             }
@@ -680,13 +733,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 match self.infcx.closure_kind(closure_def_id, closure_substs) {
                     Some(closure_kind) => {
                         if closure_kind.extends(kind) {
-                            EvaluatedToOk
+                            Ok(EvaluatedToOk)
                         } else {
-                            EvaluatedToErr
+                            Ok(EvaluatedToErr)
                         }
                     }
                     None => {
-                        EvaluatedToAmbig
+                        Ok(EvaluatedToAmbig)
                     }
                 }
             }
@@ -707,16 +760,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                 promoted: None
                             };
                             match self.tcx().const_eval(param_env.and(cid)) {
-                                Ok(_) => EvaluatedToOk,
-                                Err(_) => EvaluatedToErr
+                                Ok(_) => Ok(EvaluatedToOk),
+                                Err(_) => Ok(EvaluatedToErr)
                             }
                         } else {
-                            EvaluatedToErr
+                            Ok(EvaluatedToErr)
                         }
                     }
                     None => {
                         // Inference variables still left in param_env or substs.
-                        EvaluatedToAmbig
+                        Ok(EvaluatedToAmbig)
                     }
                 }
             }
@@ -726,7 +779,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_trait_predicate_recursively<'o>(&mut self,
                                                 previous_stack: TraitObligationStackList<'o, 'tcx>,
                                                 mut obligation: TraitObligation<'tcx>)
-                                                -> EvaluationResult
+                                                -> Result<EvaluationResult, OverflowError>
     {
         debug!("evaluate_trait_predicate_recursively({:?})",
                obligation);
@@ -745,22 +798,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             debug!("CACHE HIT: EVAL({:?})={:?}",
                    fresh_trait_ref,
                    result);
-            return result;
+            return Ok(result);
         }
 
         let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
+        let result = result?;
 
         debug!("CACHE MISS: EVAL({:?})={:?}",
                fresh_trait_ref,
                result);
         self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
 
-        result
+        Ok(result)
     }
 
     fn evaluate_stack<'o>(&mut self,
                           stack: &TraitObligationStack<'o, 'tcx>)
-                          -> EvaluationResult
+                          -> Result<EvaluationResult, OverflowError>
     {
         // In intercrate mode, whenever any of the types are unbound,
         // there can always be an impl. Even if there are no impls in
@@ -815,7 +869,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     }
                 }
             }
-            return EvaluatedToAmbig;
+            return Ok(EvaluatedToAmbig);
         }
         if unbound_input_types &&
               stack.iter().skip(1).any(
@@ -825,7 +879,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         {
             debug!("evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
                    stack.fresh_trait_ref);
-            return EvaluatedToUnknown;
+            return Ok(EvaluatedToUnknown);
         }
 
         // If there is any previous entry on the stack that precisely
@@ -860,18 +914,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             if self.coinductive_match(cycle) {
                 debug!("evaluate_stack({:?}) --> recursive, coinductive",
                        stack.fresh_trait_ref);
-                return EvaluatedToOk;
+                return Ok(EvaluatedToOk);
             } else {
                 debug!("evaluate_stack({:?}) --> recursive, inductive",
                        stack.fresh_trait_ref);
-                return EvaluatedToRecur;
+                return Ok(EvaluatedToRecur);
             }
         }
 
         match self.candidate_from_obligation(stack) {
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
-            Ok(None) => EvaluatedToAmbig,
-            Err(..) => EvaluatedToErr
+            Ok(None) => Ok(EvaluatedToAmbig),
+            Err(Overflow) => Err(OverflowError),
+            Err(..) => Ok(EvaluatedToErr)
         }
     }
 
@@ -909,7 +964,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_candidate<'o>(&mut self,
                               stack: &TraitObligationStack<'o, 'tcx>,
                               candidate: &SelectionCandidate<'tcx>)
-                              -> EvaluationResult
+                              -> Result<EvaluationResult, OverflowError>
     {
         debug!("evaluate_candidate: depth={} candidate={:?}",
                stack.obligation.recursion_depth, candidate);
@@ -921,12 +976,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         stack.list(),
                         selection.nested_obligations().iter())
                 }
-                Err(..) => EvaluatedToErr
+                Err(..) => Ok(EvaluatedToErr)
             }
-        });
+        })?;
         debug!("evaluate_candidate: depth={} result={:?}",
                stack.obligation.recursion_depth, result);
-        result
+        Ok(result)
     }
 
     fn check_evaluation_cache(&self,
@@ -1000,7 +1055,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         // not update) the cache.
         let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
         if stack.obligation.recursion_depth >= recursion_limit {
-            self.infcx().report_overflow_error(&stack.obligation, true);
+            match self.query_mode {
+                TraitQueryMode::Standard => {
+                    self.infcx().report_overflow_error(&stack.obligation, true);
+                },
+                TraitQueryMode::Canonical => {
+                    return Err(Overflow);
+                },
+            }
         }
 
         // Check the cache. Note that we skolemize the trait-ref
@@ -1081,9 +1143,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     debug!("evaluate_stack: intercrate_ambiguity_causes is some");
                     // Heuristics: show the diagnostics when there are no candidates in crate.
                     if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                        if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
-                            !self.evaluate_candidate(stack, &c).may_apply()
-                        }) {
+                        let no_candidates_apply =
+                            candidate_set
+                            .vec
+                            .iter()
+                            .map(|c| self.evaluate_candidate(stack, &c))
+                            .collect::<Result<Vec<_>, OverflowError>>()?
+                            .iter()
+                            .all(|r| !r.may_apply());
+                        if !candidate_set.ambiguous && no_candidates_apply {
                             let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
                             let self_ty = trait_ref.self_ty();
                             let trait_desc = trait_ref.to_string();
@@ -1151,18 +1219,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         }
 
         // Winnow, but record the exact outcome of evaluation, which
-        // is needed for specialization.
-        let mut candidates: Vec<_> = candidates.into_iter().filter_map(|c| {
-            let eval = self.evaluate_candidate(stack, &c);
-            if eval.may_apply() {
-                Some(EvaluatedCandidate {
+        // is needed for specialization. Propagate overflow if it occurs.
+        let candidates: Result<Vec<Option<EvaluatedCandidate>>, _> = candidates
+            .into_iter()
+            .map(|c| match self.evaluate_candidate(stack, &c) {
+                Ok(eval) if eval.may_apply() => Ok(Some(EvaluatedCandidate {
                     candidate: c,
                     evaluation: eval,
-                })
-            } else {
-                None
-            }
-        }).collect();
+                })),
+                Ok(_) => Ok(None),
+                Err(OverflowError) => Err(Overflow),
+            })
+            .collect();
+
+        let mut candidates: Vec<EvaluatedCandidate> =
+            candidates?.into_iter().filter_map(|c| c).collect();
 
         // If there are STILL multiple candidate, we can further
         // reduce the list by dropping duplicates -- including
@@ -1537,12 +1608,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let matching_bounds =
             all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
 
-        let matching_bounds =
-            matching_bounds.filter(
-                |bound| self.evaluate_where_clause(stack, bound.clone()).may_apply());
-
-        let param_candidates =
-            matching_bounds.map(|bound| ParamCandidate(bound));
+        // keep only those bounds which may apply, and propagate overflow if it occurs
+        let mut param_candidates = vec![];
+        for bound in matching_bounds {
+            let wc = self.evaluate_where_clause(stack, bound.clone())?;
+            if wc.may_apply() {
+                param_candidates.push(ParamCandidate(bound));
+            }
+        }
 
         candidates.vec.extend(param_candidates);
 
@@ -1552,14 +1625,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_where_clause<'o>(&mut self,
                                  stack: &TraitObligationStack<'o, 'tcx>,
                                  where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                                 -> EvaluationResult
+                                 -> Result<EvaluationResult, OverflowError>
     {
         self.probe(move |this, _| {
             match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
                 Ok(obligations) => {
                     this.evaluate_predicates_recursively(stack.list(), obligations.iter())
                 }
-                Err(()) => EvaluatedToErr
+                Err(()) => Ok(EvaluatedToErr)
             }
         })
     }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 1e3e4160de1..d7e42655bbb 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -177,6 +177,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
             super::ConstEvalFailure(ref err) => {
                 tcx.lift(err).map(super::ConstEvalFailure)
             }
+            super::Overflow => bug!() // FIXME: ape ConstEvalFailure?
         }
     }
 }
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 4f49b159ad3..c28fcfe8805 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -34,7 +34,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
 use mir::{self, Mir, interpret};
 use mir::interpret::{Value, PrimVal};
-use ty::subst::{Kind, Substs};
+use ty::subst::{Kind, Substs, Subst};
 use ty::ReprOptions;
 use ty::Instance;
 use traits;
@@ -2328,7 +2328,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
         let adt_def = self.adt_def(def_id);
-        let substs = self.mk_substs(iter::once(Kind::from(ty)));
+        let generics = self.generics_of(def_id);
+        let mut substs = vec![Kind::from(ty)];
+        // Add defaults for other generic params if there are some.
+        for def in generics.types.iter().skip(1) {
+            assert!(def.has_default);
+            let ty = self.type_of(def.def_id).subst(self, &substs);
+            substs.push(ty.into());
+        }
+        let substs = self.mk_substs(substs.into_iter());
         self.mk_ty(TyAdt(adt_def, substs))
     }
 
@@ -2471,7 +2479,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(0, keywords::SelfType.name().as_str())
+        self.mk_param(0, keywords::SelfType.name().as_interned_str())
     }
 
     pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index eb06852c65d..650ac4e6f6d 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -43,8 +43,8 @@ use middle::const_val::ConstVal;
 use hir::def_id::DefId;
 use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
 
+use rustc_data_structures::lazy_btree_map::LazyBTreeMap;
 use std::fmt;
-use std::collections::BTreeMap;
 use util::nodemap::FxHashSet;
 
 /// The TypeFoldable trait is implemented for every type that can be folded.
@@ -334,7 +334,7 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     current_depth: u32,
     fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
-    map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>
+    map: LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -349,7 +349,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn replace_late_bound_regions<T,F>(self,
         value: &Binder<T>,
         mut f: F)
-        -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+        -> (T, LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               T : TypeFoldable<'tcx>,
     {
@@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> {
             tcx,
             current_depth: 1,
             fld_r,
-            map: BTreeMap::default()
+            map: LazyBTreeMap::default()
         }
     }
 }
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 2819141c81b..752b7f69a6a 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -14,7 +14,7 @@ use ty::{self, Ty, TyCtxt};
 use middle::cstore::{ExternCrate, ExternCrateSource};
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 
 use std::cell::Cell;
 
@@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         let visible_parent_map = self.visible_parent_map(LOCAL_CRATE);
 
-        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<InternedString>::new());
+        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<LocalInternedString>::new());
         loop {
             // If `cur_def` is a direct or injected extern crate, push the path to the crate
             // followed by the path to the item within the crate and return.
@@ -168,8 +168,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
 
             let data = cur_def_key.disambiguated_data.data;
-            let symbol =
-                data.get_opt_name().unwrap_or_else(|| Symbol::intern("<unnamed>").as_str());
+            let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
+                Symbol::intern("<unnamed>").as_str()
+            });
             cur_path.push(symbol);
 
             match visible_parent_map.get(&cur_def) {
@@ -221,7 +222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::GlobalMetaData(..) => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
-                buffer.push(&data.as_interned_str());
+                buffer.push(&data.as_interned_str().as_symbol().as_str());
             }
             DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index 735fe06560f..57c8c4f34e7 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -9,24 +9,45 @@
 // except according to those terms.
 
 use dep_graph::SerializedDepNodeIndex;
+use dep_graph::DepNode;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use mir::interpret::{GlobalId};
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
 use ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::maps::queries;
+use ty::maps::Query;
+use ty::maps::QueryMap;
 
 use std::hash::Hash;
+use std::fmt::Debug;
 use syntax_pos::symbol::InternedString;
+use rustc_data_structures::sync::Lock;
+use rustc_data_structures::stable_hasher::HashStable;
+use ich::StableHashingContext;
 
 /// Query configuration and description traits.
 
-pub trait QueryConfig {
-    type Key: Eq + Hash + Clone;
-    type Value;
+pub trait QueryConfig<'tcx> {
+    const NAME: &'static str;
+
+    type Key: Eq + Hash + Clone + Debug;
+    type Value: Clone + for<'a> HashStable<StableHashingContext<'a>>;
+
+    fn query(key: Self::Key) -> Query<'tcx>;
+
+    // Don't use this method to access query results, instead use the methods on TyCtxt
+    fn query_map<'a>(tcx: TyCtxt<'a, 'tcx, '_>) -> &'a Lock<QueryMap<'tcx, Self>>;
+
+    fn to_dep_node(tcx: TyCtxt<'_, 'tcx, '_>, key: &Self::Key) -> DepNode;
+
+    // Don't use this method to compute query results, instead use the methods on TyCtxt
+    fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value;
+
+    fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value;
 }
 
-pub(super) trait QueryDescription<'tcx>: QueryConfig {
+pub trait QueryDescription<'tcx>: QueryConfig<'tcx> {
     fn describe(tcx: TyCtxt, key: Self::Key) -> String;
 
     #[inline]
@@ -41,7 +62,7 @@ pub(super) trait QueryDescription<'tcx>: QueryConfig {
     }
 }
 
-impl<'tcx, M: QueryConfig<Key=DefId>> QueryDescription<'tcx> for M {
+impl<'tcx, M: QueryConfig<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
     default fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         if !tcx.sess.verbose() {
             format!("processing `{}`", tcx.item_path_str(def_id))
@@ -73,6 +94,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_region
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
+    fn describe(_tcx: TyCtxt, goal: CanonicalPredicateGoal<'tcx>) -> String {
+        format!("evaluating trait selection obligation `{}`", goal.value.value)
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
     fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
         format!("computing whether `{}` is `Copy`", env.value)
diff --git a/src/librustc/ty/maps/job.rs b/src/librustc/ty/maps/job.rs
index 374406158c1..3b6af018d6b 100644
--- a/src/librustc/ty/maps/job.rs
+++ b/src/librustc/ty/maps/job.rs
@@ -17,13 +17,10 @@ use ty::context::TyCtxt;
 use errors::Diagnostic;
 
 /// Indicates the state of a query for a given key in a query map
-pub(super) enum QueryResult<'tcx, T> {
+pub(super) enum QueryResult<'tcx> {
     /// An already executing query. The query job can be used to await for its completion
     Started(Lrc<QueryJob<'tcx>>),
 
-    /// The query is complete and produced `T`
-    Complete(T),
-
     /// The query panicked. Queries trying to wait on this will raise a fatal error / silently panic
     Poisoned,
 }
diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs
index 72f2cb49abc..da29f23589e 100644
--- a/src/librustc/ty/maps/keys.rs
+++ b/src/librustc/ty/maps/keys.rs
@@ -11,7 +11,7 @@
 //! Defines the set of legal keys that can be used in queries.
 
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
@@ -200,3 +200,13 @@ impl<'tcx> Key for CanonicalTyGoal<'tcx> {
         DUMMY_SP
     }
 }
+
+impl<'tcx> Key for CanonicalPredicateGoal<'tcx> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+
+    fn default_span(&self, _tcx: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index f5cb3643de8..57223a3c7b2 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use dep_graph::{DepConstructor, DepNode};
-use errors::DiagnosticBuilder;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use hir::def::{Def, Export};
 use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs};
@@ -32,8 +31,9 @@ use mir;
 use mir::interpret::{GlobalId};
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
-use traits::Vtable;
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution};
+use traits::{self, Vtable};
+use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
+                    CanonicalTyGoal, NoSolution};
 use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
@@ -42,7 +42,7 @@ use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use ty::steal::Steal;
 use ty::subst::Substs;
 use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
-use util::common::{profq_msg, ErrorReported, ProfileQueriesMsg};
+use util::common::{ErrorReported};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_target::spec::PanicStrategy;
@@ -67,7 +67,6 @@ pub use self::plumbing::force_from_dep_node;
 
 mod job;
 pub use self::job::{QueryJob, QueryInfo};
-use self::job::QueryResult;
 
 mod keys;
 pub use self::keys::Key;
@@ -433,6 +432,12 @@ define_maps! { <'tcx>
         NoSolution,
     >,
 
+    /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
+    /// `infcx.predicate_must_hold()` instead.
+    [] fn evaluate_obligation: EvaluateObligation(
+        CanonicalPredicateGoal<'tcx>
+    ) -> Result<traits::EvaluationResult, traits::OverflowError>,
+
     [] fn substitute_normalize_and_test_predicates:
         substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
 
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
index f88e33c708e..cea2a03fd53 100644
--- a/src/librustc/ty/maps/on_disk_cache.rs
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -30,7 +30,6 @@ use syntax::codemap::{CodeMap, StableFilemapId};
 use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap};
 use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
 use ty;
-use ty::maps::job::QueryResult;
 use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use ty::context::TyCtxt;
 use util::common::time;
@@ -239,14 +238,12 @@ impl<'sess> OnDiskCache<'sess> {
                 encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
 
                 // const eval is special, it only encodes successfully evaluated constants
-                use ty::maps::plumbing::GetCacheInternal;
-                for (key, entry) in const_eval::get_cache_internal(tcx).map.iter() {
+                use ty::maps::QueryConfig;
+                let map = const_eval::query_map(tcx).borrow();
+                assert!(map.active.is_empty());
+                for (key, entry) in map.results.iter() {
                     use ty::maps::config::QueryDescription;
                     if const_eval::cache_on_disk(key.clone()) {
-                        let entry = match *entry {
-                            QueryResult::Complete(ref v) => v,
-                            _ => panic!("incomplete query"),
-                        };
                         if let Ok(ref value) = entry.value {
                             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
@@ -1124,7 +1121,7 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               encoder: &mut CacheEncoder<'enc, 'a, 'tcx, E>,
                                               query_result_index: &mut EncodedQueryResultIndex)
                                               -> Result<(), E::Error>
-    where Q: super::plumbing::GetCacheInternal<'tcx>,
+    where Q: super::config::QueryDescription<'tcx>,
           E: 'enc + TyEncoder,
           Q::Value: Encodable,
 {
@@ -1133,12 +1130,10 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     time(tcx.sess, desc, || {
 
-    for (key, entry) in Q::get_cache_internal(tcx).map.iter() {
+    let map = Q::query_map(tcx).borrow();
+    assert!(map.active.is_empty());
+    for (key, entry) in map.results.iter() {
         if Q::cache_on_disk(key.clone()) {
-            let entry = match *entry {
-                QueryResult::Complete(ref v) => v,
-                _ => panic!("incomplete query"),
-            };
             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
             // Record position of the cache entry
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 61a4eb58531..37950463f74 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -15,21 +15,29 @@
 use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
 use errors::DiagnosticBuilder;
 use errors::Level;
+use errors::Diagnostic;
+use errors::FatalError;
 use ty::tls;
 use ty::{TyCtxt};
 use ty::maps::Query;
+use ty::maps::config::QueryConfig;
 use ty::maps::config::QueryDescription;
-use ty::maps::job::{QueryResult, QueryInfo};
+use ty::maps::job::{QueryJob, QueryResult, QueryInfo};
 use ty::item_path;
 
+use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
+
 use rustc_data_structures::fx::{FxHashMap};
-use rustc_data_structures::sync::LockGuard;
-use std::marker::PhantomData;
+use rustc_data_structures::sync::{Lrc, Lock};
+use std::mem;
+use std::ptr;
+use std::collections::hash_map::Entry;
 use syntax_pos::Span;
+use syntax::codemap::DUMMY_SP;
 
-pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> {
-    phantom: PhantomData<(D, &'tcx ())>,
-    pub(super) map: FxHashMap<D::Key, QueryResult<'tcx, QueryValue<D::Value>>>,
+pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> {
+    pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
+    pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
 }
 
 pub(super) struct QueryValue<T> {
@@ -48,18 +56,166 @@ impl<T> QueryValue<T> {
     }
 }
 
-impl<'tcx, M: QueryDescription<'tcx>> QueryMap<'tcx, M> {
+impl<'tcx, M: QueryConfig<'tcx>> QueryMap<'tcx, M> {
     pub(super) fn new() -> QueryMap<'tcx, M> {
         QueryMap {
-            phantom: PhantomData,
-            map: FxHashMap(),
+            results: FxHashMap(),
+            active: FxHashMap(),
+        }
+    }
+}
+
+// If enabled, send a message to the profile-queries thread
+macro_rules! profq_msg {
+    ($tcx:expr, $msg:expr) => {
+        if cfg!(debug_assertions) {
+            if $tcx.sess.profile_queries() {
+                profq_msg($tcx.sess, $msg)
+            }
+        }
+    }
+}
+
+// If enabled, format a key using its debug string, which can be
+// expensive to compute (in terms of time).
+macro_rules! profq_query_msg {
+    ($query:expr, $tcx:expr, $key:expr) => {{
+        let msg = if cfg!(debug_assertions) {
+            if $tcx.sess.profile_queries_and_keys() {
+                Some(format!("{:?}", $key))
+            } else { None }
+        } else { None };
+        QueryMsg {
+            query: $query,
+            msg,
+        }
+    }}
+}
+
+/// A type representing the responsibility to execute the job in the `job` field.
+/// This will poison the relevant query if dropped.
+pub(super) struct JobOwner<'a, 'tcx: 'a, Q: QueryDescription<'tcx> + 'a> {
+    map: &'a Lock<QueryMap<'tcx, Q>>,
+    key: Q::Key,
+    job: Lrc<QueryJob<'tcx>>,
+}
+
+impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
+    /// Either gets a JobOwner corresponding the the query, allowing us to
+    /// start executing the query, or it returns with the result of the query.
+    /// If the query is executing elsewhere, this will wait for it.
+    /// If the query panicked, this will silently panic.
+    pub(super) fn try_get(
+        tcx: TyCtxt<'a, 'tcx, '_>,
+        span: Span,
+        key: &Q::Key,
+    ) -> TryGetJob<'a, 'tcx, Q> {
+        let map = Q::query_map(tcx);
+        loop {
+            let mut lock = map.borrow_mut();
+            if let Some(value) = lock.results.get(key) {
+                profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                let result = Ok((value.value.clone(), value.index));
+                return TryGetJob::JobCompleted(result);
+            }
+            let job = match lock.active.entry((*key).clone()) {
+                Entry::Occupied(entry) => {
+                    match *entry.get() {
+                        QueryResult::Started(ref job) => job.clone(),
+                        QueryResult::Poisoned => FatalError.raise(),
+                    }
+                }
+                Entry::Vacant(entry) => {
+                    // No job entry for this query. Return a new one to be started later
+                    return tls::with_related_context(tcx, |icx| {
+                        let info = QueryInfo {
+                            span,
+                            query: Q::query(key.clone()),
+                        };
+                        let job = Lrc::new(QueryJob::new(info, icx.query.clone()));
+                        let owner = JobOwner {
+                            map,
+                            job: job.clone(),
+                            key: (*key).clone(),
+                        };
+                        entry.insert(QueryResult::Started(job));
+                        TryGetJob::NotYetStarted(owner)
+                    })
+                }
+            };
+            mem::drop(lock);
+
+            if let Err(cycle) = job.await(tcx, span) {
+                return TryGetJob::JobCompleted(Err(cycle));
+            }
+        }
+    }
+
+    /// Completes the query by updating the query map with the `result`,
+    /// signals the waiter and forgets the JobOwner, so it won't poison the query
+    pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) {
+        // We can move out of `self` here because we `mem::forget` it below
+        let key = unsafe { ptr::read(&self.key) };
+        let job = unsafe { ptr::read(&self.job) };
+        let map = self.map;
+
+        // Forget ourself so our destructor won't poison the query
+        mem::forget(self);
+
+        let value = QueryValue::new(result.clone(), dep_node_index);
+        {
+            let mut lock = map.borrow_mut();
+            lock.active.remove(&key);
+            lock.results.insert(key, value);
         }
+
+        job.signal_complete();
+    }
+
+    /// Executes a job by changing the ImplicitCtxt to point to the
+    /// new query job while it executes. It returns the diagnostics
+    /// captured during execution and the actual result.
+    pub(super) fn start<'lcx, F, R>(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, 'lcx>,
+        compute: F)
+    -> (R, Vec<Diagnostic>)
+    where
+        F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R
+    {
+        // The TyCtxt stored in TLS has the same global interner lifetime
+        // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
+        // when accessing the ImplicitCtxt
+        let r = tls::with_related_context(tcx, move |current_icx| {
+            // Update the ImplicitCtxt to point to our new query job
+            let new_icx = tls::ImplicitCtxt {
+                tcx,
+                query: Some(self.job.clone()),
+                layout_depth: current_icx.layout_depth,
+                task: current_icx.task,
+            };
+
+            // Use the ImplicitCtxt while we execute the query
+            tls::enter_context(&new_icx, |_| {
+                compute(tcx)
+            })
+        });
+
+        // Extract the diagnostic from the job
+        let diagnostics = mem::replace(&mut *self.job.diagnostics.lock(), Vec::new());
+
+        (r, diagnostics)
     }
 }
 
-pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
-    fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                              -> LockGuard<'a, QueryMap<'tcx, Self>>;
+impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
+    fn drop(&mut self) {
+        // Poison the query so jobs waiting on it panic
+        self.map.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned);
+        // Also signal the completion of the job, so waiters
+        // will continue execution
+        self.job.signal_complete();
+    }
 }
 
 #[derive(Clone)]
@@ -70,14 +226,14 @@ pub(super) struct CycleError<'tcx> {
 }
 
 /// The result of `try_get_lock`
-pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
+pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> {
     /// The query is not yet started. Contains a guard to the map eventually used to start it.
-    NotYetStarted(LockGuard<'a, QueryMap<'tcx, D>>),
+    NotYetStarted(JobOwner<'a, 'tcx, D>),
 
     /// The query was already completed.
     /// Returns the result of the query and its dep node index
     /// if it succeeded or a cycle error if it failed
-    JobCompleted(Result<(T, DepNodeIndex), CycleError<'tcx>>),
+    JobCompleted(Result<(D::Value, DepNodeIndex), CycleError<'tcx>>),
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -180,28 +336,277 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
         }
     }
-}
 
-// If enabled, send a message to the profile-queries thread
-macro_rules! profq_msg {
-    ($tcx:expr, $msg:expr) => {
-        if cfg!(debug_assertions) {
-            if $tcx.sess.profile_queries() {
-                profq_msg($tcx.sess, $msg)
+    fn try_get_with<Q: QueryDescription<'gcx>>(
+        self,
+        span: Span,
+        key: Q::Key)
+    -> Result<Q::Value, CycleError<'gcx>>
+    {
+        debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
+               Q::NAME,
+               key,
+               span);
+
+        profq_msg!(self,
+            ProfileQueriesMsg::QueryBegin(
+                span.data(),
+                profq_query_msg!(Q::NAME, self, key),
+            )
+        );
+
+        let job = match JobOwner::try_get(self, span, &key) {
+            TryGetJob::NotYetStarted(job) => job,
+            TryGetJob::JobCompleted(result) => {
+                return result.map(|(v, index)| {
+                    self.dep_graph.read_index(index);
+                    v
+                })
             }
+        };
+
+        // Fast path for when incr. comp. is off. `to_dep_node` is
+        // expensive for some DepKinds.
+        if !self.dep_graph.is_fully_enabled() {
+            let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
+            return self.force_query_with_job::<Q>(key, job, null_dep_node).map(|(v, _)| v);
+        }
+
+        let dep_node = Q::to_dep_node(self, &key);
+
+        if dep_node.kind.is_anon() {
+            profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+
+            let res = job.start(self, |tcx| {
+                tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                    Q::compute(tcx.global_tcx(), key)
+                })
+            });
+
+            profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
+            let ((result, dep_node_index), diagnostics) = res;
+
+            self.dep_graph.read_index(dep_node_index);
+
+            self.on_disk_query_result_cache
+                .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
+
+            job.complete(&result, dep_node_index);
+
+            return Ok(result);
+        }
+
+        if !dep_node.kind.is_input() {
+            if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
+                profq_msg!(self, ProfileQueriesMsg::CacheHit);
+                return self.load_from_disk_and_cache_in_memory::<Q>(key,
+                                                                    job,
+                                                                    dep_node_index,
+                                                                    &dep_node)
+            }
+        }
+
+        match self.force_query_with_job::<Q>(key, job, dep_node) {
+            Ok((result, dep_node_index)) => {
+                self.dep_graph.read_index(dep_node_index);
+                Ok(result)
+            }
+            Err(e) => Err(e)
         }
     }
-}
 
-// If enabled, format a key using its debug string, which can be
-// expensive to compute (in terms of time).
-macro_rules! profq_key {
-    ($tcx:expr, $key:expr) => {
-        if cfg!(debug_assertions) {
-            if $tcx.sess.profile_queries_and_keys() {
-                Some(format!("{:?}", $key))
-            } else { None }
-        } else { None }
+    fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
+        self,
+        key: Q::Key,
+        job: JobOwner<'a, 'gcx, Q>,
+        dep_node_index: DepNodeIndex,
+        dep_node: &DepNode
+    ) -> Result<Q::Value, CycleError<'gcx>>
+    {
+        // Note this function can be called concurrently from the same query
+        // We must ensure that this is handled correctly
+
+        debug_assert!(self.dep_graph.is_green(dep_node));
+
+        // First we try to load the result from the on-disk cache
+        let result = if Q::cache_on_disk(key.clone()) &&
+                        self.sess.opts.debugging_opts.incremental_queries {
+            let prev_dep_node_index =
+                self.dep_graph.prev_dep_node_index_of(dep_node);
+            let result = Q::try_load_from_disk(self.global_tcx(),
+                                                    prev_dep_node_index);
+
+            // We always expect to find a cached result for things that
+            // can be forced from DepNode.
+            debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
+                            result.is_some(),
+                            "Missing on-disk cache entry for {:?}",
+                            dep_node);
+            result
+        } else {
+            // Some things are never cached on disk.
+            None
+        };
+
+        let result = if let Some(result) = result {
+            result
+        } else {
+            // We could not load a result from the on-disk cache, so
+            // recompute.
+
+            // The diagnostics for this query have already been
+            // promoted to the current session during
+            // try_mark_green(), so we can ignore them here.
+            let (result, _) = job.start(self, |tcx| {
+                // The dep-graph for this computation is already in
+                // place
+                tcx.dep_graph.with_ignore(|| {
+                    Q::compute(tcx, key)
+                })
+            });
+            result
+        };
+
+        // If -Zincremental-verify-ich is specified, re-hash results from
+        // the cache and make sure that they have the expected fingerprint.
+        if self.sess.opts.debugging_opts.incremental_verify_ich {
+            use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+            use ich::Fingerprint;
+
+            assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
+                    self.dep_graph.prev_fingerprint_of(dep_node),
+                    "Fingerprint for green query instance not loaded \
+                        from cache: {:?}", dep_node);
+
+            debug!("BEGIN verify_ich({:?})", dep_node);
+            let mut hcx = self.create_stable_hashing_context();
+            let mut hasher = StableHasher::new();
+
+            result.hash_stable(&mut hcx, &mut hasher);
+
+            let new_hash: Fingerprint = hasher.finish();
+            debug!("END verify_ich({:?})", dep_node);
+
+            let old_hash = self.dep_graph.fingerprint_of(dep_node_index);
+
+            assert!(new_hash == old_hash, "Found unstable fingerprints \
+                for {:?}", dep_node);
+        }
+
+        if self.sess.opts.debugging_opts.query_dep_graph {
+            self.dep_graph.mark_loaded_from_cache(dep_node_index, true);
+        }
+
+        job.complete(&result, dep_node_index);
+
+        Ok(result)
+    }
+
+    fn force_query_with_job<Q: QueryDescription<'gcx>>(
+        self,
+        key: Q::Key,
+        job: JobOwner<'_, 'gcx, Q>,
+        dep_node: DepNode)
+    -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> {
+        // If the following assertion triggers, it can have two reasons:
+        // 1. Something is wrong with DepNode creation, either here or
+        //    in DepGraph::try_mark_green()
+        // 2. Two distinct query keys get mapped to the same DepNode
+        //    (see for example #48923)
+        assert!(!self.dep_graph.dep_node_exists(&dep_node),
+                "Forcing query with already existing DepNode.\n\
+                    - query-key: {:?}\n\
+                    - dep-node: {:?}",
+                key, dep_node);
+
+        profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+        let res = job.start(self, |tcx| {
+            if dep_node.kind.is_eval_always() {
+                tcx.dep_graph.with_eval_always_task(dep_node,
+                                                    tcx,
+                                                    key,
+                                                    Q::compute)
+            } else {
+                tcx.dep_graph.with_task(dep_node,
+                                        tcx,
+                                        key,
+                                        Q::compute)
+            }
+        });
+        profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
+
+        let ((result, dep_node_index), diagnostics) = res;
+
+        if self.sess.opts.debugging_opts.query_dep_graph {
+            self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
+        }
+
+        if dep_node.kind != ::dep_graph::DepKind::Null {
+            self.on_disk_query_result_cache
+                .store_diagnostics(dep_node_index, diagnostics);
+        }
+
+        job.complete(&result, dep_node_index);
+
+        Ok((result, dep_node_index))
+    }
+
+    /// Ensure that either this query has all green inputs or been executed.
+    /// Executing query::ensure(D) is considered a read of the dep-node D.
+    ///
+    /// This function is particularly useful when executing passes for their
+    /// side-effects -- e.g., in order to report errors for erroneous programs.
+    ///
+    /// Note: The optimization is only available during incr. comp.
+    pub fn ensure_query<Q: QueryDescription<'gcx>>(self, key: Q::Key) -> () {
+        let dep_node = Q::to_dep_node(self, &key);
+
+        // Ensuring an "input" or anonymous query makes no sense
+        assert!(!dep_node.kind.is_anon());
+        assert!(!dep_node.kind.is_input());
+        if self.try_mark_green_and_read(&dep_node).is_none() {
+            // A None return from `try_mark_green_and_read` means that this is either
+            // a new dep node or that the dep node has already been marked red.
+            // Either way, we can't call `dep_graph.read()` as we don't have the
+            // DepNodeIndex. We must invoke the query itself. The performance cost
+            // this introduces should be negligible as we'll immediately hit the
+            // in-memory cache, or another query down the line will.
+            let _ = self.get_query::<Q>(DUMMY_SP, key);
+        }
+    }
+
+    #[allow(dead_code)]
+    fn force_query<Q: QueryDescription<'gcx>>(
+        self,
+        key: Q::Key,
+        span: Span,
+        dep_node: DepNode
+    ) -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> {
+        // We may be concurrently trying both execute and force a query
+        // Ensure that only one of them runs the query
+        let job = match JobOwner::try_get(self, span, &key) {
+            TryGetJob::NotYetStarted(job) => job,
+            TryGetJob::JobCompleted(result) => return result,
+        };
+        self.force_query_with_job::<Q>(key, job, dep_node)
+    }
+
+    pub fn try_get_query<Q: QueryDescription<'gcx>>(
+        self,
+        span: Span,
+        key: Q::Key
+    ) -> Result<Q::Value, DiagnosticBuilder<'a>> {
+        match self.try_get_with::<Q>(span, key) {
+            Ok(e) => Ok(e),
+            Err(e) => Err(self.report_cycle(e)),
+        }
+    }
+
+    pub fn get_query<Q: QueryDescription<'gcx>>(self, span: Span, key: Q::Key) -> Q::Value {
+        self.try_get_query::<Q>(span, key).unwrap_or_else(|mut e| {
+            e.emit();
+            Q::handle_cycle_error(self)
+        })
     }
 }
 
@@ -210,7 +615,7 @@ macro_rules! handle_cycle_error {
         Value::from_cycle_error($this.global_tcx())
     }};
     ([fatal_cycle$(, $modifiers:ident)*][$this:expr]) => {{
-        $this.tcx.sess.abort_if_errors();
+        $this.sess.abort_if_errors();
         unreachable!();
     }};
     ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => {
@@ -223,12 +628,7 @@ macro_rules! define_maps {
      $($(#[$attr:meta])*
        [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
 
-        use dep_graph::DepNodeIndex;
-        use std::mem;
-        use errors::Diagnostic;
-        use errors::FatalError;
-        use rustc_data_structures::sync::{Lock, LockGuard};
-        use rustc_data_structures::OnDrop;
+        use rustc_data_structures::sync::Lock;
 
         define_map_struct! {
             tcx: $tcx,
@@ -251,12 +651,6 @@ macro_rules! define_maps {
             $($(#[$attr])* $name($K)),*
         }
 
-        #[allow(bad_style)]
-        #[derive(Clone, Debug, PartialEq, Eq)]
-        pub enum QueryMsg {
-            $($name(Option<String>)),*
-        }
-
         impl<$tcx> Query<$tcx> {
             pub fn name(&self) -> &'static str {
                 match *self {
@@ -303,162 +697,38 @@ macro_rules! define_maps {
             })*
         }
 
-        $(impl<$tcx> QueryConfig for queries::$name<$tcx> {
+        $(impl<$tcx> QueryConfig<$tcx> for queries::$name<$tcx> {
             type Key = $K;
             type Value = $V;
-        }
 
-        impl<$tcx> GetCacheInternal<$tcx> for queries::$name<$tcx> {
-            fn get_cache_internal<'a>(tcx: TyCtxt<'a, $tcx, $tcx>)
-                                      -> LockGuard<'a, QueryMap<$tcx, Self>> {
-                tcx.maps.$name.borrow()
+            const NAME: &'static str = stringify!($name);
+
+            fn query(key: Self::Key) -> Query<'tcx> {
+                Query::$name(key)
             }
-        }
 
-        impl<'a, $tcx, 'lcx> queries::$name<$tcx> {
+            fn query_map<'a>(tcx: TyCtxt<'a, $tcx, '_>) -> &'a Lock<QueryMap<$tcx, Self>> {
+                &tcx.maps.$name
+            }
 
             #[allow(unused)]
-            fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode {
+            fn to_dep_node(tcx: TyCtxt<'_, $tcx, '_>, key: &Self::Key) -> DepNode {
                 use dep_graph::DepConstructor::*;
 
                 DepNode::new(tcx, $node(*key))
             }
 
-            /// Either get the lock of the query map, allowing us to
-            /// start executing the query, or it returns with the result of the query.
-            /// If the query already executed and panicked, this will fatal error / silently panic
-            fn try_get_lock(
-                tcx: TyCtxt<'a, $tcx, 'lcx>,
-                span: Span,
-                key: &$K
-            ) -> TryGetLock<'a, $tcx, $V, Self>
-            {
-                loop {
-                    let lock = tcx.maps.$name.borrow_mut();
-                    let job = if let Some(value) = lock.map.get(key) {
-                        match *value {
-                            QueryResult::Started(ref job) => Some(job.clone()),
-                            QueryResult::Complete(ref value) => {
-                                profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                                let result = Ok(((&value.value).clone(), value.index));
-                                return TryGetLock::JobCompleted(result);
-                            },
-                            QueryResult::Poisoned => FatalError.raise(),
-                        }
-                    } else {
-                        None
-                    };
-                    let job = if let Some(job) = job {
-                        job
-                    } else {
-                        return TryGetLock::NotYetStarted(lock);
-                    };
-                    mem::drop(lock);
-
-                    if let Err(cycle) = job.await(tcx, span) {
-                        return TryGetLock::JobCompleted(Err(cycle));
-                    }
-                }
+            fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value {
+                let provider = tcx.maps.providers[key.map_crate()].$name;
+                provider(tcx.global_tcx(), key)
             }
 
-            fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                            span: Span,
-                            key: $K)
-                            -> Result<$V, CycleError<$tcx>>
-            {
-                debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
-                       stringify!($name),
-                       key,
-                       span);
-
-                profq_msg!(tcx,
-                    ProfileQueriesMsg::QueryBegin(
-                        span.data(),
-                        QueryMsg::$name(profq_key!(tcx, key))
-                    )
-                );
-
-                /// Get the lock used to start the query or
-                /// return the result of the completed query
-                macro_rules! get_lock_or_return {
-                    () => {{
-                        match Self::try_get_lock(tcx, span, &key) {
-                            TryGetLock::NotYetStarted(lock) => lock,
-                            TryGetLock::JobCompleted(result) => {
-                                return result.map(|(v, index)| {
-                                    tcx.dep_graph.read_index(index);
-                                    v
-                                })
-                            }
-                        }
-                    }}
-                }
-
-                let mut lock = get_lock_or_return!();
-
-                // Fast path for when incr. comp. is off. `to_dep_node` is
-                // expensive for some DepKinds.
-                if !tcx.dep_graph.is_fully_enabled() {
-                    let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
-                    return Self::force_with_lock(tcx, key, span, lock, null_dep_node)
-                                .map(|(v, _)| v);
-                }
-
-                let dep_node = Self::to_dep_node(tcx, &key);
-
-                if dep_node.kind.is_anon() {
-                    profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
-
-                    let res = Self::start_job(tcx, span, key, lock, |tcx| {
-                        tcx.dep_graph.with_anon_task(dep_node.kind, || {
-                            Self::compute_result(tcx.global_tcx(), key)
-                        })
-                    })?;
-
-                    profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
-                    let (((result, dep_node_index), diagnostics), job) = res;
-
-                    tcx.dep_graph.read_index(dep_node_index);
-
-                    tcx.on_disk_query_result_cache
-                       .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
-
-                    let value = QueryValue::new(Clone::clone(&result), dep_node_index);
-
-                    tcx.maps
-                       .$name
-                       .borrow_mut()
-                       .map
-                       .insert(key, QueryResult::Complete(value));
-
-                    job.signal_complete();
-
-                    return Ok(result);
-                }
-
-                if !dep_node.kind.is_input() {
-                    // try_mark_green_and_read may force queries. So we must drop our lock here
-                    mem::drop(lock);
-                    if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) {
-                        profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                        return Self::load_from_disk_and_cache_in_memory(tcx,
-                                                                        key,
-                                                                        span,
-                                                                        dep_node_index,
-                                                                        &dep_node)
-                    }
-                    lock = get_lock_or_return!();
-                }
-
-                match Self::force_with_lock(tcx, key, span, lock, dep_node) {
-                    Ok((result, dep_node_index)) => {
-                        tcx.dep_graph.read_index(dep_node_index);
-                        Ok(result)
-                    }
-                    Err(e) => Err(e)
-                }
+            fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value {
+                handle_cycle_error!([$($modifiers)*][tcx])
             }
+        }
 
+        impl<'a, $tcx, 'lcx> queries::$name<$tcx> {
             /// Ensure that either this query has all green inputs or been executed.
             /// Executing query::ensure(D) is considered a read of the dep-node D.
             ///
@@ -467,282 +737,7 @@ macro_rules! define_maps {
             ///
             /// Note: The optimization is only available during incr. comp.
             pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () {
-                let dep_node = Self::to_dep_node(tcx, &key);
-
-                // Ensuring an "input" or anonymous query makes no sense
-                assert!(!dep_node.kind.is_anon());
-                assert!(!dep_node.kind.is_input());
-                if tcx.try_mark_green_and_read(&dep_node).is_none() {
-                    // A None return from `try_mark_green_and_read` means that this is either
-                    // a new dep node or that the dep node has already been marked red.
-                    // Either way, we can't call `dep_graph.read()` as we don't have the
-                    // DepNodeIndex. We must invoke the query itself. The performance cost
-                    // this introduces should be negligible as we'll immediately hit the
-                    // in-memory cache, or another query down the line will.
-                    let _ = tcx.$name(key);
-                }
-            }
-
-            /// Creates a job for the query and updates the query map indicating that it started.
-            /// Then it changes ImplicitCtxt to point to the new query job while it executes.
-            /// If the query panics, this updates the query map to indicate so.
-            fn start_job<F, R>(tcx: TyCtxt<'_, $tcx, 'lcx>,
-                               span: Span,
-                               key: $K,
-                               mut map: LockGuard<'_, QueryMap<$tcx, Self>>,
-                               compute: F)
-                -> Result<((R, Vec<Diagnostic>), Lrc<QueryJob<$tcx>>), CycleError<$tcx>>
-                where F: for<'b> FnOnce(TyCtxt<'b, $tcx, 'lcx>) -> R
-            {
-                let query = Query::$name(Clone::clone(&key));
-
-                let entry = QueryInfo {
-                    span,
-                    query,
-                };
-
-                // The TyCtxt stored in TLS has the same global interner lifetime
-                // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
-                // when accessing the ImplicitCtxt
-                let (r, job) = ty::tls::with_related_context(tcx, move |icx| {
-                    let job = Lrc::new(QueryJob::new(entry, icx.query.clone()));
-
-                    // Store the job in the query map and drop the lock to allow
-                    // others to wait it
-                    map.map.entry(key).or_insert(QueryResult::Started(job.clone()));
-                    mem::drop(map);
-
-                    let r = {
-                        let on_drop = OnDrop(|| {
-                            // Poison the query so jobs waiting on it panic
-                            tcx.maps
-                            .$name
-                            .borrow_mut()
-                            .map
-                            .insert(key, QueryResult::Poisoned);
-                            // Also signal the completion of the job, so waiters
-                            // will continue execution
-                            job.signal_complete();
-                        });
-
-                        // Update the ImplicitCtxt to point to our new query job
-                        let icx = ty::tls::ImplicitCtxt {
-                            tcx,
-                            query: Some(job.clone()),
-                            layout_depth: icx.layout_depth,
-                            task: icx.task,
-                        };
-
-                        // Use the ImplicitCtxt while we execute the query
-                        let r = ty::tls::enter_context(&icx, |icx| {
-                            compute(icx.tcx)
-                        });
-
-                        mem::forget(on_drop);
-
-                        r
-                    };
-
-                    (r, job)
-                });
-
-                // Extract the diagnostic from the job
-                let diagnostics: Vec<_> = mem::replace(&mut *job.diagnostics.lock(), Vec::new());
-
-                Ok(((r, diagnostics), job))
-            }
-
-            fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
-                let provider = tcx.maps.providers[key.map_crate()].$name;
-                provider(tcx.global_tcx(), key)
-            }
-
-            fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                                                  key: $K,
-                                                  span: Span,
-                                                  dep_node_index: DepNodeIndex,
-                                                  dep_node: &DepNode)
-                                                  -> Result<$V, CycleError<$tcx>>
-            {
-                // Note this function can be called concurrently from the same query
-                // We must ensure that this is handled correctly
-
-                debug_assert!(tcx.dep_graph.is_green(dep_node));
-
-                // First we try to load the result from the on-disk cache
-                let result = if Self::cache_on_disk(key) &&
-                                tcx.sess.opts.debugging_opts.incremental_queries {
-                    let prev_dep_node_index =
-                        tcx.dep_graph.prev_dep_node_index_of(dep_node);
-                    let result = Self::try_load_from_disk(tcx.global_tcx(),
-                                                          prev_dep_node_index);
-
-                    // We always expect to find a cached result for things that
-                    // can be forced from DepNode.
-                    debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
-                                  result.is_some(),
-                                  "Missing on-disk cache entry for {:?}",
-                                  dep_node);
-                    result
-                } else {
-                    // Some things are never cached on disk.
-                    None
-                };
-
-                let (result, job) = if let Some(result) = result {
-                    (result, None)
-                } else {
-                    // We could not load a result from the on-disk cache, so
-                    // recompute.
-
-                    // The diagnostics for this query have already been
-                    // promoted to the current session during
-                    // try_mark_green(), so we can ignore them here.
-                    let ((result, _), job) = Self::start_job(tcx,
-                                                             span,
-                                                             key,
-                                                             tcx.maps.$name.borrow_mut(),
-                                                             |tcx| {
-                        // The dep-graph for this computation is already in
-                        // place
-                        tcx.dep_graph.with_ignore(|| {
-                            Self::compute_result(tcx, key)
-                        })
-                    })?;
-                    (result, Some(job))
-                };
-
-                // If -Zincremental-verify-ich is specified, re-hash results from
-                // the cache and make sure that they have the expected fingerprint.
-                if tcx.sess.opts.debugging_opts.incremental_verify_ich {
-                    use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
-                    use ich::Fingerprint;
-
-                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) ==
-                            tcx.dep_graph.prev_fingerprint_of(dep_node),
-                            "Fingerprint for green query instance not loaded \
-                             from cache: {:?}", dep_node);
-
-                    debug!("BEGIN verify_ich({:?})", dep_node);
-                    let mut hcx = tcx.create_stable_hashing_context();
-                    let mut hasher = StableHasher::new();
-
-                    result.hash_stable(&mut hcx, &mut hasher);
-
-                    let new_hash: Fingerprint = hasher.finish();
-                    debug!("END verify_ich({:?})", dep_node);
-
-                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index);
-
-                    assert!(new_hash == old_hash, "Found unstable fingerprints \
-                        for {:?}", dep_node);
-                }
-
-                if tcx.sess.opts.debugging_opts.query_dep_graph {
-                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
-                }
-
-                let value = QueryValue::new(Clone::clone(&result), dep_node_index);
-
-                tcx.maps
-                   .$name
-                   .borrow_mut()
-                   .map
-                   .insert(key, QueryResult::Complete(value));
-
-                job.map(|j| j.signal_complete());
-
-                Ok(result)
-            }
-
-            #[allow(dead_code)]
-            fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                     key: $K,
-                     span: Span,
-                     dep_node: DepNode)
-                     -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
-                // We may be concurrently trying both execute and force a query
-                // Ensure that only one of them runs the query
-                let lock = match Self::try_get_lock(tcx, span, &key) {
-                    TryGetLock::NotYetStarted(lock) => lock,
-                    TryGetLock::JobCompleted(result) => return result,
-                };
-                Self::force_with_lock(tcx,
-                                      key,
-                                      span,
-                                      lock,
-                                      dep_node)
-            }
-
-            fn force_with_lock(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                               key: $K,
-                               span: Span,
-                               map: LockGuard<'_, QueryMap<$tcx, Self>>,
-                               dep_node: DepNode)
-                               -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
-                // If the following assertion triggers, it can have two reasons:
-                // 1. Something is wrong with DepNode creation, either here or
-                //    in DepGraph::try_mark_green()
-                // 2. Two distinct query keys get mapped to the same DepNode
-                //    (see for example #48923)
-                assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
-                        "Forcing query with already existing DepNode.\n\
-                          - query-key: {:?}\n\
-                          - dep-node: {:?}",
-                        key, dep_node);
-
-                profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
-                let res = Self::start_job(tcx,
-                                          span,
-                                          key,
-                                          map,
-                                          |tcx| {
-                    if dep_node.kind.is_eval_always() {
-                        tcx.dep_graph.with_eval_always_task(dep_node,
-                                                            tcx,
-                                                            key,
-                                                            Self::compute_result)
-                    } else {
-                        tcx.dep_graph.with_task(dep_node,
-                                                tcx,
-                                                key,
-                                                Self::compute_result)
-                    }
-                })?;
-                profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
-
-                let (((result, dep_node_index), diagnostics), job) = res;
-
-                if tcx.sess.opts.debugging_opts.query_dep_graph {
-                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false);
-                }
-
-                if dep_node.kind != ::dep_graph::DepKind::Null {
-                    tcx.on_disk_query_result_cache
-                       .store_diagnostics(dep_node_index, diagnostics);
-                }
-
-                let value = QueryValue::new(Clone::clone(&result), dep_node_index);
-
-                tcx.maps
-                   .$name
-                   .borrow_mut()
-                   .map
-                   .insert(key, QueryResult::Complete(value));
-
-                let job: Lrc<QueryJob> = job;
-
-                job.signal_complete();
-
-                Ok((result, dep_node_index))
-            }
-
-            pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-                           -> Result<$V, DiagnosticBuilder<'a>> {
-                match Self::try_get_with(tcx, span, key) {
-                    Ok(e) => Ok(e),
-                    Err(e) => Err(tcx.report_cycle(e)),
-                }
+                tcx.ensure_query::<queries::$name>(key);
             }
         })*
 
@@ -778,10 +773,7 @@ macro_rules! define_maps {
         impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
             $($(#[$attr])*
             pub fn $name(self, key: $K) -> $V {
-                queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
-                    e.emit();
-                    handle_cycle_error!([$($modifiers)*][self])
-                })
+                self.tcx.get_query::<queries::$name>(self.span, key)
             })*
         }
 
@@ -872,7 +864,6 @@ macro_rules! define_provider_struct {
 pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
                                            dep_node: &DepNode)
                                            -> bool {
-    use ty::maps::keys::Key;
     use hir::def_id::LOCAL_CRATE;
 
     // We must avoid ever having to call force_from_dep_node() for a
@@ -915,23 +906,14 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
             {
                 use $crate::util::common::{ProfileQueriesMsg, profq_msg};
 
-                // FIXME(eddyb) Get more valid Span's on queries.
-                // def_span guard is necessary to prevent a recursive loop,
-                // default_span calls def_span query internally.
-                let span = if stringify!($query) != "def_span" {
-                    $key.default_span(tcx)
-                } else {
-                    ::syntax_pos::DUMMY_SP
-                };
-
                 profq_msg!(tcx,
                     ProfileQueriesMsg::QueryBegin(
-                        span.data(),
-                        ::ty::maps::QueryMsg::$query(profq_key!(tcx, $key))
+                        DUMMY_SP.data(),
+                        profq_query_msg!(::ty::maps::queries::$query::NAME, tcx, $key),
                     )
                 );
 
-                match ::ty::maps::queries::$query::force(tcx, $key, span, *dep_node) {
+                match tcx.force_query::<::ty::maps::queries::$query>($key, DUMMY_SP, *dep_node) {
                     Ok(_) => {},
                     Err(e) => {
                         tcx.report_cycle(e).emit();
@@ -977,6 +959,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::NormalizeProjectionTy |
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::DropckOutlives |
+        DepKind::EvaluateObligation |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::InstanceDefSizeEstimate |
         DepKind::ProgramClausesForEnv |
diff --git a/src/librustc/ty/maps/values.rs b/src/librustc/ty/maps/values.rs
index 8d38d7dbbbb..d3d06248792 100644
--- a/src/librustc/ty/maps/values.rs
+++ b/src/librustc/ty/maps/values.rs
@@ -37,7 +37,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> {
 
 impl<'tcx> Value<'tcx> for ty::SymbolName {
     fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
-        ty::SymbolName { name: Symbol::intern("<error>").as_str() }
+        ty::SymbolName { name: Symbol::intern("<error>").as_interned_str() }
     }
 }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index de043668410..5a121d3edbe 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -51,7 +51,7 @@ use std::mem;
 use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::{Symbol, LocalInternedString, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
@@ -2031,7 +2031,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
-        match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
+        match tcx.try_get_query::<queries::adt_sized_constraint>(DUMMY_SP, self.did) {
             Ok(tys) => tys,
             Err(mut bug) => {
                 debug!("adt_sized_constraint: {:?} is recursive", self);
@@ -2463,7 +2463,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn item_name(self, id: DefId) -> InternedString {
         if id.index == CRATE_DEF_INDEX {
-            self.original_crate_name(id.krate).as_str()
+            self.original_crate_name(id.krate).as_interned_str()
         } else {
             let def_key = self.def_key(id);
             // The name of a StructCtor is that of its struct parent.
@@ -2820,15 +2820,13 @@ impl_stable_hash_for!(struct self::SymbolName {
 impl SymbolName {
     pub fn new(name: &str) -> SymbolName {
         SymbolName {
-            name: Symbol::intern(name).as_str()
+            name: Symbol::intern(name).as_interned_str()
         }
     }
-}
-
-impl Deref for SymbolName {
-    type Target = str;
 
-    fn deref(&self) -> &str { &self.name }
+    pub fn as_str(&self) -> LocalInternedString {
+        self.name.as_str()
+    }
 }
 
 impl fmt::Display for SymbolName {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 0dfae13cc75..e9c1e87676b 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -864,7 +864,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, keywords::SelfType.name().as_str())
+        ParamTy::new(0, keywords::SelfType.name().as_interned_str())
     }
 
     pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
@@ -876,8 +876,10 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn is_self(&self) -> bool {
-        if self.name == keywords::SelfType.name().as_str() {
-            assert_eq!(self.idx, 0);
+        // FIXME(#50125): Ignoring `Self` with `idx != 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`.
+        if self.name == keywords::SelfType.name().as_str() && self.idx == 0 {
             true
         } else {
             false
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index a10ca132472..4aa70e1f7e0 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -1024,7 +1024,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let (param_env, ty) = query.into_parts();
 
     let needs_drop = |ty: Ty<'tcx>| -> bool {
-        match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
+        match tcx.try_get_query::<ty::queries::needs_drop_raw>(DUMMY_SP, param_env.and(ty)) {
             Ok(v) => v,
             Err(mut bug) => {
                 // Cycles should be reported as an error by `check_representable`.
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index bb6aa654c29..c74e42263ef 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -25,7 +25,6 @@ use std::time::{Duration, Instant};
 
 use std::sync::mpsc::{Sender};
 use syntax_pos::{SpanData};
-use ty::maps::{QueryMsg};
 use ty::TyCtxt;
 use dep_graph::{DepNode};
 use proc_macro;
@@ -77,6 +76,13 @@ pub struct ProfQDumpParams {
     pub dump_profq_msg_log:bool,
 }
 
+#[allow(bad_style)]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct QueryMsg {
+    pub query: &'static str,
+    pub msg: Option<String>,
+}
+
 /// A sequence of these messages induce a trace of query-based incremental compilation.
 /// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
 #[derive(Clone,Debug)]
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 905776373bd..b777f513e6d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -462,7 +462,7 @@ impl PrintContext {
                 0 => Symbol::intern("'r"),
                 1 => Symbol::intern("'s"),
                 i => Symbol::intern(&format!("'t{}", i-2)),
-            }.as_str()
+            }.as_interned_str()
         }
 
         // Replace any anonymous late-bound regions with named
diff --git a/src/librustc_data_structures/lazy_btree_map.rs b/src/librustc_data_structures/lazy_btree_map.rs
new file mode 100644
index 00000000000..74f91af10fe
--- /dev/null
+++ b/src/librustc_data_structures/lazy_btree_map.rs
@@ -0,0 +1,108 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::btree_map;
+use std::collections::BTreeMap;
+
+/// A thin wrapper around BTreeMap that avoids allocating upon creation.
+///
+/// Vec, HashSet and HashMap all have the nice feature that they don't do any
+/// heap allocation when creating a new structure of the default size. In
+/// contrast, BTreeMap *does* allocate in that situation. The compiler uses
+/// B-Tree maps in some places such that many maps are created but few are
+/// inserted into, so having a BTreeMap alternative that avoids allocating on
+/// creation is a performance win.
+///
+/// Only a fraction of BTreeMap's functionality is currently supported.
+/// Additional functionality should be added on demand.
+#[derive(Debug)]
+pub struct LazyBTreeMap<K, V>(Option<BTreeMap<K, V>>);
+
+impl<K, V> LazyBTreeMap<K, V> {
+    pub fn new() -> LazyBTreeMap<K, V> {
+        LazyBTreeMap(None)
+    }
+
+    pub fn iter(&self) -> Iter<K, V> {
+        Iter(self.0.as_ref().map(|btm| btm.iter()))
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.as_ref().map_or(true, |btm| btm.is_empty())
+    }
+}
+
+impl<K: Ord, V> LazyBTreeMap<K, V> {
+    fn instantiate(&mut self) -> &mut BTreeMap<K, V> {
+        if let Some(ref mut btm) = self.0 {
+            btm
+        } else {
+            let btm = BTreeMap::new();
+            self.0 = Some(btm);
+            self.0.as_mut().unwrap()
+        }
+    }
+
+    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
+        self.instantiate().insert(key, value)
+    }
+
+    pub fn entry(&mut self, key: K) -> btree_map::Entry<K, V> {
+        self.instantiate().entry(key)
+    }
+
+    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+        Values(self.0.as_ref().map(|btm| btm.values()))
+    }
+}
+
+impl<K: Ord, V> Default for LazyBTreeMap<K, V> {
+    fn default() -> LazyBTreeMap<K, V> {
+        LazyBTreeMap::new()
+    }
+}
+
+impl<'a, K: 'a, V: 'a> IntoIterator for &'a LazyBTreeMap<K, V> {
+    type Item = (&'a K, &'a V);
+    type IntoIter = Iter<'a, K, V>;
+
+    fn into_iter(self) -> Iter<'a, K, V> {
+        self.iter()
+    }
+}
+
+pub struct Iter<'a, K: 'a, V: 'a>(Option<btree_map::Iter<'a, K, V>>);
+
+impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
+    type Item = (&'a K, &'a V);
+
+    fn next(&mut self) -> Option<(&'a K, &'a V)> {
+        self.0.as_mut().and_then(|iter| iter.next())
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.as_ref().map_or_else(|| (0, Some(0)), |iter| iter.size_hint())
+    }
+}
+
+pub struct Values<'a, K: 'a, V: 'a>(Option<btree_map::Values<'a, K, V>>);
+
+impl<'a, K, V> Iterator for Values<'a, K, V> {
+    type Item = &'a V;
+
+    fn next(&mut self) -> Option<&'a V> {
+        self.0.as_mut().and_then(|values| values.next())
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.as_ref().map_or_else(|| (0, Some(0)), |values| values.size_hint())
+    }
+}
+
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 1320fe75bc5..597d1627ada 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -60,6 +60,7 @@ pub mod bitvec;
 pub mod graph;
 pub mod indexed_set;
 pub mod indexed_vec;
+pub mod lazy_btree_map;
 pub mod obligation_forest;
 pub mod sip128;
 pub mod snapshot_map;
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index b203f387e46..3f166daac71 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1526,7 +1526,8 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
         let thread = cfg.spawn(f);
         thread.unwrap().join()
     } else {
-        Ok(f())
+        let f = panic::AssertUnwindSafe(f);
+        panic::catch_unwind(f)
     }
 }
 
diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs
index 280f3c8c796..6426286ccbc 100644
--- a/src/librustc_driver/profile/trace.rs
+++ b/src/librustc_driver/profile/trace.rs
@@ -10,7 +10,7 @@
 
 use super::*;
 use syntax_pos::SpanData;
-use rustc::ty::maps::QueryMsg;
+use rustc::util::common::QueryMsg;
 use std::fs::File;
 use std::time::{Duration, Instant};
 use std::collections::hash_map::HashMap;
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 47c49fbe9ef..d2ee3d8743c 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -303,11 +303,11 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_str())
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_interned_str())
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
-        let name = Symbol::intern(name).as_str();
+        let name = Symbol::intern(name).as_interned_str();
         self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
             index,
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 46ba94f2061..6906dacfc5e 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -74,7 +74,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
 
         let mname = self.field(attr, MODULE);
         let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
-        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
+        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str();
 
         let dep_node = DepNode::new(self.tcx,
                                     DepConstructor::CompileCodegenUnit(mangled_cgu_name));
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index bf86f6a6952..5ec8305de78 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -91,23 +91,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                 let def_id = def.def_id();
                 fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
             }
-
-            if let hir::ExprBinary(bin_op, ..) = expr.node {
-                match bin_op.node {
-                    // Hardcoding the comparison operators here seemed more
-                    // expedient than the refactoring that would be needed to
-                    // look up the `#[must_use]` attribute which does exist on
-                    // the comparison trait methods
-                    hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
-                        let msg = "unused comparison which must be used";
-                        cx.span_lint(UNUSED_MUST_USE, expr.span, msg);
-                        op_warned = true;
-                    },
-                    _ => {},
-                }
+            let must_use_op = match expr.node {
+                // Hardcoding operators here seemed more expedient than the
+                // refactoring that would be needed to look up the `#[must_use]`
+                // attribute which does exist on the comparison trait methods
+                hir::ExprBinary(bin_op, ..)  => {
+                    match bin_op.node {
+                        hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
+                            Some("comparison")
+                        },
+                        hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => {
+                            Some("arithmetic operation")
+                        },
+                        hir::BiAnd | hir::BiOr => {
+                            Some("logical operation")
+                        },
+                        hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => {
+                            Some("bitwise operation")
+                        },
+                    }
+                },
+                hir::ExprUnary(..) => Some("unary operation"),
+                _ => None
+            };
+            if let Some(must_use_op) = must_use_op {
+                cx.span_lint(UNUSED_MUST_USE, expr.span,
+                    &format!("unused {} which must be used", must_use_op));
+                op_warned = true;
             }
         }
-
         if !(ty_warned || fn_warned || op_warned) {
             cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
         }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index a11b95cb5b6..fdfe2a98bf9 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -51,7 +51,7 @@ macro_rules! provide {
         pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) {
             $(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T)
                                     -> <ty::queries::$name<$lt> as
-                                        QueryConfig>::Value
+                                        QueryConfig<$lt>>::Value
                 where T: IntoArgs,
             {
                 #[allow(unused_variables)]
@@ -535,7 +535,7 @@ impl CrateStore for cstore::CStore {
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::from_str(&name),
+            ident: ast::Ident::from_str(&name.as_str()),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 07a1da42943..57f92707ccf 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -40,7 +40,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
-use syntax::symbol::{InternedString, Symbol};
+use syntax::symbol::InternedString;
 use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
 
@@ -537,12 +537,12 @@ impl<'a, 'tcx> CrateMetadata {
 
         ty::VariantDef {
             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-            name: Symbol::intern(&self.item_name(index)),
+            name: self.item_name(index).as_symbol(),
             fields: item.children.decode(self).map(|index| {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    name: Symbol::intern(&self.item_name(index)),
+                    name: self.item_name(index).as_symbol(),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -730,7 +730,7 @@ impl<'a, 'tcx> CrateMetadata {
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
                                     def,
-                                    ident: Ident::from_str(&self.item_name(child_index)),
+                                    ident: Ident::from_interned_str(self.item_name(child_index)),
                                     vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                     is_import: false,
@@ -748,7 +748,7 @@ impl<'a, 'tcx> CrateMetadata {
                 let span = child.span.decode((self, sess));
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::from_str(&name);
+                    let ident = Ident::from_interned_str(name);
                     let vis = self.get_visibility(child_index);
                     let is_import = false;
                     callback(def::Export { def, ident, vis, span, is_import });
@@ -847,7 +847,7 @@ impl<'a, 'tcx> CrateMetadata {
         };
 
         ty::AssociatedItem {
-            name: Symbol::intern(&name),
+            name: name.as_symbol(),
             kind,
             vis: item.visibility.decode(self),
             defaultness: container.defaultness(),
@@ -914,7 +914,7 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(id)
             .children
             .decode(self)
-            .map(|index| Symbol::intern(&self.item_name(index)))
+            .map(|index| self.item_name(index).as_symbol())
             .collect()
     }
 
@@ -1112,7 +1112,7 @@ impl<'a, 'tcx> CrateMetadata {
             DefKey {
                 parent: Some(CRATE_DEF_INDEX),
                 disambiguated_data: DisambiguatedDefPathData {
-                    data: DefPathData::MacroDef(name.as_str()),
+                    data: DefPathData::MacroDef(name.as_interned_str()),
                     disambiguator: 0,
                 }
             }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4dd8d245d3b..5c7061abbb6 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -20,7 +20,7 @@ use rustc::ty::maps::Providers;
 use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place};
 use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
 use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
-use rustc::mir::ClosureRegionRequirements;
+use rustc::mir::{ClosureRegionRequirements, Local};
 
 use rustc_data_structures::control_flow_graph::dominators::Dominators;
 use rustc_data_structures::fx::FxHashSet;
@@ -729,6 +729,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         erased_drop_place_ty: ty::Ty<'gcx>,
         span: Span,
     ) {
+        let gcx = self.tcx.global_tcx();
+        let drop_field = |
+            mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+            (index, field): (usize, ty::Ty<'gcx>),
+        | {
+            let field_ty = gcx.normalize_erasing_regions(mir.param_env, field);
+            let place = drop_place.clone().field(Field::new(index), field_ty);
+
+            mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
+        };
+
         match erased_drop_place_ty.sty {
             // When a struct is being dropped, we need to check
             // whether it has a destructor, if it does, then we can
@@ -737,14 +748,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             // destructor but `bar` does not, we will only check for
             // borrows of `x.foo` and not `x.bar`. See #47703.
             ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => {
-                for (index, field) in def.all_fields().enumerate() {
-                    let gcx = self.tcx.global_tcx();
-                    let field_ty = field.ty(gcx, substs);
-                    let field_ty = gcx.normalize_erasing_regions(self.param_env, field_ty);
-                    let place = drop_place.clone().field(Field::new(index), field_ty);
-
-                    self.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
-                }
+                def.all_fields()
+                    .map(|field| field.ty(gcx, substs))
+                    .enumerate()
+                    .for_each(|field| drop_field(self, field));
+            }
+            // Same as above, but for tuples.
+            ty::TyTuple(tys) => {
+                tys.iter().cloned().enumerate()
+                    .for_each(|field| drop_field(self, field));
+            }
+            // Closures and generators also have disjoint fields, but they are only
+            // directly accessed in the body of the closure/generator.
+            ty::TyClosure(def, substs)
+            | ty::TyGenerator(def, substs, ..)
+                if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
+            => {
+                substs.upvar_tys(def, self.tcx).enumerate()
+                    .for_each(|field| drop_field(self, field));
             }
             _ => {
                 // We have now refined the type of the value being
@@ -752,7 +773,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // subfield; so check whether that field's type still
                 // "needs drop". If so, we assume that the destructor
                 // may access any data it likes (i.e., a Deep Write).
-                let gcx = self.tcx.global_tcx();
                 if erased_drop_place_ty.needs_drop(gcx, self.param_env) {
                     self.access_place(
                         ContextKind::Drop.new(loc),
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index ec7ee466008..0ed95a319f7 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -918,11 +918,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     ));
                 }
 
-                if self.is_box_free(func) {
-                    self.check_box_free_inputs(mir, term, &sig, args, term_location);
-                } else {
-                    self.check_call_inputs(mir, term, &sig, args, term_location);
-                }
+                self.check_call_inputs(mir, term, &sig, args, term_location);
             }
             TerminatorKind::Assert {
                 ref cond, ref msg, ..
@@ -1026,70 +1022,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
-        match *operand {
-            Operand::Constant(ref c) => match c.ty.sty {
-                ty::TyFnDef(ty_def_id, _) => {
-                    Some(ty_def_id) == self.tcx().lang_items().box_free_fn()
-                }
-                _ => false,
-            },
-            _ => false,
-        }
-    }
-
-    fn check_box_free_inputs(
-        &mut self,
-        mir: &Mir<'tcx>,
-        term: &Terminator<'tcx>,
-        sig: &ty::FnSig<'tcx>,
-        args: &[Operand<'tcx>],
-        term_location: Location,
-    ) {
-        debug!("check_box_free_inputs");
-
-        // box_free takes a Box as a pointer. Allow for that.
-
-        if sig.inputs().len() != 1 {
-            span_mirbug!(self, term, "box_free should take 1 argument");
-            return;
-        }
-
-        let pointee_ty = match sig.inputs()[0].sty {
-            ty::TyRawPtr(mt) => mt.ty,
-            _ => {
-                span_mirbug!(self, term, "box_free should take a raw ptr");
-                return;
-            }
-        };
-
-        if args.len() != 1 {
-            span_mirbug!(self, term, "box_free called with wrong # of args");
-            return;
-        }
-
-        let ty = args[0].ty(mir, self.tcx());
-        let arg_ty = match ty.sty {
-            ty::TyRawPtr(mt) => mt.ty,
-            ty::TyAdt(def, _) if def.is_box() => ty.boxed_ty(),
-            _ => {
-                span_mirbug!(self, term, "box_free called with bad arg ty");
-                return;
-            }
-        };
-
-        if let Err(terr) = self.sub_types(arg_ty, pointee_ty, term_location.at_self()) {
-            span_mirbug!(
-                self,
-                term,
-                "bad box_free arg ({:?} <- {:?}): {:?}",
-                pointee_ty,
-                arg_ty,
-                terr
-            );
-        }
-    }
-
     fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) {
         let is_cleanup = block_data.is_cleanup;
         self.last_span = block_data.terminator().source_info.span;
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index c130b4f550f..562f890b4c0 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -220,7 +220,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         let f = ty.fn_sig(this.hir.tcx());
                         if f.abi() == Abi::RustIntrinsic ||
                            f.abi() == Abi::PlatformIntrinsic {
-                            Some(this.hir.tcx().item_name(def_id))
+                            Some(this.hir.tcx().item_name(def_id).as_str())
                         } else {
                             None
                         }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index a25331f7279..dff9fa271ab 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -263,7 +263,7 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
     ) -> EvalResult<'tcx> {
         let substs = instance.substs;
 
-        let intrinsic_name = &ecx.tcx.item_name(instance.def_id())[..];
+        let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..];
         match intrinsic_name {
             "min_align_of" => {
                 let elem_ty = substs.type_at(0);
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4b57c641546..f6e9994b5da 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -768,9 +768,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             }
         }
 
-        if log_enabled!(::log::Level::Trace) {
-            self.dump_local(dest);
-        }
+        self.dump_local(dest);
 
         Ok(())
     }
@@ -1572,6 +1570,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
 
     pub fn dump_local(&self, place: Place) {
         // Debug output
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         match place {
             Place::Local { frame, local } => {
                 let mut allocs = Vec::new();
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 5e156e9271f..7f8205b8327 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -334,11 +334,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
 
     /// For debugging, print an allocation and all allocations it points to, recursively.
     pub fn dump_alloc(&self, id: AllocId) {
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         self.dump_allocs(vec![id]);
     }
 
     /// For debugging, print a list of allocations and all allocations they point to, recursively.
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         use std::fmt::Write;
         allocs.sort();
         allocs.dedup();
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 42cb149d682..d03204bfab1 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -219,9 +219,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             }
         };
 
-        if log_enabled!(::log::Level::Trace) {
-            self.dump_local(place);
-        }
+        self.dump_local(place);
 
         Ok(place)
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 399892522a3..75b7a10097d 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -24,7 +24,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
-#![feature(dyn_trait)]
+#![cfg_attr(stage0, feature(dyn_trait))]
 #![feature(fs_read_write)]
 #![feature(macro_vis_matcher)]
 #![feature(exhaustive_patterns)]
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 9e0c977a3f0..9e43bed1b63 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
             MonoItem::GlobalAsm(node_id) => {
                 let def_id = tcx.hir.local_def_id(node_id);
                 ty::SymbolName {
-                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_str()
+                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str()
                 }
             }
         }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index f29f86af4ab..3a65cd4ea77 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -146,7 +146,7 @@ pub trait CodegenUnitExt<'tcx> {
     }
 
     fn work_product_id(&self) -> WorkProductId {
-        WorkProductId::from_cgu_name(self.name())
+        WorkProductId::from_cgu_name(&self.name().as_str())
     }
 
     fn items_in_deterministic_order<'a>(&self,
@@ -206,9 +206,9 @@ fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
     const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
 
     if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
-        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str()
+        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str()
     } else {
-        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str()
+        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str()
     }
 }
 
@@ -740,7 +740,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         }
                     }) {
         cgu_name.push_str("-");
-        cgu_name.push_str(&part.data.as_interned_str());
+        cgu_name.push_str(&part.data.as_interned_str().as_str());
     }
 
     if volatile {
@@ -753,11 +753,11 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         CodegenUnit::mangle_name(&cgu_name)
     };
 
-    Symbol::intern(&cgu_name[..]).as_str()
+    Symbol::intern(&cgu_name[..]).as_interned_str()
 }
 
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
-    Symbol::intern(&format!("{}{}", crate_name, index)).as_str()
+    Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str()
 }
 
 fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -772,7 +772,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             debug!("CodegenUnit {}:", cgu.name());
 
             for (trans_item, linkage) in cgu.items() {
-                let symbol_name = trans_item.symbol_name(tcx);
+                let symbol_name = trans_item.symbol_name(tcx).name.as_str();
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
                                                    .unwrap_or("<no hash>");
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 31af7c21857..2bf5a49c97e 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     self.visibility_scope_info[source_info.scope].lint_root;
                 self.register_violations(&[UnsafetyViolation {
                     source_info,
-                    description: Symbol::intern("borrow of packed field").as_str(),
+                    description: Symbol::intern("borrow of packed field").as_interned_str(),
                     kind: UnsafetyViolationKind::BorrowPacked(lint_root)
                 }], &[]);
             }
@@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.visibility_scope_info[source_info.scope].lint_root;
                     self.register_violations(&[UnsafetyViolation {
                         source_info,
-                        description: Symbol::intern("use of extern static").as_str(),
+                        description: Symbol::intern("use of extern static").as_interned_str(),
                         kind: UnsafetyViolationKind::ExternStatic(lint_root)
                     }], &[]);
                 }
@@ -231,7 +231,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info,
-            description: Symbol::intern(description).as_str(),
+            description: Symbol::intern(description).as_interned_str(),
             kind: UnsafetyViolationKind::General,
         }], &[]);
     }
@@ -444,7 +444,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                 struct_span_err!(
                     tcx.sess, source_info.span, E0133,
                     "{} requires unsafe function or block", description)
-                    .span_label(source_info.span, &description[..])
+                    .span_label(source_info.span, &description.as_str()[..])
                     .emit();
             }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
@@ -452,7 +452,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                               lint_node_id,
                               source_info.span,
                               &format!("{} requires unsafe function or \
-                                        block (error E0133)", &description[..]));
+                                        block (error E0133)", &description.as_str()[..]));
             }
             UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
                 if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) {
@@ -462,7 +462,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                                   lint_node_id,
                                   source_info.span,
                                   &format!("{} requires unsafe function or \
-                                            block (error E0133)", &description[..]));
+                                            block (error E0133)", &description.as_str()[..]));
                 }
             }
         }
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 2b491385d66..2e2f8494146 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -126,7 +126,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     continue;
                 }
 
-                let callee_mir = match ty::queries::optimized_mir::try_get(self.tcx,
+                let callee_mir = match self.tcx.try_get_query::<ty::queries::optimized_mir>(
                                                                            callsite.location.span,
                                                                            callsite.callee) {
                     Ok(callee_mir) if self.should_inline(callsite, callee_mir) => {
@@ -379,8 +379,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
                 debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
 
-                let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn();
-
                 let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len());
                 let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len());
                 let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len());
@@ -460,24 +458,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
                 let return_block = destination.1;
 
-                let args : Vec<_> = if is_box_free {
-                    assert!(args.len() == 1);
-                    // box_free takes a Box, but is defined with a *mut T, inlining
-                    // needs to generate the cast.
-                    // FIXME: we should probably just generate correct MIR in the first place...
-
-                    let arg = if let Operand::Move(ref place) = args[0] {
-                        place.clone()
-                    } else {
-                        bug!("Constant arg to \"box_free\"");
-                    };
-
-                    let ptr_ty = args[0].ty(caller_mir, self.tcx);
-                    vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)]
-                } else {
-                    // Copy the arguments if needed.
-                    self.make_call_args(args, &callsite, caller_mir)
-                };
+                // Copy the arguments if needed.
+                let args: Vec<_> = self.make_call_args(args, &callsite, caller_mir);
 
                 let bb_len = caller_mir.basic_blocks().len();
                 let mut integrator = Integrator {
@@ -518,49 +500,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         }
     }
 
-    fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>,
-                         callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
-        let arg = Rvalue::Ref(
-            self.tcx.types.re_erased,
-            BorrowKind::Mut { allow_two_phase_borrow: false },
-            arg.deref());
-
-        let ty = arg.ty(caller_mir, self.tcx);
-        let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
-        let ref_tmp = caller_mir.local_decls.push(ref_tmp);
-        let ref_tmp = Place::Local(ref_tmp);
-
-        let ref_stmt = Statement {
-            source_info: callsite.location,
-            kind: StatementKind::Assign(ref_tmp.clone(), arg)
-        };
-
-        caller_mir[callsite.bb]
-            .statements.push(ref_stmt);
-
-        let pointee_ty = match ptr_ty.sty {
-            ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty,
-            _ if ptr_ty.is_box() => ptr_ty.boxed_ty(),
-            _ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty)
-        };
-        let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty);
-
-        let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Move(ref_tmp), ptr_ty);
-
-        let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
-        let cast_tmp = caller_mir.local_decls.push(cast_tmp);
-
-        let cast_stmt = Statement {
-            source_info: callsite.location,
-            kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr)
-        };
-
-        caller_mir[callsite.bb]
-            .statements.push(cast_stmt);
-
-        cast_tmp
-    }
-
     fn make_call_args(
         &self,
         args: Vec<Operand<'tcx>>,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index ff7551ed6f4..4762c6aaa27 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -868,7 +868,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
                         assert!(!self.tcx.is_const_fn(def_id));
-                        match &self.tcx.item_name(def_id)[..] {
+                        match &self.tcx.item_name(def_id).as_str()[..] {
                             "size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id),
 
                             name if name.starts_with("simd_shuffle") => {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index e5719407da6..4b7c581d3c8 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -339,18 +339,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         self.drop_ladder(fields, succ, unwind).0
     }
 
-    fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock
+    fn open_drop_for_box<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
+                             -> BasicBlock
     {
-        debug!("open_drop_for_box({:?}, {:?})", self, ty);
+        debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
 
         let interior = self.place.clone().deref();
         let interior_path = self.elaborator.deref_subpath(self.path);
 
         let succ = self.succ; // FIXME(#43234)
         let unwind = self.unwind;
-        let succ = self.box_free_block(ty, succ, unwind);
+        let succ = self.box_free_block(adt, substs, succ, unwind);
         let unwind_succ = self.unwind.map(|unwind| {
-            self.box_free_block(ty, unwind, Unwind::InCleanup)
+            self.box_free_block(adt, substs, unwind, Unwind::InCleanup)
         });
 
         self.drop_subpath(&interior, interior_path, succ, unwind_succ)
@@ -793,11 +794,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             ty::TyTuple(tys) => {
                 self.open_drop_for_tuple(tys)
             }
-            ty::TyAdt(def, _) if def.is_box() => {
-                self.open_drop_for_box(ty.boxed_ty())
-            }
             ty::TyAdt(def, substs) => {
-                self.open_drop_for_adt(def, substs)
+                if def.is_box() {
+                    self.open_drop_for_box(def, substs)
+                } else {
+                    self.open_drop_for_adt(def, substs)
+                }
             }
             ty::TyDynamic(..) => {
                 let unwind = self.unwind; // FIXME(#43234)
@@ -860,28 +862,34 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
 
     fn box_free_block<'a>(
         &mut self,
-        ty: Ty<'tcx>,
+        adt: &'tcx ty::AdtDef,
+        substs: &'tcx Substs<'tcx>,
         target: BasicBlock,
         unwind: Unwind,
     ) -> BasicBlock {
-        let block = self.unelaborated_free_block(ty, target, unwind);
+        let block = self.unelaborated_free_block(adt, substs, target, unwind);
         self.drop_flag_test_block(block, target, unwind)
     }
 
     fn unelaborated_free_block<'a>(
         &mut self,
-        ty: Ty<'tcx>,
+        adt: &'tcx ty::AdtDef,
+        substs: &'tcx Substs<'tcx>,
         target: BasicBlock,
         unwind: Unwind
     ) -> BasicBlock {
         let tcx = self.tcx();
         let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
         let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
-        let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
+        let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
+            let field = Field::new(i);
+            let field_ty = f.ty(self.tcx(), substs);
+            Operand::Move(self.place.clone().field(field, field_ty))
+        }).collect();
 
         let call = TerminatorKind::Call {
             func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
-            args: vec![Operand::Move(self.place.clone())],
+            args: args,
             destination: Some((unit_temp, target)),
             cleanup: None
         }; // FIXME(#43234)
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index f4e2136a5a1..14ceb5f59a3 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -41,7 +41,6 @@ use syntax::ext::tt::macro_rules;
 use syntax::parse::token::{self, Token};
 use syntax::std_inject::injected_crate_name;
 use syntax::symbol::keywords;
-use syntax::symbol::Symbol;
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -544,14 +543,14 @@ impl<'a> Resolver<'a> {
         }
 
         let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
-            (self.cstore.crate_name_untracked(def_id.krate).as_str(), None)
+            (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
         } else {
             let def_key = self.cstore.def_key(def_id);
             (def_key.disambiguated_data.data.get_opt_name().unwrap(),
              Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
         };
 
-        let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name));
+        let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol());
         let module =
             self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
         self.extern_module_map.insert((def_id, macros_only), module);
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index af1e17cd89c..e72e02933e5 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -397,7 +397,7 @@ impl<'a> Resolver<'a> {
 
     fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                             -> Result<Def, Determinacy> {
-        if path.segments.len() > 1 {
+        if kind != MacroKind::Bang && path.segments.len() > 1 {
             if !self.session.features_untracked().proc_macro_path_invoc {
                 emit_feature_err(
                     &self.session.parse_sess,
@@ -409,6 +409,7 @@ impl<'a> Resolver<'a> {
                 );
             }
         }
+
         let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
         if def != Err(Determinacy::Undetermined) {
             // Do not report duplicated errors on every undetermined resolution.
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 18dd04c0ee8..346e5667a7b 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -14,7 +14,7 @@ pub use self::Primitive::*;
 use spec::Target;
 
 use std::cmp;
-use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive};
+use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
 pub mod call;
 
@@ -544,6 +544,23 @@ impl Scalar {
             false
         }
     }
+
+    /// Returns the valid range as a `x..y` range.
+    ///
+    /// If `x` and `y` are equal, the range is full, not empty.
+    pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: C) -> Range<u128> {
+        // For a (max) value of -1, max will be `-1 as usize`, which overflows.
+        // However, that is fine here (it would still represent the full range),
+        // i.e., if the range is everything.
+        let bits = self.value.size(cx).bits();
+        assert!(bits <= 128);
+        let mask = !0u128 >> (128 - bits);
+        let start = self.valid_range.start;
+        let end = self.valid_range.end;
+        assert_eq!(start, start & mask);
+        assert_eq!(end, end & mask);
+        start..(end.wrapping_add(1) & mask)
+    }
 }
 
 /// Describes how the fields of a type are located in memory.
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 8f491157439..927d5c7e15a 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -29,6 +29,7 @@
 #![feature(const_fn)]
 #![feature(fs_read_write)]
 #![feature(inclusive_range)]
+#![feature(inclusive_range_fields)]
 #![feature(slice_patterns)]
 
 #[macro_use]
diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs
new file mode 100644
index 00000000000..21259bbcd38
--- /dev/null
+++ b/src/librustc_traits/evaluate_obligation.rs
@@ -0,0 +1,35 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::traits::{EvaluationResult, Obligation, ObligationCause,
+                    OverflowError, SelectionContext, TraitQueryMode};
+use rustc::traits::query::CanonicalPredicateGoal;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
+use syntax::codemap::DUMMY_SP;
+
+crate fn evaluate_obligation<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    goal: CanonicalPredicateGoal<'tcx>,
+) -> Result<EvaluationResult, OverflowError> {
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let (
+            ParamEnvAnd {
+                param_env,
+                value: predicate,
+            },
+            _canonical_inference_vars,
+        ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
+
+        let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
+        let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+
+        selcx.evaluate_obligation_recursively(&obligation)
+    })
+}
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index 90c870096e1..7f18fac2db5 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -22,6 +22,7 @@ extern crate syntax;
 extern crate syntax_pos;
 
 mod dropck_outlives;
+mod evaluate_obligation;
 mod normalize_projection_ty;
 mod normalize_erasing_regions;
 mod util;
@@ -38,6 +39,7 @@ pub fn provide(p: &mut Providers) {
             normalize_erasing_regions::normalize_ty_after_erasing_regions,
         program_clauses_for: lowering::program_clauses_for,
         program_clauses_for_env: lowering::program_clauses_for_env,
+        evaluate_obligation: evaluate_obligation::evaluate_obligation,
         ..*p
     };
 }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 483f36afe27..1d0d7ec601f 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -265,7 +265,7 @@ pub trait FnTypeExt<'a, 'tcx> {
     fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
     fn apply_attrs_llfn(&self, llfn: ValueRef);
-    fn apply_attrs_callsite(&self, callsite: ValueRef);
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef);
 }
 
 impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
@@ -640,7 +640,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn apply_attrs_callsite(&self, callsite: ValueRef) {
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
@@ -653,6 +653,24 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
             PassMode::Indirect(ref attrs) => apply(attrs),
             _ => {}
         }
+        if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
+            // If the value is a boolean, the range is 0..2 and that ultimately
+            // become 0..0 when the type becomes i1, which would be rejected
+            // by the LLVM verifier.
+            match scalar.value {
+                layout::Int(..) if !scalar.is_bool() => {
+                    let range = scalar.valid_range_exclusive(bx.cx);
+                    if range.start != range.end {
+                        // FIXME(nox): This causes very weird type errors about
+                        // SHL operators in constants in stage 2 with LLVM 3.9.
+                        if unsafe { llvm::LLVMRustVersionMajor() >= 4 } {
+                            bx.range_metadata(callsite, range);
+                        }
+                    }
+                }
+                _ => {}
+            }
+        }
         for arg in &self.args {
             if arg.pad.is_some() {
                 apply(&ArgAttributes::new());
diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs
index ffebb959ebf..871fe98ec01 100644
--- a/src/librustc_trans/allocator.rs
+++ b/src/librustc_trans/allocator.rs
@@ -11,6 +11,7 @@
 use std::ffi::CString;
 use std::ptr;
 
+use attributes;
 use libc::c_uint;
 use rustc::middle::allocator::AllocatorKind;
 use rustc::ty::TyCtxt;
@@ -67,6 +68,9 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
         if tcx.sess.target.target.options.default_hidden_visibility {
             llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
         }
+       if tcx.sess.target.target.options.requires_uwtable {
+           attributes::emit_uwtable(llfn, true);
+       }
 
         let callee = CString::new(kind.fn_name(method.name)).unwrap();
         let callee = llvm::LLVMRustGetOrInsertFunction(llmod,
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index eb5c7396ae0..f455c19cc0b 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -14,6 +14,7 @@ use std::ffi::{CStr, CString};
 use rustc::hir::{self, TransFnAttrFlags};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::session::Session;
 use rustc::session::config::Sanitizer;
 use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
@@ -104,6 +105,18 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
         cstr("probe-stack\0"), cstr("__rust_probestack\0"));
 }
 
+pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
+    const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
+        "crt-static",
+    ];
+
+    let cmdline = sess.opts.cg.target_feature.split(',')
+        .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)));
+    sess.target.target.options.features.split(',')
+        .chain(cmdline)
+        .filter(|l| !l.is_empty())
+}
+
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
 pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
@@ -131,13 +144,16 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
         unwind(llfn, false);
     }
 
-    let features =
-        trans_fn_attrs.target_features
-        .iter()
-        .map(|f| {
-            let feature = &*f.as_str();
-            format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
-        })
+    let features = llvm_target_features(cx.tcx.sess)
+        .map(|s| s.to_string())
+        .chain(
+            trans_fn_attrs.target_features
+                .iter()
+                .map(|f| {
+                    let feature = &*f.as_str();
+                    format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+                })
+        )
         .collect::<Vec<String>>()
         .join(",");
 
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index f9a8473464d..ea3f5b40860 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -959,7 +959,11 @@ impl Linker for WasmLd {
     }
 
     fn finalize(&mut self) -> Command {
-        self.cmd.arg("--threads");
+        // There have been reports in the wild (rustwasm/wasm-bindgen#119) of
+        // using threads causing weird hangs and bugs. Disable it entirely as
+        // this isn't yet the bottleneck of compilation at all anyway.
+        self.cmd.arg("--no-threads");
+
         self.cmd.arg("-z").arg("stack-size=1048576");
 
         // FIXME we probably shouldn't pass this but instead pass an explicit
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 965a34eccb8..d8520b61d91 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -132,7 +132,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         })
         .map(|def_id| {
             let export_level = if special_runtime_crate {
-                let name = tcx.symbol_name(Instance::mono(tcx, def_id));
+                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str();
                 // We can probably do better here by just ensuring that
                 // it has hidden visibility rather than public
                 // visibility, as this is primarily here to ensure it's
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 613a07cd269..148e3d0025c 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use attributes;
 use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
 use back::lto::{self, ModuleBuffer, ThinBuffer};
 use back::link::{self, get_linker, remove};
@@ -111,31 +112,6 @@ pub fn write_output_file(
     }
 }
 
-// On android, we by default compile for armv7 processors. This enables
-// things like double word CAS instructions (rather than emulating them)
-// which are *far* more efficient. This is obviously undesirable in some
-// cases, so if any sort of target feature is specified we don't append v7
-// to the feature list.
-//
-// On iOS only armv7 and newer are supported. So it is useful to
-// get all hardware potential via VFP3 (hardware floating point)
-// and NEON (SIMD) instructions supported by LLVM.
-// Note that without those flags various linking errors might
-// arise as some of intrinsics are converted into function calls
-// and nobody provides implementations those functions
-fn target_feature(sess: &Session) -> String {
-    let rustc_features = [
-        "crt-static",
-    ];
-    let requested_features = sess.opts.cg.target_feature.split(',');
-    let llvm_features = requested_features.filter(|f| {
-        !rustc_features.iter().any(|s| f.contains(s))
-    });
-    format!("{},{}",
-            sess.target.target.options.features,
-            llvm_features.collect::<Vec<_>>().join(","))
-}
-
 fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
     match optimize {
       config::OptLevel::No => llvm::CodeGenOptLevel::None,
@@ -203,7 +179,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
         None => &*sess.target.target.options.cpu
     };
     let cpu = CString::new(cpu.as_bytes()).unwrap();
-    let features = CString::new(target_feature(sess).as_bytes()).unwrap();
+    let features = attributes::llvm_target_features(sess)
+        .collect::<Vec<_>>()
+        .join(",");
+    let features = CString::new(features).unwrap();
     let is_pie_binary = !find_features && is_pie_binary(sess);
     let trap_unreachable = sess.target.target.options.trap_unreachable;
 
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 2323ec3ef11..b756a6695f9 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1037,7 +1037,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
                 cgus.dedup();
                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
                     output.push_str(" ");
-                    output.push_str(&cgu_name);
+                    output.push_str(&cgu_name.as_str());
 
                     let linkage_abbrev = match linkage {
                         Linkage::External => "External",
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 5849437758a..9263d9a5f5d 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -52,7 +52,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return llfn;
     }
 
-    let sym = tcx.symbol_name(instance);
+    let sym = tcx.symbol_name(instance).as_str();
     debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
 
     // Create a fn pointer with the substituted signature.
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 25ca2152b27..4a0619b2336 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -33,7 +33,7 @@ use libc::{c_uint, c_char};
 use std::iter;
 
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use syntax_pos::{Span, DUMMY_SP};
 
 pub use context::CodegenCx;
@@ -183,7 +183,7 @@ pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
 
 // This is a 'c-like' raw string, which differs from
 // our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef {
     unsafe {
         if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
             return llval;
@@ -208,7 +208,7 @@ pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> Value
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CodegenCx, s: InternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
         cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 122b51dbbb7..405cb83ad4d 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -118,7 +118,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
              def_id);
 
     let ty = instance.ty(cx.tcx);
-    let sym = cx.tcx.symbol_name(instance);
+    let sym = cx.tcx.symbol_name(instance).as_str();
 
     let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
 
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 76f8be9ee98..90b2fb4b59a 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -39,7 +39,7 @@ use std::ptr;
 use std::iter;
 use std::str;
 use std::sync::Arc;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use abi::Abi;
 
 /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
@@ -62,7 +62,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
                                 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
+    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, ValueRef>>,
 
     /// Reverse-direction for const ptrs cast from globals.
     /// Key is a ValueRef holding a *T,
@@ -273,7 +273,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
             let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
                 let dctx = debuginfo::CrateDebugContext::new(llmod);
                 debuginfo::metadata::compile_unit_metadata(tcx,
-                                                           codegen_unit.name(),
+                                                           &codegen_unit.name().as_str(),
                                                            &dctx);
                 Some(dctx)
             } else {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 5359e0e0405..123b9cf7931 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -1399,7 +1399,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     (discr.size(cx), discr.align(cx));
                 let discriminant_base_type_metadata =
                     type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
-                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
+                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str();
 
                 let name = CString::new(discriminant_name.as_bytes()).unwrap();
                 let discriminant_type_metadata = unsafe {
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 706dc3dca8a..193db15303f 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -394,7 +394,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             substs.types().zip(names).map(|(ty, name)| {
                 let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                 let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
-                let name = CString::new(name.as_bytes()).unwrap();
+                let name = CString::new(name.as_str().as_bytes()).unwrap();
                 unsafe {
                     llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index 891bf649c38..51c45de9dc2 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -47,7 +47,7 @@ pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
 
     let namespace_name = match def_key.disambiguated_data.data {
         DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(),
-        data => data.as_interned_str()
+        data => data.as_interned_str().as_str()
     };
 
     let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 96ed4e88471..825fac36c93 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -190,10 +190,10 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
             for path_element in cx.tcx.def_path(def_id).data {
                 output.push_str("::");
-                output.push_str(&path_element.data.as_interned_str());
+                output.push_str(&path_element.data.as_interned_str().as_str());
             }
         } else {
-            output.push_str(&cx.tcx.item_name(def_id));
+            output.push_str(&cx.tcx.item_name(def_id).as_str());
         }
     }
 
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 103b04e6f13..49a207a2d8a 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -103,7 +103,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
     let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
     let arg_tys = sig.inputs();
     let ret_ty = sig.output();
-    let name = &*tcx.item_name(def_id);
+    let name = &*tcx.item_name(def_id).as_str();
 
     let llret_ty = cx.layout_of(ret_ty).llvm_type(cx);
     let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align);
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index dab01abd335..96a10e8b99d 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -25,6 +25,7 @@
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(quote)]
+#![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 36f03605fea..e5fdc26eeaf 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -127,7 +127,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                                            ret_bx,
                                            llblock(this, cleanup),
                                            cleanup_bundle);
-                fn_ty.apply_attrs_callsite(invokeret);
+                fn_ty.apply_attrs_callsite(&bx, invokeret);
 
                 if let Some((ret_dest, target)) = destination {
                     let ret_bx = this.build_block(target);
@@ -136,7 +136,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 }
             } else {
                 let llret = bx.call(fn_ptr, &llargs, cleanup_bundle);
-                fn_ty.apply_attrs_callsite(llret);
+                fn_ty.apply_attrs_callsite(&bx, llret);
                 if this.mir[bb].is_cleanup {
                     // Cleanup is always the cold path. Don't inline
                     // drop glue. Also, when there is a deeply-nested
@@ -442,7 +442,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 // Handle intrinsics old trans wants Expr's for, ourselves.
                 let intrinsic = match def {
                     Some(ty::InstanceDef::Intrinsic(def_id))
-                        => Some(bx.tcx().item_name(def_id)),
+                        => Some(bx.tcx().item_name(def_id).as_str()),
                     _ => None
                 };
                 let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs
index b8b0c019ca6..8532c0b149d 100644
--- a/src/librustc_trans/mir/place.rs
+++ b/src/librustc_trans/mir/place.rs
@@ -91,24 +91,15 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         }
 
         let scalar_load_metadata = |load, scalar: &layout::Scalar| {
-            let (min, max) = (scalar.valid_range.start, scalar.valid_range.end);
-            let max_next = max.wrapping_add(1);
-            let bits = scalar.value.size(bx.cx).bits();
-            assert!(bits <= 128);
-            let mask = !0u128 >> (128 - bits);
-            // For a (max) value of -1, max will be `-1 as usize`, which overflows.
-            // However, that is fine here (it would still represent the full range),
-            // i.e., if the range is everything.  The lo==hi case would be
-            // rejected by the LLVM verifier (it would mean either an
-            // empty set, which is impossible, or the entire range of the
-            // type, which is pointless).
+            let vr = scalar.valid_range.clone();
             match scalar.value {
-                layout::Int(..) if max_next & mask != min & mask => {
-                    // llvm::ConstantRange can deal with ranges that wrap around,
-                    // so an overflow on (max + 1) is fine.
-                    bx.range_metadata(load, min..max_next);
+                layout::Int(..) => {
+                    let range = scalar.valid_range_exclusive(bx.cx);
+                    if range.start != range.end {
+                        bx.range_metadata(load, range);
+                    }
                 }
-                layout::Pointer if 0 < min && min < max => {
+                layout::Pointer if vr.start < vr.end && !vr.contains(&0) => {
                     bx.nonnull_metadata(load);
                 }
                 _ => {}
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index c932777402e..79e906ca975 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -536,7 +536,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         let is_float = input_ty.is_fp();
         let is_signed = input_ty.is_signed();
         let is_nil = input_ty.is_nil();
-        let is_bool = input_ty.is_bool();
         match op {
             mir::BinOp::Add => if is_float {
                 bx.fadd(lhs, rhs)
@@ -586,15 +585,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     lhs, rhs
                 )
             } else {
-                let (lhs, rhs) = if is_bool {
-                    // FIXME(#36856) -- extend the bools into `i8` because
-                    // LLVM's i1 comparisons are broken.
-                    (bx.zext(lhs, Type::i8(bx.cx)),
-                     bx.zext(rhs, Type::i8(bx.cx)))
-                } else {
-                    (lhs, rhs)
-                };
-
                 bx.icmp(
                     base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed),
                     lhs, rhs
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 06d94e8d155..d19b5af2527 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -88,7 +88,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
                self.to_raw_string(),
                cx.codegen_unit.name());
 
-        let symbol_name = self.symbol_name(cx.tcx);
+        let symbol_name = self.symbol_name(cx.tcx).as_str();
 
         debug!("symbol {}", &symbol_name);
 
diff --git a/src/librustc_trans_utils/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs
index f3b7326b210..be5bff60805 100644
--- a/src/librustc_trans_utils/symbol_names.rs
+++ b/src/librustc_trans_utils/symbol_names.rs
@@ -229,7 +229,7 @@ fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
                          -> ty::SymbolName
 {
-    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() }
+    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_interned_str() }
 }
 
 fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
@@ -355,12 +355,12 @@ impl SymbolPathBuffer {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16)
         };
-        result.result.push_str(&symbol.name);
+        result.result.push_str(&symbol.name.as_str());
         result
     }
 
     fn into_interned(self) -> ty::SymbolName {
-        ty::SymbolName { name: Symbol::intern(&self.result).as_str() }
+        ty::SymbolName { name: Symbol::intern(&self.result).as_interned_str() }
     }
 
     fn finish(mut self, hash: u64) -> String {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 6cdce127308..93dbba6e873 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -101,7 +101,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     {
         let tcx = self.tcx();
         let lifetime_name = |def_id| {
-            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_str()
+            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_interned_str()
         };
 
         let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
@@ -981,7 +981,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 let item_def_id = tcx.hir.local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)];
-                tcx.mk_param(index, tcx.hir.name(node_id).as_str())
+                tcx.mk_param(index, tcx.hir.name(node_id).as_interned_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index a87058d1fa5..3199ff17ae9 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -120,15 +120,15 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
 
         let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
 
-        let mut selcx = traits::SelectionContext::new(self.fcx);
         let obligation = traits::Obligation::new(cause.clone(),
                                                  self.fcx.param_env,
                                                  trait_ref.to_predicate());
-        if !selcx.evaluate_obligation(&obligation) {
+        if !self.fcx.predicate_may_hold(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
             return None;
         }
 
+        let mut selcx = traits::SelectionContext::new(self.fcx);
         let normalized = traits::normalize_projection_type(&mut selcx,
                                                            self.fcx.param_env,
                                                            ty::ProjectionTy::from_ref_and_name(
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index c9e53fa7674..91264849cad 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -732,8 +732,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if impl_ty.synthetic != trait_ty.synthetic {
             let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
             let impl_span = tcx.hir.span(impl_node_id);
-            let trait_node_id = tcx.hir.as_local_node_id(trait_ty.def_id).unwrap();
-            let trait_span = tcx.hir.span(trait_node_id);
+            let trait_span = tcx.def_span(trait_ty.def_id);
             let mut err = struct_span_err!(tcx.sess,
                                            impl_span,
                                            E0643,
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 283fbf8fecc..fcf7541a159 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_str());
+    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
     let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
@@ -341,7 +341,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                it: &hir::ForeignItem) {
     let param = |n| {
-        let name = Symbol::intern(&format!("P{}", n)).as_str();
+        let name = Symbol::intern(&format!("P{}", n)).as_interned_str();
         tcx.mk_param(n, name)
     };
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 5f55ee6163b..5f904a9419b 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -277,8 +277,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                      poly_trait_ref.to_predicate());
 
         // Now we want to know if this can be matched
-        let mut selcx = traits::SelectionContext::new(self);
-        if !selcx.evaluate_obligation(&obligation) {
+        if !self.predicate_may_hold(&obligation) {
             debug!("--> Cannot match obligation");
             return None; // Cannot be matched, no such method resolution is possible.
         }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index b41a6dcf384..476ae680973 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                     let predicate = trait_ref.to_predicate();
                     let obligation =
                         traits::Obligation::new(cause.clone(), self.param_env, predicate);
-                    if !selcx.evaluate_obligation(&obligation) {
+                    if !self.predicate_may_hold(&obligation) {
                         if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
                             // This candidate's primary obligation doesn't even
                             // select - don't bother registering anything in
@@ -1201,7 +1201,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             // Evaluate those obligations to see if they might possibly hold.
             for o in candidate_obligations.into_iter().chain(sub_obligations) {
                 let o = self.resolve_type_vars_if_possible(&o);
-                if !selcx.evaluate_obligation(&o) {
+                if !self.predicate_may_hold(&o) {
                     result = ProbeResult::NoMatch;
                     if let &ty::Predicate::Trait(ref pred) = &o.predicate {
                         possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index d8907866467..2dc7c7fe71a 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -19,7 +19,7 @@ use hir::def::Def;
 use hir::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::lang_items::FnOnceTraitLangItem;
 use namespace::Namespace;
-use rustc::traits::{Obligation, SelectionContext};
+use rustc::traits::Obligation;
 use util::nodemap::FxHashSet;
 
 use syntax::ast;
@@ -65,7 +65,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                              self.body_id,
                                              self.param_env,
                                              poly_trait_ref.to_predicate());
-                        SelectionContext::new(self).evaluate_obligation(&obligation)
+                        self.predicate_may_hold(&obligation)
                     })
                 })
             }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 787df7c6479..db859e42057 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -124,7 +124,7 @@ use syntax::attr;
 use syntax::codemap::{original_sp, Spanned};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, InternedString, keywords};
+use syntax::symbol::{Symbol, LocalInternedString, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{self, BytePos, Span, MultiSpan};
 
@@ -3172,7 +3172,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // Return an hint about the closest match in field names
     fn suggest_field_name(variant: &'tcx ty::VariantDef,
                           field: &Spanned<ast::Name>,
-                          skip: Vec<InternedString>)
+                          skip: Vec<LocalInternedString>)
                           -> Option<Symbol> {
         let name = field.node.as_str();
         let names = variant.fields.iter().filter_map(|field| {
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 9c4807bec2f..d0ff44c8e7e 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -655,7 +655,7 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
             // local so it should be okay to just unwrap everything.
             let trait_def_id = impl_params[&method_param.name];
             let trait_decl_span = tcx.def_span(trait_def_id);
-            error_194(tcx, type_span, trait_decl_span, &method_param.name[..]);
+            error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
         }
     }
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 2ebbd64cab9..1b8f2e661c3 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -244,7 +244,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_owner_def_id = tcx.hir.local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
     let index = generics.type_param_to_index[&def_id];
-    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_str());
+    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -842,7 +842,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     opt_self = Some(ty::TypeParameterDef {
                         index: 0,
-                        name: keywords::SelfType.name().as_str(),
+                        name: keywords::SelfType.name().as_interned_str(),
                         def_id: tcx.hir.local_def_id(param_id),
                         has_default: false,
                         object_lifetime_default: rl::Set1::Empty,
@@ -888,7 +888,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
     let regions = early_lifetimes.enumerate().map(|(i, l)| {
         ty::RegionParameterDef {
-            name: l.lifetime.name.name().as_str(),
+            name: l.lifetime.name.name().as_interned_str(),
             index: own_start + i as u32,
             def_id: tcx.hir.local_def_id(l.lifetime.id),
             pure_wrt_drop: l.pure_wrt_drop,
@@ -918,7 +918,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         ty::TypeParameterDef {
             index: type_start + i as u32,
-            name: p.name.as_str(),
+            name: p.name.as_interned_str(),
             def_id: tcx.hir.local_def_id(p.id),
             has_default: p.default.is_some(),
             object_lifetime_default:
@@ -937,7 +937,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure kind
         types.push(ty::TypeParameterDef {
             index: type_start,
-            name: Symbol::intern("<closure_kind>").as_str(),
+            name: Symbol::intern("<closure_kind>").as_interned_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -948,7 +948,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure signature
         types.push(ty::TypeParameterDef {
             index: type_start + 1,
-            name: Symbol::intern("<closure_signature>").as_str(),
+            name: Symbol::intern("<closure_signature>").as_interned_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -959,7 +959,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.with_freevars(node_id, |fv| {
             types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
                 index: type_start + i,
-                name: Symbol::intern("<upvar>").as_str(),
+                name: Symbol::intern("<upvar>").as_interned_str(),
                 def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
@@ -1429,7 +1429,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: tcx.hir.local_def_id(param.lifetime.id),
             index,
-            name: param.lifetime.name.name().as_str(),
+            name: param.lifetime.name.name().as_interned_str(),
         }));
         index += 1;
 
@@ -1443,7 +1443,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Collect the predicates that were written inline by the user on each
     // type parameter (e.g., `<T:Foo>`).
     for param in ast_generics.ty_params() {
-        let param_ty = ty::ParamTy::new(index, param.name.as_str()).to_ty(tcx);
+        let param_ty = ty::ParamTy::new(index, param.name.as_interned_str()).to_ty(tcx);
         index += 1;
 
         let bounds = compute_bounds(&icx,
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 23fe91ffdeb..958960d3a36 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -71,6 +71,8 @@ This API is completely unstable and subject to change.
 
 #![allow(non_camel_case_types)]
 
+#![cfg_attr(stage0, feature(dyn_trait))]
+
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
@@ -81,7 +83,6 @@ This API is completely unstable and subject to change.
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(slice_sort_by_cached_key)]
-#![feature(dyn_trait)]
 #![feature(never_type)]
 
 #[macro_use] extern crate log;
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 477b576ad21..221fc4dab72 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -224,7 +224,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                     let name = if p.name == "" {
                         hir::LifetimeName::Static
                     } else {
-                        hir::LifetimeName::Name(Symbol::intern(&p.name))
+                        hir::LifetimeName::Name(p.name.as_symbol())
                     };
 
                     hir::Lifetime {
@@ -261,7 +261,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                     span: DUMMY_SP,
                     def: Def::TyParam(param.def_id),
                     segments: HirVec::from_vec(vec![
-                        hir::PathSegment::from_name(Symbol::intern(&param.name))
+                        hir::PathSegment::from_name(param.name.as_symbol())
                     ]),
                 }),
             )),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fb05cbfe32c..6623d5ab3c2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1367,7 +1367,7 @@ impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
         let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, &cx.tcx.item_name(did),
+        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
             Some(did), false, vec![], empty);
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
         TraitBound(PolyTrait {
@@ -1474,7 +1474,7 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         let (trait_ref, ref bounds) = *self;
         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
-        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id),
+        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
                                  Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
@@ -2801,7 +2801,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     AdtKind::Enum => TypeKind::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, &cx.tcx.item_name(did),
+                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], substs);
                 ResolvedPath {
                     path,
@@ -2812,7 +2812,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             }
             ty::TyForeign(did) => {
                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
-                let path = external_path(cx, &cx.tcx.item_name(did),
+                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], Substs::empty());
                 ResolvedPath {
                     path: path,
@@ -2830,7 +2830,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
                     for did in obj.auto_traits() {
                         let empty = cx.tcx.intern_substs(&[]);
-                        let path = external_path(cx, &cx.tcx.item_name(did),
+                        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                             Some(did), false, vec![], empty);
                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
                         let bound = TraitBound(PolyTrait {
@@ -2853,7 +2853,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                         });
                     }
 
-                    let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
+                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
                         false, bindings, principal.skip_binder().substs);
                     ResolvedPath {
                         path,
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index fd54e9bd1e0..5e93b20ea17 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -146,9 +146,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
         window.rootPath = \"{root_path}\";\
         window.currentCrate = \"{krate}\";\
     </script>\
+    <script src=\"{root_path}aliases.js\"></script>\
     <script src=\"{root_path}main{suffix}.js\"></script>\
     <script defer src=\"{root_path}search-index.js\"></script>\
-    <script defer src=\"{root_path}aliases.js\"></script>\
 </body>\
 </html>",
     css_extension = if css_file_extension {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 82449e9b5f9..4e9781cc560 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1595,6 +1595,8 @@ impl<'a> Settings<'a> {
             settings: vec![
                 ("item-declarations", "Auto-hide item declarations.", true),
                 ("item-attributes", "Auto-hide item attributes.", true),
+                ("go-to-only-result", "Directly go to item in search if there is only one result",
+                 false),
             ],
             root_path,
             suffix,
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 58a57f43d37..bcad2eb19f5 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1013,7 +1013,8 @@
                 'returned': sortResults(results_returned, true),
                 'others': sortResults(results),
             };
-            if (ALIASES[window.currentCrate][query.raw]) {
+            if (ALIASES && ALIASES[window.currentCrate] &&
+                    ALIASES[window.currentCrate][query.raw]) {
                 var aliases = ALIASES[window.currentCrate][query.raw];
                 for (var i = 0; i < aliases.length; ++i) {
                     ret['others'].unshift(aliases[i]);
@@ -1188,6 +1189,44 @@
             return '<span>' + path.replace(/::/g, '::</span><span>');
         }
 
+        function buildHrefAndPath(item) {
+            var displayPath;
+            var href;
+            var type = itemTypes[item.ty];
+            var name = item.name;
+
+            if (type === 'mod') {
+                displayPath = item.path + '::';
+                href = rootPath + item.path.replace(/::/g, '/') + '/' +
+                       name + '/index.html';
+            } else if (type === "primitive") {
+                displayPath = "";
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + type + '.' + name + '.html';
+            } else if (type === "externcrate") {
+                displayPath = "";
+                href = rootPath + name + '/index.html';
+            } else if (item.parent !== undefined) {
+                var myparent = item.parent;
+                var anchor = '#' + type + '.' + name;
+                var parentType = itemTypes[myparent.ty];
+                if (parentType === "primitive") {
+                    displayPath = myparent.name + '::';
+                } else {
+                    displayPath = item.path + '::' + myparent.name + '::';
+                }
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + parentType +
+                       '.' + myparent.name +
+                       '.html' + anchor;
+            } else {
+                displayPath = item.path + '::';
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + type + '.' + name + '.html';
+            }
+            return [displayPath, href];
+        }
+
         function addTab(array, query, display) {
             var extraStyle = '';
             if (display === false) {
@@ -1211,35 +1250,9 @@
                     name = item.name;
                     type = itemTypes[item.ty];
 
-                    if (type === 'mod') {
-                        displayPath = item.path + '::';
-                        href = rootPath + item.path.replace(/::/g, '/') + '/' +
-                               name + '/index.html';
-                    } else if (type === "primitive") {
-                        displayPath = "";
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + type + '.' + name + '.html';
-                    } else if (type === "externcrate") {
-                        displayPath = "";
-                        href = rootPath + name + '/index.html';
-                    } else if (item.parent !== undefined) {
-                        var myparent = item.parent;
-                        var anchor = '#' + type + '.' + name;
-                        var parentType = itemTypes[myparent.ty];
-                        if (parentType === "primitive") {
-                            displayPath = myparent.name + '::';
-                        } else {
-                            displayPath = item.path + '::' + myparent.name + '::';
-                        }
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + parentType +
-                               '.' + myparent.name +
-                               '.html' + anchor;
-                    } else {
-                        displayPath = item.path + '::';
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + type + '.' + name + '.html';
-                    }
+                    var res = buildHrefAndPath(item);
+                    var href = res[1];
+                    var displayPath = res[0];
 
                     output += '<tr class="' + type + ' result"><td>' +
                               '<a href="' + href + '">' +
@@ -1268,6 +1281,16 @@
         }
 
         function showResults(results) {
+            if (results['others'].length === 1 &&
+                getCurrentValue('rustdoc-go-to-only-result') === "true") {
+                var elem = document.createElement('a');
+                var res = buildHrefAndPath(results['others'][0]);
+                elem.href = res[1];
+                elem.style.display = 'none';
+                // For firefox, we need the element to be in the DOM so it can be clicked.
+                document.body.appendChild(elem);
+                elem.click();
+            }
             var output, query = getQuery(search_input.value);
 
             currentResults = query.id;
@@ -1721,6 +1744,9 @@
 
     function toggleAllDocs(pageId) {
         var toggle = document.getElementById("toggle-all-docs");
+        if (!toggle) {
+            return;
+        }
         if (hasClass(toggle, "will-expand")) {
             updateLocalStorage("rustdoc-collapse", "false");
             removeClass(toggle, "will-expand");
@@ -1977,7 +2003,7 @@
                 collapseDocs(e.previousSibling.childNodes[0], "toggle");
             }
         }
-    })
+    });
 
     autoCollapseAllImpls(getPageId());
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 614386a583a..8efb51bccd8 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -13,6 +13,8 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
+#![cfg_attr(stage0, feature(dyn_trait))]
+
 #![feature(ascii_ctype)]
 #![feature(rustc_private)]
 #![feature(box_patterns)]
@@ -23,7 +25,6 @@
 #![feature(test)]
 #![feature(vec_remove_item)]
 #![feature(entry_and_modify)]
-#![feature(dyn_trait)]
 
 extern crate arena;
 extern crate getopts;
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 0331e90164f..a4a83712a08 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -375,9 +375,6 @@ declare_features! (
     // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
     (active, non_exhaustive, "1.22.0", Some(44109), None),
 
-    // Trait object syntax with `dyn` prefix
-    (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)),
-
     // `crate` as visibility modifier, synonymous to `pub(crate)`
     (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)),
 
@@ -592,6 +589,8 @@ declare_features! (
     (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
     // Allows #[target_feature(...)]
     (accepted, target_feature, "1.27.0", None, None),
+    // Trait object syntax with `dyn` prefix
+    (accepted, dyn_trait, "1.27.0", Some(44662), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -1657,10 +1656,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, never_type, ty.span,
                                    "The `!` type is experimental");
             }
-            ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
-                gate_feature_post!(&self, dyn_trait, ty.span,
-                                   "`dyn Trait` syntax is unstable");
-            }
             _ => {}
         }
         visit::walk_ty(self, ty)
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 44394384c7a..938711ca1d4 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -277,9 +277,10 @@ impl Token {
             DotDot | DotDotDot | DotDotEq     | // range notation
             Lt | BinOp(Shl)                   | // associated path
             ModSep                            | // global path
+            Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
             Interpolated(ref nt) => match nt.0 {
-                NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true,
+                NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) | NtLifetime(..) => true,
                 _ => false,
             },
             _ => false,
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 5e96b5ce673..658408519b9 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -21,6 +21,7 @@ use symbol::{Ident, Symbol};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashSet;
 use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
@@ -117,6 +118,32 @@ impl Mark {
             true
         })
     }
+
+    /// Computes a mark such that both input marks are descendants of (or equal to) the returned
+    /// mark. That is, the following holds:
+    ///
+    /// ```rust
+    /// let la = least_ancestor(a, b);
+    /// assert!(a.is_descendant_of(la))
+    /// assert!(b.is_descendant_of(la))
+    /// ```
+    pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
+        HygieneData::with(|data| {
+            // Compute the path from a to the root
+            let mut a_path = FxHashSet::<Mark>();
+            while a != Mark::root() {
+                a_path.insert(a);
+                a = data.marks[a.0 as usize].parent;
+            }
+
+            // While the path from b to the root hasn't intersected, move up the tree
+            while !a_path.contains(&b) {
+                b = data.marks[b.0 as usize].parent;
+            }
+
+            b
+        })
+    }
 }
 
 pub struct HygieneData {
@@ -238,6 +265,22 @@ impl SyntaxContext {
         })
     }
 
+    /// Pulls a single mark off of the syntax context. This effectively moves the
+    /// context up one macro definition level. That is, if we have a nested macro
+    /// definition as follows:
+    ///
+    /// ```rust
+    /// macro_rules! f {
+    ///    macro_rules! g {
+    ///        ...
+    ///    }
+    /// }
+    /// ```
+    ///
+    /// and we have a SyntaxContext that is referring to something declared by an invocation
+    /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
+    /// invocation of f that created g1.
+    /// Returns the mark that was removed.
     pub fn remove_mark(&mut self) -> Mark {
         HygieneData::with(|data| {
             let outer_mark = data.syntax_contexts[self.0 as usize].outer_mark;
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9a7d1fd8ee6..8d37b4aa396 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -291,6 +291,12 @@ impl Span {
         self.ctxt().outer().expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self)
     }
 
+    /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
+    /// if any
+    pub fn parent(self) -> Option<Span> {
+        self.ctxt().outer().expn_info().map(|i| i.call_site)
+    }
+
     /// Return the source callee.
     ///
     /// Returns None if the supplied span has no expansion trace,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 556ee162c6e..4a8b1e8b1c1 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -18,6 +18,7 @@ use {Span, DUMMY_SP, GLOBALS};
 use rustc_data_structures::fx::FxHashMap;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
+use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::hash::{Hash, Hasher};
 
 #[derive(Copy, Clone, Eq)]
@@ -36,6 +37,11 @@ impl Ident {
         Ident::new(name, DUMMY_SP)
     }
 
+    /// 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())
+    }
+
     /// Maps a string to an identifier with an empty syntax context.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_empty_ctxt(Symbol::intern(string))
@@ -138,14 +144,20 @@ impl Symbol {
         with_interner(|interner| interner.gensymed(self))
     }
 
-    pub fn as_str(self) -> InternedString {
+    pub fn as_str(self) -> LocalInternedString {
         with_interner(|interner| unsafe {
-            InternedString {
+            LocalInternedString {
                 string: ::std::mem::transmute::<&str, &str>(interner.get(self))
             }
         })
     }
 
+    pub fn as_interned_str(self) -> InternedString {
+        with_interner(|interner| InternedString {
+            symbol: interner.interned(self)
+        })
+    }
+
     pub fn as_u32(self) -> u32 {
         self.0
     }
@@ -365,84 +377,208 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
     GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
 }
 
-/// Represents a string stored in the thread-local interner. Because the
-/// interner lives for the life of the thread, this can be safely treated as an
-/// immortal string, as long as it never crosses between threads.
-///
-/// FIXME(pcwalton): You must be careful about what you do in the destructors
-/// of objects stored in TLS, because they may run after the interner is
-/// destroyed. In particular, they must not access string contents. This can
-/// be fixed in the future by just leaking all strings until thread death
-/// somehow.
+/// Represents a string stored in the interner. Because the interner outlives any thread
+/// which uses this type, we can safely treat `string` which points to interner data,
+/// as an immortal string, as long as this type never crosses between threads.
+// FIXME: Ensure that the interner outlives any thread which uses LocalInternedString,
+//        by creating a new thread right after constructing the interner
 #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
-pub struct InternedString {
+pub struct LocalInternedString {
     string: &'static str,
 }
 
-impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
+impl LocalInternedString {
+    pub fn as_interned_str(self) -> InternedString {
+        InternedString {
+            symbol: Symbol::intern(self.string)
+        }
+    }
+}
+
+impl<U: ?Sized> ::std::convert::AsRef<U> for LocalInternedString
+where
+    str: ::std::convert::AsRef<U>
+{
     fn as_ref(&self) -> &U {
         self.string.as_ref()
     }
 }
 
-impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
+impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for LocalInternedString {
     fn eq(&self, other: &T) -> bool {
         self.string == other.deref()
     }
 }
 
-impl ::std::cmp::PartialEq<InternedString> for str {
-    fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for str {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         self == other.string
     }
 }
 
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
-    fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a str {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         *self == other.string
     }
 }
 
-impl ::std::cmp::PartialEq<InternedString> for String {
-    fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for String {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         self == other.string
     }
 }
 
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
-    fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a String {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         *self == other.string
     }
 }
 
-impl !Send for InternedString { }
+impl !Send for LocalInternedString {}
+impl !Sync for LocalInternedString {}
 
-impl ::std::ops::Deref for InternedString {
+impl ::std::ops::Deref for LocalInternedString {
     type Target = str;
     fn deref(&self) -> &str { self.string }
 }
 
-impl fmt::Debug for InternedString {
+impl fmt::Debug for LocalInternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(self.string, f)
     }
 }
 
-impl fmt::Display for InternedString {
+impl fmt::Display for LocalInternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(self.string, f)
     }
 }
 
+impl Decodable for LocalInternedString {
+    fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
+        Ok(Symbol::intern(&d.read_str()?).as_str())
+    }
+}
+
+impl Encodable for LocalInternedString {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(self.string)
+    }
+}
+
+/// Represents a string stored in the string interner
+#[derive(Clone, Copy, Eq)]
+pub struct InternedString {
+    symbol: Symbol,
+}
+
+impl InternedString {
+    pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
+        let str = with_interner(|interner| {
+            interner.get(self.symbol) as *const str
+        });
+        // This is safe because the interner keeps string alive until it is dropped.
+        // We can access it because we know the interner is still alive since we use a
+        // scoped thread local to access it, and it was alive at the begining of this scope
+        unsafe { f(&*str) }
+    }
+
+    pub fn as_symbol(self) -> Symbol {
+        self.symbol
+    }
+
+    pub fn as_str(self) -> LocalInternedString {
+        self.symbol.as_str()
+    }
+}
+
+impl Hash for InternedString {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.with(|str| str.hash(state))
+    }
+}
+
+impl PartialOrd<InternedString> for InternedString {
+    fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
+        if self.symbol == other.symbol {
+            return Some(Ordering::Equal);
+        }
+        self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str)))
+    }
+}
+
+impl Ord for InternedString {
+    fn cmp(&self, other: &InternedString) -> Ordering {
+        if self.symbol == other.symbol {
+            return Ordering::Equal;
+        }
+        self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str)))
+    }
+}
+
+impl<T: ::std::ops::Deref<Target = str>> PartialEq<T> for InternedString {
+    fn eq(&self, other: &T) -> bool {
+        self.with(|string| string == other.deref())
+    }
+}
+
+impl PartialEq<InternedString> for InternedString {
+    fn eq(&self, other: &InternedString) -> bool {
+        self.symbol == other.symbol
+    }
+}
+
+impl PartialEq<InternedString> for str {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| self == string)
+    }
+}
+
+impl<'a> PartialEq<InternedString> for &'a str {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| *self == string)
+    }
+}
+
+impl PartialEq<InternedString> for String {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| self == string)
+    }
+}
+
+impl<'a> PartialEq<InternedString> for &'a String {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| *self == string)
+    }
+}
+
+impl ::std::convert::From<InternedString> for String {
+    fn from(val: InternedString) -> String {
+        val.as_symbol().to_string()
+    }
+}
+
+impl fmt::Debug for InternedString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.with(|str| fmt::Debug::fmt(&str, f))
+    }
+}
+
+impl fmt::Display for InternedString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.with(|str| fmt::Display::fmt(&str, f))
+    }
+}
+
 impl Decodable for InternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
-        Ok(Symbol::intern(&d.read_str()?).as_str())
+        Ok(Symbol::intern(&d.read_str()?).as_interned_str())
     }
 }
 
 impl Encodable for InternedString {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self.string)
+        self.with(|string| s.emit_str(string))
     }
 }
 
diff --git a/src/stage0.txt b/src/stage0.txt
index e8db3358cf0..a5ad2b315a1 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-04-04
+date: 2018-04-24
 rustc: beta
 cargo: beta
 
diff --git a/src/test/codegen/call-metadata.rs b/src/test/codegen/call-metadata.rs
new file mode 100644
index 00000000000..20d42ed852d
--- /dev/null
+++ b/src/test/codegen/call-metadata.rs
@@ -0,0 +1,29 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks that range metadata gets emitted on calls to functions returning a
+// scalar value.
+
+// compile-flags: -C no-prepopulate-passes
+// min-llvm-version 4.0
+
+
+#![crate_type = "lib"]
+
+pub fn test() {
+    // CHECK: call i8 @some_true(), !range [[R0:![0-9]+]]
+    // CHECK: [[R0]] = !{i8 0, i8 3}
+    some_true();
+}
+
+#[no_mangle]
+fn some_true() -> Option<bool> {
+    Some(true)
+}
diff --git a/src/test/codegen/target-feature-on-functions.rs b/src/test/codegen/target-feature-on-functions.rs
new file mode 100644
index 00000000000..e3cc2c753e5
--- /dev/null
+++ b/src/test/codegen/target-feature-on-functions.rs
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// only-x86_64
+// compile-flags: -C target-feature=+avx
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn foo() {
+    // CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} }
+}
diff --git a/src/test/compile-fail/attr-usage-inline.rs b/src/test/compile-fail/attr-usage-inline.rs
index c6b9b016331..250905dbdcd 100644
--- a/src/test/compile-fail/attr-usage-inline.rs
+++ b/src/test/compile-fail/attr-usage-inline.rs
@@ -13,7 +13,7 @@
 #[inline]
 fn f() {}
 
-#[inline] //~ ERROR: attribute should be applied to function
+#[inline] //~ ERROR: attribute should be applied to function or closure
 struct S;
 
 fn main() {}
diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
index 1333167b780..1e86603c19e 100644
--- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
+++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
@@ -10,7 +10,7 @@
 
 // ignore-tidy-linelength
 
-// revisions: nll_beyond nll_target
+// revisions: nll_target
 
 // The following revisions are disabled due to missing support from two-phase beyond autorefs
 //[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
diff --git a/src/test/compile-fail/extern-macro.rs b/src/test/compile-fail/extern-macro.rs
index 08269ce5c7e..4267103ab9a 100644
--- a/src/test/compile-fail/extern-macro.rs
+++ b/src/test/compile-fail/extern-macro.rs
@@ -10,7 +10,7 @@
 
 // #41719
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 fn main() {
     enum Foo {}
diff --git a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
index eea7ca20957..d6707f59011 100644
--- a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
+++ b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
@@ -28,4 +28,15 @@ impl Bar for () {
     //~^ Error method `bar` has incompatible signature for trait
 }
 
+// With non-local trait (#49841):
+
+use std::hash::{Hash, Hasher};
+
+struct X;
+
+impl Hash for X {
+    fn hash(&self, hasher: &mut impl Hasher) {}
+    //~^ Error method `hash` has incompatible signature for trait
+}
+
 fn main() {}
diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs
index 038eacaf110..2891cd59e3e 100644
--- a/src/test/compile-fail/impl-trait/where-allowed.rs
+++ b/src/test/compile-fail/impl-trait/where-allowed.rs
@@ -10,7 +10,6 @@
 
 //! A simple test for testing many permutations of allowedness of
 //! impl Trait
-#![feature(dyn_trait)]
 use std::fmt::Debug;
 
 // Allowed
diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs
index 2aa87f8424b..fc365a4b9aa 100644
--- a/src/test/compile-fail/issue-23080-2.rs
+++ b/src/test/compile-fail/issue-23080-2.rs
@@ -10,6 +10,8 @@
 
 // ignore-tidy-linelength
 
+//~^^^^^^^^^^^^ ERROR
+
 #![feature(optin_builtin_traits)]
 
 unsafe auto trait Trait {
@@ -22,5 +24,4 @@ fn call_method<T: Trait>(x: T) {}
 fn main() {
     // ICE
     call_method(());
-    //~^ ERROR
 }
diff --git a/src/test/compile-fail/issue-31769.rs b/src/test/compile-fail/issue-31769.rs
index 7f73d9076ec..2bd45deeab4 100644
--- a/src/test/compile-fail/issue-31769.rs
+++ b/src/test/compile-fail/issue-31769.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    #[inline] struct Foo;  //~ ERROR attribute should be applied to function
+    #[inline] struct Foo;  //~ ERROR attribute should be applied to function or closure
     #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum or union
 }
diff --git a/src/test/compile-fail/issue-43988.rs b/src/test/compile-fail/issue-43988.rs
index ff1fdaef416..0dfa9f6f0d3 100644
--- a/src/test/compile-fail/issue-43988.rs
+++ b/src/test/compile-fail/issue-43988.rs
@@ -14,12 +14,12 @@ fn main() {
 
     #[inline]
     let _a = 4;
-    //~^^ ERROR attribute should be applied to function
+    //~^^ ERROR attribute should be applied to function or closure
 
 
     #[inline(XYZ)]
     let _b = 4;
-    //~^^ ERROR attribute should be applied to function
+    //~^^ ERROR attribute should be applied to function or closure
 
     #[repr(nothing)]
     let _x = 0;
@@ -40,7 +40,7 @@ fn main() {
 
     #[inline(ABC)]
     foo();
-    //~^^ ERROR attribute should be applied to function
+    //~^^ ERROR attribute should be applied to function or closure
 
     let _z = #[repr] 1;
     //~^ ERROR attribute should not be applied to an expression
diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs
index 40412087cef..7046ee12b50 100644
--- a/src/test/compile-fail/macros-nonfatal-errors.rs
+++ b/src/test/compile-fail/macros-nonfatal-errors.rs
@@ -13,7 +13,6 @@
 
 #![feature(asm)]
 #![feature(trace_macros, concat_idents)]
-#![feature(proc_macro_path_invoc)]
 
 #[derive(Default)] //~ ERROR
 enum OrDeriveThis {}
diff --git a/src/test/compile-fail/mir_check_cast_unsize.rs b/src/test/compile-fail/mir_check_cast_unsize.rs
index e30bed61058..a2c840a7098 100644
--- a/src/test/compile-fail/mir_check_cast_unsize.rs
+++ b/src/test/compile-fail/mir_check_cast_unsize.rs
@@ -11,7 +11,6 @@
 // compile-flags: -Z borrowck=mir
 
 #![allow(dead_code)]
-#![feature(dyn_trait)]
 
 use std::fmt::Debug;
 
diff --git a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
index b64829edaa2..63cb6e82c25 100644
--- a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
+++ b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
@@ -10,7 +10,6 @@
 
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
-#![feature(proc_macro_path_invoc)]
 
 mod priv_nominal {
     pub struct Pub;
diff --git a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs
index 062dc533617..bdc0c680a92 100644
--- a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs
+++ b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs
@@ -10,7 +10,6 @@
 
 // ignore-tidy-linelength
 
-#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
diff --git a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
index 0dfa61a18ab..c25616c5435 100644
--- a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
+++ b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs
index 97d6b470d33..0c393f02323 100644
--- a/src/test/compile-fail/private-inferred-type-3.rs
+++ b/src/test/compile-fail/private-inferred-type-3.rs
@@ -18,7 +18,6 @@
 // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
 // error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
 
-#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro)]
 
 extern crate private_inferred_type as ext;
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
index dfc0107e075..5af8b063c16 100644
--- a/src/test/compile-fail/private-inferred-type.rs
+++ b/src/test/compile-fail/private-inferred-type.rs
@@ -11,7 +11,6 @@
 #![feature(associated_consts)]
 #![feature(decl_macro)]
 #![allow(private_in_public)]
-#![feature(proc_macro_path_invoc)]
 
 mod m {
     fn priv_fn() {}
diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs
index 0dd1a4e7d73..1b1a238a941 100644
--- a/src/test/compile-fail/trait-bounds-not-on-struct.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(dyn_trait)]
 #![allow(bare_trait_object)]
 
 struct Foo;
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
index 219eca6fd21..66a6e6afed3 100644
--- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
+++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
@@ -11,8 +11,6 @@
 // compile-pass
 // failure-status: 1
 
-#![feature(dyn_trait)]
-
 use std::error::Error;
 use std::io;
 
diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs
index 9bb8f691915..f359735d2f7 100644
--- a/src/test/run-pass-fulldeps/macro-quote-test.rs
+++ b/src/test/run-pass-fulldeps/macro-quote-test.rs
@@ -13,7 +13,7 @@
 // aux-build:hello_macro.rs
 // ignore-stage1
 
-#![feature(proc_macro, proc_macro_path_invoc, proc_macro_non_items)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate hello_macro;
 
diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs
index 399823ec92d..01066794242 100644
--- a/src/test/run-pass/dyn-trait.rs
+++ b/src/test/run-pass/dyn-trait.rs
@@ -10,8 +10,6 @@
 
 // ignore-pretty `dyn ::foo` parses differently in the current edition
 
-#![feature(dyn_trait)]
-
 use std::fmt::Display;
 
 static BYTE: u8 = 33;
diff --git a/src/test/run-pass/hygiene/issue-47311.rs b/src/test/run-pass/hygiene/issue-47311.rs
index c4391ad0577..3b6890cdce6 100644
--- a/src/test/run-pass/hygiene/issue-47311.rs
+++ b/src/test/run-pass/hygiene/issue-47311.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #![allow(unused)]
 
 macro m($S:ident, $x:ident) {
diff --git a/src/test/run-pass/hygiene/issue-47312.rs b/src/test/run-pass/hygiene/issue-47312.rs
index 0cda0e7c7cc..5e83f3808d8 100644
--- a/src/test/run-pass/hygiene/issue-47312.rs
+++ b/src/test/run-pass/hygiene/issue-47312.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #![allow(unused)]
 
 mod foo {
diff --git a/src/test/run-pass/hygiene/legacy_interaction.rs b/src/test/run-pass/hygiene/legacy_interaction.rs
index 5395ef35882..683a15b99ae 100644
--- a/src/test/run-pass/hygiene/legacy_interaction.rs
+++ b/src/test/run-pass/hygiene/legacy_interaction.rs
@@ -12,7 +12,7 @@
 
 // aux-build:legacy_interaction.rs
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #[allow(unused)]
 
 extern crate legacy_interaction;
diff --git a/src/test/run-pass/hygiene/lexical.rs b/src/test/run-pass/hygiene/lexical.rs
index 73deda0777e..cb02a17fec3 100644
--- a/src/test/run-pass/hygiene/lexical.rs
+++ b/src/test/run-pass/hygiene/lexical.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod bar {
     mod baz {
diff --git a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
index 66e83eb7cac..55206950214 100644
--- a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
+++ b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
@@ -13,7 +13,7 @@
 // aux-build:my_crate.rs
 // aux-build:unhygienic_example.rs
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 extern crate unhygienic_example;
 extern crate my_crate; // (b)
diff --git a/src/test/run-pass/hygiene/xcrate.rs b/src/test/run-pass/hygiene/xcrate.rs
index 95d7ae6db60..6df3a34d3c8 100644
--- a/src/test/run-pass/hygiene/xcrate.rs
+++ b/src/test/run-pass/hygiene/xcrate.rs
@@ -12,7 +12,7 @@
 
 // aux-build:xcrate.rs
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 extern crate xcrate;
 
diff --git a/src/test/ui/feature-gate-dyn-trait.rs b/src/test/run-pass/issue-47703-tuple.rs
index 4b3803d019b..4fec3efc0a0 100644
--- a/src/test/ui/feature-gate-dyn-trait.rs
+++ b/src/test/run-pass/issue-47703-tuple.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,7 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Trait {}
-type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
+#![feature(nll)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn consume(x: (&mut (), WithDrop)) -> &mut () { x.0 }
 
 fn main() {}
diff --git a/src/test/run-pass/issue-49632.rs b/src/test/run-pass/issue-49632.rs
new file mode 100644
index 00000000000..8cbb7d21af7
--- /dev/null
+++ b/src/test/run-pass/issue-49632.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(stmt_expr_attributes)]
+
+pub fn main() {
+    let _x = #[inline(always)] || {};
+    let _y = #[inline(never)] || {};
+    let _z = #[inline] || {};
+}
diff --git a/src/test/run-pass/nll/issue-48623-closure.rs b/src/test/run-pass/nll/issue-48623-closure.rs
new file mode 100644
index 00000000000..08ff54a428e
--- /dev/null
+++ b/src/test/run-pass/nll/issue-48623-closure.rs
@@ -0,0 +1,24 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn reborrow_from_closure(r: &mut ()) -> &mut () {
+    let d = WithDrop;
+    (move || { d; &mut *r })()
+}
+
+fn main() {}
diff --git a/src/test/run-pass/nll/issue-48623-generator.rs b/src/test/run-pass/nll/issue-48623-generator.rs
new file mode 100644
index 00000000000..524837c4ba9
--- /dev/null
+++ b/src/test/run-pass/nll/issue-48623-generator.rs
@@ -0,0 +1,25 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+#![feature(generators, generator_trait)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn reborrow_from_generator(r: &mut ()) {
+    let d = WithDrop;
+    move || { d; yield; &mut *r };
+}
+
+fn main() {}
diff --git a/src/test/run-pass/paths-in-macro-invocations.rs b/src/test/run-pass/paths-in-macro-invocations.rs
index 2e87809a84e..69f8906778a 100644
--- a/src/test/run-pass/paths-in-macro-invocations.rs
+++ b/src/test/run-pass/paths-in-macro-invocations.rs
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 extern crate two_macros;
 
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
index 24c30a5abc2..183bb553530 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(dyn_trait)]
-
 use std::error::Error;
 
 fn main() -> Result<(), Box<dyn Error>> {
diff --git a/src/test/ui/error-codes/E0518.stderr b/src/test/ui/error-codes/E0518.stderr
index d8feec99140..27d5d3645fd 100644
--- a/src/test/ui/error-codes/E0518.stderr
+++ b/src/test/ui/error-codes/E0518.stderr
@@ -1,19 +1,19 @@
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/E0518.rs:11:1
    |
 LL | #[inline(always)] //~ ERROR: E0518
    | ^^^^^^^^^^^^^^^^^
 LL | struct Foo;
-   | ----------- not a function
+   | ----------- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/E0518.rs:14:1
    |
 LL |   #[inline(never)] //~ ERROR: E0518
    |   ^^^^^^^^^^^^^^^^
 LL | / impl Foo {
 LL | | }
-   | |_- not a function
+   | |_- not a function or closure
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr
deleted file mode 100644
index 6e6bdf1cbf0..00000000000
--- a/src/test/ui/feature-gate-dyn-trait.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: `dyn Trait` syntax is unstable (see issue #44662)
-  --> $DIR/feature-gate-dyn-trait.rs:12:14
-   |
-LL | type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
-   |              ^^^^^^^^^
-   |
-   = help: add #![feature(dyn_trait)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
index 410f960e655..b03faad988e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
@@ -19,21 +19,21 @@
 #![inline                     = "2100"]
 
 #[inline = "2100"]
-//~^ ERROR attribute should be applied to function
+//~^ ERROR attribute should be applied to function or closure
 mod inline {
     mod inner { #![inline="2100"] }
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 
     #[inline = "2100"] fn f() { }
 
     #[inline = "2100"] struct S;
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 
     #[inline = "2100"] type T = S;
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 
     #[inline = "2100"] impl S { }
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
index d67d78e31a9..4d63c3f5012 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
@@ -1,41 +1,41 @@
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:21:1
    |
 LL |   #[inline = "2100"]
    |   ^^^^^^^^^^^^^^^^^^
-LL |   //~^ ERROR attribute should be applied to function
+LL |   //~^ ERROR attribute should be applied to function or closure
 LL | / mod inline {
 LL | |     mod inner { #![inline="2100"] }
-LL | |     //~^ ERROR attribute should be applied to function
+LL | |     //~^ ERROR attribute should be applied to function or closure
 LL | |
 ...  |
-LL | |     //~^ ERROR attribute should be applied to function
+LL | |     //~^ ERROR attribute should be applied to function or closure
 LL | | }
-   | |_- not a function
+   | |_- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:24:17
    |
 LL |     mod inner { #![inline="2100"] }
-   |     ------------^^^^^^^^^^^^^^^^^-- not a function
+   |     ------------^^^^^^^^^^^^^^^^^-- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:29:5
    |
 LL |     #[inline = "2100"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^ --------- not a function
+   |     ^^^^^^^^^^^^^^^^^^ --------- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:32:5
    |
 LL |     #[inline = "2100"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^ ----------- not a function
+   |     ^^^^^^^^^^^^^^^^^^ ----------- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:35:5
    |
 LL |     #[inline = "2100"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^ ---------- not a function
+   |     ^^^^^^^^^^^^^^^^^^ ---------- not a function or closure
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr
index be4852aaf06..af79eb7ac05 100644
--- a/src/test/ui/generator/yield-while-iterating.nll.stderr
+++ b/src/test/ui/generator/yield-while-iterating.nll.stderr
@@ -6,20 +6,6 @@ LL |         for p in &x { //~ ERROR
 LL |             yield();
    |             ------- possible yield occurs here
 
-error[E0597]: borrowed value does not live long enough
-  --> $DIR/yield-while-iterating.rs:50:17
-   |
-LL |       let mut b = || {
-   |  _________________^
-LL | |         for p in &mut x {
-LL | |             yield p;
-LL | |         }
-LL | |     };
-   | |     ^
-   | |     |
-   | |_____temporary value only lives until here
-   |       temporary value does not live long enough
-
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/yield-while-iterating.rs:67:20
    |
@@ -35,21 +21,7 @@ LL |       println!("{}", x[0]); //~ ERROR
 LL |       b.resume();
    |       - borrow later used here
 
-error[E0597]: borrowed value does not live long enough
-  --> $DIR/yield-while-iterating.rs:62:17
-   |
-LL |       let mut b = || {
-   |  _________________^
-LL | |         for p in &mut x {
-LL | |             yield p;
-LL | |         }
-LL | |     };
-   | |     ^
-   | |     |
-   | |_____temporary value only lives until here
-   |       temporary value does not live long enough
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0502, E0597, E0626.
+Some errors occurred: E0502, E0626.
 For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/hygiene/fields.rs b/src/test/ui/hygiene/fields.rs
index ed155b28037..64217770b13 100644
--- a/src/test/ui/hygiene/fields.rs
+++ b/src/test/ui/hygiene/fields.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     struct S { x: u32 }
diff --git a/src/test/ui/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs
index f3f400aafeb..7ba217061c6 100644
--- a/src/test/ui/hygiene/globs.rs
+++ b/src/test/ui/hygiene/globs.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     pub fn f() {}
diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs
index 4f997a790e6..cdba559445d 100644
--- a/src/test/ui/hygiene/impl_items.rs
+++ b/src/test/ui/hygiene/impl_items.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     struct S;
diff --git a/src/test/ui/hygiene/intercrate.rs b/src/test/ui/hygiene/intercrate.rs
index 20ca918f026..50fc985ba34 100644
--- a/src/test/ui/hygiene/intercrate.rs
+++ b/src/test/ui/hygiene/intercrate.rs
@@ -14,7 +14,7 @@
 
 // error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 extern crate intercrate;
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
index ea6a45fba6a..c90c7b3093c 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     pub macro m() { Vec::new(); ().clone() }
diff --git a/src/test/ui/hygiene/privacy.rs b/src/test/ui/hygiene/privacy.rs
index 8a392db92f9..987cad187d4 100644
--- a/src/test/ui/hygiene/privacy.rs
+++ b/src/test/ui/hygiene/privacy.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     fn f() {}
diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
index d0da6254b9b..3bd19cbc0ac 100644
--- a/src/test/ui/hygiene/trait_items.rs
+++ b/src/test/ui/hygiene/trait_items.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     pub trait T {
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 3b20451b102..efa9a58d633 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -34,6 +34,7 @@ error[E0391]: cycle detected when processing `cycle1`
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:49:16
    |
@@ -44,6 +45,7 @@ note: ...which requires processing `cycle2`...
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle1::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:42:16
    |
diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs
index 6a727942271..57a0040600a 100644
--- a/src/test/ui/impl_trait_projections.rs
+++ b/src/test/ui/impl_trait_projections.rs
@@ -7,8 +7,6 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-#![feature(dyn_trait)]
-
 use std::fmt::Debug;
 use std::option;
 
diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr
index 9b38de614fc..f6d58984ece 100644
--- a/src/test/ui/impl_trait_projections.stderr
+++ b/src/test/ui/impl_trait_projections.stderr
@@ -1,29 +1,29 @@
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:23:51
+  --> $DIR/impl_trait_projections.rs:21:51
    |
 LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
    |                                                   ^^^^^^^^^^^^^
 
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:30:9
+  --> $DIR/impl_trait_projections.rs:28:9
    |
 LL |     -> <impl Iterator as Iterator>::Item
    |         ^^^^^^^^^^^^^
 
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:37:27
+  --> $DIR/impl_trait_projections.rs:35:27
    |
 LL |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
    |                           ^^^^^^^^^^
 
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:44:29
+  --> $DIR/impl_trait_projections.rs:42:29
    |
 LL |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
    |                             ^^^^^^^^^^
 
 error[E0223]: ambiguous associated type
-  --> $DIR/impl_trait_projections.rs:23:50
+  --> $DIR/impl_trait_projections.rs:21:50
    |
 LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
    |                                                  ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
diff --git a/src/test/ui/imports/macro-paths.rs b/src/test/ui/imports/macro-paths.rs
index 51e5257be1b..e709eeee14a 100644
--- a/src/test/ui/imports/macro-paths.rs
+++ b/src/test/ui/imports/macro-paths.rs
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 extern crate two_macros;
 
diff --git a/src/test/ui/imports/shadow_builtin_macros.rs b/src/test/ui/imports/shadow_builtin_macros.rs
index aad0a43be26..93de136c405 100644
--- a/src/test/ui/imports/shadow_builtin_macros.rs
+++ b/src/test/ui/imports/shadow_builtin_macros.rs
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 mod foo {
     extern crate two_macros;
diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
index ec8c4ecf102..4cf7feddd46 100644
--- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
@@ -1,11 +1,11 @@
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait.rs:33:16
+  --> $DIR/dyn-trait.rs:32:16
    |
 LL |     static_val(x); //~ ERROR cannot infer
    |                ^
 
 error: free region `'a` does not outlive free region `'static`
-  --> $DIR/dyn-trait.rs:33:5
+  --> $DIR/dyn-trait.rs:32:5
    |
 LL |     static_val(x); //~ ERROR cannot infer
    |     ^^^^^^^^^^^^^
diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
index a504bae2e60..c27bbe77fbf 100644
--- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
@@ -13,7 +13,6 @@
 
 #![allow(warnings)]
 
-#![feature(dyn_trait)]
 #![feature(in_band_lifetimes)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
index 9d6a318c075..201470abe67 100644
--- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
@@ -1,11 +1,11 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/dyn-trait.rs:33:16
+  --> $DIR/dyn-trait.rs:32:16
    |
 LL |     static_val(x); //~ ERROR cannot infer
    |                ^
    |
-note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 32:1...
-  --> $DIR/dyn-trait.rs:32:1
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 31:1...
+  --> $DIR/dyn-trait.rs:31:1
    |
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lifetime_starts_expressions.rs b/src/test/ui/lifetime_starts_expressions.rs
new file mode 100644
index 00000000000..ffe1d7c353b
--- /dev/null
+++ b/src/test/ui/lifetime_starts_expressions.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() -> u32 {
+    return 'label: loop { break 'label 42; };
+}
+
+fn bar() -> u32 {
+    loop { break 'label: loop { break 'label 42; }; }
+    //~^ ERROR expected identifier, found keyword `loop`
+    //~| ERROR expected type, found keyword `loop`
+}
+
+pub fn main() {
+    foo();
+}
diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr
new file mode 100644
index 00000000000..de42f1daa1e
--- /dev/null
+++ b/src/test/ui/lifetime_starts_expressions.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found keyword `loop`
+  --> $DIR/lifetime_starts_expressions.rs:16:26
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |                          ^^^^ expected identifier, found keyword
+
+error: expected type, found keyword `loop`
+  --> $DIR/lifetime_starts_expressions.rs:16:26
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |                          ^^^^ expecting a type here because of type ascription
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/must-use-ops.rs b/src/test/ui/lint/must-use-ops.rs
new file mode 100644
index 00000000000..4ed82ab3b40
--- /dev/null
+++ b/src/test/ui/lint/must-use-ops.rs
@@ -0,0 +1,52 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Issue #50124 - Test warning for unused operator expressions
+
+// compile-pass
+
+#![feature(fn_must_use)]
+#![warn(unused_must_use)]
+
+fn main() {
+    let val = 1;
+    let val_pointer = &val;
+
+// Comparison Operators
+    val == 1;
+    val < 1;
+    val <= 1;
+    val != 1;
+    val >= 1;
+    val > 1;
+
+// Arithmetic Operators
+    val + 2;
+    val - 2;
+    val / 2;
+    val * 2;
+    val % 2;
+
+// Logical Operators
+    true && true;
+    false || true;
+
+// Bitwise Operators
+    5 ^ val;
+    5 & val;
+    5 | val;
+    5 << val;
+    5 >> val;
+
+// Unary Operators
+    !val;
+    -val;
+    *val_pointer;
+}
diff --git a/src/test/ui/lint/must-use-ops.stderr b/src/test/ui/lint/must-use-ops.stderr
new file mode 100644
index 00000000000..f444ef09075
--- /dev/null
+++ b/src/test/ui/lint/must-use-ops.stderr
@@ -0,0 +1,132 @@
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:23:5
+   |
+LL |     val == 1;
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must-use-ops.rs:16:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:24:5
+   |
+LL |     val < 1;
+   |     ^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:25:5
+   |
+LL |     val <= 1;
+   |     ^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:26:5
+   |
+LL |     val != 1;
+   |     ^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:27:5
+   |
+LL |     val >= 1;
+   |     ^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:28:5
+   |
+LL |     val > 1;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:31:5
+   |
+LL |     val + 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:32:5
+   |
+LL |     val - 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:33:5
+   |
+LL |     val / 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:34:5
+   |
+LL |     val * 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:35:5
+   |
+LL |     val % 2;
+   |     ^^^^^^^
+
+warning: unused logical operation which must be used
+  --> $DIR/must-use-ops.rs:38:5
+   |
+LL |     true && true;
+   |     ^^^^^^^^^^^^
+
+warning: unused logical operation which must be used
+  --> $DIR/must-use-ops.rs:39:5
+   |
+LL |     false || true;
+   |     ^^^^^^^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:42:5
+   |
+LL |     5 ^ val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:43:5
+   |
+LL |     5 & val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:44:5
+   |
+LL |     5 | val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:45:5
+   |
+LL |     5 << val;
+   |     ^^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:46:5
+   |
+LL |     5 >> val;
+   |     ^^^^^^^^
+
+warning: unused unary operation which must be used
+  --> $DIR/must-use-ops.rs:49:5
+   |
+LL |     !val;
+   |     ^^^^
+
+warning: unused unary operation which must be used
+  --> $DIR/must-use-ops.rs:50:5
+   |
+LL |     -val;
+   |     ^^^^
+
+warning: unused unary operation which must be used
+  --> $DIR/must-use-ops.rs:51:5
+   |
+LL |     *val_pointer;
+   |     ^^^^^^^^^^^^
+
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
index 34232e81cbd..9eb11148a8b 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.rs
+++ b/src/test/ui/mismatched_types/closure-arg-count.rs
@@ -39,7 +39,13 @@ fn main() {
 
     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
     //~^ ERROR function is expected to take
+
+    call(Foo);
+    //~^ ERROR function is expected to take
 }
 
 fn foo() {}
 fn qux(x: usize, y: usize) {}
+
+fn call<F, R>(_: F) where F: FnOnce() -> R {}
+struct Foo(u8);
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 6451c0d06fa..6270e794498 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -116,6 +116,21 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
 LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
    |                                         ^^^ expected function that takes 1 argument
 
-error: aborting due to 12 previous errors
+error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
+  --> $DIR/closure-arg-count.rs:43:5
+   |
+LL |     call(Foo);
+   |     ^^^^ expected function that takes 0 arguments
+...
+LL | struct Foo(u8);
+   | --------------- takes 1 argument
+   |
+note: required by `call`
+  --> $DIR/closure-arg-count.rs:50:1
+   |
+LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0593`.
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
index 7b3ed6a94fc..4767b75d89c 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
@@ -15,7 +15,6 @@
 // Iterator>::Item`, to be exact).
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 trait Anything { }
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index 0efbbdff12a..3689ca74adb 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-closure.rs:36:31
+  --> $DIR/projection-no-regions-closure.rs:35:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                               ^^^^^^^^^^^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-closure.rs:54:31
+  --> $DIR/projection-no-regions-closure.rs:53:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                               ^^^^^^^^^^^^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:36:23
+  --> $DIR/projection-no-regions-closure.rs:35:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:36:23
+  --> $DIR/projection-no-regions-closure.rs:35:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:32:1
+  --> $DIR/projection-no-regions-closure.rs:31:1
    |
 LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -51,7 +51,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:46:23
+  --> $DIR/projection-no-regions-closure.rs:45:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:42:1
+  --> $DIR/projection-no-regions-closure.rs:41:1
    |
 LL | / fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -82,7 +82,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:54:23
+  --> $DIR/projection-no-regions-closure.rs:53:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -98,7 +98,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:54:23
+  --> $DIR/projection-no-regions-closure.rs:53:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:50:1
+  --> $DIR/projection-no-regions-closure.rs:49:1
    |
 LL | / fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -124,7 +124,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:65:23
+  --> $DIR/projection-no-regions-closure.rs:64:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +140,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:60:1
+  --> $DIR/projection-no-regions-closure.rs:59:1
    |
 LL | / fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
index 32b73a51e11..dea2daf7e8e 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 trait Anything { }
 
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
index b2c5f28268d..3199ec15133 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-fn.rs:24:5
+  --> $DIR/projection-no-regions-fn.rs:23:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-fn.rs:40:5
+  --> $DIR/projection-no-regions-fn.rs:39:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-fn.rs:24:5
+  --> $DIR/projection-no-regions-fn.rs:23:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     Box::new(x.next())
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-fn.rs:40:5
+  --> $DIR/projection-no-regions-fn.rs:39:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
index cfe2880bfed..77024c4119f 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
@@ -25,7 +25,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index 0d5a2dc7c55..e1218830dbb 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -1,23 +1,23 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:56:39
+  --> $DIR/projection-one-region-closure.rs:55:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:68:39
+  --> $DIR/projection-one-region-closure.rs:67:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:90:39
+  --> $DIR/projection-one-region-closure.rs:89:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:56:29
+  --> $DIR/projection-one-region-closure.rs:55:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:56:29
+  --> $DIR/projection-one-region-closure.rs:55:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,13 +41,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
 
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
-  --> $DIR/projection-one-region-closure.rs:56:20
+  --> $DIR/projection-one-region-closure.rs:55:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:52:1
+  --> $DIR/projection-one-region-closure.rs:51:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -64,7 +64,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:68:29
+  --> $DIR/projection-one-region-closure.rs:67:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -81,7 +81,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:68:29
+  --> $DIR/projection-one-region-closure.rs:67:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -89,13 +89,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-closure.rs:68:20
+  --> $DIR/projection-one-region-closure.rs:67:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:63:1
+  --> $DIR/projection-one-region-closure.rs:62:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -113,7 +113,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:90:29
+  --> $DIR/projection-one-region-closure.rs:89:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +130,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:90:29
+  --> $DIR/projection-one-region-closure.rs:89:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,13 +138,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-closure.rs:90:20
+  --> $DIR/projection-one-region-closure.rs:89:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:75:1
+  --> $DIR/projection-one-region-closure.rs:74:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -162,7 +162,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:103:29
+  --> $DIR/projection-one-region-closure.rs:102:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -179,7 +179,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:97:1
+  --> $DIR/projection-one-region-closure.rs:96:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
index 16e91f2708f..fb1009c9cc8 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
@@ -17,7 +17,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index d4aca8380b4..76554e29f62 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -1,23 +1,23 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:48:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:48:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,13 +32,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
-  --> $DIR/projection-one-region-trait-bound-closure.rs:48:20
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:44:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:43:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -55,7 +55,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,13 +71,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:20
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:54:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:53:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -95,7 +95,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,13 +111,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:20
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:65:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:64:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -135,7 +135,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:91:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:90:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -151,7 +151,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:86:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:85:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -169,7 +169,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:103:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:102:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +184,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:95:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:94:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
index 0d42636c844..1f2f40196f8 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
@@ -16,7 +16,6 @@
 // compile-pass
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
index 875907e6b39..136e143e80e 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -1,5 +1,5 @@
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:47:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:46:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:43:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:42:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -28,7 +28,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:56:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:55:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:51:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:50:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -60,7 +60,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:75:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:74:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,7 +74,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:60:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:59:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -92,7 +92,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:84:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:83:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:79:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:78:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -124,7 +124,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:96:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:95:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -137,7 +137,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:88:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:87:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
index 7c8ef140a29..5307d0880d4 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
@@ -18,7 +18,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 7e36e467e4e..c7f45692960 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -1,29 +1,29 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:49:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:109:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:49:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
 error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:49:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:45:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:44:1
    |
 LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -65,7 +65,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +82,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:55:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:54:1
    |
 LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -109,7 +109,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -126,7 +126,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -134,7 +134,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:66:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:65:1
    |
 LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -153,7 +153,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:92:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:91:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -170,7 +170,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:87:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:86:1
    |
 LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -189,7 +189,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:101:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:100:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,7 +206,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:96:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:95:1
    |
 LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -225,7 +225,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,13 +240,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))`
-  --> $DIR/projection-two-region-trait-bound-closure.rs:109:20
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:105:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:104:1
    |
 LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -263,7 +263,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:120:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:119:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:115:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:114:1
    |
 LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -297,7 +297,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:132:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:131:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -312,7 +312,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:124:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:123:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
index 80b42c29563..7ff4b484af1 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index c8feaddff93..b4f51401a90 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -1,23 +1,23 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:31
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^^^^^^^
 
 note: External requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: where T: '_#1r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:33:1
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:32:1
    |
 LL | / fn generic<T>(value: T) {
 LL | |     let cell = Cell::new(&());
@@ -47,7 +47,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: where T: '_#1r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:1
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:41:1
    |
 LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
 LL | |     twice(cell, value, |a, b| invoke(a, b));
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
index 50763a1d508..b5cbd07b99c 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 500595e0c5d..59a8a39a7b0 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:27
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:27
    |
 LL |     with_signature(x, |y| y)
    |                           ^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
    |
 LL |     x
    |     ^
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
    |
 LL |     with_signature(x, |y| y)
    |                       ^^^^^
@@ -26,7 +26,7 @@ LL |     with_signature(x, |y| y)
    = note: where T: '_#2r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
    |
 LL |     with_signature(x, |y| y)
    |                       ^^^^^
@@ -34,7 +34,7 @@ LL |     with_signature(x, |y| y)
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:1
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:25:1
    |
 LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
 LL | | where
@@ -51,7 +51,7 @@ LL | | }
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
    |
 LL |     x
    |     ^
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
index b70fc2b2ec4..edaaeac080d 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
@@ -15,7 +15,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 4d8a66ba8e1..a53ce21b7e6 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:45:9
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:44:9
    |
 LL |         require(&x, &y)
    |         ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:79:9
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:78:9
    |
 LL |         require(&x, &y)
    |         ^^^^^^^
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -32,7 +32,7 @@ LL | |     })
    = note: where T: '_#1r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -47,7 +47,7 @@ LL | |     })
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:36:1
    |
 LL | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
 LL | |     with_signature(a, b, |x, y| {
@@ -63,7 +63,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:55:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:54:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -85,7 +85,7 @@ LL | |     })
    = note: where T: '_#2r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:51:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:50:1
    |
 LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -102,7 +102,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -123,7 +123,7 @@ LL | |     })
    = note: where T: '_#2r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -137,7 +137,7 @@ LL | |     })
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
    |
 LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -154,7 +154,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:90:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:89:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -174,7 +174,7 @@ LL | |     })
    = note: where T: '_#3r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:85:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:84:1
    |
 LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
index babe608354f..c0c483b3957 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
@@ -15,7 +15,6 @@
 #![feature(nll)]
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 use std::cell::Cell;
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
index 1510ca61e5c..dec15f47a03 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
@@ -1,5 +1,5 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn-body-nll-feature.rs:31:5
+  --> $DIR/ty-param-fn-body-nll-feature.rs:30:5
    |
 LL |     outlives(cell, t)
    |     ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
index fb4ea63f853..6226108ef19 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
@@ -14,7 +14,6 @@
 // function body.
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 use std::cell::Cell;
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
index 0596861e67b..537f1223470 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
@@ -1,11 +1,11 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn-body.rs:30:5
+  --> $DIR/ty-param-fn-body.rs:29:5
    |
 LL |     outlives(cell, t)
    |     ^^^^^^^^
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn-body.rs:30:5
+  --> $DIR/ty-param-fn-body.rs:29:5
    |
 LL |     outlives(cell, t)
    |     ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.rs b/src/test/ui/nll/ty-outlives/ty-param-fn.rs
index 42d662e1419..258d77eb2b0 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 use std::fmt::Debug;
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
index 0d09cac8c38..5ce50d81185 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn.rs:22:5
+  --> $DIR/ty-param-fn.rs:21:5
    |
 LL |     x
    |     ^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn.rs:38:5
+  --> $DIR/ty-param-fn.rs:37:5
    |
 LL |     x
    |     ^
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn.rs:22:5
+  --> $DIR/ty-param-fn.rs:21:5
    |
 LL |     x
    |     ^
@@ -19,7 +19,7 @@ LL |     x
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn.rs:38:5
+  --> $DIR/ty-param-fn.rs:37:5
    |
 LL |     x
    |     ^
diff --git a/src/test/ui/raw-literal-keywords.rs b/src/test/ui/raw-literal-keywords.rs
index 9b28aa0b151..9bb6653d770 100644
--- a/src/test/ui/raw-literal-keywords.rs
+++ b/src/test/ui/raw-literal-keywords.rs
@@ -10,7 +10,6 @@
 
 // compile-flags: -Z parse-only
 
-#![feature(dyn_trait)]
 #![feature(raw_identifiers)]
 
 fn test_if() {
diff --git a/src/test/ui/raw-literal-keywords.stderr b/src/test/ui/raw-literal-keywords.stderr
index 3758568323c..022f80ae8a4 100644
--- a/src/test/ui/raw-literal-keywords.stderr
+++ b/src/test/ui/raw-literal-keywords.stderr
@@ -1,17 +1,17 @@
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true`
-  --> $DIR/raw-literal-keywords.rs:17:10
+  --> $DIR/raw-literal-keywords.rs:16:10
    |
 LL |     r#if true { } //~ ERROR found `true`
    |          ^^^^ expected one of 8 possible tokens here
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
-  --> $DIR/raw-literal-keywords.rs:21:14
+  --> $DIR/raw-literal-keywords.rs:20:14
    |
 LL |     r#struct Test; //~ ERROR found `Test`
    |              ^^^^ expected one of 8 possible tokens here
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
-  --> $DIR/raw-literal-keywords.rs:25:13
+  --> $DIR/raw-literal-keywords.rs:24:13
    |
 LL |     r#union Test; //~ ERROR found `Test`
    |             ^^^^ expected one of 8 possible tokens here
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
index e573ad8fc1f..6c83205d050 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
@@ -13,8 +13,6 @@
 //
 // cc #48468
 
-#![feature(dyn_trait)]
-
 use std::fmt::Debug;
 
 struct Foo {
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
index 6d777841f03..1017217828a 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
@@ -1,11 +1,11 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/dyn-trait-underscore-in-struct.rs:21:24
+  --> $DIR/dyn-trait-underscore-in-struct.rs:19:24
    |
 LL |     x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
    |                        ^^ expected lifetime parameter
 
 error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/dyn-trait-underscore-in-struct.rs:21:12
+  --> $DIR/dyn-trait-underscore-in-struct.rs:19:12
    |
 LL |     x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
    |            ^^^^^^^^^^^^^^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
index 10a03786d7b..cdc0c78e694 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
@@ -1,29 +1,29 @@
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:14
+  --> $DIR/dyn-trait-underscore.rs:18:14
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |              ^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:20
+  --> $DIR/dyn-trait-underscore.rs:18:20
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |                    ^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:5
+  --> $DIR/dyn-trait-underscore.rs:18:5
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:5
+  --> $DIR/dyn-trait-underscore.rs:18:5
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: free region `` does not outlive free region `'static`
-  --> $DIR/dyn-trait-underscore.rs:18:52
+  --> $DIR/dyn-trait-underscore.rs:16:52
    |
 LL |   fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
    |  ____________________________________________________^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
index 9640d346597..247492fb7b7 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
@@ -13,8 +13,6 @@
 //
 // cc #48468
 
-#![feature(dyn_trait)]
-
 fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index f1e59aed54a..98249d3f2b5 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -1,11 +1,11 @@
 error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
-  --> $DIR/dyn-trait-underscore.rs:20:20
+  --> $DIR/dyn-trait-underscore.rs:18:20
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |                    ^^^^
    |
-note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 18:1...
-  --> $DIR/dyn-trait-underscore.rs:18:1
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 16:1...
+  --> $DIR/dyn-trait-underscore.rs:16:1
    |
 LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
 LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
@@ -13,7 +13,7 @@ LL | |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
 LL | | }
    | |_^
 note: ...so that reference does not outlive borrowed content
-  --> $DIR/dyn-trait-underscore.rs:20:14
+  --> $DIR/dyn-trait-underscore.rs:18:14
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |              ^^^^^
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 85434bb8a69..d1dac370c9e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1168,6 +1168,8 @@ impl<'test> TestCx<'test> {
         for line in proc_res.stderr.lines() {
             if line.contains("error: internal compiler error") {
                 self.fatal_proc_rec("compiler encountered internal error", proc_res);
+            } else if line.contains(" panicked at ") {
+                self.fatal_proc_rec("compiler panicked", proc_res);
             }
         }
     }