about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStefan Lankes <slankes@eonerc.rwth-aachen.de>2019-10-25 09:09:55 +0200
committerStefan Lankes <slankes@eonerc.rwth-aachen.de>2019-10-25 09:09:55 +0200
commitd349e32fc70da197918256c29a0858fe7e1a6588 (patch)
tree17f268176d32a172c84e84c30303a4794f4513b0
parentddcd157d03a067419d7f5b4375cfaff5a474856a (diff)
parentd54111afc061ef398cd8ce28984f9e8d70001b24 (diff)
downloadrust-d349e32fc70da197918256c29a0858fe7e1a6588.tar.gz
rust-d349e32fc70da197918256c29a0858fe7e1a6588.zip
Merge branch 'master' into rusty-hermit, resolve conflicts
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--Cargo.lock12
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/check.rs4
-rw-r--r--src/bootstrap/compile.rs63
-rw-r--r--src/bootstrap/dist.rs129
-rw-r--r--src/bootstrap/lib.rs1
-rw-r--r--src/ci/azure-pipelines/steps/install-windows-build-deps.yml23
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/codegen-options/index.md2
-rw-r--r--src/doc/rustc/src/command-line-arguments.md2
-rw-r--r--src/doc/rustc/src/targets/index.md6
-rw-r--r--src/doc/rustc/src/targets/known-issues.md13
-rw-r--r--src/liballoc/borrow.rs41
-rw-r--r--src/liballoc/collections/vec_deque.rs2
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/str.rs2
-rw-r--r--src/liballoc/sync.rs2
-rw-r--r--src/libcore/fmt/mod.rs2
-rw-r--r--src/libcore/macros.rs27
-rw-r--r--src/libcore/num/dec2flt/algorithm.rs9
-rw-r--r--src/libcore/option.rs5
-rw-r--r--src/libpanic_unwind/gcc.rs12
-rw-r--r--src/libpanic_unwind/seh64_gnu.rs2
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/error_codes.rs83
-rw-r--r--src/librustc/hir/lowering.rs20
-rw-r--r--src/librustc/hir/map/collector.rs4
-rw-r--r--src/librustc/hir/map/def_collector.rs29
-rw-r--r--src/librustc/hir/map/definitions.rs44
-rw-r--r--src/librustc/hir/mod.rs6
-rw-r--r--src/librustc/ich/impls_syntax.rs19
-rw-r--r--src/librustc/infer/combine.rs29
-rw-r--r--src/librustc/infer/error_reporting/mod.rs26
-rw-r--r--src/librustc/infer/mod.rs4
-rw-r--r--src/librustc/infer/nll_relate/mod.rs58
-rw-r--r--src/librustc/infer/type_variable.rs4
-rw-r--r--src/librustc/infer/unify_key.rs4
-rw-r--r--src/librustc/lint/builtin.rs169
-rw-r--r--src/librustc/lint/context.rs240
-rw-r--r--src/librustc/lint/levels.rs16
-rw-r--r--src/librustc/lint/mod.rs103
-rw-r--r--src/librustc/middle/cstore.rs8
-rw-r--r--src/librustc/mir/interpret/allocation.rs7
-rw-r--r--src/librustc/mir/mod.rs6
-rw-r--r--src/librustc/mir/mono.rs22
-rw-r--r--src/librustc/query/mod.rs4
-rw-r--r--src/librustc/session/config.rs3
-rw-r--r--src/librustc/session/mod.rs11
-rw-r--r--src/librustc/traits/error_reporting.rs34
-rw-r--r--src/librustc/traits/mod.rs3
-rw-r--r--src/librustc/traits/object_safety.rs4
-rw-r--r--src/librustc/traits/on_unimplemented.rs4
-rw-r--r--src/librustc/traits/select.rs8
-rw-r--r--src/librustc/traits/structural_impls.rs14
-rw-r--r--src/librustc/ty/context.rs43
-rw-r--r--src/librustc/ty/error.rs3
-rw-r--r--src/librustc/ty/mod.rs160
-rw-r--r--src/librustc/ty/print/obsolete.rs4
-rw-r--r--src/librustc/ty/print/pretty.rs34
-rw-r--r--src/librustc/ty/query/keys.rs4
-rw-r--r--src/librustc/ty/query/mod.rs1
-rw-r--r--src/librustc/ty/query/values.rs4
-rw-r--r--src/librustc/ty/relate.rs7
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc/ty/sty.rs18
-rw-r--r--src/librustc/ty/wf.rs25
-rw-r--r--src/librustc_codegen_llvm/base.rs6
-rw-r--r--src/librustc_codegen_llvm/consts.rs2
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs4
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs4
-rw-r--r--src/librustc_codegen_llvm/debuginfo/namespace.rs2
-rw-r--r--src/librustc_codegen_llvm/lib.rs7
-rw-r--r--src/librustc_codegen_ssa/back/write.rs12
-rw-r--r--src/librustc_codegen_ssa/base.rs41
-rw-r--r--src/librustc_codegen_ssa/debuginfo/type_names.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs4
-rw-r--r--src/librustc_codegen_utils/codegen_backend.rs4
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs23
-rw-r--r--src/librustc_codegen_utils/symbol_names/legacy.rs2
-rw-r--r--src/librustc_data_structures/graph/dominators/mod.rs27
-rw-r--r--src/librustc_driver/Cargo.toml1
-rw-r--r--src/librustc_driver/lib.rs35
-rw-r--r--src/librustc_errors/diagnostic.rs26
-rw-r--r--src/librustc_errors/diagnostic_builder.rs5
-rw-r--r--src/librustc_incremental/assert_module_sources.rs8
-rw-r--r--src/librustc_interface/interface.rs17
-rw-r--r--src/librustc_interface/passes.rs181
-rw-r--r--src/librustc_interface/queries.rs55
-rw-r--r--src/librustc_interface/util.rs6
-rw-r--r--src/librustc_lint/builtin.rs17
-rw-r--r--src/librustc_lint/lib.rs236
-rw-r--r--src/librustc_lint/unused.rs2
-rw-r--r--src/librustc_metadata/creader.rs217
-rw-r--r--src/librustc_metadata/cstore.rs47
-rw-r--r--src/librustc_metadata/cstore_impl.rs19
-rw-r--r--src/librustc_metadata/decoder.rs40
-rw-r--r--src/librustc_metadata/encoder.rs84
-rw-r--r--src/librustc_metadata/locator.rs86
-rw-r--r--src/librustc_metadata/schema.rs52
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs14
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs144
-rw-r--r--src/librustc_mir/interpret/eval_context.rs4
-rw-r--r--src/librustc_mir/interpret/intrinsics/type_name.rs2
-rw-r--r--src/librustc_mir/interpret/memory.rs7
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs41
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs27
-rw-r--r--src/librustc_plugin/load.rs21
-rw-r--r--src/librustc_plugin/registry.rs42
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs21
-rw-r--r--src/librustc_resolve/diagnostics.rs10
-rw-r--r--src/librustc_resolve/error_codes.rs25
-rw-r--r--src/librustc_resolve/late.rs23
-rw-r--r--src/librustc_resolve/lib.rs101
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
-rw-r--r--src/librustc_typeck/astconv.rs9
-rw-r--r--src/librustc_typeck/check/cast.rs43
-rw-r--r--src/librustc_typeck/check/coercion.rs31
-rw-r--r--src/librustc_typeck/check/expr.rs14
-rw-r--r--src/librustc_typeck/check/intrinsic.rs6
-rw-r--r--src/librustc_typeck/check/method/confirm.rs20
-rw-r--r--src/librustc_typeck/check/mod.rs15
-rw-r--r--src/librustc_typeck/coherence/mod.rs5
-rw-r--r--src/librustc_typeck/collect.rs29
-rw-r--r--src/librustc_typeck/error_codes.rs62
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/librustdoc/core.rs15
-rw-r--r--src/librustdoc/doctree.rs2
-rw-r--r--src/librustdoc/html/render.rs1
-rw-r--r--src/librustdoc/html/static/main.js3
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--src/librustdoc/test.rs1
-rw-r--r--src/libstd/Cargo.toml2
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/panicking.rs2
-rw-r--r--src/libstd/sys/unix/rand.rs2
-rw-r--r--src/libstd/sys/wasi/thread.rs8
-rw-r--r--src/libstd/sys/windows/handle.rs2
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/process.rs5
-rw-r--r--src/libstd/sys/windows/rand.rs2
-rw-r--r--src/libstd/sys/windows/thread_local.rs2
-rw-r--r--src/libstd/sys/windows/time.rs4
-rw-r--r--src/libstd/thread/local.rs5
-rw-r--r--src/libsyntax/ast.rs9
-rw-r--r--src/libsyntax/feature_gate/active.rs3
-rw-r--r--src/libsyntax/parse/parser.rs7
-rw-r--r--src/libsyntax/parse/parser/item.rs10
-rw-r--r--src/libsyntax/tokenstream.rs17
-rw-r--r--src/libsyntax_ext/format.rs5
-rw-r--r--src/libsyntax_pos/symbol.rs121
-rw-r--r--src/libtest/bench.rs4
-rw-r--r--src/libtest/cli.rs2
-rw-r--r--src/libtest/console.rs2
-rw-r--r--src/libtest/lib.rs7
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs6
-rw-r--r--src/test/run-make-fulldeps/issue-19371/foo.rs1
-rw-r--r--src/test/rustdoc/const-generics/const-impl.rs1
-rw-r--r--src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs7
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs24
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate.rs5
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs8
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs6
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-tool-test.rs8
-rw-r--r--src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs10
-rw-r--r--src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr2
-rw-r--r--src/test/ui/asm/issue-51431.rs10
-rw-r--r--src/test/ui/asm/issue-51431.stderr8
-rw-r--r--src/test/ui/associated-const/issue-63496.rs9
-rw-r--r--src/test/ui/associated-const/issue-63496.stderr21
-rw-r--r--src/test/ui/ast-json/ast-json-output.stdout2
-rw-r--r--src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr3
-rw-r--r--src/test/ui/async-await/issues/issue-51719.stderr1
-rw-r--r--src/test/ui/async-await/issues/issue-51751.stderr1
-rw-r--r--src/test/ui/async-await/issues/issue-62009-1.stderr3
-rw-r--r--src/test/ui/async-await/issues/issue-62009-2.stderr1
-rw-r--r--src/test/ui/async-await/issues/non-async-enclosing-span.stderr1
-rw-r--r--src/test/ui/break-outside-loop.rs8
-rw-r--r--src/test/ui/break-outside-loop.stderr10
-rw-r--r--src/test/ui/closures/issue-41366.rs13
-rw-r--r--src/test/ui/closures/issue-41366.stderr22
-rw-r--r--src/test/ui/closures/issue-52437.rs5
-rw-r--r--src/test/ui/closures/issue-52437.stderr15
-rw-r--r--src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs18
-rw-r--r--src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr12
-rw-r--r--src/test/ui/coherence/impl-foreign-for-foreign.rs17
-rw-r--r--src/test/ui/coherence/impl-foreign-for-foreign.stderr12
-rw-r--r--src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs25
-rw-r--r--src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr30
-rw-r--r--src/test/ui/coherence/impl-foreign-for-foreign[local].rs16
-rw-r--r--src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs21
-rw-r--r--src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr21
-rw-r--r--src/test/ui/coherence/impl-foreign-for-fundamental[local].rs17
-rw-r--r--src/test/ui/coherence/impl-foreign-for-local.rs15
-rw-r--r--src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs26
-rw-r--r--src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr30
-rw-r--r--src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs18
-rw-r--r--src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs23
-rw-r--r--src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr21
-rw-r--r--src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs17
-rw-r--r--src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr11
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs17
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs17
-rw-r--r--src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs19
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs2
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr14
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.rs3
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr19
-rw-r--r--src/test/ui/const-generics/forbid-non-structural_match-types.rs13
-rw-r--r--src/test/ui/const-generics/forbid-non-structural_match-types.stderr17
-rw-r--r--src/test/ui/const-generics/issues/issue-62579-no-match.rs15
-rw-r--r--src/test/ui/const-generics/issues/issue-62579-no-match.stderr8
-rw-r--r--src/test/ui/const-generics/issues/issue-65675.rs10
-rw-r--r--src/test/ui/const-generics/issues/issue-65675.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs41
-rw-r--r--src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr46
-rw-r--r--src/test/ui/fmt/format-string-error.rs2
-rw-r--r--src/test/ui/fmt/format-string-error.stderr8
-rw-r--r--src/test/ui/if/ifmt-bad-arg.stderr10
-rw-r--r--src/test/ui/intrinsics/intrinsic-alignment.rs3
-rw-r--r--src/test/ui/issues/issue-19538.stderr1
-rw-r--r--src/test/ui/issues/issue-20692.stderr1
-rw-r--r--src/test/ui/issues/issue-38604.stderr1
-rw-r--r--src/test/ui/issues/issue-65611.rs63
-rw-r--r--src/test/ui/issues/issue-65611.stderr18
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr (renamed from src/test/ui/kindck/kindck-inherited-copy-bound.stderr)7
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr25
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.rs11
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.fixed7
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.rs7
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.stderr106
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.fixed21
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.rs21
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.stderr658
-rw-r--r--src/test/ui/object-safety/object-safety-associated-consts.curr.stderr (renamed from src/test/ui/object-safety/object-safety-associated-consts.stderr)2
-rw-r--r--src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr15
-rw-r--r--src/test/ui/object-safety/object-safety-associated-consts.rs6
-rw-r--r--src/test/ui/object-safety/object-safety-generics.curr.stderr (renamed from src/test/ui/object-safety/object-safety-generics.stderr)4
-rw-r--r--src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr27
-rw-r--r--src/test/ui/object-safety/object-safety-generics.rs10
-rw-r--r--src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr (renamed from src/test/ui/object-safety/object-safety-mentions-Self.stderr)8
-rw-r--r--src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr27
-rw-r--r--src/test/ui/object-safety/object-safety-mentions-Self.rs20
-rw-r--r--src/test/ui/object-safety/object-safety-no-static.curr.stderr12
-rw-r--r--src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr15
-rw-r--r--src/test/ui/object-safety/object-safety-no-static.rs16
-rw-r--r--src/test/ui/object-safety/object-safety-sized-2.curr.stderr (renamed from src/test/ui/object-safety/object-safety-sized-2.stderr)2
-rw-r--r--src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr13
-rw-r--r--src/test/ui/object-safety/object-safety-sized-2.rs9
-rw-r--r--src/test/ui/object-safety/object-safety-sized.curr.stderr (renamed from src/test/ui/object-safety/object-safety-sized.stderr)2
-rw-r--r--src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr13
-rw-r--r--src/test/ui/object-safety/object-safety-sized.rs7
-rw-r--r--src/test/ui/repr/repr-packed-contains-align.stderr1
-rw-r--r--src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs23
-rw-r--r--src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs69
-rw-r--r--src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs37
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr24
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr15
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.rs8
-rw-r--r--src/test/ui/signal-alternate-stack-cleanup.rs1
-rw-r--r--src/test/ui/structs-enums/rec-align-u64.rs3
-rw-r--r--src/test/ui/traits/trait-object-safety.stderr1
-rw-r--r--src/test/ui/traits/trait-test-2.stderr1
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs17
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs18
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr33
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj.rs18
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr33
-rw-r--r--src/test/ui/wf/wf-unsafe-trait-obj-match.rs29
-rw-r--r--src/test/ui/wf/wf-unsafe-trait-obj-match.stderr38
-rw-r--r--src/tools/build-manifest/src/main.rs30
m---------src/tools/cargo0
m---------src/tools/clippy36
-rw-r--r--src/tools/linkchecker/main.rs1
277 files changed, 3601 insertions, 2749 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c3a9a68963e..37a217d2a04 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -128,6 +128,14 @@ the master branch to your feature branch.
 Also, please make sure that fixup commits are squashed into other related
 commits with meaningful commit messages.
 
+GitHub allows [closing issues using keywords][closing-keywords]. This feature
+should be used to keep the issue tracker tidy. However, it is generally preferred
+to put the "closes #123" text in the PR description rather than the issue commit;
+particularly during rebasing, citing the issue number in the commit can "spam"
+the issue in question.
+
+[closing-keywords]: https://help.github.com/en/articles/closing-issues-using-keywords
+
 Please make sure your pull request is in compliance with Rust's style
 guidelines by running
 
diff --git a/Cargo.lock b/Cargo.lock
index e83d38b569f..a8fc36063fb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -556,9 +556,9 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "676a74b493d50ac33cacd83fd536597e6b52c0b46b9856f7b9c809d82fef4ac0"
+checksum = "f75b10a18fb53549fdd090846eb01c7f8593914494d1faabc4d3005c436e417a"
 dependencies = [
  "diff",
  "filetime",
@@ -1297,9 +1297,9 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a"
+checksum = "3cd9867f119b19fecb08cd5c326ad4488d7a1da4bf75b4d95d71db742525aaab"
 dependencies = [
  "autocfg",
  "compiler_builtins",
@@ -3494,6 +3494,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_interface",
+ "rustc_lint",
  "rustc_metadata",
  "rustc_mir",
  "rustc_plugin",
@@ -4156,9 +4157,8 @@ dependencies = [
  "core",
  "dlmalloc",
  "fortanix-sgx-abi",
- "hashbrown 0.6.1",
+ "hashbrown 0.6.2",
  "hermit-abi",
- "libc",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b8071b98f70..2748903f2d4 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -443,6 +443,7 @@ impl<'a> Builder<'a> {
                 dist::Rustc,
                 dist::DebuggerScripts,
                 dist::Std,
+                dist::RustcDev,
                 dist::Analysis,
                 dist::Src,
                 dist::PlainSourceTarball,
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index cadb9a7e441..df1c7257584 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -55,6 +55,7 @@ impl Step for Std {
                   cargo,
                   args(builder.kind),
                   &libstd_stamp(builder, compiler, target),
+                  vec![],
                   true);
 
         let libdir = builder.sysroot_libdir(compiler, target);
@@ -103,6 +104,7 @@ impl Step for Rustc {
                   cargo,
                   args(builder.kind),
                   &librustc_stamp(builder, compiler, target),
+                  vec![],
                   true);
 
         let libdir = builder.sysroot_libdir(compiler, target);
@@ -155,6 +157,7 @@ impl Step for CodegenBackend {
                   cargo,
                   args(builder.kind),
                   &codegen_backend_stamp(builder, compiler, target, backend),
+                  vec![],
                   true);
     }
 }
@@ -199,6 +202,7 @@ impl Step for Rustdoc {
                   cargo,
                   args(builder.kind),
                   &rustdoc_stamp(builder, compiler, target),
+                  vec![],
                   true);
 
         let libdir = builder.sysroot_libdir(compiler, target);
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 5074b035789..da8d43ed49b 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -69,7 +69,7 @@ impl Step for Std {
             return;
         }
 
-        builder.ensure(StartupObjects { compiler, target });
+        let mut target_deps = builder.ensure(StartupObjects { compiler, target });
 
         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
         if compiler_to_use != compiler {
@@ -91,7 +91,7 @@ impl Step for Std {
             return;
         }
 
-        copy_third_party_objects(builder, &compiler, target);
+        target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
         std_cargo(builder, &compiler, target, &mut cargo);
@@ -102,6 +102,7 @@ impl Step for Std {
                   cargo,
                   vec![],
                   &libstd_stamp(builder, compiler, target),
+                  target_deps,
                   false);
 
         builder.ensure(StdLink {
@@ -113,9 +114,22 @@ impl Step for Std {
 }
 
 /// Copies third pary objects needed by various targets.
-fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned<String>) {
+fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned<String>)
+    -> Vec<PathBuf>
+{
     let libdir = builder.sysroot_libdir(*compiler, target);
 
+    let mut target_deps = vec![];
+
+    let mut copy_and_stamp = |sourcedir: &Path, name: &str| {
+        let target = libdir.join(name);
+        builder.copy(
+            &sourcedir.join(name),
+            &target,
+        );
+        target_deps.push(target);
+    };
+
     // Copies the crt(1,i,n).o startup objects
     //
     // Since musl supports fully static linking, we can cross link for it even
@@ -123,19 +137,13 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target:
     // files. As those shipped with glibc won't work, copy the ones provided by
     // musl so we have them on linux-gnu hosts.
     if target.contains("musl") {
+        let srcdir = builder.musl_root(target).unwrap().join("lib");
         for &obj in &["crt1.o", "crti.o", "crtn.o"] {
-            builder.copy(
-                &builder.musl_root(target).unwrap().join("lib").join(obj),
-                &libdir.join(obj),
-            );
+            copy_and_stamp(&srcdir, obj);
         }
     } else if target.ends_with("-wasi") {
-        for &obj in &["crt1.o"] {
-            builder.copy(
-                &builder.wasi_root(target).unwrap().join("lib/wasm32-wasi").join(obj),
-                &libdir.join(obj),
-            );
-        }
+        let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
+        copy_and_stamp(&srcdir, "crt1.o");
     }
 
     // Copies libunwind.a compiled to be linked wit x86_64-fortanix-unknown-sgx.
@@ -145,11 +153,11 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target:
     // which is provided by std for this target.
     if target == "x86_64-fortanix-unknown-sgx" {
         let src_path_env = "X86_FORTANIX_SGX_LIBS";
-        let obj = "libunwind.a";
         let src = env::var(src_path_env).expect(&format!("{} not found in env", src_path_env));
-        let src = Path::new(&src).join(obj);
-        builder.copy(&src, &libdir.join(obj));
+        copy_and_stamp(Path::new(&src), "libunwind.a");
     }
+
+    target_deps
 }
 
 /// Configure cargo to compile the standard library, adding appropriate env vars
@@ -306,7 +314,7 @@ pub struct StartupObjects {
 }
 
 impl Step for StartupObjects {
-    type Output = ();
+    type Output = Vec<PathBuf>;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         run.path("src/rtstartup")
@@ -325,13 +333,15 @@ impl Step for StartupObjects {
     /// They don't require any library support as they're just plain old object
     /// files, so we just use the nightly snapshot compiler to always build them (as
     /// no other compilers are guaranteed to be available).
-    fn run(self, builder: &Builder<'_>) {
+    fn run(self, builder: &Builder<'_>) -> Vec<PathBuf> {
         let for_compiler = self.compiler;
         let target = self.target;
         if !target.contains("windows-gnu") {
-            return
+            return vec![]
         }
 
+        let mut target_deps = vec![];
+
         let src_dir = &builder.src.join("src/rtstartup");
         let dst_dir = &builder.native_dir(target).join("rtstartup");
         let sysroot_dir = &builder.sysroot_libdir(for_compiler, target);
@@ -350,7 +360,9 @@ impl Step for StartupObjects {
                             .arg(src_file));
             }
 
-            builder.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o"));
+            let target = sysroot_dir.join(file.to_string() + ".o");
+            builder.copy(dst_file, &target);
+            target_deps.push(target);
         }
 
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
@@ -358,8 +370,12 @@ impl Step for StartupObjects {
                                     builder.cc(target),
                                     target,
                                     obj);
-            builder.copy(&src, &sysroot_dir.join(obj));
+            let target = sysroot_dir.join(obj);
+            builder.copy(&src, &target);
+            target_deps.push(target);
         }
+
+        target_deps
     }
 }
 
@@ -437,6 +453,7 @@ impl Step for Rustc {
                   cargo,
                   vec![],
                   &librustc_stamp(builder, compiler, target),
+                  vec![],
                   false);
 
         builder.ensure(RustcLink {
@@ -585,7 +602,7 @@ impl Step for CodegenBackend {
 
         let tmp_stamp = out_dir.join(".tmp.stamp");
 
-        let files = run_cargo(builder, cargo, vec![], &tmp_stamp, false);
+        let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false);
         if builder.config.dry_run {
             return;
         }
@@ -941,6 +958,7 @@ pub fn run_cargo(builder: &Builder<'_>,
                  cargo: Cargo,
                  tail_args: Vec<String>,
                  stamp: &Path,
+                 additional_target_deps: Vec<PathBuf>,
                  is_check: bool)
     -> Vec<PathBuf>
 {
@@ -1057,6 +1075,7 @@ pub fn run_cargo(builder: &Builder<'_>,
         deps.push((path_to_add.into(), false));
     }
 
+    deps.extend(additional_target_deps.into_iter().map(|d| (d, false)));
     deps.sort();
     let mut new_contents = Vec::new();
     for (dep, proc_macro) in deps.iter() {
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 514ad114449..93143570b0f 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -637,6 +637,28 @@ impl Step for DebuggerScripts {
     }
 }
 
+fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
+    // The only true set of target libraries came from the build triple, so
+    // let's reduce redundant work by only producing archives from that host.
+    if compiler.host != builder.config.build {
+        builder.info("\tskipping, not a build host");
+        true
+    } else {
+        false
+    }
+}
+
+/// Copy stamped files into an image's `target/lib` directory.
+fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) {
+    let dst = image.join("lib/rustlib").join(target).join("lib");
+    t!(fs::create_dir_all(&dst));
+    for (path, host) in builder.read_stamp_file(stamp) {
+        if !host || builder.config.build == target {
+            builder.copy(&path, &dst.join(path.file_name().unwrap()));
+        }
+    }
+}
+
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Std {
     pub compiler: Compiler,
@@ -667,44 +689,19 @@ impl Step for Std {
         let target = self.target;
 
         let name = pkgname(builder, "rust-std");
-
-        // The only true set of target libraries came from the build triple, so
-        // let's reduce redundant work by only producing archives from that host.
-        if compiler.host != builder.config.build {
-            builder.info("\tskipping, not a build host");
-            return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
+        let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target));
+        if skip_host_target_lib(builder, compiler) {
+            return archive;
         }
 
-        // We want to package up as many target libraries as possible
-        // for the `rust-std` package, so if this is a host target we
-        // depend on librustc and otherwise we just depend on libtest.
-        if builder.hosts.iter().any(|t| t == target) {
-            builder.ensure(compile::Rustc { compiler, target });
-        } else {
-            builder.ensure(compile::Std { compiler, target });
-        }
+        builder.ensure(compile::Std { compiler, target });
 
         let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
         let _ = fs::remove_dir_all(&image);
 
-        let dst = image.join("lib/rustlib").join(target);
-        t!(fs::create_dir_all(&dst));
-        let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
-        src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
-        builder.cp_filtered(&src, &dst, &|path| {
-            if let Some(name) = path.file_name().and_then(|s| s.to_str()) {
-                if name == builder.config.rust_codegen_backends_dir.as_str() {
-                    return false
-                }
-                if name == "bin" {
-                    return false
-                }
-                if name.contains("LLVM") {
-                    return false
-                }
-            }
-            true
-        });
+        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
+        let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
+        copy_target_libs(builder, &target, &image, &stamp);
 
         let mut cmd = rust_installer(builder);
         cmd.arg("generate")
@@ -723,7 +720,73 @@ impl Step for Std {
         let _time = timeit(builder);
         builder.run(&mut cmd);
         builder.remove_dir(&image);
-        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
+        archive
+    }
+}
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct RustcDev {
+    pub compiler: Compiler,
+    pub target: Interned<String>,
+}
+
+impl Step for RustcDev {
+    type Output = PathBuf;
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("rustc-dev")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(RustcDev {
+            compiler: run.builder.compiler_for(
+                run.builder.top_stage,
+                run.builder.config.build,
+                run.target,
+            ),
+            target: run.target,
+        });
+    }
+
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        let compiler = self.compiler;
+        let target = self.target;
+
+        let name = pkgname(builder, "rustc-dev");
+        let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target));
+        if skip_host_target_lib(builder, compiler) {
+            return archive;
+        }
+
+        builder.ensure(compile::Rustc { compiler, target });
+
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
+        let _ = fs::remove_dir_all(&image);
+
+        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
+        let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
+        copy_target_libs(builder, &target, &image, &stamp);
+
+        let mut cmd = rust_installer(builder);
+        cmd.arg("generate")
+           .arg("--product-name=Rust")
+           .arg("--rel-manifest-dir=rustlib")
+           .arg("--success-message=Rust-is-ready-to-develop.")
+           .arg("--image-dir").arg(&image)
+           .arg("--work-dir").arg(&tmpdir(builder))
+           .arg("--output-dir").arg(&distdir(builder))
+           .arg(format!("--package-name={}-{}", name, target))
+           .arg(format!("--component-name=rustc-dev-{}", target))
+           .arg("--legacy-manifest-dirs=rustlib,cargo");
+
+        builder.info(&format!("Dist rustc-dev stage{} ({} -> {})",
+            compiler.stage, &compiler.host, target));
+        let _time = timeit(builder);
+        builder.run(&mut cmd);
+        builder.remove_dir(&image);
+        archive
     }
 }
 
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 42c3cfbd84a..cbdb174c02d 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1137,6 +1137,7 @@ impl Build {
     pub fn copy(&self, src: &Path, dst: &Path) {
         if self.config.dry_run { return; }
         self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst));
+        if src == dst { return; }
         let _ = fs::remove_file(&dst);
         let metadata = t!(src.symlink_metadata());
         if metadata.file_type().is_symlink() {
diff --git a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml
index bd4f1ed0cea..812339900fe 100644
--- a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml
+++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml
@@ -84,6 +84,17 @@ steps:
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],''))
   displayName: Download custom MinGW
 
+# FIXME(#65767): workaround msys bug, step 1
+- bash: |
+    set -e
+    arch=i686
+    if [ "$MSYS_BITS" = "64" ]; then
+      arch=x86_64
+    fi
+    curl -O https://ci-mirrors.rust-lang.org/rustc/msys2-repo/mingw/$arch/mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz
+  condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
+  displayName: Download working ca-certificates for msys
+
 # Otherwise install MinGW through `pacman`
 - bash: |
     set -e
@@ -96,6 +107,18 @@ steps:
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],''))
   displayName: Download standard MinGW
 
+# FIXME(#65767): workaround msys bug, step 2
+- bash: |
+    set -e
+    arch=i686
+    if [ "$MSYS_BITS" = "64" ]; then
+      arch=x86_64
+    fi
+    pacman -U --noconfirm --noprogressbar mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz
+    rm mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz
+  condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
+  displayName: Install working ca-certificates for msys
+
 # Make sure we use the native python interpreter instead of some msys equivalent
 # one way or another. The msys interpreters seem to have weird path conversions
 # baked in which break LLVM's build system one way or another, so let's use the
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index d5564fd798f..b603c7b231e 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -14,6 +14,7 @@
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
+    - [Known Issues](targets/known-issues.md)
 - [Profile-guided Optimization](profile-guided-optimization.md)
 - [Linker-plugin based LTO](linker-plugin-lto.md)
 - [Contributing to `rustc`](contributing.md)
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index e73fd43f19a..f5d5f2089d7 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -61,6 +61,8 @@ enabling or disabling a feature.
 To see the valid options and an example of use, run `rustc --print
 target-features`.
 
+Using this flag is unsafe and might result in [undefined runtime behavior](../targets/known-issues.md).
+
 ## passes
 
 This flag can be used to add extra LLVM passes to the compilation.
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index b2cc65c11fd..bdb3c519658 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -145,7 +145,7 @@ of print values are:
   target CPU may be selected with the `-C target-cpu=val` flag.
 - `target-features` — List of available target features for the current
   target. Target features may be enabled with the `-C target-feature=val`
-  flag.
+  flag. This flag is unsafe. See [known issues](targets/known-issues.md) for more details.
 - `relocation-models` — List of relocation models. Relocation models may be
   selected with the `-C relocation-model=val` flag.
 - `code-models` — List of code models. Code models may be selected with the
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
index 3d63d072bef..5859df83f64 100644
--- a/src/doc/rustc/src/targets/index.md
+++ b/src/doc/rustc/src/targets/index.md
@@ -11,3 +11,9 @@ To compile to a particular target, use the `--target` flag:
 ```bash
 $ rustc src/main.rs --target=wasm32-unknown-unknown
 ```
+## Target Features
+`x86`,  and `ARMv8` are two popular CPU architectures. Their instruction sets form a common baseline across most CPUs. However, some CPUs extend these with custom instruction sets, e.g. vector (`AVX`), bitwise manipulation (`BMI`) or cryptographic (`AES`).
+
+Developers, who know on which CPUs their compiled code is going to run can choose to add (or remove) CPU specific instruction sets via the `-C target-feature=val` flag.
+
+Please note, that this flag is generally considered as unsafe. More details can be found in [this section](known-issues.md).
diff --git a/src/doc/rustc/src/targets/known-issues.md b/src/doc/rustc/src/targets/known-issues.md
new file mode 100644
index 00000000000..89fd8ea6d32
--- /dev/null
+++ b/src/doc/rustc/src/targets/known-issues.md
@@ -0,0 +1,13 @@
+# Known Issues
+This section informs you about known "gotchas". Keep in mind, that this section is (and always will be) incomplete. For suggestions and amendments, feel free to [contribute](../contributing.md) to this guide.
+
+## Target Features
+Most target-feature problems arise, when mixing code that have the target-feature _enabled_ with code that have it _disabled_. If you want to avoid undefined behavior, it is recommended to build _all code_ (including the standard library and imported crates) with a common set of target-features.
+
+By default, compiling your code with the `-C target-feature` flag will not recompile the entire standard library and/or imported crates with matching target features. Therefore, target features are generally considered as unsafe. Using `#[target_feature]` on individual functions makes the function unsafe.
+
+Examples:
+
+| Target-Feature | Issue | Seen on | Description | Details |
+| -------------- | ----- | ------- | ----------- | ------- |
+| `+soft-float` <br> and <br> `-sse` | Segfaults and ABI mismatches | `x86` and `x86-64` | The `x86` and `x86_64` architecture uses SSE registers (aka `xmm`) for floating point operations. Using software emulated floats ("soft-floats") disables usage of `xmm` registers, but parts of Rust's core libraries (e.g. `std::f32` or `std::f64`) are compiled without soft-floats and expect parameters to be passed in `xmm` registers. This leads to ABI mismatches. <br><br>  Attempting to compile with disabled SSE causes the same error, too. | [#63466](https://github.com/rust-lang/rust/issues/63466) |
diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs
index a9c5bce4c25..d2bdda83fa9 100644
--- a/src/liballoc/borrow.rs
+++ b/src/liballoc/borrow.rs
@@ -207,6 +207,47 @@ impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> {
 }
 
 impl<B: ?Sized + ToOwned> Cow<'_, B> {
+    /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cow_is_borrowed)]
+    /// use std::borrow::Cow;
+    ///
+    /// let cow = Cow::Borrowed("moo");
+    /// assert!(cow.is_borrowed());
+    ///
+    /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string());
+    /// assert!(!bull.is_borrowed());
+    /// ```
+    #[unstable(feature = "cow_is_borrowed", issue = "65143")]
+    pub fn is_borrowed(&self) -> bool {
+        match *self {
+            Borrowed(_) => true,
+            Owned(_) => false,
+        }
+    }
+
+    /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cow_is_borrowed)]
+    /// use std::borrow::Cow;
+    ///
+    /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string());
+    /// assert!(cow.is_owned());
+    ///
+    /// let bull = Cow::Borrowed("...moo?");
+    /// assert!(!bull.is_owned());
+    /// ```
+    #[unstable(feature = "cow_is_borrowed", issue = "65143")]
+    pub fn is_owned(&self) -> bool {
+        !self.is_borrowed()
+    }
+
     /// Acquires a mutable reference to the owned form of the data.
     ///
     /// Clones the data if it is not already owned.
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 0bf573f5e25..8f3dfabd888 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -1817,7 +1817,7 @@ impl<T> VecDeque<T> {
             }
         }
 
-        return elem;
+        elem
     }
 
     /// Splits the `VecDeque` into two at the given index.
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 3684162d8b1..94379afc2bd 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -85,6 +85,7 @@
 #![feature(const_generic_impls_guard)]
 #![feature(const_generics)]
 #![feature(const_in_array_repeat_expressions)]
+#![feature(cow_is_borrowed)]
 #![feature(dispatch_from_dyn)]
 #![feature(core_intrinsics)]
 #![feature(container_error_extra)]
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 9231c2d3f1d..83816d8b954 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -456,7 +456,7 @@ impl str {
                 }
             }
         }
-        return s;
+        s
     }
 
     /// Converts a [`Box<str>`] into a [`String`] without copying or allocating.
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 69f8f71197c..80d6c6e0d43 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -1638,7 +1638,7 @@ impl<T: ?Sized> Clone for Weak<T> {
             }
         }
 
-        return Weak { ptr: self.ptr };
+        Weak { ptr: self.ptr }
     }
 }
 
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 8413b2e0ac4..0e83a282b18 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -2025,7 +2025,7 @@ impl<T: ?Sized> Pointer for *const T {
         if f.alternate() {
             f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
 
-            if let None = f.width {
+            if f.width.is_none() {
                 f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2);
             }
         }
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 1320e63df06..35558e3abcd 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -238,6 +238,33 @@ macro_rules! debug_assert_ne {
     ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
 }
 
+/// Returns whether the given expression matches any of the given patterns.
+///
+/// Like in a `match` expression, the pattern can be optionally followed by `if`
+/// and a guard expression that has access to names bound by the pattern.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(matches_macro)]
+///
+/// let foo = 'f';
+/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));
+///
+/// let bar = Some(4);
+/// assert!(matches!(bar, Some(x) if x > 2));
+/// ```
+#[macro_export]
+#[unstable(feature = "matches_macro", issue = "65721")]
+macro_rules! matches {
+    ($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )?) => {
+        match $expression {
+            $( $pattern )|+ $( if $guard )? => true,
+            _ => false
+        }
+    }
+}
+
 /// Unwraps a result or propagates its error.
 ///
 /// The `?` operator was added to replace `try!` and should be used instead.
diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs
index fa3c8075378..ed89852dc48 100644
--- a/src/libcore/num/dec2flt/algorithm.rs
+++ b/src/libcore/num/dec2flt/algorithm.rs
@@ -143,13 +143,12 @@ pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Opt
 /// > not a bound for the true error, but bounds the difference between the approximation z and
 /// > the best possible approximation that uses p bits of significand.)
 pub fn bellerophon<T: RawFloat>(f: &Big, e: i16) -> T {
-    let slop;
-    if f <= &Big::from_u64(T::MAX_SIG) {
+    let slop = if f <= &Big::from_u64(T::MAX_SIG) {
         // The cases abs(e) < log5(2^N) are in fast_path()
-        slop = if e >= 0 { 0 } else { 3 };
+        if e >= 0 { 0 } else { 3 }
     } else {
-        slop = if e >= 0 { 1 } else { 4 };
-    }
+        if e >= 0 { 1 } else { 4 }
+    };
     let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize();
     let exp_p_n = 1 << (P - T::SIG_BITS as u32);
     let lowbits: i64 = (z.f % exp_p_n) as i64;
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 9eb29eae7f7..89f2d7ab29c 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -837,9 +837,8 @@ impl<T> Option<T> {
     #[inline]
     #[stable(feature = "option_entry", since = "1.20.0")]
     pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
-        match *self {
-            None => *self = Some(f()),
-            _ => (),
+        if let None = *self {
+            *self = Some(f());
         }
 
         match *self {
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 236ed150505..a35847c85fc 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -156,21 +156,21 @@ unsafe extern "C" fn rust_eh_personality(version: c_int,
     if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
         match eh_action {
             EHAction::None |
-            EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
-            EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
-            EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
+            EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
+            EHAction::Catch(_) => uw::_URC_HANDLER_FOUND,
+            EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR,
         }
     } else {
         match eh_action {
-            EHAction::None => return uw::_URC_CONTINUE_UNWIND,
+            EHAction::None => uw::_URC_CONTINUE_UNWIND,
             EHAction::Cleanup(lpad) |
             EHAction::Catch(lpad) => {
                 uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
                 uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
                 uw::_Unwind_SetIP(context, lpad);
-                return uw::_URC_INSTALL_CONTEXT;
+                uw::_URC_INSTALL_CONTEXT
             }
-            EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
+            EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
         }
     }
 }
diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs
index 457ffcd34f9..16b699a4437 100644
--- a/src/libpanic_unwind/seh64_gnu.rs
+++ b/src/libpanic_unwind/seh64_gnu.rs
@@ -46,7 +46,7 @@ pub fn payload() -> *mut u8 {
 
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     let panic_ctx = Box::from_raw(ptr as *mut PanicData);
-    return panic_ctx.data;
+    panic_ctx.data
 }
 
 // SEH doesn't support resuming unwinds after calling a landing pad like
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 0686bec0621..dea8d70aaf4 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -59,7 +59,7 @@ use crate::ich::{Fingerprint, StableHashingContext};
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use std::fmt;
 use std::hash::Hash;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 use crate::traits;
 use crate::traits::query::{
     CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
@@ -426,7 +426,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
 
     [anon] TraitSelect,
 
-    [] CompileCodegenUnit(InternedString),
+    [] CompileCodegenUnit(Symbol),
 
     [eval_always] Analysis(CrateNum),
 ]);
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index 3d501cacf6f..122ae4a6cf6 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -2045,8 +2045,8 @@ so that a generator can then be constructed:
 async fn bar<T>() -> () {}
 
 async fn foo() {
-  bar::<String>().await;
-  //   ^^^^^^^^ specify type explicitly
+    bar::<String>().await;
+    //   ^^^^^^^^ specify type explicitly
 }
 ```
 "##,
@@ -2126,6 +2126,84 @@ static X: u32 = 42;
 ```
 "##,
 
+E0728: r##"
+[`await`] has been used outside [`async`] function or block.
+
+Erroneous code examples:
+
+```edition2018,compile_fail,E0728
+# use std::pin::Pin;
+# use std::future::Future;
+# use std::task::{Context, Poll};
+#
+# struct WakeOnceThenComplete(bool);
+#
+# fn wake_and_yield_once() -> WakeOnceThenComplete {
+#     WakeOnceThenComplete(false)
+# }
+#
+# impl Future for WakeOnceThenComplete {
+#     type Output = ();
+#     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+#         if self.0 {
+#             Poll::Ready(())
+#         } else {
+#             cx.waker().wake_by_ref();
+#             self.0 = true;
+#             Poll::Pending
+#         }
+#     }
+# }
+#
+fn foo() {
+    wake_and_yield_once().await // `await` is used outside `async` context
+}
+```
+
+[`await`] is used to suspend the current computation until the given
+future is ready to produce a value. So it is legal only within
+an [`async`] context, like an `async fn` or an `async` block.
+
+```edition2018
+# use std::pin::Pin;
+# use std::future::Future;
+# use std::task::{Context, Poll};
+#
+# struct WakeOnceThenComplete(bool);
+#
+# fn wake_and_yield_once() -> WakeOnceThenComplete {
+#     WakeOnceThenComplete(false)
+# }
+#
+# impl Future for WakeOnceThenComplete {
+#     type Output = ();
+#     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+#         if self.0 {
+#             Poll::Ready(())
+#         } else {
+#             cx.waker().wake_by_ref();
+#             self.0 = true;
+#             Poll::Pending
+#         }
+#     }
+# }
+#
+async fn foo() {
+    wake_and_yield_once().await // `await` is used within `async` function
+}
+
+fn bar(x: u8) -> impl Future<Output = u8> {
+    async move {
+        wake_and_yield_once().await; // `await` is used within `async` block
+        x
+    }
+}
+```
+
+[`async`]: https://doc.rust-lang.org/std/keyword.async.html
+[`await`]: https://doc.rust-lang.org/std/keyword.await.html
+"##,
+
 E0734: r##"
 A stability attribute has been used outside of the standard library.
 
@@ -2218,6 +2296,5 @@ See [RFC 2091] for details on this and other limitations.
 //  E0702, // replaced with a generic attribute input check
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
     E0727, // `async` generators are not yet supported
-    E0728, // `await` must be in an `async` function or block
     E0739, // invalid track_caller application/syntax
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index d5287fd415b..002e6874466 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -83,8 +83,6 @@ pub struct LoweringContext<'a> {
     /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
     sess: &'a Session,
 
-    cstore: &'a dyn CrateStore,
-
     resolver: &'a mut dyn Resolver,
 
     /// HACK(Centril): there is a cyclic dependency between the parser and lowering
@@ -160,6 +158,8 @@ pub struct LoweringContext<'a> {
 }
 
 pub trait Resolver {
+    fn cstore(&self) -> &dyn CrateStore;
+
     /// Obtains resolution for a `NodeId` with a single resolution.
     fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
 
@@ -240,7 +240,6 @@ impl<'a> ImplTraitContext<'a> {
 
 pub fn lower_crate(
     sess: &Session,
-    cstore: &dyn CrateStore,
     dep_graph: &DepGraph,
     krate: &Crate,
     resolver: &mut dyn Resolver,
@@ -256,7 +255,6 @@ pub fn lower_crate(
     LoweringContext {
         crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
         sess,
-        cstore,
         resolver,
         nt_to_tokenstream,
         items: BTreeMap::new(),
@@ -792,15 +790,15 @@ impl<'a> LoweringContext<'a> {
         // really show up for end-user.
         let (str_name, kind) = match hir_name {
             ParamName::Plain(ident) => (
-                ident.as_interned_str(),
+                ident.name,
                 hir::LifetimeParamKind::InBand,
             ),
             ParamName::Fresh(_) => (
-                kw::UnderscoreLifetime.as_interned_str(),
+                kw::UnderscoreLifetime,
                 hir::LifetimeParamKind::Elided,
             ),
             ParamName::Error => (
-                kw::UnderscoreLifetime.as_interned_str(),
+                kw::UnderscoreLifetime,
                 hir::LifetimeParamKind::Error,
             ),
         };
@@ -980,7 +978,7 @@ impl<'a> LoweringContext<'a> {
         if id.is_local() {
             self.resolver.definitions().def_key(id.index)
         } else {
-            self.cstore.def_key(id)
+            self.resolver.cstore().def_key(id)
         }
     }
 
@@ -1590,7 +1588,7 @@ impl<'a> LoweringContext<'a> {
                     self.context.resolver.definitions().create_def_with_parent(
                         self.parent,
                         def_node_id,
-                        DefPathData::LifetimeNs(name.ident().as_interned_str()),
+                        DefPathData::LifetimeNs(name.ident().name),
                         ExpnId::root(),
                         lifetime.span);
 
@@ -1727,8 +1725,8 @@ impl<'a> LoweringContext<'a> {
                             return n;
                         }
                         assert!(!def_id.is_local());
-                        let item_generics =
-                            self.cstore.item_generics_cloned_untracked(def_id, self.sess);
+                        let item_generics = self.resolver.cstore()
+                            .item_generics_cloned_untracked(def_id, self.sess);
                         let n = item_generics.own_counts().lifetimes;
                         self.type_def_lifetime_params.insert(def_id, n);
                         n
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 1a970c7a2c1..307dbe7dab0 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -186,13 +186,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             });
 
         let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| {
-            let name = cstore.crate_name_untracked(cnum).as_interned_str();
+            let name = cstore.crate_name_untracked(cnum);
             let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
             let hash = cstore.crate_hash_untracked(cnum);
             (name, disambiguator, hash)
         }).collect();
 
-        upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name, dis));
+        upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
 
         // We hash the final, remapped names of all local source files so we
         // don't have to include the path prefix remapping commandline args.
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 9be339be703..7c8fdcc8b12 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -57,7 +57,7 @@ impl<'a> DefCollector<'a> {
 
         // For async functions, we need to create their inner defs inside of a
         // closure to match their desugared representation.
-        let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
+        let fn_def_data = DefPathData::ValueNs(name);
         let fn_def = self.create_def(id, fn_def_data, span);
         return self.with_parent(fn_def, |this| {
             this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
@@ -83,8 +83,7 @@ impl<'a> DefCollector<'a> {
                 .unwrap_or_else(|| {
                     let node_id = NodeId::placeholder_from_expn_id(self.expansion);
                     sym::integer(self.definitions.placeholder_field_indices[&node_id])
-                })
-                .as_interned_str();
+                });
             let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span);
             self.with_parent(def, |this| visit::walk_struct_field(this, field));
         }
@@ -109,7 +108,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
             ItemKind::OpaqueTy(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
-            ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
+            ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
             ItemKind::Fn(
                 ref decl,
                 ref header,
@@ -127,8 +126,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                 )
             }
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.as_interned_str()),
-            ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.as_interned_str()),
+                DefPathData::ValueNs(i.ident.name),
+            ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
@@ -162,7 +161,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         }
 
         let def = self.create_def(foreign_item.id,
-                                  DefPathData::ValueNs(foreign_item.ident.as_interned_str()),
+                                  DefPathData::ValueNs(foreign_item.ident.name),
                                   foreign_item.span);
 
         self.with_parent(def, |this| {
@@ -175,7 +174,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             return self.visit_macro_invoc(v.id);
         }
         let def = self.create_def(v.id,
-                                  DefPathData::TypeNs(v.ident.as_interned_str()),
+                                  DefPathData::TypeNs(v.ident.name),
                                   v.span);
         self.with_parent(def, |this| {
             if let Some(ctor_hir_id) = v.data.ctor_id() {
@@ -202,7 +201,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             self.visit_macro_invoc(param.id);
             return;
         }
-        let name = param.ident.as_interned_str();
+        let name = param.ident.name;
         let def_path_data = match param.kind {
             GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name),
             GenericParamKind::Type { .. } => DefPathData::TypeNs(name),
@@ -216,9 +215,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.kind {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.as_interned_str()),
+                DefPathData::ValueNs(ti.ident.name),
             TraitItemKind::Type(..) => {
-                DefPathData::TypeNs(ti.ident.as_interned_str())
+                DefPathData::TypeNs(ti.ident.name)
             },
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
         };
@@ -243,12 +242,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     body,
                 )
             }
-            ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.as_interned_str()),
+            ImplItemKind::Method(..) |
+            ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
             ImplItemKind::TyAlias(..) |
-            ImplItemKind::OpaqueTy(..) => {
-                DefPathData::TypeNs(ii.ident.as_interned_str())
-            },
+            ImplItemKind::OpaqueTy(..) => DefPathData::TypeNs(ii.ident.name),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
         };
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index d95637c3b98..5993a97c40d 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -18,7 +18,7 @@ use std::fmt::Write;
 use std::hash::Hash;
 use syntax::ast;
 use syntax_expand::hygiene::ExpnId;
-use syntax::symbol::{Symbol, sym, InternedString};
+use syntax::symbol::{Symbol, sym};
 use syntax_pos::{Span, DUMMY_SP};
 
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
@@ -136,7 +136,9 @@ impl DefKey {
 
         ::std::mem::discriminant(data).hash(&mut hasher);
         if let Some(name) = data.get_opt_name() {
-            name.hash(&mut hasher);
+            // Get a stable hash by considering the symbol chars rather than
+            // the symbol index.
+            name.as_str().hash(&mut hasher);
         }
 
         disambiguator.hash(&mut hasher);
@@ -218,7 +220,7 @@ impl DefPath {
         for component in &self.data {
             write!(s,
                    "::{}[{}]",
-                   component.data.as_interned_str(),
+                   component.data.as_symbol(),
                    component.disambiguator)
                 .unwrap();
         }
@@ -238,11 +240,11 @@ impl DefPath {
 
         for component in &self.data {
             if component.disambiguator == 0 {
-                write!(s, "::{}", component.data.as_interned_str()).unwrap();
+                write!(s, "::{}", component.data.as_symbol()).unwrap();
             } else {
                 write!(s,
                        "{}[{}]",
-                       component.data.as_interned_str(),
+                       component.data.as_symbol(),
                        component.disambiguator)
                        .unwrap();
             }
@@ -262,11 +264,11 @@ impl DefPath {
             opt_delimiter.map(|d| s.push(d));
             opt_delimiter = Some('-');
             if component.disambiguator == 0 {
-                write!(s, "{}", component.data.as_interned_str()).unwrap();
+                write!(s, "{}", component.data.as_symbol()).unwrap();
             } else {
                 write!(s,
                        "{}[{}]",
-                       component.data.as_interned_str(),
+                       component.data.as_symbol(),
                        component.disambiguator)
                        .unwrap();
             }
@@ -290,13 +292,13 @@ pub enum DefPathData {
     /// An impl.
     Impl,
     /// Something in the type namespace.
-    TypeNs(InternedString),
+    TypeNs(Symbol),
     /// Something in the value namespace.
-    ValueNs(InternedString),
+    ValueNs(Symbol),
     /// Something in the macro namespace.
-    MacroNs(InternedString),
+    MacroNs(Symbol),
     /// Something in the lifetime namespace.
-    LifetimeNs(InternedString),
+    LifetimeNs(Symbol),
     /// A closure expression.
     ClosureExpr,
 
@@ -311,7 +313,7 @@ pub enum DefPathData {
     /// Identifies a piece of crate metadata that is global to a whole crate
     /// (as opposed to just one item). `GlobalMetaData` components are only
     /// supposed to show up right below the crate root.
-    GlobalMetaData(InternedString),
+    GlobalMetaData(Symbol),
 }
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -545,7 +547,7 @@ impl Definitions {
 }
 
 impl DefPathData {
-    pub fn get_opt_name(&self) -> Option<InternedString> {
+    pub fn get_opt_name(&self) -> Option<Symbol> {
         use self::DefPathData::*;
         match *self {
             TypeNs(name) |
@@ -564,15 +566,15 @@ impl DefPathData {
         }
     }
 
-    pub fn as_interned_str(&self) -> InternedString {
+    pub fn as_symbol(&self) -> Symbol {
         use self::DefPathData::*;
-        let s = match *self {
+        match *self {
             TypeNs(name) |
             ValueNs(name) |
             MacroNs(name) |
             LifetimeNs(name) |
             GlobalMetaData(name) => {
-                return name
+                name
             }
             // Note that this does not show up in user print-outs.
             CrateRoot => sym::double_braced_crate,
@@ -582,13 +584,11 @@ impl DefPathData {
             Ctor => sym::double_braced_constructor,
             AnonConst => sym::double_braced_constant,
             ImplTrait => sym::double_braced_opaque,
-        };
-
-        s.as_interned_str()
+        }
     }
 
     pub fn to_string(&self) -> String {
-        self.as_interned_str().to_string()
+        self.as_symbol().to_string()
     }
 }
 
@@ -610,7 +610,7 @@ macro_rules! define_global_metadata_kind {
                     definitions.create_def_with_parent(
                         CRATE_DEF_INDEX,
                         ast::DUMMY_NODE_ID,
-                        DefPathData::GlobalMetaData(instance.name().as_interned_str()),
+                        DefPathData::GlobalMetaData(instance.name()),
                         ExpnId::root(),
                         DUMMY_SP
                     );
@@ -624,7 +624,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_interned_str()),
+                        data: DefPathData::GlobalMetaData(self.name()),
                         disambiguator: 0,
                     }
                 };
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 364a8ace1aa..38c84ad3347 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -19,7 +19,7 @@ use crate::ty::query::Providers;
 use crate::util::nodemap::{NodeMap, FxHashSet};
 
 use errors::FatalError;
-use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan};
+use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use syntax::source_map::Spanned;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
 use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
@@ -628,9 +628,9 @@ impl Generics {
         own_counts
     }
 
-    pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> {
+    pub fn get_named(&self, name: Symbol) -> Option<&GenericParam> {
         for param in &self.params {
-            if name == param.name.ident().as_interned_str() {
+            if name == param.name.ident().name {
                 return Some(param);
             }
         }
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index defc3fb25bc..dc1f6fd3131 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -9,7 +9,7 @@ use std::mem;
 use syntax::ast;
 use syntax::feature_gate;
 use syntax::parse::token;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use syntax::tokenstream;
 use syntax_pos::SourceFile;
 
@@ -18,20 +18,21 @@ use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
 use smallvec::SmallVec;
 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
 
-impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
+impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
     #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.with(|s| s.hash_stable(hcx, hasher))
+        let str = self as &str;
+        str.hash_stable(hcx, hasher)
     }
 }
 
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
-    type KeyType = InternedString;
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
+    type KeyType = LocalInternedString;
 
     #[inline]
     fn to_stable_hash_key(&self,
                           _: &StableHashingContext<'a>)
-                          -> InternedString {
+                          -> LocalInternedString {
         self.clone()
     }
 }
@@ -44,13 +45,13 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
 }
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
-    type KeyType = InternedString;
+    type KeyType = LocalInternedString;
 
     #[inline]
     fn to_stable_hash_key(&self,
                           _: &StableHashingContext<'a>)
-                          -> InternedString {
-        self.as_interned_str()
+                          -> LocalInternedString {
+        self.as_str()
     }
 }
 
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index f06dbc72cd9..51ae4e49493 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -494,7 +494,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 if sub_vid == self.for_vid_sub_root {
                     // If sub-roots are equal, then `for_vid` and
                     // `vid` are related via subtyping.
-                    return Err(TypeError::CyclicTy(self.root_ty));
+                    Err(TypeError::CyclicTy(self.root_ty))
                 } else {
                     match variables.probe(vid) {
                         TypeVariableValue::Known { value: u } => {
@@ -527,7 +527,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                             let u = self.tcx().mk_ty_var(new_var_id);
                             debug!("generalize: replacing original vid={:?} with new={:?}",
                                    vid, u);
-                            return Ok(u);
+                            Ok(u)
                         }
                     }
                 }
@@ -602,19 +602,26 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
         assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
 
-        match c {
-            ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
+        match c.val {
+            ConstValue::Infer(InferConst::Var(vid)) => {
                 let mut variable_table = self.infcx.const_unification_table.borrow_mut();
-                match variable_table.probe_value(*vid).val.known() {
-                    Some(u) => {
-                        self.relate(&u, &u)
+                let var_value = variable_table.probe_value(vid);
+                match var_value.val {
+                    ConstVariableValue::Known { value: u } => self.relate(&u, &u),
+                    ConstVariableValue::Unknown { universe } => {
+                        if self.for_universe.can_name(universe) {
+                            Ok(c)
+                        } else {
+                            let new_var_id = variable_table.new_key(ConstVarValue {
+                                origin: var_value.origin,
+                                val: ConstVariableValue::Unknown { universe: self.for_universe },
+                            });
+                            Ok(self.tcx().mk_const_var(new_var_id, c.ty))
+                        }
                     }
-                    None => Ok(c),
                 }
             }
-            _ => {
-                relate::super_relate_consts(self, c, c)
-            }
+            _ => relate::super_relate_consts(self, c, c),
         }
     }
 }
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index f6068855e63..a50cc86862e 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -542,7 +542,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 disambiguated_data: &DisambiguatedDefPathData,
             ) -> Result<Self::Path, Self::Error> {
                 let mut path = print_prefix(self)?;
-                path.push(disambiguated_data.data.as_interned_str().to_string());
+                path.push(disambiguated_data.data.as_symbol().to_string());
                 Ok(path)
             }
             fn path_generic_args(
@@ -1146,10 +1146,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         let span = cause.span(self.tcx);
 
-        diag.span_label(span, terr.to_string());
-        if let Some((sp, msg)) = secondary_span {
-            diag.span_label(sp, msg);
-        }
+        // Ignore msg for object safe coercion
+        // since E0038 message will be printed
+        match terr {
+            TypeError::ObjectUnsafeCoercion(_) => {}
+            _ => {
+                diag.span_label(span, terr.to_string());
+                if let Some((sp, msg)) = secondary_span {
+                    diag.span_label(sp, msg);
+                }
+            }
+        };
 
         if let Some((expected, found)) = expected_found {
             match (terr, is_simple_error, expected == found) {
@@ -1169,6 +1176,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         &sort_string(values.found),
                     );
                 }
+                (TypeError::ObjectUnsafeCoercion(_), ..) => {
+                    diag.note_unsuccessfull_coercion(found, expected);
+                }
                 (_, false, _) => {
                     if let Some(exp_found) = exp_found {
                         self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
@@ -1267,6 +1277,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let span = trace.cause.span(self.tcx);
         let failure_code = trace.cause.as_failure_code(terr);
         let mut diag = match failure_code {
+            FailureCode::Error0038(did) => {
+                let violations = self.tcx.object_safety_violations(did);
+                self.tcx.report_object_safety_error(span, did, violations)
+            }
             FailureCode::Error0317(failure_str) => {
                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
             }
@@ -1628,6 +1642,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 }
 
 enum FailureCode {
+    Error0038(DefId),
     Error0317(&'static str),
     Error0580(&'static str),
     Error0308(&'static str),
@@ -1666,6 +1681,7 @@ impl<'tcx> ObligationCause<'tcx> {
                 TypeError::IntrinsicCast => {
                     Error0308("cannot coerce intrinsics to function pointers")
                 }
+                TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()),
                 _ => Error0308("mismatched types"),
             },
         }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index f4ed7dac1f7..e385d576b8c 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -32,7 +32,7 @@ use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::collections::BTreeMap;
 use std::fmt;
 use syntax::ast;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 use syntax_pos::Span;
 
 use self::combine::CombineFields;
@@ -392,7 +392,7 @@ pub enum RegionVariableOrigin {
     Coercion(Span),
 
     /// Region variables created as the values for early-bound regions
-    EarlyBoundRegion(Span, InternedString),
+    EarlyBoundRegion(Span, Symbol),
 
     /// Region variables created for bound regions
     /// in a function or method that is called
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index 64ef0421808..d6f76e9ee34 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -27,7 +27,8 @@ use crate::ty::error::TypeError;
 use crate::ty::fold::{TypeFoldable, TypeVisitor};
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::subst::GenericArg;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt, InferConst};
+use crate::infer::{ConstVariableValue, ConstVarValue};
 use crate::mir::interpret::ConstValue;
 use rustc_data_structures::fx::FxHashMap;
 use std::fmt::Debug;
@@ -324,7 +325,7 @@ where
         let vid = pair.vid();
         let value_ty = pair.value_ty();
 
-        // FIXME -- this logic assumes invariance, but that is wrong.
+        // FIXME(invariance) -- this logic assumes invariance, but that is wrong.
         // This only presently applies to chalk integration, as NLL
         // doesn't permit type variables to appear on both sides (and
         // doesn't use lazy norm).
@@ -616,15 +617,21 @@ where
     fn consts(
         &mut self,
         a: &'tcx ty::Const<'tcx>,
-        b: &'tcx ty::Const<'tcx>,
+        mut b: &'tcx ty::Const<'tcx>,
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
-        if let ty::Const { val: ConstValue::Bound(..), .. } = a {
-            // FIXME(const_generics): I'm unsure how this branch should actually be handled,
-            // so this is probably not correct.
-            self.infcx.super_combine_consts(self, a, b)
-        } else {
-            debug!("consts(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance);
-            relate::super_relate_consts(self, a, b)
+        let a = self.infcx.shallow_resolve(a);
+
+        if !D::forbid_inference_vars() {
+            b = self.infcx.shallow_resolve(b);
+        }
+
+        match b.val {
+            ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+                // Forbid inference variables in the RHS.
+                bug!("unexpected inference var {:?}", b)
+            }
+            // FIXME(invariance): see the related FIXME above.
+            _ => self.infcx.super_combine_consts(self, a, b)
         }
     }
 
@@ -991,15 +998,28 @@ where
         a: &'tcx ty::Const<'tcx>,
         _: &'tcx ty::Const<'tcx>,
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
-        debug!("TypeGeneralizer::consts(a={:?})", a);
-
-        if let ty::Const { val: ConstValue::Bound(..), .. } = a {
-            bug!(
-                "unexpected inference variable encountered in NLL generalization: {:?}",
-                a
-            );
-        } else {
-            relate::super_relate_consts(self, a, a)
+        match a.val {
+            ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+                bug!(
+                    "unexpected inference variable encountered in NLL generalization: {:?}",
+                    a
+                );
+            }
+            ConstValue::Infer(InferConst::Var(vid)) => {
+                let mut variable_table = self.infcx.const_unification_table.borrow_mut();
+                let var_value = variable_table.probe_value(vid);
+                match var_value.val.known() {
+                    Some(u) => self.relate(&u, &u),
+                    None => {
+                        let new_var_id = variable_table.new_key(ConstVarValue {
+                            origin: var_value.origin,
+                            val: ConstVariableValue::Unknown { universe: self.universe },
+                        });
+                        Ok(self.tcx().mk_const_var(new_var_id, a.ty))
+                    }
+                }
+            }
+            _ => relate::super_relate_consts(self, a, a),
         }
     }
 
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index ce1b54bb1c8..f79a30c7ae8 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -1,4 +1,4 @@
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use crate::ty::{self, Ty, TyVid};
 
@@ -49,7 +49,7 @@ pub enum TypeVariableOriginKind {
     MiscVariable,
     NormalizeProjectionType,
     TypeInference,
-    TypeParameterDefinition(InternedString),
+    TypeParameterDefinition(Symbol),
 
     /// One of the upvars or closure kind parameters in a `ClosureSubsts`
     /// (before it has been determined).
diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs
index 846611db054..b0b6d971c60 100644
--- a/src/librustc/infer/unify_key.rs
+++ b/src/librustc/infer/unify_key.rs
@@ -3,7 +3,7 @@ use crate::mir::interpret::ConstValue;
 use rustc_data_structures::unify::{NoError, EqUnifyValue, UnifyKey, UnifyValue, UnificationTable};
 use rustc_data_structures::unify::InPlace;
 use syntax_pos::{Span, DUMMY_SP};
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 
 use std::cmp;
 use std::marker::PhantomData;
@@ -90,7 +90,7 @@ pub struct ConstVariableOrigin {
 pub enum ConstVariableOriginKind {
     MiscVariable,
     ConstInference,
-    ConstParameterDefinition(InternedString),
+    ConstParameterDefinition(Symbol),
     SubstitutionPlaceholder,
 }
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 4c28f6372fe..15598b60f5c 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -4,11 +4,12 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::lint::{LintPass, LateLintPass, LintArray};
+use crate::lint::{LintPass, LateLintPass, LintArray, FutureIncompatibleInfo};
 use crate::middle::stability;
 use crate::session::Session;
 use errors::{Applicability, DiagnosticBuilder, pluralise};
 use syntax::ast;
+use syntax::edition::Edition;
 use syntax::source_map::Span;
 use syntax::symbol::Symbol;
 
@@ -22,7 +23,7 @@ declare_lint! {
     pub CONST_ERR,
     Deny,
     "constant evaluation detected erroneous expression",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 declare_lint! {
@@ -71,7 +72,7 @@ declare_lint! {
     pub UNREACHABLE_CODE,
     Warn,
     "detects unreachable code paths",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 declare_lint! {
@@ -131,7 +132,11 @@ declare_lint! {
 declare_lint! {
     pub PRIVATE_IN_PUBLIC,
     Warn,
-    "detect private items in public interfaces not caught by the old implementation"
+    "detect private items in public interfaces not caught by the old implementation",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
+        edition: None,
+    };
 }
 
 declare_lint! {
@@ -143,13 +148,21 @@ declare_lint! {
 declare_lint! {
     pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
     Deny,
-    "detect public re-exports of private extern crates"
+    "detect public re-exports of private extern crates",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub INVALID_TYPE_PARAM_DEFAULT,
     Deny,
-    "type parameter default erroneously allowed in invalid location"
+    "type parameter default erroneously allowed in invalid location",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
+        edition: None,
+    };
 }
 
 declare_lint! {
@@ -161,63 +174,99 @@ declare_lint! {
 declare_lint! {
     pub SAFE_EXTERN_STATICS,
     Deny,
-    "safe access to extern statics was erroneously allowed"
+    "safe access to extern statics was erroneously allowed",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub SAFE_PACKED_BORROWS,
     Warn,
-    "safe borrows of fields of packed structs were was erroneously allowed"
+    "safe borrows of fields of packed structs were was erroneously allowed",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub PATTERNS_IN_FNS_WITHOUT_BODY,
     Warn,
-    "patterns in functions without body were erroneously allowed"
+    "patterns in functions without body were erroneously allowed",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub LEGACY_DIRECTORY_OWNERSHIP,
     Deny,
     "non-inline, non-`#[path]` modules (e.g., `mod foo;`) were erroneously allowed in some files \
-     not named `mod.rs`"
+     not named `mod.rs`",
+     @future_incompatible = FutureIncompatibleInfo {
+         reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
+         edition: None,
+     };
 }
 
 declare_lint! {
     pub LEGACY_CONSTRUCTOR_VISIBILITY,
     Deny,
-    "detects use of struct constructors that would be invisible with new visibility rules"
+    "detects use of struct constructors that would be invisible with new visibility rules",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub MISSING_FRAGMENT_SPECIFIER,
     Deny,
-    "detects missing fragment specifiers in unused `macro_rules!` patterns"
+    "detects missing fragment specifiers in unused `macro_rules!` patterns",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
     Deny,
-    "detects parenthesized generic parameters in type and module names"
+    "detects parenthesized generic parameters in type and module names",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub LATE_BOUND_LIFETIME_ARGUMENTS,
     Warn,
-    "detects generic lifetime arguments in path segments with late bound lifetime parameters"
+    "detects generic lifetime arguments in path segments with late bound lifetime parameters",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub ORDER_DEPENDENT_TRAIT_OBJECTS,
     Deny,
-    "trait-object types were treated as different depending on marker-trait order"
+    "trait-object types were treated as different depending on marker-trait order",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub DEPRECATED,
     Warn,
     "detects use of deprecated items",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 declare_lint! {
@@ -253,7 +302,11 @@ declare_lint! {
 declare_lint! {
     pub TYVAR_BEHIND_RAW_POINTER,
     Warn,
-    "raw pointer to an inference variable"
+    "raw pointer to an inference variable",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
+        edition: Some(Edition::Edition2018),
+    };
 }
 
 declare_lint! {
@@ -272,19 +325,33 @@ declare_lint! {
     pub ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
     Allow,
     "fully qualified paths that start with a module name \
-     instead of `crate`, `self`, or an extern crate name"
+     instead of `crate`, `self`, or an extern crate name",
+     @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #53130 <https://github.com/rust-lang/rust/issues/53130>",
+        edition: Some(Edition::Edition2018),
+     };
 }
 
 declare_lint! {
     pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
     Warn,
-    "floating-point literals cannot be used in patterns"
+    "floating-point literals cannot be used in patterns",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub UNSTABLE_NAME_COLLISIONS,
     Warn,
-    "detects name collision with an existing but unstable method"
+    "detects name collision with an existing but unstable method",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
+        edition: None,
+        // Note: this item represents future incompatibility of all unstable functions in the
+        //       standard library, and thus should never be removed or changed to an error.
+    };
 }
 
 declare_lint! {
@@ -302,7 +369,11 @@ declare_lint! {
 declare_lint! {
     pub DUPLICATE_MACRO_EXPORTS,
     Deny,
-    "detects duplicate macro exports"
+    "detects duplicate macro exports",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
+        edition: Some(Edition::Edition2018),
+    };
 }
 
 declare_lint! {
@@ -326,13 +397,21 @@ declare_lint! {
 declare_lint! {
     pub WHERE_CLAUSES_OBJECT_SAFETY,
     Warn,
-    "checks the object safety of where clauses"
+    "checks the object safety of where clauses",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
     Warn,
-    "detects proc macro derives using inaccessible names from parent modules"
+    "detects proc macro derives using inaccessible names from parent modules",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
+        edition: None,
+    };
 }
 
 declare_lint! {
@@ -346,7 +425,11 @@ declare_lint! {
     pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
     Deny,
     "macro-expanded `macro_export` macros from the current crate \
-     cannot be referred to by absolute paths"
+     cannot be referred to by absolute paths",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
+        edition: None,
+    };
 }
 
 declare_lint! {
@@ -359,7 +442,11 @@ declare_lint! {
     pub INDIRECT_STRUCTURAL_MATCH,
     // defaulting to allow until rust-lang/rust#62614 is fixed.
     Allow,
-    "pattern with const indirectly referencing non-`#[structural_match]` type"
+    "pattern with const indirectly referencing non-`#[structural_match]` type",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
+        edition: None,
+    };
 }
 
 /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
@@ -367,7 +454,11 @@ pub mod parser {
     declare_lint! {
         pub ILL_FORMED_ATTRIBUTE_INPUT,
         Warn,
-        "ill-formed attribute inputs that were previously accepted and used in practice"
+        "ill-formed attribute inputs that were previously accepted and used in practice",
+        @future_incompatible = super::FutureIncompatibleInfo {
+            reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
+            edition: None,
+        };
     }
 
     declare_lint! {
@@ -387,31 +478,47 @@ declare_lint! {
     pub DEPRECATED_IN_FUTURE,
     Allow,
     "detects use of items that will be deprecated in a future version",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 declare_lint! {
     pub AMBIGUOUS_ASSOCIATED_ITEMS,
     Deny,
-    "ambiguous associated items"
+    "ambiguous associated items",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub NESTED_IMPL_TRAIT,
     Warn,
-    "nested occurrence of `impl Trait` type"
+    "nested occurrence of `impl Trait` type",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #59014 <https://github.com/rust-lang/rust/issues/59014>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub MUTABLE_BORROW_RESERVATION_CONFLICT,
     Warn,
-    "reservation of a two-phased borrow conflicts with other shared borrows"
+    "reservation of a two-phased borrow conflicts with other shared borrows",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
+        edition: None,
+    };
 }
 
 declare_lint! {
     pub SOFT_UNSTABLE,
     Deny,
-    "a feature gate that doesn't break dependent crates"
+    "a feature gate that doesn't break dependent crates",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
+        edition: None,
+    };
 }
 
 declare_lint_pass! {
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index fa73a3c6c46..1cb53d754dc 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -22,11 +22,11 @@ use crate::hir::intravisit as hir_visit;
 use crate::hir::intravisit::Visitor;
 use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
 use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject};
-use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer};
+use crate::lint::{Level, Lint, LintId, LintPass, LintBuffer, FutureIncompatibleInfo};
 use crate::lint::builtin::BuiltinLintDiagnostics;
 use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
 use crate::middle::privacy::AccessLevels;
-use crate::session::{config, early_error, Session};
+use crate::session::Session;
 use crate::ty::{self, print::Printer, subst::GenericArg, TyCtxt, Ty};
 use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
 use crate::util::nodemap::FxHashMap;
@@ -35,10 +35,9 @@ use crate::util::common::time;
 use errors::DiagnosticBuilder;
 use std::slice;
 use std::default::Default as StdDefault;
-use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter};
+use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter};
 use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
 use syntax::ast;
-use syntax::edition;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit as ast_visit;
 use syntax_pos::{MultiSpan, Span, symbol::Symbol};
@@ -50,24 +49,25 @@ use syntax_pos::{MultiSpan, Span, symbol::Symbol};
 pub struct LintStore {
     /// Registered lints. The bool is true if the lint was
     /// added by a plugin.
-    lints: Vec<(&'static Lint, bool)>,
+    lints: Vec<&'static Lint>,
 
-    /// Trait objects for each lint pass.
-    /// This is only `None` while performing a lint pass.
-    pre_expansion_passes: Option<Vec<EarlyLintPassObject>>,
-    early_passes: Option<Vec<EarlyLintPassObject>>,
-    late_passes: Lock<Option<Vec<LateLintPassObject>>>,
-    late_module_passes: Vec<LateLintPassObject>,
+    /// Constructor functions for each variety of lint pass.
+    ///
+    /// These should only be called once, but since we want to avoid locks or
+    /// interior mutability, we don't enforce this (and lints should, in theory,
+    /// be compatible with being constructed more than once, though not
+    /// necessarily in a sane manner. This is safe though.)
+    pre_expansion_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
+    early_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
+    late_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
+    /// This is unique in that we construct them per-module, so not once.
+    late_module_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
 
     /// Lints indexed by name.
     by_name: FxHashMap<String, TargetLint>,
 
     /// Map of registered lint groups to what lints they expand to.
     lint_groups: FxHashMap<&'static str, LintGroup>,
-
-    /// Extra info for future incompatibility lints, describing the
-    /// issue or RFC that caused the incompatibility.
-    future_incompatible: FxHashMap<LintId, FutureIncompatibleInfo>,
 }
 
 /// Lints that are buffered up early on in the `Session` before the
@@ -81,18 +81,6 @@ pub struct BufferedEarlyLint {
     pub diagnostic: BuiltinLintDiagnostics,
 }
 
-/// Extra information for a future incompatibility lint. See the call
-/// to `register_future_incompatible` in `librustc_lint/lib.rs` for
-/// guidelines.
-pub struct FutureIncompatibleInfo {
-    pub id: LintId,
-    /// e.g., a URL for an issue/PR/RFC or error code
-    pub reference: &'static str,
-    /// If this is an edition fixing lint, the edition in which
-    /// this lint becomes obsolete
-    pub edition: Option<edition::Edition>,
-}
-
 /// The target of the `by_name` map, which accounts for renaming/deprecation.
 enum TargetLint {
     /// A direct lint target
@@ -142,17 +130,16 @@ impl LintStore {
     pub fn new() -> LintStore {
         LintStore {
             lints: vec![],
-            pre_expansion_passes: Some(vec![]),
-            early_passes: Some(vec![]),
-            late_passes: Lock::new(Some(vec![])),
+            pre_expansion_passes: vec![],
+            early_passes: vec![],
+            late_passes: vec![],
             late_module_passes: vec![],
             by_name: Default::default(),
-            future_incompatible: Default::default(),
             lint_groups: Default::default(),
         }
     }
 
-    pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] {
+    pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] {
         &self.lints
     }
 
@@ -168,99 +155,64 @@ impl LintStore {
             .collect()
     }
 
-    pub fn register_early_pass(&mut self,
-                               sess: Option<&Session>,
-                               from_plugin: bool,
-                               register_only: bool,
-                               pass: EarlyLintPassObject) {
-        self.push_pass(sess, from_plugin, &pass);
-        if !register_only {
-            self.early_passes.as_mut().unwrap().push(pass);
-        }
+    pub fn register_early_pass(
+        &mut self,
+        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync
+    ) {
+        self.early_passes.push(Box::new(pass));
     }
 
     pub fn register_pre_expansion_pass(
         &mut self,
-        sess: Option<&Session>,
-        from_plugin: bool,
-        register_only: bool,
-        pass: EarlyLintPassObject,
+        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
     ) {
-        self.push_pass(sess, from_plugin, &pass);
-        if !register_only {
-            self.pre_expansion_passes.as_mut().unwrap().push(pass);
-        }
+        self.pre_expansion_passes.push(Box::new(pass));
     }
 
-    pub fn register_late_pass(&mut self,
-                              sess: Option<&Session>,
-                              from_plugin: bool,
-                              register_only: bool,
-                              per_module: bool,
-                              pass: LateLintPassObject) {
-        self.push_pass(sess, from_plugin, &pass);
-        if !register_only {
-            if per_module {
-                self.late_module_passes.push(pass);
-            } else {
-                self.late_passes.lock().as_mut().unwrap().push(pass);
-            }
-        }
+    pub fn register_late_pass(
+        &mut self,
+        pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
+    ) {
+        self.late_passes.push(Box::new(pass));
+    }
+
+    pub fn register_late_mod_pass(
+        &mut self,
+        pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
+    ) {
+        self.late_module_passes.push(Box::new(pass));
     }
 
     // Helper method for register_early/late_pass
-    fn push_pass<P: LintPass + ?Sized + 'static>(&mut self,
-                                        sess: Option<&Session>,
-                                        from_plugin: bool,
-                                        pass: &Box<P>) {
-        for lint in pass.get_lints() {
-            self.lints.push((lint, from_plugin));
+    pub fn register_lints(&mut self, lints: &[&'static Lint]) {
+        for lint in lints {
+            self.lints.push(lint);
 
             let id = LintId::of(lint);
             if self.by_name.insert(lint.name_lower(), Id(id)).is_some() {
-                let msg = format!("duplicate specification of lint {}", lint.name_lower());
-                match (sess, from_plugin) {
-                    // We load builtin lints first, so a duplicate is a compiler bug.
-                    // Use early_error when handling -W help with no crate.
-                    (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
-                    (Some(_), false) => bug!("{}", msg),
-
-                    // A duplicate name from a plugin is a user error.
-                    (Some(sess), true)  => sess.err(&msg[..]),
-                }
+                bug!("duplicate specification of lint {}", lint.name_lower())
             }
-        }
-    }
 
-    pub fn register_future_incompatible(&mut self,
-                                        sess: Option<&Session>,
-                                        lints: Vec<FutureIncompatibleInfo>) {
+            if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible {
+                if let Some(edition) = edition {
+                    self.lint_groups.entry(edition.lint_name())
+                        .or_insert(LintGroup {
+                            lint_ids: vec![],
+                            from_plugin: lint.is_plugin,
+                            depr: None,
+                        })
+                        .lint_ids.push(id);
+                }
 
-        for edition in edition::ALL_EDITIONS {
-            let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id)
-                             .collect::<Vec<_>>();
-            if !lints.is_empty() {
-                self.register_group(sess, false, edition.lint_name(), None, lints)
+                self.lint_groups.entry("future_incompatible")
+                    .or_insert(LintGroup {
+                        lint_ids: vec![],
+                        from_plugin: lint.is_plugin,
+                        depr: None,
+                    })
+                    .lint_ids.push(id);
             }
         }
-
-        let mut future_incompatible = Vec::with_capacity(lints.len());
-        for lint in lints {
-            future_incompatible.push(lint.id);
-            self.future_incompatible.insert(lint.id, lint);
-        }
-
-        self.register_group(
-            sess,
-            false,
-            "future_incompatible",
-            None,
-            future_incompatible,
-        );
-    }
-
-    pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
-        self.future_incompatible.get(&id)
     }
 
     pub fn register_group_alias(
@@ -277,7 +229,6 @@ impl LintStore {
 
     pub fn register_group(
         &mut self,
-        sess: Option<&Session>,
         from_plugin: bool,
         name: &'static str,
         deprecated_name: Option<&'static str>,
@@ -300,16 +251,7 @@ impl LintStore {
         }
 
         if !new {
-            let msg = format!("duplicate specification of lint group {}", name);
-            match (sess, from_plugin) {
-                // We load builtin lints first, so a duplicate is a compiler bug.
-                // Use early_error when handling -W help with no crate.
-                (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
-                (Some(_), false) => bug!("{}", msg),
-
-                // A duplicate name from a plugin is a user error.
-                (Some(sess), true)  => sess.err(&msg[..]),
-            }
+            bug!("duplicate specification of lint group {}", name);
         }
     }
 
@@ -522,7 +464,7 @@ pub struct LateContext<'a, 'tcx> {
     pub access_levels: &'a AccessLevels,
 
     /// The store of registered lints and the lint levels.
-    lint_store: ReadGuard<'a, LintStore>,
+    lint_store: &'tcx LintStore,
 
     last_node_with_lint_attrs: hir::HirId,
 
@@ -550,7 +492,7 @@ pub struct EarlyContext<'a> {
     builder: LintLevelsBuilder<'a>,
 
     /// The store of registered lints and the lint levels.
-    lint_store: ReadGuard<'a, LintStore>,
+    lint_store: &'a LintStore,
 
     buffered: LintBuffer,
 }
@@ -639,14 +581,15 @@ pub trait LintContext: Sized {
 impl<'a> EarlyContext<'a> {
     fn new(
         sess: &'a Session,
+        lint_store: &'a LintStore,
         krate: &'a ast::Crate,
         buffered: LintBuffer,
     ) -> EarlyContext<'a> {
         EarlyContext {
             sess,
             krate,
-            lint_store: sess.lint_store.borrow(),
-            builder: LintLevelSets::builder(sess),
+            lint_store,
+            builder: LintLevelSets::builder(sess, lint_store),
             buffered,
         }
     }
@@ -681,7 +624,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
                           f: F)
         where F: FnOnce(&mut Self)
     {
-        let push = self.context.builder.push(attrs);
+        let push = self.context.builder.push(attrs, &self.context.lint_store);
         self.check_id(id);
         self.enter_attrs(attrs);
         f(self);
@@ -875,7 +818,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
                     _ => {}
                 }
 
-                path.push(disambiguated_data.data.as_interned_str().as_symbol());
+                path.push(disambiguated_data.data.as_symbol());
                 Ok(path)
             }
 
@@ -1355,10 +1298,6 @@ impl LintPass for LateLintPassObjects<'_> {
     fn name(&self) -> &'static str {
         panic!()
     }
-
-    fn get_lints(&self) -> LintArray {
-        panic!()
-    }
 }
 
 macro_rules! expand_late_lint_pass_impl_methods {
@@ -1393,7 +1332,7 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
         tables: &ty::TypeckTables::empty(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
-        lint_store: tcx.sess.lint_store.borrow(),
+        lint_store: &tcx.lint_store,
         last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
         generics: None,
         only_module: true,
@@ -1425,8 +1364,8 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
 
     late_lint_mod_pass(tcx, module_def_id, builtin_lints);
 
-    let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes
-                                .iter().map(|pass| pass.fresh_late_pass()).collect();
+    let mut passes: Vec<_> = tcx.lint_store.late_module_passes
+                                .iter().map(|pass| (pass)()).collect();
 
     if !passes.is_empty() {
         late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
@@ -1443,7 +1382,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
         tables: &ty::TypeckTables::empty(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
-        lint_store: tcx.sess.lint_store.borrow(),
+        lint_store: &tcx.lint_store,
         last_node_with_lint_attrs: hir::CRATE_HIR_ID,
         generics: None,
         only_module: false,
@@ -1467,7 +1406,8 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
 }
 
 fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
-    let mut passes = tcx.sess.lint_store.borrow().late_passes.lock().take().unwrap();
+    let mut passes = tcx.lint_store
+        .late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
 
     if !tcx.sess.opts.debugging_opts.no_interleave_lints {
         if !passes.is_empty() {
@@ -1482,8 +1422,8 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b
             });
         }
 
-        let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes
-                                    .iter().map(|pass| pass.fresh_late_pass()).collect();
+        let mut passes: Vec<_> = tcx.lint_store.late_module_passes
+                                    .iter().map(|pass| (pass)()).collect();
 
         for pass in &mut passes {
             time(tcx.sess, &format!("running late module lint: {}", pass.name()), || {
@@ -1491,9 +1431,6 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b
             });
         }
     }
-
-    // Put the passes back in the session.
-    *tcx.sess.lint_store.borrow().late_passes.lock() = Some(passes);
 }
 
 /// Performs lint checking on a crate.
@@ -1525,10 +1462,6 @@ impl LintPass for EarlyLintPassObjects<'_> {
     fn name(&self) -> &'static str {
         panic!()
     }
-
-    fn get_lints(&self) -> LintArray {
-        panic!()
-    }
 }
 
 macro_rules! expand_early_lint_pass_impl_methods {
@@ -1553,12 +1486,13 @@ early_lint_methods!(early_lint_pass_impl, []);
 
 fn early_lint_crate<T: EarlyLintPass>(
     sess: &Session,
+    lint_store: &LintStore,
     krate: &ast::Crate,
     pass: T,
     buffered: LintBuffer,
 ) -> LintBuffer {
     let mut cx = EarlyContextAndPass {
-        context: EarlyContext::new(sess, krate, buffered),
+        context: EarlyContext::new(sess, lint_store, krate, buffered),
         pass,
     };
 
@@ -1577,28 +1511,30 @@ fn early_lint_crate<T: EarlyLintPass>(
 
 pub fn check_ast_crate<T: EarlyLintPass>(
     sess: &Session,
+    lint_store: &LintStore,
     krate: &ast::Crate,
     pre_expansion: bool,
     builtin_lints: T,
 ) {
-    let (mut passes, mut buffered) = if pre_expansion {
+    let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion {
         (
-            sess.lint_store.borrow_mut().pre_expansion_passes.take().unwrap(),
+            lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(),
             LintBuffer::default(),
         )
     } else {
         (
-            sess.lint_store.borrow_mut().early_passes.take().unwrap(),
+            lint_store.early_passes.iter().map(|p| (p)()).collect(),
             sess.buffered_lints.borrow_mut().take().unwrap(),
         )
     };
 
     if !sess.opts.debugging_opts.no_interleave_lints {
-        buffered = early_lint_crate(sess, krate, builtin_lints, buffered);
+        buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered);
 
         if !passes.is_empty() {
             buffered = early_lint_crate(
                 sess,
+                lint_store,
                 krate,
                 EarlyLintPassObjects { lints: &mut passes[..] },
                 buffered,
@@ -1609,6 +1545,7 @@ pub fn check_ast_crate<T: EarlyLintPass>(
             buffered = time(sess, &format!("running lint: {}", pass.name()), || {
                 early_lint_crate(
                     sess,
+                    lint_store,
                     krate,
                     EarlyLintPassObjects { lints: slice::from_mut(pass) },
                     buffered,
@@ -1617,13 +1554,6 @@ pub fn check_ast_crate<T: EarlyLintPass>(
         }
     }
 
-    // Put the lint store levels and passes back in the session.
-    if pre_expansion {
-        sess.lint_store.borrow_mut().pre_expansion_passes = Some(passes);
-    } else {
-        sess.lint_store.borrow_mut().early_passes = Some(passes);
-    }
-
     // All of the buffered lints should have been emitted at this point.
     // If not, that means that we somehow buffered a lint for a node id
     // that was not lint-checked (perhaps it doesn't exist?). This is a bug.
@@ -1653,7 +1583,7 @@ impl Decodable for LintId {
     fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
         let s = d.read_str()?;
         ty::tls::with(|tcx| {
-            match tcx.sess.lint_store.borrow().find_lints(&s) {
+            match tcx.lint_store.find_lints(&s) {
                 Ok(ids) => {
                     if ids.len() != 0 {
                         panic!("invalid lint-id `{}`", s);
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 8ed06cbdc76..4c60492e470 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -3,7 +3,7 @@ use std::cmp;
 use crate::hir::HirId;
 use crate::ich::StableHashingContext;
 use crate::lint::builtin;
-use crate::lint::context::CheckLintNameResult;
+use crate::lint::context::{LintStore, CheckLintNameResult};
 use crate::lint::{self, Lint, LintId, Level, LintSource};
 use crate::session::Session;
 use crate::util::nodemap::FxHashMap;
@@ -35,21 +35,20 @@ enum LintSet {
 }
 
 impl LintLevelSets {
-    pub fn new(sess: &Session) -> LintLevelSets {
+    pub fn new(sess: &Session, lint_store: &LintStore) -> LintLevelSets {
         let mut me = LintLevelSets {
             list: Vec::new(),
             lint_cap: Level::Forbid,
         };
-        me.process_command_line(sess);
+        me.process_command_line(sess, lint_store);
         return me
     }
 
-    pub fn builder(sess: &Session) -> LintLevelsBuilder<'_> {
-        LintLevelsBuilder::new(sess, LintLevelSets::new(sess))
+    pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> {
+        LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store))
     }
 
-    fn process_command_line(&mut self, sess: &Session) {
-        let store = sess.lint_store.borrow();
+    fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
         let mut specs = FxHashMap::default();
         self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
 
@@ -186,9 +185,8 @@ impl<'a> LintLevelsBuilder<'a> {
     ///   #[allow]
     ///
     /// Don't forget to call `pop`!
-    pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
+    pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush {
         let mut specs = FxHashMap::default();
-        let store = self.sess.lint_store.borrow();
         let sess = self.sess;
         let bad_attr = |span| {
             struct_span_err!(sess, span, E0452, "malformed lint attribute input")
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 7443cca822a..3c35bdae66e 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -45,7 +45,7 @@ use syntax_pos::Span;
 
 pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore,
                         check_crate, check_ast_crate, late_lint_mod, CheckLintNameResult,
-                        FutureIncompatibleInfo, BufferedEarlyLint,};
+                        BufferedEarlyLint,};
 
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
@@ -76,9 +76,35 @@ pub struct Lint {
 
     /// `true` if this lint is reported even inside expansions of external macros.
     pub report_in_external_macro: bool,
+
+    pub future_incompatible: Option<FutureIncompatibleInfo>,
+
+    pub is_plugin: bool,
+}
+
+/// Extra information for a future incompatibility lint.
+#[derive(Copy, Clone, Debug)]
+pub struct FutureIncompatibleInfo {
+    /// e.g., a URL for an issue/PR/RFC or error code
+    pub reference: &'static str,
+    /// If this is an edition fixing lint, the edition in which
+    /// this lint becomes obsolete
+    pub edition: Option<Edition>,
 }
 
 impl Lint {
+    pub const fn default_fields_for_macro() -> Self {
+        Lint {
+            name: "",
+            default_level: Level::Forbid,
+            desc: "",
+            edition_lint_opts: None,
+            is_plugin: false,
+            report_in_external_macro: false,
+            future_incompatible: None,
+        }
+    }
+
     /// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`.
     pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
         match lint_id {
@@ -105,18 +131,21 @@ impl Lint {
 #[macro_export]
 macro_rules! declare_lint {
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
-        declare_lint!{$vis $NAME, $Level, $desc, false}
-    );
-    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, report_in_external_macro: $rep: expr) => (
-        declare_lint!{$vis $NAME, $Level, $desc, $rep}
+        declare_lint!(
+            $vis $NAME, $Level, $desc,
+        );
     );
-    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+    ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
+     $(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: stringify!($NAME),
             default_level: $crate::lint::$Level,
             desc: $desc,
             edition_lint_opts: None,
-            report_in_external_macro: $external,
+            is_plugin: false,
+            $($v: true,)*
+            $(future_incompatible: Some($fi),)*
+            ..$crate::lint::Lint::default_fields_for_macro()
         };
     );
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
@@ -128,6 +157,7 @@ macro_rules! declare_lint {
             desc: $desc,
             edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)),
             report_in_external_macro: false,
+            is_plugin: false,
         };
     );
 }
@@ -156,6 +186,8 @@ macro_rules! declare_tool_lint {
             desc: $desc,
             edition_lint_opts: None,
             report_in_external_macro: $external,
+            future_incompatible: None,
+            is_plugin: true,
         };
     );
 }
@@ -173,14 +205,6 @@ pub type LintArray = Vec<&'static Lint>;
 
 pub trait LintPass {
     fn name(&self) -> &'static str;
-
-    /// Gets descriptions of the lints this `LintPass` object can emit.
-    ///
-    /// N.B., there is no enforcement that the object only emits lints it registered.
-    /// And some `rustc` internal `LintPass`es register lints to be emitted by other
-    /// parts of the compiler. If you want enforced access restrictions for your
-    /// `Lint`, make it a private `static` item in its own module.
-    fn get_lints(&self) -> LintArray;
 }
 
 /// Implements `LintPass for $name` with the given list of `Lint` statics.
@@ -189,7 +213,9 @@ macro_rules! impl_lint_pass {
     ($name:ident => [$($lint:expr),* $(,)?]) => {
         impl LintPass for $name {
             fn name(&self) -> &'static str { stringify!($name) }
-            fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) }
+        }
+        impl $name {
+            pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) }
         }
     };
 }
@@ -287,9 +313,6 @@ macro_rules! expand_lint_pass_methods {
 macro_rules! declare_late_lint_pass {
     ([], [$hir:tt], [$($methods:tt)*]) => (
         pub trait LateLintPass<'a, $hir>: LintPass {
-            fn fresh_late_pass(&self) -> LateLintPassObject {
-                panic!()
-            }
             expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
         }
     )
@@ -327,6 +350,12 @@ macro_rules! declare_combined_late_lint_pass {
                     $($passes: $constructor,)*
                 }
             }
+
+            $v fn get_lints() -> LintArray {
+                let mut lints = Vec::new();
+                $(lints.extend_from_slice(&$passes::get_lints());)*
+                lints
+            }
         }
 
         impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
@@ -337,12 +366,6 @@ macro_rules! declare_combined_late_lint_pass {
             fn name(&self) -> &'static str {
                 panic!()
             }
-
-            fn get_lints(&self) -> LintArray {
-                let mut lints = Vec::new();
-                $(lints.extend_from_slice(&self.$passes.get_lints());)*
-                lints
-            }
         }
     )
 }
@@ -454,6 +477,12 @@ macro_rules! declare_combined_early_lint_pass {
                     $($passes: $constructor,)*
                 }
             }
+
+            $v fn get_lints() -> LintArray {
+                let mut lints = Vec::new();
+                $(lints.extend_from_slice(&$passes::get_lints());)*
+                lints
+            }
         }
 
         impl EarlyLintPass for $name {
@@ -464,12 +493,6 @@ macro_rules! declare_combined_early_lint_pass {
             fn name(&self) -> &'static str {
                 panic!()
             }
-
-            fn get_lints(&self) -> LintArray {
-                let mut lints = Vec::new();
-                $(lints.extend_from_slice(&self.$passes.get_lints());)*
-                lints
-            }
         }
     )
 }
@@ -649,9 +672,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
     };
 
     // Check for future incompatibility lints and issue a stronger warning.
-    let lints = sess.lint_store.borrow();
     let lint_id = LintId::of(lint);
-    let future_incompatible = lints.future_incompatible(lint_id);
+    let future_incompatible = lint.future_incompatible;
 
     // If this code originates in a foreign macro, aka something that this crate
     // did not itself author, then it's likely that there's nothing this crate
@@ -755,13 +777,15 @@ pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 
 fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     assert_eq!(cnum, LOCAL_CRATE);
+    let store = &tcx.lint_store;
     let mut builder = LintLevelMapBuilder {
-        levels: LintLevelSets::builder(tcx.sess),
+        levels: LintLevelSets::builder(tcx.sess, &store),
         tcx: tcx,
+        store: store,
     };
     let krate = tcx.hir().krate();
 
-    let push = builder.levels.push(&krate.attrs);
+    let push = builder.levels.push(&krate.attrs, &store);
     builder.levels.register_id(hir::CRATE_HIR_ID);
     for macro_def in &krate.exported_macros {
        builder.levels.register_id(macro_def.hir_id);
@@ -772,19 +796,20 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     tcx.arena.alloc(builder.levels.build_map())
 }
 
-struct LintLevelMapBuilder<'tcx> {
+struct LintLevelMapBuilder<'a, 'tcx> {
     levels: levels::LintLevelsBuilder<'tcx>,
     tcx: TyCtxt<'tcx>,
+    store: &'a LintStore,
 }
 
-impl LintLevelMapBuilder<'tcx> {
+impl LintLevelMapBuilder<'_, '_> {
     fn with_lint_attrs<F>(&mut self,
                           id: hir::HirId,
                           attrs: &[ast::Attribute],
                           f: F)
         where F: FnOnce(&mut Self)
     {
-        let push = self.levels.push(attrs);
+        let push = self.levels.push(attrs, self.store);
         if push.changed {
             self.levels.register_id(id);
         }
@@ -793,7 +818,7 @@ impl LintLevelMapBuilder<'tcx> {
     }
 }
 
-impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
+impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
         intravisit::NestedVisitorMap::All(&self.tcx.hir())
     }
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index ec1e32988a6..d5558db2397 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -16,7 +16,7 @@ use syntax::ast;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_target::spec::Target;
-use rustc_data_structures::sync::{self, MetadataRef, Lrc};
+use rustc_data_structures::sync::{self, MetadataRef};
 use rustc_macros::HashStable;
 
 pub use self::NativeLibraryKind::*;
@@ -191,6 +191,8 @@ pub trait MetadataLoader {
                           -> Result<MetadataRef, String>;
 }
 
+pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
+
 /// A store of Rust crates, through which their metadata can be accessed.
 ///
 /// Note that this trait should probably not be expanding today. All new
@@ -201,13 +203,13 @@ pub trait MetadataLoader {
 /// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
 /// during resolve)
 pub trait CrateStore {
-    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>;
+    fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any;
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey;
     fn def_path(&self, def: DefId) -> hir_map::DefPath;
     fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash;
-    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable>;
+    fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable;
 
     // "queries" used in resolve that aren't tracked for incremental compilation
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index 796d293e2c6..aa8ac4902a8 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -353,11 +353,14 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
         &mut self,
         cx: &impl HasDataLayout,
         ptr: Pointer<Tag>,
-        src: impl IntoIterator<Item=u8, IntoIter: iter::ExactSizeIterator>,
+        src: impl IntoIterator<Item=u8>,
     ) -> InterpResult<'tcx>
     {
         let mut src = src.into_iter();
-        let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?;
+        let (lower, upper) = src.size_hint();
+        let len = upper.expect("can only write bounded iterators");
+        assert_eq!(lower, len, "can only write iterators with a precise length");
+        let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(len as u64))?;
         // `zip` would stop when the first iterator ends; we want to definitely
         // cover all of `bytes`.
         for dest in bytes {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index ccf64c51e13..08e7001681c 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -37,7 +37,7 @@ use std::slice;
 use std::vec::IntoIter;
 use std::{iter, mem, option, u32};
 use syntax::ast::Name;
-use syntax::symbol::{InternedString, Symbol};
+use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 
 pub use crate::mir::interpret::AssertMessage;
@@ -2736,8 +2736,8 @@ pub enum UnsafetyViolationKind {
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
 pub struct UnsafetyViolation {
     pub source_info: SourceInfo,
-    pub description: InternedString,
-    pub details: InternedString,
+    pub description: Symbol,
+    pub details: Symbol,
     pub kind: UnsafetyViolationKind,
 }
 
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index eeb997d75ca..58f99667cb3 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -1,6 +1,6 @@
 use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use crate::hir::HirId;
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 use syntax::attr::InlineAttr;
 use syntax::source_map::Span;
 use crate::ty::{Instance, InstanceDef, TyCtxt, SymbolName, subst::InternalSubsts};
@@ -80,7 +80,7 @@ impl<'tcx> MonoItem<'tcx> {
             MonoItem::GlobalAsm(hir_id) => {
                 let def_id = tcx.hir().local_def_id(hir_id);
                 SymbolName {
-                    name: InternedString::intern(&format!("global_asm_{:?}", def_id))
+                    name: Symbol::intern(&format!("global_asm_{:?}", def_id))
                 }
             }
         }
@@ -246,7 +246,7 @@ pub struct CodegenUnit<'tcx> {
     /// name be unique amongst **all** crates. Therefore, it should
     /// contain something unique to this crate (e.g., a module path)
     /// as well as the crate name and disambiguator.
-    name: InternedString,
+    name: Symbol,
     items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
     size_estimate: Option<usize>,
 }
@@ -294,7 +294,7 @@ impl_stable_hash_for!(enum self::Visibility {
 });
 
 impl<'tcx> CodegenUnit<'tcx> {
-    pub fn new(name: InternedString) -> CodegenUnit<'tcx> {
+    pub fn new(name: Symbol) -> CodegenUnit<'tcx> {
         CodegenUnit {
             name: name,
             items: Default::default(),
@@ -302,11 +302,11 @@ impl<'tcx> CodegenUnit<'tcx> {
         }
     }
 
-    pub fn name(&self) -> &InternedString {
-        &self.name
+    pub fn name(&self) -> Symbol {
+        self.name
     }
 
-    pub fn set_name(&mut self, name: InternedString) {
+    pub fn set_name(&mut self, name: Symbol) {
         self.name = name;
     }
 
@@ -474,7 +474,7 @@ impl CodegenUnitNameBuilder<'tcx> {
                                    cnum: CrateNum,
                                    components: I,
                                    special_suffix: Option<S>)
-                                   -> InternedString
+                                   -> Symbol
         where I: IntoIterator<Item=C>,
               C: fmt::Display,
               S: fmt::Display,
@@ -487,7 +487,7 @@ impl CodegenUnitNameBuilder<'tcx> {
             cgu_name
         } else {
             let cgu_name = &cgu_name.as_str()[..];
-            InternedString::intern(&CodegenUnit::mangle_name(cgu_name))
+            Symbol::intern(&CodegenUnit::mangle_name(cgu_name))
         }
     }
 
@@ -497,7 +497,7 @@ impl CodegenUnitNameBuilder<'tcx> {
                                              cnum: CrateNum,
                                              components: I,
                                              special_suffix: Option<S>)
-                                             -> InternedString
+                                             -> Symbol
         where I: IntoIterator<Item=C>,
               C: fmt::Display,
               S: fmt::Display,
@@ -543,6 +543,6 @@ impl CodegenUnitNameBuilder<'tcx> {
             write!(cgu_name, ".{}", special_suffix).unwrap();
         }
 
-        InternedString::intern(&cgu_name[..])
+        Symbol::intern(&cgu_name[..])
     }
 }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 2c407a24493..fdca6d0e17a 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -15,7 +15,7 @@ use crate::traits::query::{
 };
 
 use std::borrow::Cow;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
@@ -924,7 +924,7 @@ rustc_queries! {
             desc { "collect_and_partition_mono_items" }
         }
         query is_codegened_item(_: DefId) -> bool {}
-        query codegen_unit(_: InternedString) -> Arc<CodegenUnit<'tcx>> {
+        query codegen_unit(_: Symbol) -> Arc<CodegenUnit<'tcx>> {
             no_force
             desc { "codegen_unit" }
         }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 2446d4f4788..33b9ddaa622 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1149,7 +1149,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
     target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
         "select target processor (`rustc --print target-cpus` for details)"),
     target_feature: String = (String::new(), parse_string, [TRACKED],
-        "target specific attributes (`rustc --print target-features` for details)"),
+        "target specific attributes. (`rustc --print target-features` for details). \
+        This feature is unsafe."),
     passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
         "a list of extra LLVM passes to run (space separated)"),
     llvm_args: Vec<String> = (Vec::new(), parse_list, [TRACKED],
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index b65bf2230b3..bd2460cfab1 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -14,7 +14,7 @@ use crate::util::common::{duration_to_secs_str, ErrorReported};
 
 use rustc_data_structures::base_n;
 use rustc_data_structures::sync::{
-    self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, Ordering,
+    self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering,
     Ordering::SeqCst,
 };
 
@@ -77,9 +77,11 @@ pub struct Session {
     /// if the value stored here has been affected by path remapping.
     pub working_dir: (PathBuf, bool),
 
-    // FIXME: `lint_store` and `buffered_lints` are not thread-safe,
-    // but are only used in a single thread.
-    pub lint_store: RwLock<lint::LintStore>,
+    /// This is intended to be used from a single thread.
+    ///
+    /// FIXME: there was a previous comment about this not being thread safe,
+    /// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread
+    /// safe at least from a "Rust safety" standpoint.
     pub buffered_lints: Lock<Option<lint::LintBuffer>>,
 
     /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
@@ -1213,7 +1215,6 @@ fn build_session_(
         sysroot,
         local_crate_source_file,
         working_dir,
-        lint_store: RwLock::new(lint::LintStore::new()),
         buffered_lints: Lock::new(Some(Default::default())),
         one_time_diagnostics: Default::default(),
         plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index daa4a215a23..e684cdc0a38 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -406,7 +406,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 },
                 GenericParamDefKind::Lifetime => continue,
             };
-            let name = param.name.as_symbol();
+            let name = param.name;
             flags.push((name, Some(value)));
         }
 
@@ -793,15 +793,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
                         let violations = self.tcx.object_safety_violations(trait_def_id);
-                        if let Some(err) = self.tcx.report_object_safety_error(
+                        self.tcx.report_object_safety_error(
                             span,
                             trait_def_id,
                             violations,
-                        ) {
-                            err
-                        } else {
-                            return;
-                        }
+                        )
                     }
 
                     ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
@@ -937,11 +933,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
             TraitNotObjectSafe(did) => {
                 let violations = self.tcx.object_safety_violations(did);
-                if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) {
-                    err
-                } else {
-                    return;
-                }
+                self.tcx.report_object_safety_error(span, did, violations)
             }
 
             // already reported in the query
@@ -1665,11 +1657,7 @@ impl<'tcx> TyCtxt<'tcx> {
         span: Span,
         trait_def_id: DefId,
         violations: Vec<ObjectSafetyViolation>,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
-        if self.sess.trait_methods_not_found.borrow().contains(&span) {
-            // Avoid emitting error caused by non-existing method (#58734)
-            return None;
-        }
+    ) -> DiagnosticBuilder<'tcx> {
         let trait_str = self.def_path_str(trait_def_id);
         let span = self.sess.source_map().def_span(span);
         let mut err = struct_span_err!(
@@ -1687,7 +1675,13 @@ impl<'tcx> TyCtxt<'tcx> {
                 };
             }
         }
-        Some(err)
+
+        if self.sess.trait_methods_not_found.borrow().contains(&span) {
+            // Avoid emitting error caused by non-existing method (#58734)
+            err.cancel();
+        }
+
+        err
     }
 }
 
@@ -2098,6 +2092,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 err.note(&format!("required for the cast to the object type `{}`",
                                   self.ty_to_string(object_ty)));
             }
+            ObligationCauseCode::Coercion { source: _, target } => {
+                err.note(&format!("required by cast to type `{}`",
+                                  self.ty_to_string(target)));
+            }
             ObligationCauseCode::RepeatVec => {
                 err.note("the `Copy` trait is required because the \
                           repeated element will be copied");
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index d96330bf0a9..eb4b114eb30 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -188,6 +188,9 @@ pub enum ObligationCauseCode<'tcx> {
     /// Obligation incurred due to an object cast.
     ObjectCastObligation(/* Object type */ Ty<'tcx>),
 
+    /// Obligation incurred due to a coercion.
+    Coercion { source: Ty<'tcx>, target: Ty<'tcx> },
+
     // Various cases where expressions must be sized/copy/etc:
     /// L = X implies that L is Sized
     AssignmentLhsSized,
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index e0ef179911b..e42c3a63541 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -19,7 +19,7 @@ use crate::ty::subst::{Subst, InternalSubsts};
 use std::borrow::Cow;
 use std::iter::{self};
 use syntax::ast::{self};
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -560,7 +560,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // are implemented
         let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
             ::std::u32::MAX,
-            InternedString::intern("RustaceansAreAwesome"),
+            Symbol::intern("RustaceansAreAwesome"),
         );
 
         // `Receiver[Self => U]`
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 5a988d9509e..c1c814f9b03 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -250,7 +250,7 @@ impl<'tcx> OnUnimplementedFormatString {
                     Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
                     // So is `{A}` if A is a type parameter
                     Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
-                        param.name.as_symbol() == s
+                        param.name == s
                     }) {
                         Some(_) => (),
                         None => {
@@ -289,7 +289,7 @@ impl<'tcx> OnUnimplementedFormatString {
                 },
                 GenericParamDefKind::Lifetime => return None
             };
-            let name = param.name.as_symbol();
+            let name = param.name;
             Some((name, value))
         }).collect::<FxHashMap<Symbol, String>>();
         let empty_string = String::new();
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 44d611ace77..d8a27f1e040 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2246,7 +2246,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
 
                     if let Some(principal) = data.principal() {
-                        principal.with_self_ty(self.tcx(), self_ty)
+                        if !self.infcx.tcx.features().object_safe_for_dispatch {
+                            principal.with_self_ty(self.tcx(), self_ty)
+                        } else if self.tcx().is_object_safe(principal.def_id()) {
+                            principal.with_self_ty(self.tcx(), self_ty)
+                        } else {
+                            return;
+                        }
                     } else {
                         // Only auto-trait bounds exist.
                         return;
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index dab62a6bcb5..18db3c8d10b 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -4,7 +4,7 @@ use crate::traits;
 use crate::traits::project::Normalized;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::{self, Lift, Ty, TyCtxt};
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 
 use std::fmt;
 use std::rc::Rc;
@@ -261,11 +261,11 @@ impl fmt::Display for traits::QuantifierKind {
 /// for debug output in tests anyway.
 struct BoundNamesCollector {
     // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
-    regions: BTreeSet<InternedString>,
+    regions: BTreeSet<Symbol>,
 
     // Sort by `BoundVar` index, so usually this should be equivalent to the order given
     // by the list of type parameters.
-    types: BTreeMap<u32, InternedString>,
+    types: BTreeMap<u32, Symbol>,
 
     binder_index: ty::DebruijnIndex,
 }
@@ -319,7 +319,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
                     match bound_ty.kind {
                         ty::BoundTyKind::Param(name) => name,
                         ty::BoundTyKind::Anon =>
-                            InternedString::intern(&format!("^{}", bound_ty.var.as_u32()),
+                            Symbol::intern(&format!("^{}", bound_ty.var.as_u32()),
                         ),
                     }
                 );
@@ -340,7 +340,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
                     }
 
                     ty::BoundRegion::BrAnon(var) => {
-                        self.regions.insert(InternedString::intern(&format!("'^{}", var)));
+                        self.regions.insert(Symbol::intern(&format!("'^{}", var)));
                     }
 
                     _ => (),
@@ -481,6 +481,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                    .and_then(|r| Some(super::ObjectTypeBound(ty, r)))
             ),
             super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
+            super::Coercion { source, target } => Some(super::Coercion {
+                source: tcx.lift(&source)?,
+                target: tcx.lift(&target)?,
+            }),
             super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
             super::TupleInitializerSized => Some(super::TupleInitializerSized),
             super::StructInitializerSized => Some(super::StructInitializerSized),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d118bef37fc..f99298281fe 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -72,7 +72,7 @@ use syntax::ast;
 use syntax::attr;
 use syntax::source_map::MultiSpan;
 use syntax::feature_gate;
-use syntax::symbol::{Symbol, InternedString, kw, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax_pos::Span;
 
 pub struct AllArenas {
@@ -949,7 +949,7 @@ impl<'tcx> CommonTypes<'tcx> {
             f64: mk(Float(ast::FloatTy::F64)),
             self_param: mk(ty::Param(ty::ParamTy {
                 index: 0,
-                name: kw::SelfUpper.as_interned_str(),
+                name: kw::SelfUpper,
             })),
 
             trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
@@ -1027,10 +1027,12 @@ pub struct GlobalCtxt<'tcx> {
 
     interners: CtxtInterners<'tcx>,
 
-    cstore: &'tcx CrateStoreDyn,
+    cstore: Box<CrateStoreDyn>,
 
     pub sess: &'tcx Session,
 
+    pub lint_store: Lrc<lint::LintStore>,
+
     pub dep_graph: DepGraph,
 
     pub prof: SelfProfilerRef,
@@ -1192,11 +1194,11 @@ impl<'tcx> TyCtxt<'tcx> {
     /// reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
-        cstore: &'tcx CrateStoreDyn,
+        lint_store: Lrc<lint::LintStore>,
         local_providers: ty::query::Providers<'tcx>,
         extern_providers: ty::query::Providers<'tcx>,
         arenas: &'tcx AllArenas,
-        resolutions: ty::Resolutions,
+        resolutions: ty::ResolverOutputs,
         hir: hir_map::Map<'tcx>,
         on_disk_query_result_cache: query::OnDiskCache<'tcx>,
         crate_name: &str,
@@ -1210,34 +1212,28 @@ impl<'tcx> TyCtxt<'tcx> {
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
         let dep_graph = hir.dep_graph.clone();
-        let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0);
+        let cstore = resolutions.cstore;
+        let crates = cstore.crates_untracked();
+        let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0);
         let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1);
         providers[LOCAL_CRATE] = local_providers;
 
         let def_path_hash_to_def_id = if s.opts.build_dep_graph() {
-            let upstream_def_path_tables: Vec<(CrateNum, Lrc<_>)> = cstore
-                .crates_untracked()
+            let def_path_tables = crates
                 .iter()
                 .map(|&cnum| (cnum, cstore.def_path_table(cnum)))
-                .collect();
-
-            let def_path_tables = || {
-                upstream_def_path_tables
-                    .iter()
-                    .map(|&(cnum, ref rc)| (cnum, &**rc))
-                    .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table())))
-            };
+                .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table())));
 
             // Precompute the capacity of the hashmap so we don't have to
             // re-allocate when populating it.
-            let capacity = def_path_tables().map(|(_, t)| t.size()).sum::<usize>();
+            let capacity = def_path_tables.clone().map(|(_, t)| t.size()).sum::<usize>();
 
             let mut map: FxHashMap<_, _> = FxHashMap::with_capacity_and_hasher(
                 capacity,
                 ::std::default::Default::default()
             );
 
-            for (cnum, def_path_table) in def_path_tables() {
+            for (cnum, def_path_table) in def_path_tables {
                 def_path_table.add_def_path_hashes_to(cnum, &mut map);
             }
 
@@ -1255,6 +1251,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         GlobalCtxt {
             sess: s,
+            lint_store,
             cstore,
             arena: WorkerLocal::new(|_| Arena::default()),
             interners,
@@ -1413,8 +1410,8 @@ impl<'tcx> TyCtxt<'tcx> {
 
     // Note that this is *untracked* and should only be used within the query
     // system if the result is otherwise tracked through queries
-    pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc<dyn Any> {
-        self.cstore.crate_data_as_rc_any(cnum)
+    pub fn crate_data_as_any(self, cnum: CrateNum) -> &'tcx dyn Any {
+        self.cstore.crate_data_as_any(cnum)
     }
 
     #[inline(always)]
@@ -1424,7 +1421,7 @@ impl<'tcx> TyCtxt<'tcx> {
         StableHashingContext::new(self.sess,
                                   krate,
                                   self.hir().definitions(),
-                                  self.cstore)
+                                  &*self.cstore)
     }
 
     // This method makes sure that we have a DepNode and a Fingerprint for
@@ -2552,7 +2549,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
-    pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> {
+    pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
         self.mk_ty(Param(ParamTy { index, name: name }))
     }
 
@@ -2560,7 +2557,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn mk_const_param(
         self,
         index: u32,
-        name: InternedString,
+        name: Symbol,
         ty: Ty<'tcx>
     ) -> &'tcx Const<'tcx> {
         self.mk_const(ty::Const {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 3395715f67f..77613b548cf 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -45,7 +45,7 @@ pub enum TypeError<'tcx> {
     ProjectionMismatched(ExpectedFound<DefId>),
     ProjectionBoundsLength(ExpectedFound<usize>),
     ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
-
+    ObjectUnsafeCoercion(DefId),
     ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
 
     IntrinsicCast,
@@ -178,6 +178,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             IntrinsicCast => {
                 write!(f, "cannot coerce intrinsics to function pointers")
             }
+            ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"),
         }
     }
 }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index d377b7328e8..4660e8025d4 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -4,7 +4,7 @@ pub use self::Variance::*;
 pub use self::AssocItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::IntVarValue::*;
-pub use self::fold::TypeFoldable;
+pub use self::fold::{TypeFoldable, TypeVisitor};
 
 use crate::hir::{map as hir_map, GlobMap, TraitMap};
 use crate::hir::Node;
@@ -15,6 +15,7 @@ use rustc_macros::HashStable;
 use crate::ich::Fingerprint;
 use crate::ich::StableHashingContext;
 use crate::infer::canonical::Canonical;
+use crate::middle::cstore::CrateStoreDyn;
 use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
 use crate::mir::Body;
@@ -46,11 +47,11 @@ use std::ops::Range;
 use syntax::ast::{self, Name, Ident, NodeId};
 use syntax::attr;
 use syntax_expand::hygiene::ExpnId;
-use syntax::symbol::{kw, sym, Symbol, InternedString};
+use syntax::symbol::{kw, sym, Symbol};
 use syntax_pos::Span;
 
 use smallvec;
-use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use rustc_index::vec::{Idx, IndexVec};
 
@@ -119,8 +120,9 @@ mod sty;
 
 // Data types
 
-#[derive(Clone)]
-pub struct Resolutions {
+pub struct ResolverOutputs {
+    pub definitions: hir_map::Definitions,
+    pub cstore: Box<CrateStoreDyn>,
     pub extern_crate_map: NodeMap<CrateNum>,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
@@ -849,7 +851,7 @@ impl ty::EarlyBoundRegion {
     /// Does this early bound region have a name? Early bound regions normally
     /// always have names except when using anonymous lifetimes (`'_`).
     pub fn has_name(&self) -> bool {
-        self.name != kw::UnderscoreLifetime.as_interned_str()
+        self.name != kw::UnderscoreLifetime
     }
 }
 
@@ -866,7 +868,7 @@ pub enum GenericParamDefKind {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub struct GenericParamDef {
-    pub name: InternedString,
+    pub name: Symbol,
     pub def_id: DefId,
     pub index: u32,
 
@@ -3019,7 +3021,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     }),
                 _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| {
                     bug!("item_name: no name for {:?}", self.def_path(id));
-                }).as_symbol(),
+                }),
             }
         }
     }
@@ -3393,6 +3395,129 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
     fn_like.asyncness()
 }
 
+pub enum NonStructuralMatchTy<'tcx> {
+    Adt(&'tcx AdtDef),
+    Param,
+}
+
+/// This method traverses the structure of `ty`, trying to find an
+/// instance of an ADT (i.e. struct or enum) that was declared without
+/// the `#[structural_match]` attribute, or a generic type parameter
+/// (which cannot be determined to be `structural_match`).
+///
+/// The "structure of a type" includes all components that would be
+/// considered when doing a pattern match on a constant of that
+/// type.
+///
+///  * This means this method descends into fields of structs/enums,
+///    and also descends into the inner type `T` of `&T` and `&mut T`
+///
+///  * The traversal doesn't dereference unsafe pointers (`*const T`,
+///    `*mut T`), and it does not visit the type arguments of an
+///    instantiated generic like `PhantomData<T>`.
+///
+/// The reason we do this search is Rust currently require all ADTs
+/// reachable from a constant's type to be annotated with
+/// `#[structural_match]`, an attribute which essentially says that
+/// the implementation of `PartialEq::eq` behaves *equivalently* to a
+/// comparison against the unfolded structure.
+///
+/// For more background on why Rust has this requirement, and issues
+/// that arose when the requirement was not enforced completely, see
+/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
+pub fn search_for_structural_match_violation<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+) -> Option<NonStructuralMatchTy<'tcx>> {
+    let mut search = Search { tcx, found: None, seen: FxHashSet::default() };
+    ty.visit_with(&mut search);
+    return search.found;
+
+    struct Search<'tcx> {
+        tcx: TyCtxt<'tcx>,
+
+        // Records the first ADT or type parameter we find without `#[structural_match`.
+        found: Option<NonStructuralMatchTy<'tcx>>,
+
+        // Tracks ADTs previously encountered during search, so that
+        // we will not recurse on them again.
+        seen: FxHashSet<hir::def_id::DefId>,
+    }
+
+    impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
+        fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+            debug!("Search visiting ty: {:?}", ty);
+
+            let (adt_def, substs) = match ty.kind {
+                ty::Adt(adt_def, substs) => (adt_def, substs),
+                ty::Param(_) => {
+                    self.found = Some(NonStructuralMatchTy::Param);
+                    return true; // Stop visiting.
+                }
+                ty::RawPtr(..) => {
+                    // `#[structural_match]` ignores substructure of
+                    // `*const _`/`*mut _`, so skip super_visit_with
+                    //
+                    // (But still tell caller to continue search.)
+                    return false;
+                }
+                ty::FnDef(..) | ty::FnPtr(..) => {
+                    // types of formals and return in `fn(_) -> _` are also irrelevant
+                    //
+                    // (But still tell caller to continue search.)
+                    return false;
+                }
+                ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0)
+                => {
+                    // rust-lang/rust#62336: ignore type of contents
+                    // for empty array.
+                    return false;
+                }
+                _ => {
+                    ty.super_visit_with(self);
+                    return false;
+                }
+            };
+
+            if !self.tcx.has_attr(adt_def.did, sym::structural_match) {
+                self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
+                debug!("Search found adt_def: {:?}", adt_def);
+                return true; // Stop visiting.
+            }
+
+            if !self.seen.insert(adt_def.did) {
+                debug!("Search already seen adt_def: {:?}", adt_def);
+                // let caller continue its search
+                return false;
+            }
+
+            // `#[structural_match]` does not care about the
+            // instantiation of the generics in an ADT (it
+            // instead looks directly at its fields outside
+            // this match), so we skip super_visit_with.
+            //
+            // (Must not recur on substs for `PhantomData<T>` cf
+            // rust-lang/rust#55028 and rust-lang/rust#55837; but also
+            // want to skip substs when only uses of generic are
+            // behind unsafe pointers `*const T`/`*mut T`.)
+
+            // even though we skip super_visit_with, we must recur on
+            // fields of ADT.
+            let tcx = self.tcx;
+            for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
+                if field_ty.visit_with(self) {
+                    // found an ADT without `#[structural_match]`; halt visiting!
+                    assert!(self.found.is_some());
+                    return true;
+                }
+            }
+
+            // Even though we do not want to recur on substs, we do
+            // want our caller to continue its own search.
+            false
+        }
+    }
+}
 
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
     context::provide(providers);
@@ -3429,11 +3554,11 @@ pub struct CrateInherentImpls {
     pub inherent_impls: DefIdMap<Vec<DefId>>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub struct SymbolName {
     // FIXME: we don't rely on interning or equality here - better have
     // this be a `&'tcx str`.
-    pub name: InternedString
+    pub name: Symbol
 }
 
 impl_stable_hash_for!(struct self::SymbolName {
@@ -3443,11 +3568,24 @@ impl_stable_hash_for!(struct self::SymbolName {
 impl SymbolName {
     pub fn new(name: &str) -> SymbolName {
         SymbolName {
-            name: InternedString::intern(name)
+            name: Symbol::intern(name)
         }
     }
 }
 
+impl PartialOrd for SymbolName {
+    fn partial_cmp(&self, other: &SymbolName) -> Option<Ordering> {
+        self.name.as_str().partial_cmp(&other.name.as_str())
+    }
+}
+
+/// Ordering must use the chars to ensure reproducible builds.
+impl Ord for SymbolName {
+    fn cmp(&self, other: &SymbolName) -> Ordering {
+        self.name.as_str().cmp(&other.name.as_str())
+    }
+}
+
 impl fmt::Display for SymbolName {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(&self.name, fmt)
diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs
index df39d0ccc9e..e72916de6a9 100644
--- a/src/librustc/ty/print/obsolete.rs
+++ b/src/librustc/ty/print/obsolete.rs
@@ -218,9 +218,9 @@ impl DefPathBasedNames<'tcx> {
         // foo::bar::ItemName::
         for part in self.tcx.def_path(def_id).data {
             if self.omit_disambiguators {
-                write!(output, "{}::", part.data.as_interned_str()).unwrap();
+                write!(output, "{}::", part.data.as_symbol()).unwrap();
             } else {
-                write!(output, "{}[{}]::", part.data.as_interned_str(), part.disambiguator)
+                write!(output, "{}[{}]::", part.data.as_symbol(), part.disambiguator)
                     .unwrap();
             }
         }
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 363109a0582..8a98a5d8361 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -14,7 +14,7 @@ use rustc_apfloat::Float;
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr::{SignedInt, UnsignedInt};
-use syntax::symbol::{kw, InternedString};
+use syntax::symbol::{kw, Symbol};
 
 use std::cell::Cell;
 use std::fmt::{self, Write as _};
@@ -384,7 +384,7 @@ pub trait PrettyPrinter<'tcx>:
                 let reexport = self.tcx().item_children(visible_parent)
                     .iter()
                     .find(|child| child.res.def_id() == def_id)
-                    .map(|child| child.ident.as_interned_str());
+                    .map(|child| child.ident.name);
                 if let Some(reexport) = reexport {
                     *name = reexport;
                 }
@@ -392,7 +392,7 @@ pub trait PrettyPrinter<'tcx>:
             // Re-exported `extern crate` (#43189).
             DefPathData::CrateRoot => {
                 data = DefPathData::TypeNs(
-                    self.tcx().original_crate_name(def_id.krate).as_interned_str(),
+                    self.tcx().original_crate_name(def_id.krate),
                 );
             }
             _ => {}
@@ -992,7 +992,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
     empty_path: bool,
     in_value: bool,
 
-    used_region_names: FxHashSet<InternedString>,
+    used_region_names: FxHashSet<Symbol>,
     region_index: usize,
     binder_depth: usize,
 
@@ -1222,7 +1222,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
 
         // FIXME(eddyb) `name` should never be empty, but it
         // currently is for `extern { ... }` "foreign modules".
-        let name = disambiguated_data.data.as_interned_str().as_str();
+        let name = disambiguated_data.data.as_symbol().as_str();
         if !name.is_empty() {
             if !self.empty_path {
                 write!(self, "::")?;
@@ -1332,16 +1332,16 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
 
         match *region {
             ty::ReEarlyBound(ref data) => {
-                data.name.as_symbol() != kw::Invalid &&
-                data.name.as_symbol() != kw::UnderscoreLifetime
+                data.name != kw::Invalid &&
+                data.name != kw::UnderscoreLifetime
             }
 
             ty::ReLateBound(_, br) |
             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
-                    if name.as_symbol() != kw::Invalid &&
-                       name.as_symbol() != kw::UnderscoreLifetime {
+                    if name != kw::Invalid &&
+                       name != kw::UnderscoreLifetime {
                         return true;
                     }
                 }
@@ -1397,7 +1397,7 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
         // `explain_region()` or `note_and_explain_region()`.
         match *region {
             ty::ReEarlyBound(ref data) => {
-                if data.name.as_symbol() != kw::Invalid {
+                if data.name != kw::Invalid {
                     p!(write("{}", data.name));
                     return Ok(self);
                 }
@@ -1406,8 +1406,8 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
-                    if name.as_symbol() != kw::Invalid &&
-                       name.as_symbol() != kw::UnderscoreLifetime {
+                    if name != kw::Invalid &&
+                       name != kw::UnderscoreLifetime {
                         p!(write("{}", name));
                         return Ok(self);
                     }
@@ -1474,11 +1474,11 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
     where
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
-        fn name_by_region_index(index: usize) -> InternedString {
+        fn name_by_region_index(index: usize) -> Symbol {
             match index {
-                0 => InternedString::intern("'r"),
-                1 => InternedString::intern("'s"),
-                i => InternedString::intern(&format!("'t{}", i-2)),
+                0 => Symbol::intern("'r"),
+                1 => Symbol::intern("'s"),
+                i => Symbol::intern(&format!("'t{}", i-2)),
             }
         }
 
@@ -1541,7 +1541,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
         where T: TypeFoldable<'tcx>
     {
 
-        struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<InternedString>);
+        struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
             fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
                 match *r {
diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs
index f61801cd232..0a217e9ae66 100644
--- a/src/librustc/ty/query/keys.rs
+++ b/src/librustc/ty/query/keys.rs
@@ -9,7 +9,7 @@ use crate::ty::fast_reject::SimplifiedType;
 use crate::mir;
 
 use syntax_pos::{Span, DUMMY_SP};
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 
 /// The `Key` trait controls what types can legally be used as the key
 /// for a query.
@@ -188,7 +188,7 @@ impl<'tcx> Key for traits::Environment<'tcx> {
     }
 }
 
-impl Key for InternedString {
+impl Key for Symbol {
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
     }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 4279ca8c3da..9b15ad560b5 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -55,7 +55,6 @@ use std::ops::Deref;
 use std::sync::Arc;
 use std::any::type_name;
 use syntax_pos::{Span, DUMMY_SP};
-use syntax_pos::symbol::InternedString;
 use syntax::attr;
 use syntax::ast;
 use syntax::feature_gate;
diff --git a/src/librustc/ty/query/values.rs b/src/librustc/ty/query/values.rs
index 0149f757164..f0d1639f72f 100644
--- a/src/librustc/ty/query/values.rs
+++ b/src/librustc/ty/query/values.rs
@@ -1,7 +1,7 @@
 use crate::ty::{self, Ty, TyCtxt, AdtSizedConstraint};
 use crate::ty::util::NeedsDrop;
 
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 
 pub(super) trait Value<'tcx>: Sized {
     fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self;
@@ -22,7 +22,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> {
 
 impl<'tcx> Value<'tcx> for ty::SymbolName {
     fn from_cycle_error(_: TyCtxt<'tcx>) -> Self {
-        ty::SymbolName { name: InternedString::intern("<error>") }
+        ty::SymbolName { name: Symbol::intern("<error>") }
     }
 }
 
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 41f34703622..1da65f4b51d 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -557,10 +557,9 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         x.val
     };
 
-    // Currently, the values that can be unified are those that
-    // implement both `PartialEq` and `Eq`, corresponding to
-    // `structural_match` types.
-    // FIXME(const_generics): check for `structural_match` synthetic attribute.
+    // Currently, the values that can be unified are primitive types,
+    // and those that derive both `PartialEq` and `Eq`, corresponding
+    // to `structural_match` types.
     let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) {
         (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
             // The caller should handle these cases!
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 6b1f10bdb21..5d78d563e9a 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -749,6 +749,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
             ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
             ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
             IntrinsicCast => IntrinsicCast,
+            ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion),
         })
     }
 }
@@ -1350,6 +1351,7 @@ EnumTypeFoldableImpl! {
         (ty::error::TypeError::ExistentialMismatch)(x),
         (ty::error::TypeError::ConstMismatch)(x),
         (ty::error::TypeError::IntrinsicCast),
+        (ty::error::TypeError::ObjectUnsafeCoercion)(x),
     }
 }
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 298e7989596..3a9994ac64c 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -24,7 +24,7 @@ use std::marker::PhantomData;
 use std::ops::Range;
 use rustc_target::spec::abi;
 use syntax::ast::{self, Ident};
-use syntax::symbol::{kw, InternedString};
+use syntax::symbol::{kw, Symbol};
 
 use self::InferTy::*;
 use self::TyKind::*;
@@ -55,7 +55,7 @@ pub enum BoundRegion {
     ///
     /// The `DefId` is needed to distinguish free regions in
     /// the event of shadowing.
-    BrNamed(DefId, InternedString),
+    BrNamed(DefId, Symbol),
 
     /// Anonymous region for the implicit env pointer parameter
     /// to a closure
@@ -1121,16 +1121,16 @@ pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
          Hash, RustcEncodable, RustcDecodable, HashStable)]
 pub struct ParamTy {
     pub index: u32,
-    pub name: InternedString,
+    pub name: Symbol,
 }
 
 impl<'tcx> ParamTy {
-    pub fn new(index: u32, name: InternedString) -> ParamTy {
+    pub fn new(index: u32, name: Symbol) -> ParamTy {
         ParamTy { index, name: name }
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, kw::SelfUpper.as_interned_str())
+        ParamTy::new(0, kw::SelfUpper)
     }
 
     pub fn for_def(def: &ty::GenericParamDef) -> ParamTy {
@@ -1146,11 +1146,11 @@ impl<'tcx> ParamTy {
          Eq, PartialEq, Ord, PartialOrd, HashStable)]
 pub struct ParamConst {
     pub index: u32,
-    pub name: InternedString,
+    pub name: Symbol,
 }
 
 impl<'tcx> ParamConst {
-    pub fn new(index: u32, name: InternedString) -> ParamConst {
+    pub fn new(index: u32, name: Symbol) -> ParamConst {
         ParamConst { index, name }
     }
 
@@ -1323,7 +1323,7 @@ impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {}
 pub struct EarlyBoundRegion {
     pub def_id: DefId,
     pub index: u32,
-    pub name: InternedString,
+    pub name: Symbol,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
@@ -1387,7 +1387,7 @@ pub struct BoundTy {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum BoundTyKind {
     Anon,
-    Param(InternedString),
+    Param(Symbol),
 }
 
 impl_stable_hash_for!(struct BoundTy { var, kind });
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index ecb075e30b1..b50e819c956 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -380,16 +380,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     // obligations that don't refer to Self and
                     // checking those
 
-                    let cause = self.cause(traits::MiscObligation);
-                    let component_traits =
-                        data.auto_traits().chain(data.principal_def_id());
-                    self.out.extend(
-                        component_traits.map(|did| traits::Obligation::new(
-                            cause.clone(),
-                            param_env,
-                            ty::Predicate::ObjectSafe(did)
-                        ))
-                    );
+                    let defer_to_coercion =
+                        self.infcx.tcx.features().object_safe_for_dispatch;
+
+                    if !defer_to_coercion {
+                        let cause = self.cause(traits::MiscObligation);
+                        let component_traits =
+                            data.auto_traits().chain(data.principal_def_id());
+                        self.out.extend(
+                            component_traits.map(|did| traits::Obligation::new(
+                                cause.clone(),
+                                param_env,
+                                ty::Predicate::ObjectSafe(did)
+                            ))
+                        );
+                    }
                 }
 
                 // Inference variables are the complicated case, since we don't
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index bd7d0d4017d..edd34b52ead 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -36,7 +36,7 @@ use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm;
 
 use std::ffi::CString;
 use std::time::Instant;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 use rustc::hir::CodegenFnAttrs;
 
 use crate::value::Value;
@@ -105,7 +105,7 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> {
 
 pub fn compile_codegen_unit(
     tcx: TyCtxt<'tcx>,
-    cgu_name: InternedString,
+    cgu_name: Symbol,
     tx_to_llvm_workers: &std::sync::mpsc::Sender<Box<dyn std::any::Any + Send>>,
 ) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
@@ -131,7 +131,7 @@ pub fn compile_codegen_unit(
 
     fn module_codegen(
         tcx: TyCtxt<'_>,
-        cgu_name: InternedString,
+        cgu_name: Symbol,
     ) -> ModuleCodegen<ModuleLlvm> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index d4df5b4a804..fd7054a5a0a 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -221,7 +221,7 @@ impl CodegenCx<'ll, 'tcx> {
                  def_id);
 
         let ty = instance.ty(self.tcx);
-        let sym = self.tcx.symbol_name(instance).name.as_symbol();
+        let sym = self.tcx.symbol_name(instance).name;
 
         debug!("get_static: sym={} instance={:?}", sym, instance);
 
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 7bd82ced3c3..f0148a21ae6 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -46,7 +46,7 @@ use std::iter;
 use std::ptr;
 use std::path::{Path, PathBuf};
 use syntax::ast;
-use syntax::symbol::{Interner, InternedString};
+use syntax::symbol::{Interner, Symbol};
 use syntax_pos::{self, Span, FileName};
 
 impl PartialEq for llvm::Metadata {
@@ -2125,7 +2125,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'
 
     fn get_parameter_names(cx: &CodegenCx<'_, '_>,
                            generics: &ty::Generics)
-                           -> Vec<InternedString> {
+                           -> Vec<Symbol> {
         let mut names = generics.parent.map_or(vec![], |def_id| {
             get_parameter_names(cx, cx.tcx.generics_of(def_id))
         });
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 6e4ed42c45e..5b59f4c28de 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -36,7 +36,7 @@ use std::ffi::{CStr, CString};
 
 use syntax_pos::{self, Span, Pos};
 use syntax::ast;
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
 use rustc_codegen_ssa::traits::*;
 
@@ -490,7 +490,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         fn get_parameter_names(cx: &CodegenCx<'_, '_>,
                                generics: &ty::Generics)
-                               -> Vec<InternedString> {
+                               -> Vec<Symbol> {
             let mut names = generics.parent.map_or(vec![], |def_id| {
                 get_parameter_names(cx, cx.tcx.generics_of(def_id))
             });
diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs
index 889984749fd..628d1372b57 100644
--- a/src/librustc_codegen_llvm/debuginfo/namespace.rs
+++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs
@@ -35,7 +35,7 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll 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().as_str()
+        data => data.as_symbol().as_str()
     };
 
     let namespace_name = SmallCStr::new(&namespace_name);
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 9b55bef0c51..e09b600afd4 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -50,14 +50,13 @@ use rustc_codegen_ssa::CompiledModule;
 use errors::{FatalError, Handler};
 use rustc::dep_graph::WorkProduct;
 use syntax_expand::allocator::AllocatorKind;
-use syntax_pos::symbol::InternedString;
 pub use llvm_util::target_features;
 use std::any::Any;
 use std::sync::Arc;
 use std::ffi::CStr;
 
 use rustc::dep_graph::DepGraph;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
 use rustc::session::Session;
 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
 use rustc::ty::{self, TyCtxt};
@@ -123,7 +122,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
     }
     fn compile_codegen_unit(
         &self, tcx: TyCtxt<'_>,
-        cgu_name: InternedString,
+        cgu_name: Symbol,
         tx: &std::sync::mpsc::Sender<Box<dyn Any + Send>>,
     ) {
         base::compile_codegen_unit(tcx, cgu_name, tx);
@@ -261,7 +260,7 @@ impl CodegenBackend for LlvmCodegenBackend {
         target_features(sess)
     }
 
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
+    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
         box metadata::LlvmMetadataLoader
     }
 
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 8bc815f2c62..762b50f1659 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -259,7 +259,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
     needs_thin_lto: Vec<(String, B::ThinBuffer)>,
     import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>
 ) -> Vec<(WorkItem<B>, u64)> {
-    let _prof_timer = cgcx.prof.generic_activity("codegen_run_lto");
+    let _prof_timer = cgcx.prof.generic_activity("codegen_generate_lto_work");
 
     let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() {
         assert!(needs_thin_lto.is_empty());
@@ -674,11 +674,11 @@ impl<B: WriteBackendMethods> WorkItem<B> {
         }
     }
 
-    pub fn name(&self) -> String {
+    fn profiling_event_id(&self) -> &'static str {
         match *self {
-            WorkItem::Optimize(ref m) => format!("optimize: {}", m.name),
-            WorkItem::CopyPostLtoArtifacts(ref m) => format!("copy post LTO artifacts: {}", m.name),
-            WorkItem::LTO(ref m) => format!("lto: {}", m.name()),
+            WorkItem::Optimize(_) => "codegen_module_optimize",
+            WorkItem::CopyPostLtoArtifacts(_) => "codegen_copy_artifacts_from_incr_cache",
+            WorkItem::LTO(_) => "codegen_module_perform_lto",
         }
     }
 }
@@ -1587,7 +1587,7 @@ fn spawn_work<B: ExtraBackendMethods>(
         // as a diagnostic was already sent off to the main thread - just
         // surface that there was an error in this worker.
         bomb.result = {
-            let _prof_timer = cgcx.prof.generic_activity(&work.name());
+            let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id());
             execute_work_item(&cgcx, work).ok()
         };
     });
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index f4f3dd4d2d2..bf687f84635 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -406,6 +406,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
         rust_main_def_id: DefId,
         use_start_lang_item: bool,
     ) {
+        // The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
+        // depending on whether the target needs `argc` and `argv` to be passed in.
         let llfty = if cx.sess().target.target.options.main_needs_argc_argv {
             cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int())
         } else {
@@ -440,19 +442,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
 
         bx.insert_reference_to_gdb_debug_scripts_section_global();
 
-        let (arg_argc, arg_argv) = if cx.sess().target.target.options.main_needs_argc_argv {
-            // Params from native main() used as args for rust start function
-            let param_argc = bx.get_param(0);
-            let param_argv = bx.get_param(1);
-            let arg_argc = bx.intcast(param_argc, cx.type_isize(), true);
-            let arg_argv = param_argv;
-            (arg_argc, arg_argv)
-        } else {
-            // The Rust start function doesn't need argc and argv, so just pass zeros.
-            let arg_argc = bx.const_int(cx.type_int(), 0);
-            let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p()));
-            (arg_argc, arg_argv)
-        };
+        let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
 
         let (start_fn, args) = if use_start_lang_item {
             let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None);
@@ -477,6 +467,27 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
     }
 }
 
+/// Obtain the `argc` and `argv` values to pass to the rust start function.
+fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+    cx: &'a Bx::CodegenCx,
+    bx: &mut Bx
+) -> (Bx::Value, Bx::Value)
+{
+    if cx.sess().target.target.options.main_needs_argc_argv {
+        // Params from native `main()` used as args for rust start function
+        let param_argc = bx.get_param(0);
+        let param_argv = bx.get_param(1);
+        let arg_argc = bx.intcast(param_argc, cx.type_isize(), true);
+        let arg_argv = param_argv;
+        (arg_argc, arg_argv)
+    } else {
+        // The Rust start function doesn't need `argc` and `argv`, so just pass zeros.
+        let arg_argc = bx.const_int(cx.type_int(), 0);
+        let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p()));
+        (arg_argc, arg_argv)
+    }
+}
+
 pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
 
 pub fn codegen_crate<B: ExtraBackendMethods>(
@@ -515,7 +526,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     // unnecessarily.
     if tcx.dep_graph.is_fully_enabled() {
         for cgu in &codegen_units {
-            tcx.codegen_unit(cgu.name().clone());
+            tcx.codegen_unit(cgu.name());
         }
     }
 
@@ -603,7 +614,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         match cgu_reuse {
             CguReuse::No => {
                 let start_time = Instant::now();
-                backend.compile_codegen_unit(tcx, *cgu.name(), &ongoing_codegen.coordinator_send);
+                backend.compile_codegen_unit(tcx, cgu.name(), &ongoing_codegen.coordinator_send);
                 total_codegen_time += start_time.elapsed();
                 false
             }
diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs
index d875c60959c..166a74fe487 100644
--- a/src/librustc_codegen_ssa/debuginfo/type_names.rs
+++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs
@@ -221,7 +221,7 @@ pub fn push_debuginfo_type_name<'tcx>(
             output.push_str(&tcx.crate_name(def_id.krate).as_str());
             for path_element in tcx.def_path(def_id).data {
                 output.push_str("::");
-                output.push_str(&path_element.data.as_interned_str().as_str());
+                output.push_str(&path_element.data.as_symbol().as_str());
             }
         } else {
             output.push_str(&tcx.item_name(def_id).as_str());
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 7cae3e9ade5..1fff740d740 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -10,7 +10,7 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use std::sync::Arc;
 use std::sync::mpsc;
 use syntax_expand::allocator::AllocatorKind;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 
 pub trait BackendTypes {
     type Value: CodegenObject;
@@ -50,7 +50,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
     fn compile_codegen_unit(
         &self,
         tcx: TyCtxt<'_>,
-        cgu_name: InternedString,
+        cgu_name: Symbol,
         tx_to_llvm_workers: &mpsc::Sender<Box<dyn std::any::Any + Send>>,
     );
     // If find_features is true this won't access `sess.crate_types` by assuming
diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs
index 1077c1f4263..0e2c3731eae 100644
--- a/src/librustc_codegen_utils/codegen_backend.rs
+++ b/src/librustc_codegen_utils/codegen_backend.rs
@@ -14,7 +14,7 @@ use rustc::util::common::ErrorReported;
 use rustc::session::config::{OutputFilenames, PrintRequest};
 use rustc::ty::TyCtxt;
 use rustc::ty::query::Providers;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
 use rustc::dep_graph::DepGraph;
 
 pub use rustc_data_structures::sync::MetadataRef;
@@ -26,7 +26,7 @@ pub trait CodegenBackend {
     fn print_passes(&self) {}
     fn print_version(&self) {}
 
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync>;
+    fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
     fn provide(&self, _providers: &mut Providers<'_>);
     fn provide_extern(&self, _providers: &mut Providers<'_>);
     fn codegen_crate<'tcx>(
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 7ccd024769f..c52c6cfa83c 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -95,7 +95,7 @@ use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, Instance};
 use rustc::mir::mono::{MonoItem, InstantiationMode};
 
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::Symbol;
 
 use log::debug;
 
@@ -112,7 +112,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString {
+fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
     let def_id = instance.def_id();
     let substs = instance.substs;
 
@@ -123,13 +123,11 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString {
     if def_id.is_local() {
         if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return
-                InternedString::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator));
+            return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator));
         }
         if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return
-                InternedString::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator));
+            return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator));
         }
     }
 
@@ -146,23 +144,22 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString {
     let attrs = tcx.codegen_fn_attrs(def_id);
     if is_foreign {
         if let Some(name) = attrs.link_name {
-            return name.as_interned_str();
+            return name;
         }
         // Don't mangle foreign items.
-        return tcx.item_name(def_id).as_interned_str();
+        return tcx.item_name(def_id);
     }
 
-    if let Some(name) = &attrs.export_name {
+    if let Some(name) = attrs.export_name {
         // Use provided name
-        return name.as_interned_str();
+        return name;
     }
 
     if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
         // Don't mangle
-        return tcx.item_name(def_id).as_interned_str();
+        return tcx.item_name(def_id);
     }
 
-
     let is_generic = substs.non_erasable_generics().next().is_some();
     let avoid_cross_crate_conflicts =
         // If this is an instance of a generic function, we also hash in
@@ -222,5 +219,5 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString {
         SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
     };
 
-    InternedString::intern(&mangled)
+    Symbol::intern(&mangled)
 }
diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs
index cf575c54293..601a33a66bb 100644
--- a/src/librustc_codegen_utils/symbol_names/legacy.rs
+++ b/src/librustc_codegen_utils/symbol_names/legacy.rs
@@ -335,7 +335,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> {
             self.path.finalize_pending_component();
         }
 
-        self.write_str(&disambiguated_data.data.as_interned_str().as_str())?;
+        self.write_str(&disambiguated_data.data.as_symbol().as_str())?;
         Ok(self)
     }
     fn path_generic_args(
diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs
index 29a8a98d229..444463c08e5 100644
--- a/src/librustc_data_structures/graph/dominators/mod.rs
+++ b/src/librustc_data_structures/graph/dominators/mod.rs
@@ -17,7 +17,7 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
     dominators_given_rpo(graph, &rpo)
 }
 
-pub fn dominators_given_rpo<G: ControlFlowGraph>(
+fn dominators_given_rpo<G: ControlFlowGraph>(
     graph: &G,
     rpo: &[G::Node],
 ) -> Dominators<G::Node> {
@@ -43,14 +43,12 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(
             let mut new_idom = None;
             for pred in graph.predecessors(node) {
                 if immediate_dominators[pred].is_some() {
-                    // (*)
                     // (*) dominators for `pred` have been calculated
-                    new_idom = intersect_opt(
-                        &post_order_rank,
-                        &immediate_dominators,
-                        new_idom,
-                        Some(pred),
-                    );
+                    new_idom = Some(if let Some(new_idom) = new_idom {
+                        intersect(&post_order_rank, &immediate_dominators, new_idom, pred)
+                    } else {
+                        pred
+                    });
                 }
             }
 
@@ -67,19 +65,6 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(
     }
 }
 
-fn intersect_opt<Node: Idx>(
-    post_order_rank: &IndexVec<Node, usize>,
-    immediate_dominators: &IndexVec<Node, Option<Node>>,
-    node1: Option<Node>,
-    node2: Option<Node>,
-) -> Option<Node> {
-    match (node1, node2) {
-        (None, None) => None,
-        (Some(n), None) | (None, Some(n)) => Some(n),
-        (Some(n1), Some(n2)) => Some(intersect(post_order_rank, immediate_dominators, n1, n2)),
-    }
-}
-
 fn intersect<Node: Idx>(
     post_order_rank: &IndexVec<Node, usize>,
     immediate_dominators: &IndexVec<Node, Option<Node>>,
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index aa74966d0ab..a9e4e6db1c7 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -16,6 +16,7 @@ log = "0.4"
 env_logger = { version = "0.7", default-features = false }
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
+rustc_lint = { path = "../librustc_lint" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_metadata = { path = "../librustc_metadata" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index bfcbec8b78f..15adf7e4add 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -36,11 +36,11 @@ use rustc::session::config::nightly_options;
 use rustc::session::{early_error, early_warn};
 use rustc::lint::Lint;
 use rustc::lint;
+use rustc::middle::cstore::MetadataLoader;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::ty::TyCtxt;
 use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported};
 use rustc_metadata::locator;
-use rustc_metadata::cstore::CStore;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_interface::interface;
 use rustc_interface::util::get_codegen_sysroot;
@@ -106,6 +106,8 @@ pub fn abort_on_err<T>(result: Result<T, ErrorReported>, sess: &Session) -> T {
 pub trait Callbacks {
     /// Called before creating the compiler instance
     fn config(&mut self, _config: &mut interface::Config) {}
+    /// Called early during compilation to allow other drivers to easily register lints.
+    fn extra_lints(&mut self, _ls: &mut lint::LintStore) {}
     /// Called after parsing. Return value instructs the compiler whether to
     /// continue the compilation afterwards (defaults to `Compilation::Continue`)
     fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation {
@@ -182,6 +184,7 @@ pub fn run_compiler(
             stderr: None,
             crate_name: None,
             lint_caps: Default::default(),
+            register_lints: None,
         };
         callbacks.config(&mut config);
         config
@@ -202,9 +205,13 @@ pub fn run_compiler(
                     interface::run_compiler(config, |compiler| {
                         let sopts = &compiler.session().opts;
                         if sopts.describe_lints {
+                            let lint_store = rustc_lint::new_lint_store(
+                                sopts.debugging_opts.no_interleave_lints,
+                                compiler.session().unstable_options(),
+                            );
                             describe_lints(
                                 compiler.session(),
-                                &*compiler.session().lint_store.borrow(),
+                                &lint_store,
                                 false
                             );
                             return;
@@ -255,6 +262,7 @@ pub fn run_compiler(
         stderr: None,
         crate_name: None,
         lint_caps: Default::default(),
+        register_lints: None,
     };
 
     callbacks.config(&mut config);
@@ -269,7 +277,7 @@ pub fn run_compiler(
             compiler.output_file(),
         ).and_then(|| RustcDefaultCalls::list_metadata(
             sess,
-            compiler.cstore(),
+            &*compiler.codegen_backend().metadata_loader(),
             &matches,
             compiler.input()
         ));
@@ -321,12 +329,14 @@ pub fn run_compiler(
             return sess.compile_status();
         }
 
-        compiler.register_plugins()?;
+        {
+            let (_, _, lint_store) = &*compiler.register_plugins()?.peek();
 
-        // Lint plugins are registered; now we can process command line flags.
-        if sess.opts.describe_lints {
-            describe_lints(&sess, &sess.lint_store.borrow(), true);
-            return sess.compile_status();
+            // Lint plugins are registered; now we can process command line flags.
+            if sess.opts.describe_lints {
+                describe_lints(&sess, &lint_store, true);
+                return sess.compile_status();
+            }
         }
 
         compiler.expansion()?;
@@ -604,7 +614,7 @@ fn show_content_with_pager(content: &String) {
 
 impl RustcDefaultCalls {
     pub fn list_metadata(sess: &Session,
-                         cstore: &CStore,
+                         metadata_loader: &dyn MetadataLoader,
                          matches: &getopts::Matches,
                          input: &Input)
                          -> Compilation {
@@ -616,7 +626,7 @@ impl RustcDefaultCalls {
                     let mut v = Vec::new();
                     locator::list_file_metadata(&sess.target.target,
                                                 path,
-                                                cstore,
+                                                metadata_loader,
                                                 &mut v)
                             .unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
@@ -835,8 +845,7 @@ Available lint options:
 
 ");
 
-    fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
-        let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
+    fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
         // The sort doesn't case-fold but it's doubtful we care.
         lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name));
         lints
@@ -852,7 +861,7 @@ Available lint options:
     let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints()
                                                    .iter()
                                                    .cloned()
-                                                   .partition(|&(_, p)| p);
+                                                   .partition(|&lint| lint.is_plugin);
     let plugin = sort_lints(sess, plugin);
     let builtin = sort_lints(sess, builtin);
 
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index fd74d8673da..1781f2e1650 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -152,6 +152,32 @@ impl Diagnostic {
         self.note_expected_found_extra(label, expected, found, &"", &"")
     }
 
+    pub fn note_unsuccessfull_coercion(&mut self,
+                                       expected: DiagnosticStyledString,
+                                       found: DiagnosticStyledString)
+                                       -> &mut Self
+    {
+        let mut msg: Vec<_> =
+            vec![(format!("required when trying to coerce from type `"),
+                  Style::NoStyle)];
+        msg.extend(expected.0.iter()
+                   .map(|x| match *x {
+                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
+                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
+                   }));
+        msg.push((format!("` to type '"), Style::NoStyle));
+        msg.extend(found.0.iter()
+                   .map(|x| match *x {
+                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
+                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
+                   }));
+        msg.push((format!("`"), Style::NoStyle));
+
+        // For now, just attach these as notes
+        self.highlighted_note(msg);
+        self
+    }
+
     pub fn note_expected_found_extra(&mut self,
                                      label: &dyn fmt::Display,
                                      expected: DiagnosticStyledString,
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index cc60bf89c7e..40642dd14b8 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -209,6 +209,11 @@ impl<'a> DiagnosticBuilder<'a> {
                                               found_extra: &dyn fmt::Display,
                                               ) -> &mut Self);
 
+    forward!(pub fn note_unsuccessfull_coercion(&mut self,
+                                                expected: DiagnosticStyledString,
+                                                found: DiagnosticStyledString,
+                                                ) -> &mut Self);
+
     forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                                   sp: S,
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index e08eeaf8575..ca035d0cdcb 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -27,7 +27,7 @@ use rustc::mir::mono::CodegenUnitNameBuilder;
 use rustc::ty::TyCtxt;
 use std::collections::BTreeSet;
 use syntax::ast;
-use syntax::symbol::{InternedString, Symbol, sym};
+use syntax::symbol::{Symbol, sym};
 use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED,
                  ATTR_EXPECTED_CGU_REUSE};
 
@@ -45,8 +45,8 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
             .collect_and_partition_mono_items(LOCAL_CRATE)
             .1
             .iter()
-            .map(|cgu| *cgu.name())
-            .collect::<BTreeSet<InternedString>>();
+            .map(|cgu| cgu.name())
+            .collect::<BTreeSet<Symbol>>();
 
         let ams = AssertModuleSource {
             tcx,
@@ -61,7 +61,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
 
 struct AssertModuleSource<'tcx> {
     tcx: TyCtxt<'tcx>,
-    available_cgus: BTreeSet<InternedString>,
+    available_cgus: BTreeSet<Symbol>,
 }
 
 impl AssertModuleSource<'tcx> {
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index 5e1ad3e61dd..e014e4ed0fd 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -11,7 +11,6 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::OnDrop;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-use rustc_metadata::cstore::CStore;
 use std::path::PathBuf;
 use std::result;
 use std::sync::{Arc, Mutex};
@@ -37,8 +36,8 @@ pub struct Compiler {
     pub(crate) output_dir: Option<PathBuf>,
     pub(crate) output_file: Option<PathBuf>,
     pub(crate) queries: Queries,
-    pub(crate) cstore: Lrc<CStore>,
     pub(crate) crate_name: Option<String>,
+    pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
 }
 
 impl Compiler {
@@ -48,9 +47,6 @@ impl Compiler {
     pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
         &self.codegen_backend
     }
-    pub fn cstore(&self) -> &Lrc<CStore> {
-        &self.cstore
-    }
     pub fn source_map(&self) -> &Lrc<SourceMap> {
         &self.source_map
     }
@@ -137,6 +133,13 @@ pub struct Config {
 
     pub crate_name: Option<String>,
     pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
+
+    /// This is a callback from the driver that is called when we're registering lints;
+    /// it is called during plugin registration when we have the LintStore in a non-shared state.
+    ///
+    /// Note that if you find a Some here you probably want to call that function in the new
+    /// function being registered.
+    pub register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
 }
 
 pub fn run_compiler_in_existing_thread_pool<F, R>(config: Config, f: F) -> R
@@ -152,19 +155,17 @@ where
         config.lint_caps,
     );
 
-    let cstore = Lrc::new(CStore::new(codegen_backend.metadata_loader()));
-
     let compiler = Compiler {
         sess,
         codegen_backend,
         source_map,
-        cstore,
         input: config.input,
         input_path: config.input_path,
         output_dir: config.output_dir,
         output_file: config.output_file,
         queries: Default::default(),
         crate_name: config.crate_name,
+        register_lints: config.register_lints,
     };
 
     let _sess_abort_error = OnDrop(|| {
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 89de5714695..58936172c5b 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -9,8 +9,8 @@ use rustc::hir::lowering::lower_crate;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::lint;
 use rustc::middle::{self, reachable, resolve_lifetime, stability};
-use rustc::middle::cstore::CrateStore;
-use rustc::ty::{self, AllArenas, Resolutions, TyCtxt, GlobalCtxt};
+use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
+use rustc::ty::{self, AllArenas, ResolverOutputs, TyCtxt, GlobalCtxt};
 use rustc::ty::steal::Steal;
 use rustc::traits;
 use rustc::util::common::{time, ErrorReported};
@@ -23,8 +23,7 @@ use rustc_codegen_utils::link::filename_for_metadata;
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
 use rustc_incremental;
-use rustc_metadata::creader::CrateLoader;
-use rustc_metadata::cstore::{self, CStore};
+use rustc_metadata::cstore;
 use rustc_mir as mir;
 use rustc_passes::{self, ast_validation, hir_stats, layout_test};
 use rustc_plugin as plugin;
@@ -46,12 +45,10 @@ use syntax_ext;
 use rustc_serialize::json;
 use tempfile::Builder as TempFileBuilder;
 
+use std::{env, fs, iter, mem};
 use std::any::Any;
-use std::env;
 use std::ffi::OsString;
-use std::fs;
 use std::io::{self, Write};
-use std::iter;
 use std::path::PathBuf;
 use std::cell::RefCell;
 use std::rc::Rc;
@@ -105,7 +102,7 @@ fn count_nodes(krate: &ast::Crate) -> usize {
 declare_box_region_type!(
     pub BoxedResolver,
     for(),
-    (&mut Resolver<'_>) -> (Result<ast::Crate>, ExpansionResult)
+    (&mut Resolver<'_>) -> (Result<ast::Crate>, ResolverOutputs)
 );
 
 /// Runs the "early phases" of the compiler: initial `cfg` processing,
@@ -117,7 +114,8 @@ declare_box_region_type!(
 /// Returns `None` if we're aborting after handling -W help.
 pub fn configure_and_expand(
     sess: Lrc<Session>,
-    cstore: Lrc<CStore>,
+    lint_store: Lrc<lint::LintStore>,
+    metadata_loader: Box<MetadataLoaderDyn>,
     krate: ast::Crate,
     crate_name: &str,
     plugin_info: PluginInfo,
@@ -130,15 +128,14 @@ pub fn configure_and_expand(
     let crate_name = crate_name.to_string();
     let (result, resolver) = BoxedResolver::new(static move || {
         let sess = &*sess;
-        let crate_loader = CrateLoader::new(sess, &*cstore, &crate_name);
         let resolver_arenas = Resolver::arenas();
         let res = configure_and_expand_inner(
             sess,
-            &*cstore,
+            &lint_store,
             krate,
             &crate_name,
             &resolver_arenas,
-            &crate_loader,
+            &*metadata_loader,
             plugin_info,
         );
         let mut resolver = match res {
@@ -152,68 +149,16 @@ pub fn configure_and_expand(
             }
         };
         box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver));
-        ExpansionResult::from_owned_resolver(resolver)
+        resolver.into_outputs()
     });
     result.map(|k| (k, resolver))
 }
 
-pub struct ExpansionResult {
-    pub defs: Steal<hir::map::Definitions>,
-    pub resolutions: Steal<Resolutions>,
-}
-
-impl ExpansionResult {
-    fn from_owned_resolver(
-        resolver: Resolver<'_>,
-    ) -> Self {
-        ExpansionResult {
-            defs: Steal::new(resolver.definitions),
-            resolutions: Steal::new(Resolutions {
-                extern_crate_map: resolver.extern_crate_map,
-                export_map: resolver.export_map,
-                trait_map: resolver.trait_map,
-                glob_map: resolver.glob_map,
-                maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
-                maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
-                extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
-                    (ident.name, entry.introduced_by_item)
-                }).collect(),
-            }),
-        }
-    }
-
-    pub fn from_resolver_ref(
-        resolver: &Resolver<'_>,
-    ) -> Self {
-        ExpansionResult {
-            defs: Steal::new(resolver.definitions.clone()),
-            resolutions: Steal::new(Resolutions {
-                extern_crate_map: resolver.extern_crate_map.clone(),
-                export_map: resolver.export_map.clone(),
-                trait_map: resolver.trait_map.clone(),
-                glob_map: resolver.glob_map.clone(),
-                maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
-                maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
-                extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
-                    (ident.name, entry.introduced_by_item)
-                }).collect(),
-            }),
-        }
-    }
-}
-
 impl BoxedResolver {
-    pub fn to_expansion_result(
-        resolver: Rc<RefCell<BoxedResolver>>,
-    ) -> ExpansionResult {
+    pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
         match Rc::try_unwrap(resolver) {
             Ok(resolver) => resolver.into_inner().complete(),
-            Err(resolver) => {
-                let resolver = &*resolver;
-                resolver.borrow_mut().access(|resolver| {
-                    ExpansionResult::from_resolver_ref(resolver)
-                })
-            }
+            Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
         }
     }
 }
@@ -224,10 +169,11 @@ pub struct PluginInfo {
 
 pub fn register_plugins<'a>(
     sess: &'a Session,
-    cstore: &'a CStore,
+    metadata_loader: &'a dyn MetadataLoader,
+    register_lints: impl Fn(&Session, &mut lint::LintStore),
     mut krate: ast::Crate,
     crate_name: &str,
-) -> Result<(ast::Crate, PluginInfo)> {
+) -> Result<(ast::Crate, PluginInfo, Lrc<lint::LintStore>)> {
     krate = time(sess, "attributes injection", || {
         syntax_ext::cmdline_attrs::inject(
             krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr
@@ -271,14 +217,20 @@ pub fn register_plugins<'a>(
     let registrars = time(sess, "plugin loading", || {
         plugin::load::load_plugins(
             sess,
-            &cstore,
+            metadata_loader,
             &krate,
-            crate_name,
             Some(sess.opts.debugging_opts.extra_plugins.clone()),
         )
     });
 
-    let mut registry = Registry::new(sess, krate.span);
+    let mut lint_store = rustc_lint::new_lint_store(
+        sess.opts.debugging_opts.no_interleave_lints,
+        sess.unstable_options(),
+    );
+
+    (register_lints)(&sess, &mut lint_store);
+
+    let mut registry = Registry::new(sess, &mut lint_store, krate.span);
 
     time(sess, "plugin registration", || {
         for registrar in registrars {
@@ -289,44 +241,30 @@ pub fn register_plugins<'a>(
 
     let Registry {
         syntax_exts,
-        early_lint_passes,
-        late_lint_passes,
-        lint_groups,
         llvm_passes,
         attributes,
         ..
     } = registry;
 
-    let mut ls = sess.lint_store.borrow_mut();
-    for pass in early_lint_passes {
-        ls.register_early_pass(Some(sess), true, false, pass);
-    }
-    for pass in late_lint_passes {
-        ls.register_late_pass(Some(sess), true, false, false, pass);
-    }
-
-    for (name, (to, deprecated_name)) in lint_groups {
-        ls.register_group(Some(sess), true, name, deprecated_name, to);
-    }
-
     *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
     *sess.plugin_attributes.borrow_mut() = attributes;
 
-    Ok((krate, PluginInfo { syntax_exts }))
+    Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store)))
 }
 
 fn configure_and_expand_inner<'a>(
     sess: &'a Session,
-    cstore: &'a CStore,
+    lint_store: &'a lint::LintStore,
     mut krate: ast::Crate,
     crate_name: &str,
     resolver_arenas: &'a ResolverArenas<'a>,
-    crate_loader: &'a CrateLoader<'a>,
+    metadata_loader: &'a MetadataLoaderDyn,
     plugin_info: PluginInfo,
 ) -> Result<(ast::Crate, Resolver<'a>)> {
     time(sess, "pre-AST-expansion lint checks", || {
         lint::check_ast_crate(
             sess,
+            lint_store,
             &krate,
             true,
             rustc_lint::BuiltinCombinedPreExpansionLintPass::new());
@@ -334,10 +272,9 @@ fn configure_and_expand_inner<'a>(
 
     let mut resolver = Resolver::new(
         sess,
-        cstore,
         &krate,
         crate_name,
-        crate_loader,
+        metadata_loader,
         &resolver_arenas,
     );
     syntax_ext::register_builtin_macros(&mut resolver, sess.edition());
@@ -536,7 +473,7 @@ fn configure_and_expand_inner<'a>(
 
 pub fn lower_to_hir(
     sess: &Session,
-    cstore: &CStore,
+    lint_store: &lint::LintStore,
     resolver: &mut Resolver<'_>,
     dep_graph: &DepGraph,
     krate: &ast::Crate,
@@ -544,7 +481,7 @@ pub fn lower_to_hir(
     // Lower AST to HIR.
     let hir_forest = time(sess, "lowering AST -> HIR", || {
         let nt_to_tokenstream = syntax::parse::nt_to_tokenstream;
-        let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, nt_to_tokenstream);
+        let hir_crate = lower_crate(sess, &dep_graph, &krate, resolver, nt_to_tokenstream);
 
         if sess.opts.debugging_opts.hir_stats {
             hir_stats::print_hir_stats(&hir_crate);
@@ -554,7 +491,13 @@ pub fn lower_to_hir(
     });
 
     time(sess, "early lint checks", || {
-        lint::check_ast_crate(sess, &krate, false, rustc_lint::BuiltinCombinedEarlyLintPass::new())
+        lint::check_ast_crate(
+            sess,
+            lint_store,
+            &krate,
+            false,
+            rustc_lint::BuiltinCombinedEarlyLintPass::new(),
+        )
     });
 
     // Discard hygiene data, which isn't required after lowering to HIR.
@@ -644,8 +587,12 @@ fn escape_dep_filename(filename: &FileName) -> String {
     filename.to_string().replace(" ", "\\ ")
 }
 
-fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames: &[PathBuf]) {
-    let sess = &compiler.sess;
+fn write_out_deps(
+    sess: &Session,
+    boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
+    outputs: &OutputFilenames,
+    out_filenames: &[PathBuf],
+) {
     // Write out dependency rules to the dep-info file if requested
     if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
         return;
@@ -664,18 +611,20 @@ fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames:
             .collect();
 
         if sess.binary_dep_depinfo() {
-            for cnum in compiler.cstore.crates_untracked() {
-                let source = compiler.cstore.crate_source_untracked(cnum);
-                if let Some((path, _)) = source.dylib {
-                    files.push(escape_dep_filename(&FileName::Real(path)));
-                }
-                if let Some((path, _)) = source.rlib {
-                    files.push(escape_dep_filename(&FileName::Real(path)));
+            boxed_resolver.borrow().borrow_mut().access(|resolver| {
+                for cnum in resolver.cstore().crates_untracked() {
+                    let source = resolver.cstore().crate_source_untracked(cnum);
+                    if let Some((path, _)) = source.dylib {
+                        files.push(escape_dep_filename(&FileName::Real(path)));
+                    }
+                    if let Some((path, _)) = source.rlib {
+                        files.push(escape_dep_filename(&FileName::Real(path)));
+                    }
+                    if let Some((path, _)) = source.rmeta {
+                        files.push(escape_dep_filename(&FileName::Real(path)));
+                    }
                 }
-                if let Some((path, _)) = source.rmeta {
-                    files.push(escape_dep_filename(&FileName::Real(path)));
-                }
-            }
+            });
         }
 
         let mut file = fs::File::create(&deps_filename)?;
@@ -713,6 +662,7 @@ pub fn prepare_outputs(
     sess: &Session,
     compiler: &Compiler,
     krate: &ast::Crate,
+    boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
     crate_name: &str
 ) -> Result<OutputFilenames> {
     // FIXME: rustdoc passes &[] instead of &krate.attrs here
@@ -754,7 +704,7 @@ pub fn prepare_outputs(
         }
     }
 
-    write_out_deps(compiler, &outputs, &output_paths);
+    write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
 
     let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
         && sess.opts.output_types.len() == 1;
@@ -817,27 +767,26 @@ impl BoxedGlobalCtxt {
 
 pub fn create_global_ctxt(
     compiler: &Compiler,
+    lint_store: Lrc<lint::LintStore>,
     mut hir_forest: hir::map::Forest,
-    defs: hir::map::Definitions,
-    resolutions: Resolutions,
+    mut resolver_outputs: ResolverOutputs,
     outputs: OutputFilenames,
     crate_name: &str,
 ) -> BoxedGlobalCtxt {
     let sess = compiler.session().clone();
-    let cstore = compiler.cstore.clone();
     let codegen_backend = compiler.codegen_backend().clone();
     let crate_name = crate_name.to_string();
+    let defs = mem::take(&mut resolver_outputs.definitions);
 
     let ((), result) = BoxedGlobalCtxt::new(static move || {
         let sess = &*sess;
-        let cstore = &*cstore;
 
         let global_ctxt: Option<GlobalCtxt<'_>>;
         let arenas = AllArenas::new();
 
         // Construct the HIR map.
         let hir_map = time(sess, "indexing HIR", || {
-            hir::map::map_crate(sess, cstore, &mut hir_forest, &defs)
+            hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs)
         });
 
         let query_result_on_disk_cache = time(sess, "load query result cache", || {
@@ -854,11 +803,11 @@ pub fn create_global_ctxt(
 
         let gcx = TyCtxt::create_global_ctxt(
             sess,
-            cstore,
+            lint_store,
             local_providers,
             extern_providers,
             &arenas,
-            resolutions,
+            resolver_outputs,
             hir_map,
             query_result_on_disk_cache,
             &crate_name,
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index cd72dc9453c..ea51e63725e 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -1,12 +1,17 @@
 use crate::interface::{Compiler, Result};
-use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo};
+use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt, PluginInfo};
 
 use rustc_incremental::DepGraphFuture;
+use rustc_data_structures::sync::Lrc;
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::util::common::{time, ErrorReported};
 use rustc::hir;
+use rustc::lint;
+use rustc::session::Session;
+use rustc::lint::LintStore;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::ty::steal::Steal;
+use rustc::ty::ResolverOutputs;
 use rustc::dep_graph::DepGraph;
 use std::cell::{Ref, RefMut, RefCell};
 use std::rc::Rc;
@@ -74,10 +79,10 @@ pub(crate) struct Queries {
     dep_graph_future: Query<Option<DepGraphFuture>>,
     parse: Query<ast::Crate>,
     crate_name: Query<String>,
-    register_plugins: Query<(ast::Crate, PluginInfo)>,
-    expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>)>,
+    register_plugins: Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>,
+    expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
-    lower_to_hir: Query<(Steal<hir::map::Forest>, ExpansionResult)>,
+    lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
     prepare_outputs: Query<OutputFilenames>,
     global_ctxt: Query<BoxedGlobalCtxt>,
     ongoing_codegen: Query<Box<dyn Any>>,
@@ -106,14 +111,19 @@ impl Compiler {
         })
     }
 
-    pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo)>> {
+    pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>> {
         self.queries.register_plugins.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let krate = self.parse()?.take();
 
+            let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
             let result = passes::register_plugins(
                 self.session(),
-                self.cstore(),
+                &*self.codegen_backend().metadata_loader(),
+                self.register_lints
+                    .as_ref()
+                    .map(|p| &**p)
+                    .unwrap_or_else(|| empty),
                 krate,
                 &crate_name,
             );
@@ -148,17 +158,20 @@ impl Compiler {
 
     pub fn expansion(
         &self
-    ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>)>> {
+    ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
         self.queries.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
-            let (krate, plugin_info) = self.register_plugins()?.take();
+            let (krate, plugin_info, lint_store) = self.register_plugins()?.take();
             passes::configure_and_expand(
                 self.sess.clone(),
-                self.cstore().clone(),
+                lint_store.clone(),
+                self.codegen_backend().metadata_loader(),
                 krate,
                 &crate_name,
                 plugin_info,
-            ).map(|(krate, resolver)| (krate, Steal::new(Rc::new(RefCell::new(resolver)))))
+            ).map(|(krate, resolver)| {
+                (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store)
+            })
         })
     }
 
@@ -179,32 +192,35 @@ impl Compiler {
         })
     }
 
-    pub fn lower_to_hir(&self) -> Result<&Query<(Steal<hir::map::Forest>, ExpansionResult)>> {
+    pub fn lower_to_hir(
+        &self,
+    ) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
         self.queries.lower_to_hir.compute(|| {
             let expansion_result = self.expansion()?;
             let peeked = expansion_result.peek();
             let krate = &peeked.0;
             let resolver = peeked.1.steal();
+            let lint_store = &peeked.2;
             let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
                 passes::lower_to_hir(
                     self.session(),
-                    self.cstore(),
+                    lint_store,
                     resolver,
                     &*self.dep_graph()?.peek(),
                     &krate
                 )
             })?);
-            Ok((hir, BoxedResolver::to_expansion_result(resolver)))
+            Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
         })
     }
 
     pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
         self.queries.prepare_outputs.compute(|| {
-            let krate = self.expansion()?;
-            let krate = krate.peek();
+            let expansion_result = self.expansion()?;
+            let (krate, boxed_resolver, _) = &*expansion_result.peek();
             let crate_name = self.crate_name()?;
             let crate_name = crate_name.peek();
-            passes::prepare_outputs(self.session(), self, &krate.0, &*crate_name)
+            passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name)
         })
     }
 
@@ -212,14 +228,15 @@ impl Compiler {
         self.queries.global_ctxt.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let outputs = self.prepare_outputs()?.peek().clone();
+            let lint_store = self.expansion()?.peek().2.clone();
             let hir = self.lower_to_hir()?;
             let hir = hir.peek();
-            let (ref hir_forest, ref expansion) = *hir;
+            let (hir_forest, resolver_outputs) = &*hir;
             Ok(passes::create_global_ctxt(
                 self,
+                lint_store,
                 hir_forest.steal(),
-                expansion.defs.steal(),
-                expansion.resolutions.steal(),
+                resolver_outputs.steal(),
                 outputs,
                 &crate_name))
         })
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 0c272f0c456..8f11dc93727 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -13,7 +13,6 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_errors::registry::Registry;
-use rustc_lint;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_mir;
 use rustc_passes;
@@ -108,11 +107,6 @@ pub fn create_session(
 
     let codegen_backend = get_codegen_backend(&sess);
 
-    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-    if sess.unstable_options() {
-        rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess));
-    }
-
     let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
     add_configuration(&mut cfg, &sess, &*codegen_backend);
     sess.parse_sess.config = cfg;
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 5d9a97cc21e..ad674911e6f 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -27,6 +27,7 @@ use rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx};
 use rustc::{lint, util};
+use rustc::lint::FutureIncompatibleInfo;
 use hir::Node;
 use util::nodemap::HirIdSet;
 use lint::{LateContext, LintContext, LintArray};
@@ -280,7 +281,7 @@ declare_lint! {
     pub MISSING_DOCS,
     Allow,
     "detects missing documentation for public members",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 pub struct MissingDoc {
@@ -601,7 +602,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
 declare_lint! {
     pub ANONYMOUS_PARAMETERS,
     Allow,
-    "detects anonymous parameters"
+    "detects anonymous parameters",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
+        edition: Some(Edition::Edition2018),
+    };
 }
 
 declare_lint_pass!(
@@ -1344,7 +1349,7 @@ declare_lint! {
     UNNAMEABLE_TEST_ITEMS,
     Warn,
     "detects an item that cannot be named being marked as `#[test_case]`",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 pub struct UnnameableTestItems {
@@ -1393,7 +1398,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
 declare_lint! {
     pub KEYWORD_IDENTS,
     Allow,
-    "detects edition keywords being used as an identifier"
+    "detects edition keywords being used as an identifier",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
+        edition: Some(Edition::Edition2018),
+    };
 }
 
 declare_lint_pass!(
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index f83755181f8..b1beef04c59 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -33,27 +33,21 @@ use rustc::lint;
 use rustc::lint::{EarlyContext, LateContext, LateLintPass, EarlyLintPass, LintPass, LintArray};
 use rustc::lint::builtin::{
     BARE_TRAIT_OBJECTS,
-    ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
     ELIDED_LIFETIMES_IN_PATHS,
     EXPLICIT_OUTLIVES_REQUIREMENTS,
     INTRA_DOC_LINK_RESOLUTION_FAILURE,
     MISSING_DOC_CODE_EXAMPLES,
     PRIVATE_DOC_TESTS,
-    parser::ILL_FORMED_ATTRIBUTE_INPUT,
 };
-use rustc::session;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 
 use syntax::ast;
-use syntax::edition::Edition;
 use syntax_pos::Span;
 
-use session::Session;
 use lint::LintId;
-use lint::FutureIncompatibleInfo;
 
 use redundant_semicolon::*;
 use nonstandard_style::*;
@@ -192,59 +186,60 @@ late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass])
 
 late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]);
 
+pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> lint::LintStore {
+    let mut lint_store = lint::LintStore::new();
+
+    register_builtins(&mut lint_store, no_interleave_lints);
+    if internal_lints {
+        register_internals(&mut lint_store);
+    }
+
+    lint_store
+}
+
 /// Tell the `LintStore` about all the built-in lints (the ones
 /// defined in this crate and the ones defined in
 /// `rustc::lint::builtin`).
-pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
+fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) {
     macro_rules! add_lint_group {
-        ($sess:ident, $name:expr, $($lint:ident),*) => (
-            store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]);
+        ($name:expr, $($lint:ident),*) => (
+            store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]);
         )
     }
 
     macro_rules! register_pass {
-        ($method:ident, $constructor:expr, [$($args:expr),*]) => (
-            store.$method(sess, false, false, $($args,)* box $constructor);
+        ($method:ident, $ty:ident, $constructor:expr) => (
+            store.register_lints(&$ty::get_lints());
+            store.$method(|| box $constructor);
         )
     }
 
     macro_rules! register_passes {
-        ([$method:ident, $args:tt], [$($passes:ident: $constructor:expr,)*]) => (
+        ($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
             $(
-                register_pass!($method, $constructor, $args);
+                register_pass!($method, $passes, $constructor);
             )*
         )
     }
 
-    if sess.map(|sess| sess.opts.debugging_opts.no_interleave_lints).unwrap_or(false) {
-        pre_expansion_lint_passes!(register_passes, [register_pre_expansion_pass, []]);
-        early_lint_passes!(register_passes, [register_early_pass, []]);
-        late_lint_passes!(register_passes, [register_late_pass, [false]]);
-        late_lint_mod_passes!(register_passes, [register_late_pass, [true]]);
+    if no_interleave_lints {
+        pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass);
+        early_lint_passes!(register_passes, register_early_pass);
+        late_lint_passes!(register_passes, register_late_pass);
+        late_lint_mod_passes!(register_passes, register_late_mod_pass);
     } else {
-        store.register_pre_expansion_pass(
-            sess,
-            false,
-            true,
-            box BuiltinCombinedPreExpansionLintPass::new()
-        );
-        store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new());
-        store.register_late_pass(
-            sess, false, true, true, box BuiltinCombinedModuleLateLintPass::new()
-        );
-        store.register_late_pass(
-            sess, false, true, false, box BuiltinCombinedLateLintPass::new()
-        );
+        store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
+        store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
+        store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
+        store.register_lints(&BuiltinCombinedLateLintPass::get_lints());
     }
 
-    add_lint_group!(sess,
-                    "nonstandard_style",
+    add_lint_group!("nonstandard_style",
                     NON_CAMEL_CASE_TYPES,
                     NON_SNAKE_CASE,
                     NON_UPPER_CASE_GLOBALS);
 
-    add_lint_group!(sess,
-                    "unused",
+    add_lint_group!("unused",
                     UNUSED_IMPORTS,
                     UNUSED_VARIABLES,
                     UNUSED_ASSIGNMENTS,
@@ -265,8 +260,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                     UNUSED_LABELS,
                     UNUSED_PARENS);
 
-    add_lint_group!(sess,
-                    "rust_2018_idioms",
+    add_lint_group!("rust_2018_idioms",
                     BARE_TRAIT_OBJECTS,
                     UNUSED_EXTERN_CRATES,
                     ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
@@ -282,165 +276,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                     // MACRO_USE_EXTERN_CRATE,
                     );
 
-    add_lint_group!(sess,
-                    "rustdoc",
+    add_lint_group!("rustdoc",
                     INTRA_DOC_LINK_RESOLUTION_FAILURE,
                     MISSING_DOC_CODE_EXAMPLES,
                     PRIVATE_DOC_TESTS);
 
-    // Guidelines for creating a future incompatibility lint:
-    //
-    // - Create a lint defaulting to warn as normal, with ideally the same error
-    //   message you would normally give
-    // - Add a suitable reference, typically an RFC or tracking issue. Go ahead
-    //   and include the full URL, sort items in ascending order of issue numbers.
-    // - Later, change lint to error
-    // - Eventually, remove lint
-    store.register_future_incompatible(sess, vec![
-        FutureIncompatibleInfo {
-            id: LintId::of(PRIVATE_IN_PUBLIC),
-            reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
-            reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
-            reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(DUPLICATE_MACRO_EXPORTS),
-            reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
-            edition: Some(Edition::Edition2018),
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(KEYWORD_IDENTS),
-            reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
-            edition: Some(Edition::Edition2018),
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(SAFE_EXTERN_STATICS),
-            reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
-            reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
-            reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
-            reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
-            reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
-            reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ANONYMOUS_PARAMETERS),
-            reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
-            edition: Some(Edition::Edition2018),
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
-            reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
-            reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(SAFE_PACKED_BORROWS),
-            reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS),
-            reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
-            reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
-            edition: Some(Edition::Edition2018),
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(UNSTABLE_NAME_COLLISIONS),
-            reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
-            edition: None,
-            // Note: this item represents future incompatibility of all unstable functions in the
-            //       standard library, and thus should never be removed or changed to an error.
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE),
-            reference: "issue #53130 <https://github.com/rust-lang/rust/issues/53130>",
-            edition: Some(Edition::Edition2018),
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(WHERE_CLAUSES_OBJECT_SAFETY),
-            reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK),
-            reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS),
-            reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(ILL_FORMED_ATTRIBUTE_INPUT),
-            reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS),
-            reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(NESTED_IMPL_TRAIT),
-            reference: "issue #59014 <https://github.com/rust-lang/rust/issues/59014>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(MUTABLE_BORROW_RESERVATION_CONFLICT),
-            reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(INDIRECT_STRUCTURAL_MATCH),
-            reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
-            id: LintId::of(SOFT_UNSTABLE),
-            reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
-            edition: None,
-        },
-        ]);
-
     // Register renamed and removed lints.
     store.register_renamed("single_use_lifetime", "single_use_lifetimes");
     store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths");
@@ -496,12 +336,14 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
         "converted into hard error, see https://github.com/rust-lang/rust/issues/46205");
 }
 
-pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
-    store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
-    store.register_early_pass(sess, false, false, box LintPassImpl);
-    store.register_late_pass(sess, false, false, false, box TyTyKind);
+fn register_internals(store: &mut lint::LintStore) {
+    store.register_lints(&DefaultHashTypes::get_lints());
+    store.register_early_pass(|| box DefaultHashTypes::new());
+    store.register_lints(&LintPassImpl::get_lints());
+    store.register_early_pass(|| box LintPassImpl);
+    store.register_lints(&TyTyKind::get_lints());
+    store.register_late_pass(|| box TyTyKind);
     store.register_group(
-        sess,
         false,
         "rustc::internal",
         None,
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index a93946df68f..61b8cbe369a 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -25,7 +25,7 @@ declare_lint! {
     pub UNUSED_MUST_USE,
     Warn,
     "unused result of a type flagged as `#[must_use]`",
-    report_in_external_macro: true
+    report_in_external_macro
 }
 
 declare_lint! {
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 7412e8a2cb9..f0a68058de8 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -3,7 +3,7 @@
 use crate::cstore::{self, CStore, MetadataBlob};
 use crate::locator::{self, CratePaths};
 use crate::schema::{CrateRoot, CrateDep};
-use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell};
+use rustc_data_structures::sync::{RwLock, Lock, AtomicCell};
 
 use rustc::hir::def_id::CrateNum;
 use rustc_data_structures::svh::Svh;
@@ -14,21 +14,20 @@ use rustc::session::{Session, CrateDisambiguator};
 use rustc::session::config::{Sanitizer, self};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 use rustc::session::search_paths::PathKind;
-use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource};
+use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
 use rustc::util::common::record_time;
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::map::Definitions;
 use rustc::hir::def_id::LOCAL_CRATE;
 
-use std::ops::Deref;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::{cmp, fs};
 
 use syntax::ast;
 use syntax::attr;
 use syntax_expand::allocator::{global_allocator_spans, AllocatorKind};
 use syntax::symbol::{Symbol, sym};
-use syntax::{span_err, span_fatal};
+use syntax::span_fatal;
 use syntax_pos::{Span, DUMMY_SP};
 use log::{debug, info, log_enabled};
 use proc_macro::bridge::client::ProcMacro;
@@ -39,9 +38,12 @@ crate struct Library {
 }
 
 pub struct CrateLoader<'a> {
+    // Immutable configuration.
     sess: &'a Session,
-    cstore: &'a CStore,
+    metadata_loader: &'a MetadataLoaderDyn,
     local_crate_name: Symbol,
+    // Mutable output.
+    cstore: CStore,
 }
 
 fn dump_crates(cstore: &CStore) {
@@ -58,29 +60,6 @@ fn dump_crates(cstore: &CStore) {
     });
 }
 
-// Extra info about a crate loaded for plugins or exported macros.
-struct ExtensionCrate {
-    metadata: PMDSource,
-    dylib: Option<PathBuf>,
-    target_only: bool,
-}
-
-enum PMDSource {
-    Registered(Lrc<cstore::CrateMetadata>),
-    Owned(Library),
-}
-
-impl Deref for PMDSource {
-    type Target = MetadataBlob;
-
-    fn deref(&self) -> &MetadataBlob {
-        match *self {
-            PMDSource::Registered(ref cmd) => &cmd.blob,
-            PMDSource::Owned(ref lib) => &lib.metadata
-        }
-    }
-}
-
 enum LoadResult {
     Previous(CrateNum),
     Loaded(Library),
@@ -99,14 +78,27 @@ impl<'a> LoadError<'a> {
 }
 
 impl<'a> CrateLoader<'a> {
-    pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self {
+    pub fn new(
+        sess: &'a Session,
+        metadata_loader: &'a MetadataLoaderDyn,
+        local_crate_name: &str,
+    ) -> Self {
         CrateLoader {
             sess,
-            cstore,
+            metadata_loader,
             local_crate_name: Symbol::intern(local_crate_name),
+            cstore: Default::default(),
         }
     }
 
+    pub fn cstore(&self) -> &CStore {
+        &self.cstore
+    }
+
+    pub fn into_cstore(self) -> CStore {
+        self.cstore
+    }
+
     fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
                       -> Option<CrateNum> {
         let mut ret = None;
@@ -187,14 +179,14 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn register_crate(
-        &self,
+        &mut self,
         host_lib: Option<Library>,
         root: Option<&CratePaths>,
         span: Span,
         lib: Library,
         dep_kind: DepKind,
         name: Symbol
-    ) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
+    ) -> CrateNum {
         let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
 
         let Library { source, metadata } = lib;
@@ -248,9 +240,9 @@ impl<'a> CrateLoader<'a> {
             crate_root.def_path_table.decode((&metadata, self.sess))
         });
 
-        let cmeta = cstore::CrateMetadata {
+        self.cstore.set_crate_data(cnum, cstore::CrateMetadata {
             extern_crate: Lock::new(None),
-            def_path_table: Lrc::new(def_path_table),
+            def_path_table,
             trait_impls,
             root: crate_root,
             blob: metadata,
@@ -264,11 +256,9 @@ impl<'a> CrateLoader<'a> {
             private_dep,
             raw_proc_macros,
             dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
-        };
+        });
 
-        let cmeta = Lrc::new(cmeta);
-        self.cstore.set_crate_data(cnum, cmeta.clone());
-        (cnum, cmeta)
+        cnum
     }
 
     fn load_proc_macro<'b>(
@@ -327,22 +317,22 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn resolve_crate<'b>(
-        &'b self,
+        &'b mut self,
         name: Symbol,
         span: Span,
         dep_kind: DepKind,
         dep: Option<(&'b CratePaths, &'b CrateDep)>,
-    ) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
+    ) -> CrateNum {
         self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
     }
 
     fn maybe_resolve_crate<'b>(
-        &'b self,
+        &'b mut self,
         name: Symbol,
         span: Span,
         mut dep_kind: DepKind,
         dep: Option<(&'b CratePaths, &'b CrateDep)>,
-    ) -> Result<(CrateNum, Lrc<cstore::CrateMetadata>), LoadError<'b>> {
+    ) -> Result<CrateNum, LoadError<'b>> {
         info!("resolving crate `{}`", name);
         let (root, hash, extra_filename, path_kind) = match dep {
             Some((root, dep)) =>
@@ -370,7 +360,7 @@ impl<'a> CrateLoader<'a> {
                 rejected_via_filename: vec![],
                 should_match_name: true,
                 is_proc_macro: Some(false),
-                metadata_loader: &*self.cstore.metadata_loader,
+                metadata_loader: self.metadata_loader,
             };
 
             self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| {
@@ -388,7 +378,7 @@ impl<'a> CrateLoader<'a> {
                 data.dep_kind.with_lock(|data_dep_kind| {
                     *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
                 });
-                Ok((cnum, data))
+                Ok(cnum)
             }
             (LoadResult::Loaded(library), host_library) => {
                 Ok(self.register_crate(host_library, root, span, library, dep_kind, name))
@@ -466,7 +456,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     // Go through the crate metadata and load any crates that it references
-    fn resolve_crate_deps(&self,
+    fn resolve_crate_deps(&mut self,
                           root: &CratePaths,
                           crate_root: &CrateRoot<'_>,
                           metadata: &MetadataBlob,
@@ -492,73 +482,10 @@ impl<'a> CrateLoader<'a> {
                 DepKind::MacrosOnly => DepKind::MacrosOnly,
                 _ => dep.kind,
             };
-            self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))).0
+            self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep)))
         })).collect()
     }
 
-    fn read_extension_crate(&self, name: Symbol, span: Span) -> ExtensionCrate {
-        info!("read extension crate `{}`", name);
-        let target_triple = self.sess.opts.target_triple.clone();
-        let host_triple = TargetTriple::from_triple(config::host_triple());
-        let is_cross = target_triple != host_triple;
-        let mut target_only = false;
-        let mut locate_ctxt = locator::Context {
-            sess: self.sess,
-            span,
-            crate_name: name,
-            hash: None,
-            extra_filename: None,
-            filesearch: self.sess.host_filesearch(PathKind::Crate),
-            target: &self.sess.host,
-            triple: host_triple,
-            root: None,
-            rejected_via_hash: vec![],
-            rejected_via_triple: vec![],
-            rejected_via_kind: vec![],
-            rejected_via_version: vec![],
-            rejected_via_filename: vec![],
-            should_match_name: true,
-            is_proc_macro: None,
-            metadata_loader: &*self.cstore.metadata_loader,
-        };
-        let library = self.load(&mut locate_ctxt).or_else(|| {
-            if !is_cross {
-                return None
-            }
-            // Try loading from target crates. This will abort later if we
-            // try to load a plugin registrar function,
-            target_only = true;
-
-            locate_ctxt.target = &self.sess.target.target;
-            locate_ctxt.triple = target_triple;
-            locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
-
-            self.load(&mut locate_ctxt)
-        });
-        let library = match library {
-            Some(l) => l,
-            None => locate_ctxt.report_errs(),
-        };
-
-        let (dylib, metadata) = match library {
-            LoadResult::Previous(cnum) => {
-                let data = self.cstore.get_crate_data(cnum);
-                (data.source.dylib.clone(), PMDSource::Registered(data))
-            }
-            LoadResult::Loaded(library) => {
-                let dylib = library.source.dylib.clone();
-                let metadata = PMDSource::Owned(library);
-                (dylib, metadata)
-            }
-        };
-
-        ExtensionCrate {
-            metadata,
-            dylib: dylib.map(|p| p.0),
-            target_only,
-        }
-    }
-
     fn dlsym_proc_macros(&self,
                          path: &Path,
                          disambiguator: CrateDisambiguator,
@@ -590,42 +517,7 @@ impl<'a> CrateLoader<'a> {
         decls
     }
 
-    /// Look for a plugin registrar. Returns library path, crate
-    /// SVH and DefIndex of the registrar function.
-    pub fn find_plugin_registrar(&self,
-                                 span: Span,
-                                 name: Symbol)
-                                 -> Option<(PathBuf, CrateDisambiguator)> {
-        let ekrate = self.read_extension_crate(name, span);
-
-        if ekrate.target_only {
-            // Need to abort before syntax expansion.
-            let message = format!("plugin `{}` is not available for triple `{}` \
-                                   (only found {})",
-                                  name,
-                                  config::host_triple(),
-                                  self.sess.opts.target_triple);
-            span_fatal!(self.sess, span, E0456, "{}", &message);
-        }
-
-        let root = ekrate.metadata.get_root();
-        match ekrate.dylib.as_ref() {
-            Some(dylib) => {
-                Some((dylib.to_path_buf(), root.disambiguator))
-            }
-            None => {
-                span_err!(self.sess, span, E0457,
-                          "plugin `{}` only found in rlib format, but must be available \
-                           in dylib format",
-                          name);
-                // No need to abort because the loading code will just ignore this
-                // empty dylib.
-                None
-            }
-        }
-    }
-
-    fn inject_panic_runtime(&self, krate: &ast::Crate) {
+    fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
         let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
@@ -687,7 +579,8 @@ impl<'a> CrateLoader<'a> {
         };
         info!("panic runtime not found -- loading {}", name);
 
-        let (cnum, data) = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
+        let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
+        let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
@@ -706,7 +599,7 @@ impl<'a> CrateLoader<'a> {
                                   &|data| data.root.needs_panic_runtime);
     }
 
-    fn inject_sanitizer_runtime(&self) {
+    fn inject_sanitizer_runtime(&mut self) {
         if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
             // Sanitizers can only be used on some tested platforms with
             // executables linked to `std`
@@ -791,7 +684,8 @@ impl<'a> CrateLoader<'a> {
                 });
                 info!("loading sanitizer: {}", name);
 
-                let data = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None).1;
+                let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None);
+                let data = self.cstore.get_crate_data(cnum);
 
                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
                 if !data.root.sanitizer_runtime {
@@ -804,14 +698,15 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn inject_profiler_runtime(&self) {
+    fn inject_profiler_runtime(&mut self) {
         if self.sess.opts.debugging_opts.profile ||
            self.sess.opts.cg.profile_generate.enabled()
         {
             info!("loading profiler");
 
             let name = Symbol::intern("profiler_builtins");
-            let data = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None).1;
+            let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
+            let data = self.cstore.get_crate_data(cnum);
 
             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
             if !data.root.profiler_runtime {
@@ -957,10 +852,8 @@ impl<'a> CrateLoader<'a> {
             data.dependencies.borrow_mut().push(krate);
         });
     }
-}
 
-impl<'a> CrateLoader<'a> {
-    pub fn postprocess(&self, krate: &ast::Crate) {
+    pub fn postprocess(&mut self, krate: &ast::Crate) {
         self.inject_sanitizer_runtime();
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
@@ -971,7 +864,11 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    pub fn process_extern_crate(&self, item: &ast::Item, definitions: &Definitions) -> CrateNum {
+    pub fn process_extern_crate(
+        &mut self,
+        item: &ast::Item,
+        definitions: &Definitions,
+    ) -> CrateNum {
         match item.kind {
             ast::ItemKind::ExternCrate(orig_name) => {
                 debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
@@ -990,7 +887,7 @@ impl<'a> CrateLoader<'a> {
                     DepKind::Explicit
                 };
 
-                let cnum = self.resolve_crate(name, item.span, dep_kind, None).0;
+                let cnum = self.resolve_crate(name, item.span, dep_kind, None);
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
                 let path_len = definitions.def_path(def_id.index).data.len();
@@ -1010,8 +907,8 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    pub fn process_path_extern(&self, name: Symbol, span: Span) -> CrateNum {
-        let cnum = self.resolve_crate(name, span, DepKind::Explicit, None).0;
+    pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
+        let cnum = self.resolve_crate(name, span, DepKind::Explicit, None);
 
         self.update_extern_crate(
             cnum,
@@ -1028,8 +925,8 @@ impl<'a> CrateLoader<'a> {
         cnum
     }
 
-    pub fn maybe_process_path_extern(&self, name: Symbol, span: Span) -> Option<CrateNum> {
-        let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?.0;
+    pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
+        let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?;
 
         self.update_extern_crate(
             cnum,
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 9a0b98ffb73..6b06cf575ed 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -5,12 +5,13 @@ use crate::schema;
 use rustc::dep_graph::DepNodeIndex;
 use rustc::hir::def_id::{CrateNum, DefIndex};
 use rustc::hir::map::definitions::DefPathTable;
-use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoader};
+use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate};
 use rustc::mir::interpret::AllocDecodingState;
 use rustc_index::vec::IndexVec;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell};
 use syntax::ast;
+use syntax::edition::Edition;
 use syntax_expand::base::SyntaxExtension;
 use syntax_pos;
 use proc_macro::bridge::client::ProcMacro;
@@ -36,7 +37,7 @@ crate struct ImportedSourceFile {
     pub translated_source_file: Lrc<syntax_pos::SourceFile>,
 }
 
-pub struct CrateMetadata {
+crate struct CrateMetadata {
     /// The primary crate data - binary metadata blob.
     crate blob: MetadataBlob,
 
@@ -53,7 +54,7 @@ pub struct CrateMetadata {
     /// hashmap, which gives the reverse mapping. This allows us to
     /// quickly retrace a `DefPath`, which is needed for incremental
     /// compilation support.
-    crate def_path_table: Lrc<DefPathTable>,
+    crate def_path_table: DefPathTable,
     /// Trait impl data.
     /// FIXME: Used only from queries and can use query cache,
     /// so pre-decoding can probably be avoided.
@@ -94,50 +95,48 @@ pub struct CrateMetadata {
     crate extern_crate: Lock<Option<ExternCrate>>,
 }
 
+#[derive(Clone)]
 pub struct CStore {
-    metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
-    crate metadata_loader: Box<dyn MetadataLoader + Sync>,
+    metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>,
 }
 
 pub enum LoadedMacro {
-    MacroDef(ast::Item),
+    MacroDef(ast::Item, Edition),
     ProcMacro(SyntaxExtension),
 }
 
-impl CStore {
-    pub fn new(metadata_loader: Box<dyn MetadataLoader + Sync>) -> CStore {
+impl Default for CStore {
+    fn default() -> Self {
         CStore {
             // We add an empty entry for LOCAL_CRATE (which maps to zero) in
             // order to make array indices in `metas` match with the
             // corresponding `CrateNum`. This first entry will always remain
             // `None`.
-            metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
-            metadata_loader,
+            metas: IndexVec::from_elem_n(None, 1),
         }
     }
+}
 
-    crate fn alloc_new_crate_num(&self) -> CrateNum {
-        let mut metas = self.metas.borrow_mut();
-        let cnum = CrateNum::new(metas.len());
-        metas.push(None);
-        cnum
+impl CStore {
+    crate fn alloc_new_crate_num(&mut self) -> CrateNum {
+        self.metas.push(None);
+        CrateNum::new(self.metas.len() - 1)
     }
 
-    crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
-        self.metas.borrow()[cnum].clone()
+    crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata {
+        self.metas[cnum].as_ref()
             .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
     }
 
-    crate fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
-        let mut metas = self.metas.borrow_mut();
-        assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
-        metas[cnum] = Some(data);
+    crate fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
+        assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry");
+        self.metas[cnum] = Some(Lrc::new(data));
     }
 
     crate fn iter_crate_data<I>(&self, mut i: I)
-        where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
+        where I: FnMut(CrateNum, &CrateMetadata)
     {
-        for (k, v) in self.metas.borrow().iter_enumerated() {
+        for (k, v) in self.metas.iter_enumerated() {
             if let &Some(ref v) = v {
                 i(k, v);
             }
@@ -168,7 +167,7 @@ impl CStore {
 
     crate fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
         let mut ordering = Vec::new();
-        for (num, v) in self.metas.borrow().iter_enumerated() {
+        for (num, v) in self.metas.iter_enumerated() {
             if let &Some(_) = v {
                 self.push_dependencies_in_postorder(&mut ordering, num);
             }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 4cd1ff7b4a4..d942a19194a 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -29,7 +29,6 @@ use std::sync::Arc;
 use syntax::ast;
 use syntax::attr;
 use syntax::source_map;
-use syntax::edition::Edition;
 use syntax::parse::source_file_to_stream;
 use syntax::parse::parser::emit_unclosed_delims;
 use syntax::source_map::Spanned;
@@ -54,7 +53,7 @@ macro_rules! provide {
                 let ($def_id, $other) = def_id_arg.into_args();
                 assert!(!$def_id.is_local());
 
-                let $cdata = $tcx.crate_data_as_rc_any($def_id.krate);
+                let $cdata = $tcx.crate_data_as_any($def_id.krate);
                 let $cdata = $cdata.downcast_ref::<cstore::CrateMetadata>()
                     .expect("CrateStore created data is not a CrateMetadata");
 
@@ -411,10 +410,6 @@ impl cstore::CStore {
         }
     }
 
-    pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition {
-        self.get_crate_data(cnum).root.edition
-    }
-
     pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec<Spanned<Symbol>> {
         self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
     }
@@ -460,7 +455,7 @@ impl cstore::CStore {
 
         LoadedMacro::MacroDef(ast::Item {
             // FIXME: cross-crate hygiene
-            ident: ast::Ident::with_dummy_span(name.as_symbol()),
+            ident: ast::Ident::with_dummy_span(name),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
@@ -470,7 +465,7 @@ impl cstore::CStore {
             }),
             vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             tokens: None,
-        })
+        }, data.root.edition)
     }
 
     pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem {
@@ -483,8 +478,8 @@ impl cstore::CStore {
 }
 
 impl CrateStore for cstore::CStore {
-    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any> {
-        self.get_crate_data(krate)
+    fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any {
+        self.get_crate_data(cnum)
     }
 
     fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
@@ -525,8 +520,8 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(def.krate).def_path_hash(def.index)
     }
 
-    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
-        self.get_crate_data(cnum).def_path_table.clone()
+    fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
+        &self.get_crate_data(cnum).def_path_table
     }
 
     fn crates_untracked(&self) -> Vec<CrateNum>
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index b8b00302440..8c52168b418 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -35,7 +35,7 @@ use syntax::ast::{self, Ident};
 use syntax::source_map::{self, respan, Spanned};
 use syntax::symbol::{Symbol, sym};
 use syntax_expand::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension};
-use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}};
+use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
 use log::debug;
 use proc_macro::bridge::client::ProcMacro;
 use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
@@ -448,7 +448,7 @@ impl<'tcx> EntryKind<'tcx> {
             EntryKind::Mod(_) => DefKind::Mod,
             EntryKind::Variant(_) => DefKind::Variant,
             EntryKind::Trait(_) => DefKind::Trait,
-            EntryKind::TraitAlias(_) => DefKind::TraitAlias,
+            EntryKind::TraitAlias => DefKind::TraitAlias,
             EntryKind::Enum(..) => DefKind::Enum,
             EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
             EntryKind::ForeignType => DefKind::ForeignTy,
@@ -458,7 +458,7 @@ impl<'tcx> EntryKind<'tcx> {
             EntryKind::Impl(_) |
             EntryKind::Field |
             EntryKind::Generator(_) |
-            EntryKind::Closure(_) => return None,
+            EntryKind::Closure => return None,
         })
     }
 }
@@ -514,7 +514,6 @@ impl<'a, 'tcx> CrateMetadata {
                 .data
                 .get_opt_name()
                 .expect("no name in item_name")
-                .as_symbol()
         } else {
             Symbol::intern(self.raw_proc_macro(item_index).name())
         }
@@ -575,7 +574,7 @@ impl<'a, 'tcx> CrateMetadata {
                                   data.is_marker,
                                   self.def_path_table.def_path_hash(item_id))
             },
-            EntryKind::TraitAlias(_) => {
+            EntryKind::TraitAlias => {
                 ty::TraitDef::new(self.local_def_id(item_id),
                                   hir::Unsafety::Normal,
                                   false,
@@ -680,13 +679,7 @@ impl<'a, 'tcx> CrateMetadata {
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> ty::GenericPredicates<'tcx> {
-        let super_predicates = match self.kind(item_id) {
-            EntryKind::Trait(data) => data.decode(self).super_predicates,
-            EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
-            _ => bug!("def-index does not refer to trait or trait alias"),
-        };
-
-        super_predicates.decode((self, tcx))
+        self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
     }
 
     crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
@@ -717,7 +710,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> {
+    fn get_impl_data(&self, id: DefIndex) -> ImplData {
         match self.kind(id) {
             EntryKind::Impl(data) => data.decode(self),
             _ => bug!(),
@@ -744,7 +737,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
-        self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx)))
+        self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
     }
 
     /// Iterates over all the stability attributes in the given crate.
@@ -864,7 +857,7 @@ impl<'a, 'tcx> CrateMetadata {
                 let span = self.get_span(child_index, sess);
                 if let (Some(kind), Some(name)) =
                     (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::from_interned_str(name);
+                    let ident = Ident::with_dummy_span(name);
                     let vis = self.get_visibility(child_index);
                     let def_id = self.local_def_id(child_index);
                     let res = Res::Def(kind, def_id);
@@ -987,7 +980,7 @@ impl<'a, 'tcx> CrateMetadata {
         };
 
         ty::AssocItem {
-            ident: Ident::from_interned_str(name),
+            ident: Ident::with_dummy_span(name),
             kind,
             vis: self.get_visibility(id),
             defaultness: container.defaultness(),
@@ -1118,7 +1111,7 @@ impl<'a, 'tcx> CrateMetadata {
         def_key.parent.and_then(|parent_index| {
             match self.kind(parent_index) {
                 EntryKind::Trait(_) |
-                EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
+                EntryKind::TraitAlias => Some(self.local_def_id(parent_index)),
                 _ => None,
             }
         })
@@ -1245,16 +1238,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
-        let sig = match self.kind(id) {
-            EntryKind::Fn(data) |
-            EntryKind::ForeignFn(data) => data.decode(self).sig,
-            EntryKind::Method(data) => data.decode(self).fn_data.sig,
-            EntryKind::Variant(data) |
-            EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(),
-            EntryKind::Closure(data) => data.decode(self).sig,
-            _ => bug!(),
-        };
-        sig.decode((self, tcx))
+        self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx))
     }
 
     #[inline]
@@ -1262,7 +1246,7 @@ impl<'a, 'tcx> CrateMetadata {
         let mut key = self.def_path_table.def_key(index);
         if self.is_proc_macro(index) {
             let name = self.raw_proc_macro(index).name();
-            key.disambiguated_data.data = DefPathData::MacroNs(InternedString::intern(name));
+            key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
         }
         key
     }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 6ae8c2fc6c6..0dc9f91ae00 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -71,11 +71,14 @@ struct PerDefTables<'tcx> {
     deprecation: PerDefTable<Lazy<attr::Deprecation>>,
 
     ty: PerDefTable<Lazy<Ty<'tcx>>>,
+    fn_sig: PerDefTable<Lazy<ty::PolyFnSig<'tcx>>>,
+    impl_trait_ref: PerDefTable<Lazy<ty::TraitRef<'tcx>>>,
     inherent_impls: PerDefTable<Lazy<[DefIndex]>>,
     variances: PerDefTable<Lazy<[ty::Variance]>>,
     generics: PerDefTable<Lazy<ty::Generics>>,
     predicates: PerDefTable<Lazy<ty::GenericPredicates<'tcx>>>,
     predicates_defined_on: PerDefTable<Lazy<ty::GenericPredicates<'tcx>>>,
+    super_predicates: PerDefTable<Lazy<ty::GenericPredicates<'tcx>>>,
 
     mir: PerDefTable<Lazy<mir::Body<'tcx>>>,
     promoted_mir: PerDefTable<Lazy<IndexVec<mir::Promoted, mir::Body<'tcx>>>>,
@@ -508,11 +511,14 @@ impl<'tcx> EncodeContext<'tcx> {
             deprecation: self.per_def.deprecation.encode(&mut self.opaque),
 
             ty: self.per_def.ty.encode(&mut self.opaque),
+            fn_sig: self.per_def.fn_sig.encode(&mut self.opaque),
+            impl_trait_ref: self.per_def.impl_trait_ref.encode(&mut self.opaque),
             inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque),
             variances: self.per_def.variances.encode(&mut self.opaque),
             generics: self.per_def.generics.encode(&mut self.opaque),
             predicates: self.per_def.predicates.encode(&mut self.opaque),
             predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque),
+            super_predicates: self.per_def.super_predicates.encode(&mut self.opaque),
 
             mir: self.per_def.mir.encode(&mut self.opaque),
             promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque),
@@ -635,13 +641,7 @@ impl EncodeContext<'tcx> {
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
-            // FIXME(eddyb) deduplicate these with `encode_enum_variant_ctor`.
             ctor: variant.ctor_def_id.map(|did| did.index),
-            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
-                variant.ctor_def_id.map(|ctor_def_id| self.lazy(&tcx.fn_sig(ctor_def_id)))
-            } else {
-                None
-            },
         };
 
         let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
@@ -660,6 +660,11 @@ impl EncodeContext<'tcx> {
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
+            // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
+            if let Some(ctor_def_id) = variant.ctor_def_id {
+                record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
+            }
+            // FIXME(eddyb) is this ever used?
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -679,15 +684,11 @@ impl EncodeContext<'tcx> {
         let def_id = variant.ctor_def_id.unwrap();
         debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
 
+        // FIXME(eddyb) encode only the `CtorKind` for constructors.
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             ctor: Some(def_id.index),
-            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
-                Some(self.lazy(tcx.fn_sig(def_id)))
-            } else {
-                None
-            }
         };
 
         // Variant constructors have the same visibility as the parent enums, unless marked as
@@ -706,6 +707,7 @@ impl EncodeContext<'tcx> {
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
+            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -780,11 +782,6 @@ impl EncodeContext<'tcx> {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             ctor: Some(def_id.index),
-            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
-                Some(self.lazy(tcx.fn_sig(def_id)))
-            } else {
-                None
-            }
         };
 
         let struct_id = tcx.hir().as_local_hir_id(adt_def_id).unwrap();
@@ -811,6 +808,7 @@ impl EncodeContext<'tcx> {
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
+            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -835,6 +833,11 @@ impl EncodeContext<'tcx> {
             self.tcx.predicates_defined_on(def_id))
     }
 
+    fn encode_super_predicates(&mut self, def_id: DefId) {
+        debug!("EncodeContext::encode_super_predicates({:?})", def_id);
+        record!(self.per_def.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
+    }
+
     fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
@@ -874,7 +877,6 @@ impl EncodeContext<'tcx> {
                         asyncness: m_sig.header.asyncness,
                         constness: hir::Constness::NotConst,
                         param_names,
-                        sig: self.lazy(tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -906,6 +908,7 @@ impl EncodeContext<'tcx> {
             ty::AssocKind::OpaqueTy => unreachable!(),
         }
         if trait_item.kind == ty::AssocKind::Method {
+            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -952,7 +955,6 @@ impl EncodeContext<'tcx> {
                         asyncness: sig.header.asyncness,
                         constness: sig.header.constness,
                         param_names: self.encode_fn_param_names_for_body(body),
-                        sig: self.lazy(tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -973,6 +975,7 @@ impl EncodeContext<'tcx> {
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if impl_item.kind == ty::AssocKind::Method {
+            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -1081,7 +1084,6 @@ impl EncodeContext<'tcx> {
                     asyncness: header.asyncness,
                     constness: header.constness,
                     param_names: self.encode_fn_param_names_for_body(body),
-                    sig: self.lazy(tcx.fn_sig(def_id)),
                 };
 
                 EntryKind::Fn(self.lazy(data))
@@ -1109,7 +1111,6 @@ impl EncodeContext<'tcx> {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     ctor,
-                    ctor_sig: None,
                 }), adt_def.repr)
             }
             hir::ItemKind::Union(..) => {
@@ -1120,7 +1121,6 @@ impl EncodeContext<'tcx> {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     ctor: None,
-                    ctor_sig: None,
                 }), adt_def.repr)
             }
             hir::ItemKind::Impl(_, _, defaultness, ..) => {
@@ -1154,7 +1154,6 @@ impl EncodeContext<'tcx> {
                     defaultness,
                     parent_impl: parent,
                     coerce_unsized_info,
-                    trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)),
                 };
 
                 EntryKind::Impl(self.lazy(data))
@@ -1166,18 +1165,11 @@ impl EncodeContext<'tcx> {
                     paren_sugar: trait_def.paren_sugar,
                     has_auto_impl: self.tcx.trait_is_auto(def_id),
                     is_marker: trait_def.is_marker,
-                    super_predicates: self.lazy(tcx.super_predicates_of(def_id)),
                 };
 
                 EntryKind::Trait(self.lazy(data))
             }
-            hir::ItemKind::TraitAlias(..) => {
-                let data = TraitAliasData {
-                    super_predicates: self.lazy(tcx.super_predicates_of(def_id)),
-                };
-
-                EntryKind::TraitAlias(self.lazy(data))
-            }
+            hir::ItemKind::TraitAlias(..) => EntryKind::TraitAlias,
             hir::ItemKind::ExternCrate(_) |
             hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
         });
@@ -1232,6 +1224,14 @@ impl EncodeContext<'tcx> {
             hir::ItemKind::Impl(..) => self.encode_item_type(def_id),
             _ => {}
         }
+        if let hir::ItemKind::Fn(..) = item.kind {
+            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+        }
+        if let hir::ItemKind::Impl(..) = item.kind {
+            if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
+                record!(self.per_def.impl_trait_ref[def_id] <- trait_ref);
+            }
+        }
         self.encode_inherent_implementations(def_id);
         match item.kind {
             hir::ItemKind::Enum(..) |
@@ -1269,6 +1269,13 @@ impl EncodeContext<'tcx> {
             }
             _ => {} // not *wrong* for other kinds of items, but not needed
         }
+        match item.kind {
+            hir::ItemKind::Trait(..) |
+            hir::ItemKind::TraitAlias(..) => {
+                self.encode_super_predicates(def_id);
+            }
+            _ => {}
+        }
 
         let mir = match item.kind {
             hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true,
@@ -1321,10 +1328,12 @@ impl EncodeContext<'tcx> {
     fn encode_info_for_closure(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
 
-        let tables = self.tcx.typeck_tables_of(def_id);
+        // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
+        // including on the signature, which is inferred in `typeck_tables_of.
         let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
+        let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id);
 
-        record!(self.per_def.kind[def_id] <- match tables.node_type(hir_id).kind {
+        record!(self.per_def.kind[def_id] <- match ty.kind {
             ty::Generator(def_id, ..) => {
                 let layout = self.tcx.generator_layout(def_id);
                 let data = GeneratorData {
@@ -1333,11 +1342,7 @@ impl EncodeContext<'tcx> {
                 EntryKind::Generator(self.lazy(data))
             }
 
-            ty::Closure(def_id, substs) => {
-                let sig = substs.as_closure().sig(def_id, self.tcx);
-                let data = ClosureData { sig: self.lazy(sig) };
-                EntryKind::Closure(self.lazy(data))
-            }
+            ty::Closure(..) => EntryKind::Closure,
 
             _ => bug!("closure that is neither generator nor closure"),
         });
@@ -1345,6 +1350,9 @@ impl EncodeContext<'tcx> {
         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
         record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
         self.encode_item_type(def_id);
+        if let ty::Closure(def_id, substs) = ty.kind {
+            record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx));
+        }
         self.encode_generics(def_id);
         self.encode_optimized_mir(def_id);
         self.encode_promoted_mir(def_id);
@@ -1553,7 +1561,6 @@ impl EncodeContext<'tcx> {
                     asyncness: hir::IsAsync::NotAsync,
                     constness: hir::Constness::NotConst,
                     param_names: self.encode_fn_param_names(names),
-                    sig: self.lazy(tcx.fn_sig(def_id)),
                 };
                 EntryKind::ForeignFn(self.lazy(data))
             }
@@ -1569,6 +1576,7 @@ impl EncodeContext<'tcx> {
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if let hir::ForeignItemKind::Fn(..) = nitem.kind {
+            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 05676dad334..a5298402dd4 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -212,7 +212,7 @@
 //! no means all of the necessary details. Take a look at the rest of
 //! metadata::locator or metadata::creader for all the juicy details!
 
-use crate::cstore::{MetadataBlob, CStore};
+use crate::cstore::MetadataBlob;
 use crate::creader::Library;
 use crate::schema::{METADATA_HEADER, rustc_version};
 
@@ -220,12 +220,13 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
 use rustc::middle::cstore::{CrateSource, MetadataLoader};
-use rustc::session::{config, Session};
+use rustc::session::{config, Session, CrateDisambiguator};
 use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
 use rustc::session::search_paths::PathKind;
 use rustc::util::nodemap::FxHashMap;
 
 use errors::DiagnosticBuilder;
+use syntax::{span_err, span_fatal};
 use syntax::symbol::{Symbol, sym};
 use syntax::struct_span_err;
 use syntax_pos::Span;
@@ -911,10 +912,87 @@ fn get_metadata_section_imp(target: &Target,
     }
 }
 
+/// Look for a plugin registrar. Returns its library path and crate disambiguator.
+pub fn find_plugin_registrar(
+    sess: &Session,
+    metadata_loader: &dyn MetadataLoader,
+    span: Span,
+    name: Symbol,
+) -> Option<(PathBuf, CrateDisambiguator)> {
+    info!("find plugin registrar `{}`", name);
+    let target_triple = sess.opts.target_triple.clone();
+    let host_triple = TargetTriple::from_triple(config::host_triple());
+    let is_cross = target_triple != host_triple;
+    let mut target_only = false;
+    let mut locate_ctxt = Context {
+        sess,
+        span,
+        crate_name: name,
+        hash: None,
+        extra_filename: None,
+        filesearch: sess.host_filesearch(PathKind::Crate),
+        target: &sess.host,
+        triple: host_triple,
+        root: None,
+        rejected_via_hash: vec![],
+        rejected_via_triple: vec![],
+        rejected_via_kind: vec![],
+        rejected_via_version: vec![],
+        rejected_via_filename: vec![],
+        should_match_name: true,
+        is_proc_macro: None,
+        metadata_loader,
+    };
+
+    let library = locate_ctxt.maybe_load_library_crate().or_else(|| {
+        if !is_cross {
+            return None
+        }
+        // Try loading from target crates. This will abort later if we
+        // try to load a plugin registrar function,
+        target_only = true;
+
+        locate_ctxt.target = &sess.target.target;
+        locate_ctxt.triple = target_triple;
+        locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate);
+
+        locate_ctxt.maybe_load_library_crate()
+    });
+    let library = match library {
+        Some(l) => l,
+        None => locate_ctxt.report_errs(),
+    };
+
+    if target_only {
+        // Need to abort before syntax expansion.
+        let message = format!("plugin `{}` is not available for triple `{}` \
+                                (only found {})",
+                                name,
+                                config::host_triple(),
+                                sess.opts.target_triple);
+        span_fatal!(sess, span, E0456, "{}", &message);
+    }
+
+    match library.source.dylib {
+        Some(dylib) => {
+            Some((dylib.0, library.metadata.get_root().disambiguator))
+        }
+        None => {
+            span_err!(sess, span, E0457,
+                        "plugin `{}` only found in rlib format, but must be available \
+                        in dylib format",
+                        name);
+            // No need to abort because the loading code will just ignore this
+            // empty dylib.
+            None
+        }
+    }
+}
+
 /// A diagnostic function for dumping crate metadata to an output stream.
 pub fn list_file_metadata(target: &Target,
                           path: &Path,
-                          cstore: &CStore,
+                          metadata_loader: &dyn MetadataLoader,
                           out: &mut dyn io::Write)
                           -> io::Result<()> {
     let filename = path.file_name().unwrap().to_str().unwrap();
@@ -925,7 +1003,7 @@ pub fn list_file_metadata(target: &Target,
     } else {
         CrateFlavor::Dylib
     };
-    match get_metadata_section(target, flavor, path, &*cstore.metadata_loader) {
+    match get_metadata_section(target, flavor, path, metadata_loader) {
         Ok(metadata) => metadata.list_crate_metadata(out),
         Err(msg) => write!(out, "{}\n", msg),
     }
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 96f35783278..ad39aa34fd5 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -238,11 +238,14 @@ crate struct LazyPerDefTables<'tcx> {
     pub deprecation: Lazy!(PerDefTable<Lazy<attr::Deprecation>>),
 
     pub ty: Lazy!(PerDefTable<Lazy!(Ty<'tcx>)>),
+    pub fn_sig: Lazy!(PerDefTable<Lazy!(ty::PolyFnSig<'tcx>)>),
+    pub impl_trait_ref: Lazy!(PerDefTable<Lazy!(ty::TraitRef<'tcx>)>),
     pub inherent_impls: Lazy!(PerDefTable<Lazy<[DefIndex]>>),
     pub variances: Lazy!(PerDefTable<Lazy<[ty::Variance]>>),
     pub generics: Lazy!(PerDefTable<Lazy<ty::Generics>>),
     pub predicates: Lazy!(PerDefTable<Lazy!(ty::GenericPredicates<'tcx>)>),
     pub predicates_defined_on: Lazy!(PerDefTable<Lazy!(ty::GenericPredicates<'tcx>)>),
+    pub super_predicates: Lazy!(PerDefTable<Lazy!(ty::GenericPredicates<'tcx>)>),
 
     pub mir: Lazy!(PerDefTable<Lazy!(mir::Body<'tcx>)>),
     pub promoted_mir: Lazy!(PerDefTable<Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>),
@@ -264,22 +267,22 @@ crate enum EntryKind<'tcx> {
     OpaqueTy,
     Enum(ReprOptions),
     Field,
-    Variant(Lazy!(VariantData<'tcx>)),
-    Struct(Lazy!(VariantData<'tcx>), ReprOptions),
-    Union(Lazy!(VariantData<'tcx>), ReprOptions),
-    Fn(Lazy!(FnData<'tcx>)),
-    ForeignFn(Lazy!(FnData<'tcx>)),
+    Variant(Lazy<VariantData>),
+    Struct(Lazy<VariantData>, ReprOptions),
+    Union(Lazy<VariantData>, ReprOptions),
+    Fn(Lazy<FnData>),
+    ForeignFn(Lazy<FnData>),
     Mod(Lazy<ModData>),
     MacroDef(Lazy<MacroDef>),
-    Closure(Lazy!(ClosureData<'tcx>)),
+    Closure,
     Generator(Lazy!(GeneratorData<'tcx>)),
-    Trait(Lazy!(TraitData<'tcx>)),
-    Impl(Lazy!(ImplData<'tcx>)),
-    Method(Lazy!(MethodData<'tcx>)),
+    Trait(Lazy<TraitData>),
+    Impl(Lazy<ImplData>),
+    Method(Lazy<MethodData>),
     AssocType(AssocContainer),
     AssocOpaqueTy(AssocContainer),
     AssocConst(AssocContainer, ConstQualif, Lazy<RenderedConst>),
-    TraitAlias(Lazy!(TraitAliasData<'tcx>)),
+    TraitAlias,
 }
 
 /// Additional data for EntryKind::Const and EntryKind::AssocConst
@@ -305,47 +308,37 @@ crate struct MacroDef {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-crate struct FnData<'tcx> {
+crate struct FnData {
     pub asyncness: hir::IsAsync,
     pub constness: hir::Constness,
     pub param_names: Lazy<[ast::Name]>,
-    pub sig: Lazy!(ty::PolyFnSig<'tcx>),
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-crate struct VariantData<'tcx> {
+crate struct VariantData {
     pub ctor_kind: CtorKind,
     pub discr: ty::VariantDiscr,
     /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
     pub ctor: Option<DefIndex>,
-    /// If this is a tuple struct or variant
-    /// ctor, this is its "function" signature.
-    pub ctor_sig: Option<Lazy!(ty::PolyFnSig<'tcx>)>,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-crate struct TraitData<'tcx> {
+crate struct TraitData {
     pub unsafety: hir::Unsafety,
     pub paren_sugar: bool,
     pub has_auto_impl: bool,
     pub is_marker: bool,
-    pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>),
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-crate struct TraitAliasData<'tcx> {
-    pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>),
-}
-
-#[derive(RustcEncodable, RustcDecodable)]
-crate struct ImplData<'tcx> {
+crate struct ImplData {
     pub polarity: ty::ImplPolarity,
     pub defaultness: hir::Defaultness,
     pub parent_impl: Option<DefId>,
 
     /// This is `Some` only for impls of `CoerceUnsized`.
+    // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
     pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
-    pub trait_ref: Option<Lazy!(ty::TraitRef<'tcx>)>,
 }
 
 
@@ -388,18 +381,13 @@ impl AssocContainer {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-crate struct MethodData<'tcx> {
-    pub fn_data: FnData<'tcx>,
+crate struct MethodData {
+    pub fn_data: FnData,
     pub container: AssocContainer,
     pub has_self: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-crate struct ClosureData<'tcx> {
-    pub sig: Lazy!(ty::PolyFnSig<'tcx>),
-}
-
-#[derive(RustcEncodable, RustcDecodable)]
 crate struct GeneratorData<'tcx> {
     pub layout: mir::GeneratorLayout<'tcx>,
 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 6fb976e0d84..d6e84940291 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -18,14 +18,14 @@ use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
 use syntax::symbol::kw;
 use rustc_data_structures::fx::FxHashMap;
-use syntax_pos::{Span, symbol::InternedString};
+use syntax_pos::{Span, symbol::Symbol};
 
 /// A name for a particular region used in emitting diagnostics. This name could be a generated
 /// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
 #[derive(Debug, Clone)]
 crate struct RegionName {
     /// The name of the region (interned).
-    crate name: InternedString,
+    crate name: Symbol,
     /// Where the region comes from.
     crate source: RegionNameSource,
 }
@@ -109,7 +109,7 @@ impl RegionName {
     }
 
     #[allow(dead_code)]
-    crate fn name(&self) -> InternedString {
+    crate fn name(&self) -> Symbol {
         self.name
     }
 
@@ -273,7 +273,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             ty::ReStatic => Some(RegionName {
-                name: kw::StaticLifetime.as_interned_str(),
+                name: kw::StaticLifetime,
                 source: RegionNameSource::Static
             }),
 
@@ -360,7 +360,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         error_region: &RegionKind,
-        name: InternedString,
+        name: Symbol,
     ) -> Span {
         let scope = error_region.free_region_binding_scope(tcx);
         let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
@@ -837,10 +837,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     /// Creates a synthetic region named `'1`, incrementing the counter.
-    fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString {
+    fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> Symbol {
         let c = renctx.counter;
         renctx.counter += 1;
 
-        InternedString::intern(&format!("'{:?}", c))
+        Symbol::intern(&format!("'{:?}", c))
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index fd1f333010a..b876fd83ec9 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -790,7 +790,7 @@ fn for_each_late_bound_region_defined_on<'tcx>(
                 owner: fn_def_id.index,
                 local_id: *late_bound,
             };
-            let name = tcx.hir().name(hir_id).as_interned_str();
+            let name = tcx.hir().name(hir_id);
             let region_def_id = tcx.hir().local_def_id(hir_id);
             let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
                 scope: fn_def_id,
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index e6f7a042f1c..7bb96661bb7 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -908,7 +908,7 @@ fn convert_path_expr<'a, 'tcx>(
             let generics = cx.tcx.generics_of(item_def_id);
             let local_def_id = cx.tcx.hir().local_def_id(hir_id);
             let index = generics.param_def_id_to_index[&local_def_id];
-            let name = cx.tcx.hir().name(hir_id).as_interned_str();
+            let name = cx.tcx.hir().name(hir_id);
             let val = ConstValue::Param(ty::ParamConst::new(index, name));
             ExprKind::Literal {
                 literal: cx.tcx.mk_const(
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 58480912929..98e286e61e9 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -25,7 +25,6 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 use rustc::hir::ptr::P;
 
 use rustc_index::vec::Idx;
-use rustc_data_structures::fx::FxHashSet;
 
 use std::cmp::Ordering;
 use std::fmt;
@@ -1000,15 +999,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         if self.include_lint_checks && !saw_error {
             // If we were able to successfully convert the const to some pat, double-check
             // that the type of the const obeys `#[structural_match]` constraint.
-            if let Some(adt_def) = search_for_adt_without_structural_match(self.tcx, cv.ty) {
-
-                let path = self.tcx.def_path_str(adt_def.did);
-                let msg = format!(
-                    "to use a constant of type `{}` in a pattern, \
-                     `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                    path,
-                    path,
-                );
+            if let Some(non_sm_ty) = ty::search_for_structural_match_violation(self.tcx, cv.ty) {
+                let msg = match non_sm_ty {
+                    ty::NonStructuralMatchTy::Adt(adt_def) => {
+                        let path = self.tcx.def_path_str(adt_def.did);
+                        format!(
+                            "to use a constant of type `{}` in a pattern, \
+                             `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                            path,
+                            path,
+                        )
+                    }
+                    ty::NonStructuralMatchTy::Param => {
+                        bug!("use of constant whose type is a parameter inside a pattern");
+                    }
+                };
 
                 // before issuing lint, double-check there even *is* a
                 // semantic PartialEq for us to dispatch to.
@@ -1169,125 +1174,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     }
 }
 
-/// This method traverses the structure of `ty`, trying to find an
-/// instance of an ADT (i.e. struct or enum) that was declared without
-/// the `#[structural_match]` attribute.
-///
-/// The "structure of a type" includes all components that would be
-/// considered when doing a pattern match on a constant of that
-/// type.
-///
-///  * This means this method descends into fields of structs/enums,
-///    and also descends into the inner type `T` of `&T` and `&mut T`
-///
-///  * The traversal doesn't dereference unsafe pointers (`*const T`,
-///    `*mut T`), and it does not visit the type arguments of an
-///    instantiated generic like `PhantomData<T>`.
-///
-/// The reason we do this search is Rust currently require all ADT's
-/// reachable from a constant's type to be annotated with
-/// `#[structural_match]`, an attribute which essentially says that
-/// the implementation of `PartialEq::eq` behaves *equivalently* to a
-/// comparison against the unfolded structure.
-///
-/// For more background on why Rust has this requirement, and issues
-/// that arose when the requirement was not enforced completely, see
-/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
-fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>,
-                                                 ty: Ty<'tcx>)
-                                                 -> Option<&'tcx AdtDef>
-{
-    // Import here (not mod level), because `TypeFoldable::fold_with`
-    // conflicts with `PatternFoldable::fold_with`
-    use crate::rustc::ty::fold::TypeVisitor;
-    use crate::rustc::ty::TypeFoldable;
-
-    let mut search = Search { tcx, found: None, seen: FxHashSet::default() };
-    ty.visit_with(&mut search);
-    return search.found;
-
-    struct Search<'tcx> {
-        tcx: TyCtxt<'tcx>,
-
-        // records the first ADT we find without `#[structural_match`
-        found: Option<&'tcx AdtDef>,
-
-        // tracks ADT's previously encountered during search, so that
-        // we will not recur on them again.
-        seen: FxHashSet<hir::def_id::DefId>,
-    }
-
-    impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
-        fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
-            debug!("Search visiting ty: {:?}", ty);
-
-            let (adt_def, substs) = match ty.kind {
-                ty::Adt(adt_def, substs) => (adt_def, substs),
-                ty::RawPtr(..) => {
-                    // `#[structural_match]` ignores substructure of
-                    // `*const _`/`*mut _`, so skip super_visit_with
-                    //
-                    // (But still tell caller to continue search.)
-                    return false;
-                }
-                ty::FnDef(..) | ty::FnPtr(..) => {
-                    // types of formals and return in `fn(_) -> _` are also irrelevant
-                    //
-                    // (But still tell caller to continue search.)
-                    return false;
-                }
-                ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0)
-                => {
-                    // rust-lang/rust#62336: ignore type of contents
-                    // for empty array.
-                    return false;
-                }
-                _ => {
-                    ty.super_visit_with(self);
-                    return false;
-                }
-            };
-
-            if !self.tcx.has_attr(adt_def.did, sym::structural_match) {
-                self.found = Some(&adt_def);
-                debug!("Search found adt_def: {:?}", adt_def);
-                return true // Halt visiting!
-            }
-
-            if !self.seen.insert(adt_def.did) {
-                debug!("Search already seen adt_def: {:?}", adt_def);
-                // let caller continue its search
-                return false;
-            }
-
-            // `#[structural_match]` does not care about the
-            // instantiation of the generics in an ADT (it
-            // instead looks directly at its fields outside
-            // this match), so we skip super_visit_with.
-            //
-            // (Must not recur on substs for `PhantomData<T>` cf
-            // rust-lang/rust#55028 and rust-lang/rust#55837; but also
-            // want to skip substs when only uses of generic are
-            // behind unsafe pointers `*const T`/`*mut T`.)
-
-            // even though we skip super_visit_with, we must recur on
-            // fields of ADT.
-            let tcx = self.tcx;
-            for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
-                if field_ty.visit_with(self) {
-                    // found an ADT without `#[structural_match]`; halt visiting!
-                    assert!(self.found.is_some());
-                    return true;
-                }
-            }
-
-            // Even though we do not want to recur on substs, we do
-            // want our caller to continue its own search.
-            false
-        }
-    }
-}
-
 impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 2ab7c41bb78..d929e958f05 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> {
     pub extra: Extra,
 }
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, Debug)] // Miri debug-prints these
 pub enum StackPopCleanup {
     /// Jump to the next block in the caller, or cause UB if None (that's a function
     /// that may never return). Also store layout of return place so
@@ -113,7 +113,7 @@ pub struct LocalState<'tcx, Tag=(), Id=AllocId> {
 }
 
 /// Current value of a local variable
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq, Debug)] // Miri debug-prints these
 pub enum LocalValue<Tag=(), Id=AllocId> {
     /// This local is not currently alive, and cannot be used at all.
     Dead,
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index f9200f8c1c0..f1f9fac08ca 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -148,7 +148,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
 
         self.path.push_str("::");
 
-        self.path.push_str(&disambiguated_data.data.as_interned_str().as_str());
+        self.path.push_str(&disambiguated_data.data.as_symbol().as_str());
         Ok(self)
     }
 
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index eef1868ec65..d113ee33162 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -7,7 +7,7 @@
 //! short-circuiting the empty case!
 
 use std::collections::VecDeque;
-use std::{ptr, iter};
+use std::ptr;
 use std::borrow::Cow;
 
 use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
@@ -791,11 +791,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     pub fn write_bytes(
         &mut self,
         ptr: Scalar<M::PointerTag>,
-        src: impl IntoIterator<Item=u8, IntoIter: iter::ExactSizeIterator>,
+        src: impl IntoIterator<Item=u8>,
     ) -> InterpResult<'tcx>
     {
         let src = src.into_iter();
-        let size = Size::from_bytes(src.len() as u64);
+        let size = Size::from_bytes(src.size_hint().0 as u64);
+        // `write_bytes` checks that this lower bound matches the upper bound matches reality.
         let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? {
             Some(ptr) => ptr,
             None => return Ok(()), // zero-sized access
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index b9d38028b72..42f08771f86 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -96,7 +96,7 @@ use std::collections::hash_map::Entry;
 use std::cmp;
 use std::sync::Arc;
 
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def::DefKind;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
@@ -121,7 +121,7 @@ pub enum PartitioningStrategy {
 }
 
 // Anything we can't find a proper codegen unit for goes into this.
-fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> InternedString {
+fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
     name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
 }
 
@@ -185,9 +185,7 @@ where
         internalization_candidates: _,
     } = post_inlining;
 
-    result.sort_by(|cgu1, cgu2| {
-        cgu1.name().cmp(cgu2.name())
-    });
+    result.sort_by_cached_key(|cgu| cgu.name().as_str());
 
     result
 }
@@ -203,7 +201,7 @@ struct PreInliningPartitioning<'tcx> {
 /// to keep track of that.
 #[derive(Clone, PartialEq, Eq, Debug)]
 enum MonoItemPlacement {
-    SingleCgu { cgu_name: InternedString },
+    SingleCgu { cgu_name: Symbol },
     MultipleCgus,
 }
 
@@ -251,8 +249,8 @@ where
             None => fallback_cgu_name(cgu_name_builder),
         };
 
-        let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
-            .or_insert_with(|| CodegenUnit::new(codegen_unit_name.clone()));
+        let codegen_unit = codegen_units.entry(codegen_unit_name)
+            .or_insert_with(|| CodegenUnit::new(codegen_unit_name));
 
         let mut can_be_internalized = true;
         let (linkage, visibility) = mono_item_linkage_and_visibility(
@@ -273,8 +271,7 @@ where
     // crate with just types (for example), we could wind up with no CGU.
     if codegen_units.is_empty() {
         let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
-        codegen_units.insert(codegen_unit_name.clone(),
-                             CodegenUnit::new(codegen_unit_name.clone()));
+        codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
     }
 
     PreInliningPartitioning {
@@ -492,7 +489,7 @@ fn merge_codegen_units<'tcx>(
     // smallest into each other) we're sure to start off with a deterministic
     // order (sorted by name). This'll mean that if two cgus have the same size
     // the stable sort below will keep everything nice and deterministic.
-    codegen_units.sort_by_key(|cgu| *cgu.name());
+    codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str());
 
     // Merge the two smallest codegen units until the target size is reached.
     while codegen_units.len() > target_cgu_count {
@@ -537,7 +534,7 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<
             follow_inlining(*root, inlining_map, &mut reachable);
         }
 
-        let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name().clone());
+        let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
 
         // Add all monomorphizations that are not already there.
         for mono_item in reachable {
@@ -564,8 +561,8 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<
                     Entry::Occupied(e) => {
                         let placement = e.into_mut();
                         debug_assert!(match *placement {
-                            MonoItemPlacement::SingleCgu { ref cgu_name } => {
-                                *cgu_name != *new_codegen_unit.name()
+                            MonoItemPlacement::SingleCgu { cgu_name } => {
+                                cgu_name != new_codegen_unit.name()
                             }
                             MonoItemPlacement::MultipleCgus => true,
                         });
@@ -573,7 +570,7 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<
                     }
                     Entry::Vacant(e) => {
                         e.insert(MonoItemPlacement::SingleCgu {
-                            cgu_name: new_codegen_unit.name().clone()
+                            cgu_name: new_codegen_unit.name()
                         });
                     }
                 }
@@ -638,7 +635,7 @@ fn internalize_symbols<'tcx>(
     // accessed from outside its defining codegen unit.
     for cgu in &mut partitioning.codegen_units {
         let home_cgu = MonoItemPlacement::SingleCgu {
-            cgu_name: cgu.name().clone()
+            cgu_name: cgu.name()
         };
 
         for (accessee, linkage_and_visibility) in cgu.items_mut() {
@@ -717,7 +714,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
     }
 }
 
-type CguNameCache = FxHashMap<(DefId, bool), InternedString>;
+type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
 
 fn compute_codegen_unit_name(
     tcx: TyCtxt<'_>,
@@ -725,7 +722,7 @@ fn compute_codegen_unit_name(
     def_id: DefId,
     volatile: bool,
     cache: &mut CguNameCache,
-) -> InternedString {
+) -> Symbol {
     // Find the innermost module that is not nested within a function.
     let mut current_def_id = def_id;
     let mut cgu_def_id = None;
@@ -762,7 +759,7 @@ fn compute_codegen_unit_name(
         let components = def_path
             .data
             .iter()
-            .map(|part| part.data.as_interned_str());
+            .map(|part| part.data.as_symbol());
 
         let volatile_suffix = if volatile {
             Some("volatile")
@@ -777,7 +774,7 @@ fn compute_codegen_unit_name(
 fn numbered_codegen_unit_name(
     name_builder: &mut CodegenUnitNameBuilder<'_>,
     index: usize,
-) -> InternedString {
+) -> Symbol {
     name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
 }
 
@@ -929,7 +926,7 @@ fn collect_and_partition_mono_items(
             for (&mono_item, &linkage) in cgu.items() {
                 item_to_cgus.entry(mono_item)
                             .or_default()
-                            .push((cgu.name().clone(), linkage));
+                            .push((cgu.name(), linkage));
             }
         }
 
@@ -991,7 +988,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     providers.codegen_unit = |tcx, name| {
         let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
         all.iter()
-            .find(|cgu| *cgu.name() == name)
+            .find(|cgu| cgu.name() == name)
             .cloned()
             .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
     };
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 70855d70228..3ff36e01275 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -12,7 +12,7 @@ use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSA
 use rustc::mir::*;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext};
 
-use syntax::symbol::{InternedString, sym};
+use syntax::symbol::{Symbol, sym};
 
 use std::ops::Bound;
 
@@ -167,9 +167,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     (CastTy::FnPtr, CastTy::Int(_)) => {
                         self.register_violations(&[UnsafetyViolation {
                             source_info: self.source_info,
-                            description: InternedString::intern("cast of pointer to int"),
-                            details: InternedString::intern(
-                                "casting pointers to integers in constants"),
+                            description: Symbol::intern("cast of pointer to int"),
+                            details: Symbol::intern("casting pointers to integers in constants"),
                             kind: UnsafetyViolationKind::General,
                         }], &[]);
                     },
@@ -185,8 +184,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind {
                     self.register_violations(&[UnsafetyViolation {
                         source_info: self.source_info,
-                        description: InternedString::intern("pointer operation"),
-                        details: InternedString::intern("operations on pointers in constants"),
+                        description: Symbol::intern("pointer operation"),
+                        details: Symbol::intern("operations on pointers in constants"),
                         kind: UnsafetyViolationKind::General,
                     }], &[]);
                 }
@@ -219,8 +218,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.source_scope_local_data[source_info.scope].lint_root;
                     self.register_violations(&[UnsafetyViolation {
                         source_info,
-                        description: InternedString::intern("use of extern static"),
-                        details: InternedString::intern(
+                        description: Symbol::intern("use of extern static"),
+                        details: Symbol::intern(
                             "extern statics are not controlled by the Rust type system: \
                             invalid data, aliasing violations or data races will cause \
                             undefined behavior"),
@@ -240,8 +239,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.source_scope_local_data[source_info.scope].lint_root;
                     self.register_violations(&[UnsafetyViolation {
                         source_info,
-                        description: InternedString::intern("borrow of packed field"),
-                        details: InternedString::intern(
+                        description: Symbol::intern("borrow of packed field"),
+                        details: Symbol::intern(
                             "fields of packed structs might be misaligned: dereferencing a \
                             misaligned pointer or even just creating a misaligned reference \
                             is undefined behavior"),
@@ -334,8 +333,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info,
-            description: InternedString::intern(description),
-            details: InternedString::intern(details),
+            description: Symbol::intern(description),
+            details: Symbol::intern(details),
             kind,
         }], &[]);
     }
@@ -438,8 +437,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                                 let source_info = self.source_info;
                                 self.register_violations(&[UnsafetyViolation {
                                     source_info,
-                                    description: InternedString::intern(description),
-                                    details: InternedString::intern(details),
+                                    description: Symbol::intern(description),
+                                    details: Symbol::intern(details),
                                     kind: UnsafetyViolationKind::GeneralAndConstFn,
                                 }], &[]);
                             }
diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs
index 4481892bcf2..8ceb56b0fd2 100644
--- a/src/librustc_plugin/load.rs
+++ b/src/librustc_plugin/load.rs
@@ -1,8 +1,8 @@
 //! Used by `rustc` when loading a plugin.
 
+use rustc::middle::cstore::MetadataLoader;
 use rustc::session::Session;
-use rustc_metadata::creader::CrateLoader;
-use rustc_metadata::cstore::CStore;
+use rustc_metadata::locator;
 use crate::registry::Registry;
 
 use std::borrow::ToOwned;
@@ -25,7 +25,7 @@ pub struct PluginRegistrar {
 
 struct PluginLoader<'a> {
     sess: &'a Session,
-    reader: CrateLoader<'a>,
+    metadata_loader: &'a dyn MetadataLoader,
     plugins: Vec<PluginRegistrar>,
 }
 
@@ -37,11 +37,10 @@ fn call_malformed_plugin_attribute(sess: &Session, span: Span) {
 
 /// Read plugin metadata and dynamically load registrar functions.
 pub fn load_plugins(sess: &Session,
-                    cstore: &CStore,
+                    metadata_loader: &dyn MetadataLoader,
                     krate: &ast::Crate,
-                    crate_name: &str,
                     addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
-    let mut loader = PluginLoader::new(sess, cstore, crate_name);
+    let mut loader = PluginLoader { sess, metadata_loader, plugins: Vec::new() };
 
     // do not report any error now. since crate attributes are
     // not touched by expansion, every use of plugin without
@@ -80,16 +79,8 @@ pub fn load_plugins(sess: &Session,
 }
 
 impl<'a> PluginLoader<'a> {
-    fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self {
-        PluginLoader {
-            sess,
-            reader: CrateLoader::new(sess, cstore, crate_name),
-            plugins: vec![],
-        }
-    }
-
     fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec<ast::NestedMetaItem>) {
-        let registrar = self.reader.find_plugin_registrar(span, name);
+        let registrar = locator::find_plugin_registrar(self.sess, self.metadata_loader, span, name);
 
         if let Some((lib, disambiguator)) = registrar {
             let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator);
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index b826dd91198..2e23b8c870c 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -1,8 +1,7 @@
 //! Used by plugin crates to tell `rustc` about the plugins they provide.
 
-use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
+use rustc::lint::LintStore;
 use rustc::session::Session;
-use rustc::util::nodemap::FxHashMap;
 
 use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
 use syntax_expand::base::MacroExpanderFn;
@@ -26,6 +25,9 @@ pub struct Registry<'a> {
     /// from the plugin registrar.
     pub sess: &'a Session,
 
+    /// The `LintStore` allows plugins to register new lints.
+    pub lint_store: &'a mut LintStore,
+
     #[doc(hidden)]
     pub args_hidden: Option<Vec<ast::NestedMetaItem>>,
 
@@ -36,15 +38,6 @@ pub struct Registry<'a> {
     pub syntax_exts: Vec<NamedSyntaxExtension>,
 
     #[doc(hidden)]
-    pub early_lint_passes: Vec<EarlyLintPassObject>,
-
-    #[doc(hidden)]
-    pub late_lint_passes: Vec<LateLintPassObject>,
-
-    #[doc(hidden)]
-    pub lint_groups: FxHashMap<&'static str, (Vec<LintId>, Option<&'static str>)>,
-
-    #[doc(hidden)]
     pub llvm_passes: Vec<String>,
 
     #[doc(hidden)]
@@ -53,15 +46,13 @@ pub struct Registry<'a> {
 
 impl<'a> Registry<'a> {
     #[doc(hidden)]
-    pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
+    pub fn new(sess: &'a Session, lint_store: &'a mut LintStore, krate_span: Span) -> Registry<'a> {
         Registry {
             sess,
+            lint_store,
             args_hidden: None,
             krate_span,
             syntax_exts: vec![],
-            early_lint_passes: vec![],
-            late_lint_passes: vec![],
-            lint_groups: FxHashMap::default(),
             llvm_passes: vec![],
             attributes: vec![],
         }
@@ -99,27 +90,6 @@ impl<'a> Registry<'a> {
         self.register_syntax_extension(Symbol::intern(name), ext);
     }
 
-    /// Register a compiler lint pass.
-    pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) {
-        self.early_lint_passes.push(lint_pass);
-    }
-
-    /// Register a compiler lint pass.
-    pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) {
-        self.late_lint_passes.push(lint_pass);
-    }
-    /// Register a lint group.
-    pub fn register_lint_group(
-        &mut self,
-        name: &'static str,
-        deprecated_name: Option<&'static str>,
-        to: Vec<&'static Lint>
-    ) {
-        self.lint_groups.insert(name,
-                                (to.into_iter().map(|x| LintId::of(x)).collect(),
-                                 deprecated_name));
-    }
-
     /// Register an LLVM pass.
     ///
     /// Registration with LLVM itself is handled through static C++ objects with
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index e261d3af61f..c0fb8e33a81 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -110,14 +110,14 @@ impl<'a> Resolver<'a> {
         }
 
         let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
-            (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
+            (self.cstore().crate_name_untracked(def_id.krate), None)
         } else {
-            let def_key = self.cstore.def_key(def_id);
+            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(DefKind::Mod, def_id, name.as_symbol());
+        let kind = ModuleKind::Def(DefKind::Mod, def_id, name);
         let module = self.arenas.alloc_module(ModuleData::new(
             parent, kind, def_id, ExpnId::root(), DUMMY_SP
         ));
@@ -153,9 +153,8 @@ impl<'a> Resolver<'a> {
             return Some(ext.clone());
         }
 
-        let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) {
-            LoadedMacro::MacroDef(item) =>
-                self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)),
+        let ext = Lrc::new(match self.cstore().load_macro_untracked(def_id, &self.session) {
+            LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition),
             LoadedMacro::ProcMacro(ext) => ext,
         });
 
@@ -177,7 +176,7 @@ impl<'a> Resolver<'a> {
 
     crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
         let def_id = module.def_id().expect("unpopulated module without a def-id");
-        for child in self.cstore.item_children_untracked(def_id, self.session) {
+        for child in self.cstore().item_children_untracked(def_id, self.session) {
             let child = child.map_id(|_| panic!("unexpected id"));
             BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) }
                 .build_reduced_graph_for_external_crate_res(child);
@@ -885,19 +884,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 bug!("unexpected resolution: {:?}", res)
         }
         // Record some extra data for better diagnostics.
+        let cstore = self.r.cstore();
         match res {
             Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
-                let field_names =
-                    self.r.cstore.struct_field_names_untracked(def_id, self.r.session);
+                let field_names = cstore.struct_field_names_untracked(def_id, self.r.session);
                 self.insert_field_names(def_id, field_names);
             }
             Res::Def(DefKind::Method, def_id) => {
-                if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
+                if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
                     self.r.has_self.insert(def_id);
                 }
             }
             Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
-                let parent = self.r.cstore.def_key(def_id).parent;
+                let parent = cstore.def_key(def_id).parent;
                 if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) {
                     self.r.struct_constructors.insert(struct_def_id, (res, vis));
                 }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 5647d5b2794..7634093fbef 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -367,16 +367,6 @@ impl<'a> Resolver<'a> {
                     span, "`Self` in type parameter default".to_string());
                 err
             }
-            ResolutionError::ConstParamDependentOnTypeParam => {
-                let mut err = struct_span_err!(
-                    self.session,
-                    span,
-                    E0671,
-                    "const parameters cannot depend on type parameters"
-                );
-                err.span_label(span, format!("const parameter depends on type parameter"));
-                err
-            }
         }
     }
 
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index b82cba8c83d..9883a64a1e8 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1831,7 +1831,7 @@ An item usage is ambiguous.
 
 Erroneous code example:
 
-```compile_fail,E0659
+```compile_fail,edition2018,E0659
 pub mod moon {
     pub fn foo() {}
 }
@@ -1841,12 +1841,12 @@ pub mod earth {
 }
 
 mod collider {
-    pub use moon::*;
-    pub use earth::*;
+    pub use crate::moon::*;
+    pub use crate::earth::*;
 }
 
 fn main() {
-    collider::foo(); // ERROR: `foo` is ambiguous
+    crate::collider::foo(); // ERROR: `foo` is ambiguous
 }
 ```
 
@@ -1858,7 +1858,7 @@ functions collide.
 To solve this error, the best solution is generally to keep the path before the
 item when using it. Example:
 
-```
+```edition2018
 pub mod moon {
     pub fn foo() {}
 }
@@ -1868,25 +1868,26 @@ pub mod earth {
 }
 
 mod collider {
-    pub use moon;
-    pub use earth;
+    pub use crate::moon;
+    pub use crate::earth;
 }
 
 fn main() {
-    collider::moon::foo(); // ok!
-    collider::earth::foo(); // ok!
+    crate::collider::moon::foo(); // ok!
+    crate::collider::earth::foo(); // ok!
 }
 ```
 "##,
 
 E0671: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 Const parameters cannot depend on type parameters.
 The following is therefore invalid:
-```compile_fail,E0671
+```compile_fail,E0741
 #![feature(const_generics)]
 
-fn const_id<T, const N: T>() -> T { // error: const parameter
-                                    // depends on type parameter
+fn const_id<T, const N: T>() -> T { // error
     N
 }
 ```
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 73a282b1a0e..136ab1f0444 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -111,9 +111,6 @@ crate enum RibKind<'a> {
     /// from the default of a type parameter because they're not declared
     /// before said type parameter. Also see the `visit_generics` override.
     ForwardTyParamBanRibKind,
-
-    /// We forbid the use of type parameters as the types of const parameters.
-    TyParamAsConstParamTy,
 }
 
 impl RibKind<'_> {
@@ -128,8 +125,7 @@ impl RibKind<'_> {
             | MacroDefinition(_) => false,
             AssocItemRibKind
             | ItemRibKind(_)
-            | ForwardTyParamBanRibKind
-            | TyParamAsConstParamTy => true,
+            | ForwardTyParamBanRibKind => true,
         }
     }
 }
@@ -483,18 +479,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
             default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
         }
 
-        // We also ban access to type parameters for use as the types of const parameters.
-        let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
-        const_ty_param_ban_rib.bindings.extend(generics.params.iter()
-            .filter(|param| {
-                if let GenericParamKind::Type { .. } = param.kind {
-                    true
-                } else {
-                    false
-                }
-            })
-            .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err)));
-
         for param in &generics.params {
             match param.kind {
                 GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
@@ -513,15 +497,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
                     default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
                 }
                 GenericParamKind::Const { ref ty } => {
-                    self.ribs[TypeNS].push(const_ty_param_ban_rib);
-
                     for bound in &param.bounds {
                         self.visit_param_bound(bound);
                     }
-
                     self.visit_ty(ty);
-
-                    const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
                 }
             }
         }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 17d8f0f211a..92392806347 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -21,14 +21,14 @@ use Determinacy::*;
 
 use rustc::hir::map::Definitions;
 use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
-use rustc::middle::cstore::CrateStore;
+use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
 use rustc::session::Session;
 use rustc::lint;
 use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap};
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::{TraitMap, GlobMap};
-use rustc::ty::{self, DefIdTree};
+use rustc::ty::{self, DefIdTree, ResolverOutputs};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 use rustc::span_bug;
 
@@ -215,8 +215,6 @@ enum ResolutionError<'a> {
     ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
     /// Error E0735: type parameters with a default cannot use `Self`
     SelfInTyParamDefault,
-    /// Error E0671: const parameter cannot depend on type parameter.
-    ConstParamDependentOnTypeParam,
 }
 
 // A minimal representation of a path segment. We use this in resolve because
@@ -829,14 +827,13 @@ pub struct ExternPreludeEntry<'a> {
 /// This is the visitor that walks the whole crate.
 pub struct Resolver<'a> {
     session: &'a Session,
-    cstore: &'a CStore,
 
-    pub definitions: Definitions,
+    definitions: Definitions,
 
-    pub graph_root: Module<'a>,
+    graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
-    pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
+    extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
 
     /// N.B., this is used only for better diagnostics, not name resolution itself.
     has_self: FxHashSet<DefId>,
@@ -869,9 +866,9 @@ pub struct Resolver<'a> {
     label_res_map: NodeMap<NodeId>,
 
     /// `CrateNum` resolutions of `extern crate` items.
-    pub extern_crate_map: NodeMap<CrateNum>,
-    pub export_map: ExportMap<NodeId>,
-    pub trait_map: TraitMap,
+    extern_crate_map: NodeMap<CrateNum>,
+    export_map: ExportMap<NodeId>,
+    trait_map: TraitMap,
 
     /// A map from nodes to anonymous modules.
     /// Anonymous modules are pseudo-modules that are implicitly created around items
@@ -898,11 +895,11 @@ pub struct Resolver<'a> {
     underscore_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
-    pub glob_map: GlobMap,
+    glob_map: GlobMap,
 
     used_imports: FxHashSet<(NodeId, Namespace)>,
-    pub maybe_unused_trait_imports: NodeSet,
-    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
+    maybe_unused_trait_imports: NodeSet,
+    maybe_unused_extern_crates: Vec<(NodeId, Span)>,
 
     /// Privacy errors are delayed until the end in order to deduplicate them.
     privacy_errors: Vec<PrivacyError<'a>>,
@@ -916,11 +913,11 @@ pub struct Resolver<'a> {
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
 
-    crate_loader: &'a CrateLoader<'a>,
+    crate_loader: CrateLoader<'a>,
     macro_names: FxHashSet<Ident>,
     builtin_macros: FxHashMap<Name, SyntaxExtension>,
     macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
-    pub all_macros: FxHashMap<Name, Res>,
+    all_macros: FxHashMap<Name, Res>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
     dummy_ext_bang: Lrc<SyntaxExtension>,
     dummy_ext_derive: Lrc<SyntaxExtension>,
@@ -1015,7 +1012,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
     fn parent(self, id: DefId) -> Option<DefId> {
         match id.krate {
             LOCAL_CRATE => self.definitions.def_key(id.index).parent,
-            _ => self.cstore.def_key(id).parent,
+            _ => self.cstore().def_key(id).parent,
         }.map(|index| DefId { index, ..id })
     }
 }
@@ -1023,6 +1020,10 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
 /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
 /// the resolver is no longer needed as all the relevant information is inline.
 impl<'a> hir::lowering::Resolver for Resolver<'a> {
+    fn cstore(&self) -> &dyn CrateStore {
+        self.cstore()
+    }
+
     fn resolve_str_path(
         &mut self,
         span: Span,
@@ -1083,10 +1084,9 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
 
 impl<'a> Resolver<'a> {
     pub fn new(session: &'a Session,
-               cstore: &'a CStore,
                krate: &Crate,
                crate_name: &str,
-               crate_loader: &'a CrateLoader<'a>,
+               metadata_loader: &'a MetadataLoaderDyn,
                arenas: &'a ResolverArenas<'a>)
                -> Resolver<'a> {
         let root_def_id = DefId::local(CRATE_DEF_INDEX);
@@ -1147,8 +1147,6 @@ impl<'a> Resolver<'a> {
         Resolver {
             session,
 
-            cstore,
-
             definitions,
 
             // The outermost module has def ID 0; this is not reflected in the
@@ -1202,7 +1200,7 @@ impl<'a> Resolver<'a> {
                 vis: ty::Visibility::Public,
             }),
 
-            crate_loader,
+            crate_loader: CrateLoader::new(session, metadata_loader, crate_name),
             macro_names: FxHashSet::default(),
             builtin_macros: Default::default(),
             macro_use_prelude: FxHashMap::default(),
@@ -1236,6 +1234,42 @@ impl<'a> Resolver<'a> {
         Default::default()
     }
 
+    pub fn into_outputs(self) -> ResolverOutputs {
+        ResolverOutputs {
+            definitions: self.definitions,
+            cstore: Box::new(self.crate_loader.into_cstore()),
+            extern_crate_map: self.extern_crate_map,
+            export_map: self.export_map,
+            trait_map: self.trait_map,
+            glob_map: self.glob_map,
+            maybe_unused_trait_imports: self.maybe_unused_trait_imports,
+            maybe_unused_extern_crates: self.maybe_unused_extern_crates,
+            extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| {
+                (ident.name, entry.introduced_by_item)
+            }).collect(),
+        }
+    }
+
+    pub fn clone_outputs(&self) -> ResolverOutputs {
+        ResolverOutputs {
+            definitions: self.definitions.clone(),
+            cstore: Box::new(self.cstore().clone()),
+            extern_crate_map: self.extern_crate_map.clone(),
+            export_map: self.export_map.clone(),
+            trait_map: self.trait_map.clone(),
+            glob_map: self.glob_map.clone(),
+            maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(),
+            maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(),
+            extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| {
+                (ident.name, entry.introduced_by_item)
+            }).collect(),
+        }
+    }
+
+    pub fn cstore(&self) -> &CStore {
+        self.crate_loader.cstore()
+    }
+
     fn non_macro_attr(&self, mark_used: bool) -> Lrc<SyntaxExtension> {
         self.non_macro_attrs[mark_used as usize].clone()
     }
@@ -2169,15 +2203,6 @@ impl<'a> Resolver<'a> {
             return Res::Err;
         }
 
-        // An invalid use of a type parameter as the type of a const parameter.
-        if let TyParamAsConstParamTy = all_ribs[rib_index].kind {
-            if record_used {
-                self.report_error(span, ResolutionError::ConstParamDependentOnTypeParam);
-            }
-            assert_eq!(res, Res::Err);
-            return Res::Err;
-        }
-
         match res {
             Res::Local(_) => {
                 use ResolutionError::*;
@@ -2186,7 +2211,7 @@ impl<'a> Resolver<'a> {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
-                        ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
+                        ForwardTyParamBanRibKind => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => {
@@ -2220,7 +2245,7 @@ impl<'a> Resolver<'a> {
                     let has_generic_params = match rib.kind {
                         NormalRibKind | AssocItemRibKind |
                         ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
-                        ConstantItemRibKind | TyParamAsConstParamTy => {
+                        ConstantItemRibKind => {
                             // Nothing to do. Continue.
                             continue;
                         }
@@ -2808,6 +2833,16 @@ impl<'a> Resolver<'a> {
         seg.id = self.session.next_node_id();
         seg
     }
+
+    // For rustdoc.
+    pub fn graph_root(&self) -> Module<'a> {
+        self.graph_root
+    }
+
+    // For rustdoc.
+    pub fn all_macros(&self) -> &FxHashMap<Name, Res> {
+        &self.all_macros
+    }
 }
 
 fn names_to_string(names: &[Name]) -> String {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 34edd5eaf4f..31340ddd683 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1344,7 +1344,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 if res != Res::Err {
                     if let Some(def_id) = res.opt_def_id() {
                         if !def_id.is_local() {
-                            this.cstore.export_macros_untracked(def_id.krate);
+                            this.cstore().export_macros_untracked(def_id.krate);
                         }
                     }
                     reexports.push(Export {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 8eab9c4e67e..79dc4f7e136 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -131,7 +131,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     {
         let tcx = self.tcx();
         let lifetime_name = |def_id| {
-            tcx.hir().name(tcx.hir().as_local_hir_id(def_id).unwrap()).as_interned_str()
+            tcx.hir().name(tcx.hir().as_local_hir_id(def_id).unwrap())
         };
 
         let r = match tcx.named_region(lifetime.hir_id) {
@@ -1274,8 +1274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     span,
                     item.trait_ref().def_id(),
                     object_safety_violations
-                )
-                    .map(|mut err| err.emit());
+                ).emit();
                 return tcx.types.err;
             }
         }
@@ -2023,7 +2022,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let item_def_id = tcx.hir().local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.param_def_id_to_index[&def_id];
-                tcx.mk_ty_param(index, tcx.hir().name(hir_id).as_interned_str())
+                tcx.mk_ty_param(index, tcx.hir().name(hir_id))
             }
             Res::SelfTy(Some(_), None) => {
                 // `Self` in trait or type alias.
@@ -2204,7 +2203,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let item_def_id = tcx.hir().local_def_id(item_id);
             let generics = tcx.generics_of(item_def_id);
             let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)];
-            let name = tcx.hir().name(hir_id).as_interned_str();
+            let name = tcx.hir().name(hir_id);
             const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
         }
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index dfeb5fb958c..9cbde276ae9 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -428,21 +428,36 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             self.report_cast_to_unsized_type(fcx);
         } else if self.expr_ty.references_error() || self.cast_ty.references_error() {
             // No sense in giving duplicate error messages
-        } else if self.try_coercion_cast(fcx) {
-            self.trivial_cast_lint(fcx);
-            debug!(" -> CoercionCast");
-            fcx.tables.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id);
-
         } else {
-            match self.do_check(fcx) {
-                Ok(k) => {
-                    debug!(" -> {:?}", k);
+            match self.try_coercion_cast(fcx) {
+                Ok(()) => {
+                    self.trivial_cast_lint(fcx);
+                    debug!(" -> CoercionCast");
+                    fcx.tables.borrow_mut()
+                        .set_coercion_cast(self.expr.hir_id.local_id);
+                }
+                Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => {
+                    self.report_object_unsafe_cast(&fcx, did);
+                }
+                Err(_) => {
+                    match self.do_check(fcx) {
+                        Ok(k) => {
+                            debug!(" -> {:?}", k);
+                        }
+                        Err(e) => self.report_cast_error(fcx, e),
+                    };
                 }
-                Err(e) => self.report_cast_error(fcx, e),
             };
         }
     }
 
+    fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) {
+        let violations = fcx.tcx.object_safety_violations(did);
+        let mut err = fcx.tcx.report_object_safety_error(self.cast_span, did, violations);
+        err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty)));
+        err.emit();
+    }
+
     /// Checks a cast, and report an error if one exists. In some cases, this
     /// can return Ok and create type errors in the fcx rather than returning
     /// directly. coercion-cast is handled in check instead of here.
@@ -646,8 +661,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         }
     }
 
-    fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool {
-        fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok()
+    fn try_coercion_cast(
+        &self,
+        fcx: &FnCtxt<'a, 'tcx>,
+    ) -> Result<(), ty::error::TypeError<'_>> {
+        match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) {
+            Ok(_) => Ok(()),
+            Err(err) => Err(err),
+        }
     }
 }
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index bfccb032458..f79351dc903 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -61,10 +61,11 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast
 };
-use rustc::ty::{self, TypeAndMut, Ty, subst::SubstsRef};
+use rustc::ty::{self, TypeAndMut, Ty};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::error::TypeError;
 use rustc::ty::relate::RelateResult;
+use rustc::ty::subst::SubstsRef;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
 use syntax::feature_gate;
@@ -196,9 +197,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // a "spurious" type variable, and we don't want to have that
         // type variable in memory if the coercion fails.
         let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
-        if unsize.is_ok() {
-            debug!("coerce: unsize successful");
-            return unsize;
+        match unsize {
+            Ok(_) => {
+                debug!("coerce: unsize successful");
+                return unsize;
+            }
+            Err(TypeError::ObjectUnsafeCoercion(did)) => {
+                debug!("coerce: unsize not object safe");
+                return Err(TypeError::ObjectUnsafeCoercion(did));
+            }
+            Err(_) => {}
         }
         debug!("coerce: unsize failed");
 
@@ -539,7 +547,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         let mut selcx = traits::SelectionContext::new(self);
 
         // Create an obligation for `Source: CoerceUnsized<Target>`.
-        let cause = ObligationCause::misc(self.cause.span, self.body_id);
+        let cause = ObligationCause::new(
+            self.cause.span,
+            self.body_id,
+            ObligationCauseCode::Coercion { source, target },
+        );
 
         // Use a FIFO queue for this custom fulfillment procedure.
         //
@@ -566,14 +578,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             let obligation = queue.remove(0);
             debug!("coerce_unsized resolve step: {:?}", obligation);
             let trait_ref = match obligation.predicate {
-                ty::Predicate::Trait(ref t) if traits.contains(&t.def_id()) => {
-                    if unsize_did == t.def_id() {
-                        if let ty::Tuple(..) = &t.skip_binder().input_types().nth(1).unwrap().kind {
+                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
+                    if unsize_did == tr.def_id() {
+                        let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind;
+                        if let ty::Tuple(..) = sty {
                             debug!("coerce_unsized: found unsized tuple coercion");
                             has_unsized_tuple_coercion = true;
                         }
                     }
-                    t.clone()
+                    tr.clone()
                 }
                 _ => {
                     coercion.obligations.push(obligation);
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index f5f85bbcb10..8668dd99a8c 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -566,7 +566,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // the `enclosing_loops` field and let's coerce the
             // type of `expr_opt` into what is expected.
             let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
-            let ctxt = enclosing_breakables.find_breakable(target_id);
+            let ctxt = match enclosing_breakables.opt_find_breakable(target_id) {
+                Some(ctxt) => ctxt,
+                None => { // Avoid ICE when `break` is inside a closure (#65383).
+                    self.tcx.sess.delay_span_bug(
+                        expr.span,
+                        "break was outside loop, but no error was emitted",
+                    );
+                    return tcx.types.err;
+                }
+            };
+
             if let Some(ref mut coerce) = ctxt.coerce {
                 if let Some(ref e) = expr_opt {
                     coerce.coerce(self, &cause, e, e_ty);
@@ -592,7 +602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             } else {
                 // If `ctxt.coerce` is `None`, we can just ignore
-                // the type of the expresison.  This is because
+                // the type of the expression.  This is because
                 // either this was a break *without* a value, in
                 // which case it is always a legal type (`()`), or
                 // else an error would have been flagged by the
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index aeb2c40e2ef..72a0fe887b9 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -7,7 +7,7 @@ use rustc::ty::subst::Subst;
 use crate::require_same_types;
 
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::InternedString;
+use syntax::symbol::Symbol;
 
 use rustc::hir;
 
@@ -80,7 +80,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
 /// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n)));
+    let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
     let name = it.ident.as_str();
 
     let mk_va_list_ty = |mutbl| {
@@ -387,7 +387,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
 pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
     let param = |n| {
-        let name = InternedString::intern(&format!("P{}", n));
+        let name = Symbol::intern(&format!("P{}", n));
         tcx.mk_ty_param(n, name)
     };
 
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 9baf06be3f6..59636d32bc0 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -141,14 +141,24 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     ///////////////////////////////////////////////////////////////////////////
     // ADJUSTMENTS
 
-    fn adjust_self_ty(&mut self,
-                      unadjusted_self_ty: Ty<'tcx>,
-                      pick: &probe::Pick<'tcx>)
-                      -> Ty<'tcx> {
+    fn adjust_self_ty(
+        &mut self,
+        unadjusted_self_ty: Ty<'tcx>,
+        pick: &probe::Pick<'tcx>,
+    ) -> Ty<'tcx> {
         // Commit the autoderefs by calling `autoderef` again, but this
         // time writing the results into the various tables.
         let mut autoderef = self.autoderef(self.span, unadjusted_self_ty);
-        let (_, n) = autoderef.nth(pick.autoderefs).unwrap();
+        let (_, n) = match autoderef.nth(pick.autoderefs) {
+            Some(n) => n,
+            None => {
+                self.tcx.sess.delay_span_bug(
+                    syntax_pos::DUMMY_SP,
+                    &format!("failed autoderef {}", pick.autoderefs),
+                );
+                return self.tcx.types.err;
+            }
+        };
         assert_eq!(n, pick.autoderefs);
 
         let mut adjustments = autoderef.adjust_steps(self, Needs::None);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 73a025182a7..96a097695fa 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -536,10 +536,16 @@ pub struct EnclosingBreakables<'tcx> {
 
 impl<'tcx> EnclosingBreakables<'tcx> {
     fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
-        let ix = *self.by_id.get(&target_id).unwrap_or_else(|| {
+        self.opt_find_breakable(target_id).unwrap_or_else(|| {
             bug!("could not find enclosing breakable with id {}", target_id);
-        });
-        &mut self.stack[ix]
+        })
+    }
+
+    fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
+        match self.by_id.get(&target_id) {
+            Some(ix) => Some(&mut self.stack[*ix]),
+            None => None,
+        }
     }
 }
 
@@ -2761,8 +2767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut opaque_types = self.opaque_types.borrow_mut();
         for (ty, decl) in opaque_type_map {
-            let old_value = opaque_types.insert(ty, decl);
-            assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl);
+            let _ = opaque_types.insert(ty, decl);
         }
 
         value
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index a44c475e0f8..8adf4bb94a8 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -183,8 +183,11 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
 
         for component_def_id in component_def_ids {
             if !tcx.is_object_safe(component_def_id) {
-                // This is an error, but it will be reported by wfcheck.  Ignore it here.
+                // Without the 'object_safe_for_dispatch' feature this is an error
+                // which will be reported by wfcheck.  Ignore it here.
                 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
+                // With the feature enabled, the trait is not implemented automatically,
+                // so this is valid.
             } else {
                 let mut supertrait_def_ids =
                     traits::supertrait_def_ids(tcx, component_def_id);
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 1749fd1075e..00435d67184 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -36,7 +36,7 @@ use syntax::ast;
 use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used};
 use syntax::feature_gate;
-use syntax::symbol::{InternedString, kw, Symbol, sym};
+use syntax::symbol::{kw, Symbol, sym};
 use syntax_pos::{Span, DUMMY_SP};
 
 use rustc::hir::def::{CtorKind, Res, DefKind};
@@ -265,7 +265,7 @@ fn type_param_predicates(
     let param_owner_def_id = tcx.hir().local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
     let index = generics.param_def_id_to_index[&def_id];
-    let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id).as_interned_str());
+    let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id));
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -961,7 +961,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
 
                     opt_self = Some(ty::GenericParamDef {
                         index: 0,
-                        name: kw::SelfUpper.as_interned_str(),
+                        name: kw::SelfUpper,
                         def_id: tcx.hir().local_def_id(param_id),
                         pure_wrt_drop: false,
                         kind: ty::GenericParamDefKind::Type {
@@ -1006,7 +1006,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
         early_lifetimes
             .enumerate()
             .map(|(i, param)| ty::GenericParamDef {
-                name: param.name.ident().as_interned_str(),
+                name: param.name.ident().name,
                 index: own_start + i as u32,
                 def_id: tcx.hir().local_def_id(param.hir_id),
                 pure_wrt_drop: param.pure_wrt_drop,
@@ -1060,7 +1060,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
 
                 let param_def = ty::GenericParamDef {
                     index: type_start + i as u32,
-                    name: param.name.ident().as_interned_str(),
+                    name: param.name.ident().name,
                     def_id: tcx.hir().local_def_id(param.hir_id),
                     pure_wrt_drop: param.pure_wrt_drop,
                     kind,
@@ -1090,7 +1090,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
                 .enumerate()
                 .map(|(i, &arg)| ty::GenericParamDef {
                     index: type_start + i as u32,
-                    name: InternedString::intern(arg),
+                    name: Symbol::intern(arg),
                     def_id,
                     pure_wrt_drop: false,
                     kind: ty::GenericParamDefKind::Type {
@@ -1105,7 +1105,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
             params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
                 ty::GenericParamDef {
                     index: type_start + i,
-                    name: InternedString::intern("<upvar>"),
+                    name: Symbol::intern("<upvar>"),
                     def_id,
                     pure_wrt_drop: false,
                     kind: ty::GenericParamDefKind::Type {
@@ -1532,6 +1532,17 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                         );
                     };
                 }
+                if ty::search_for_structural_match_violation(tcx, ty).is_some() {
+                    struct_span_err!(
+                        tcx.sess,
+                        hir_ty.span,
+                        E0741,
+                        "the types of const generic parameters must derive `PartialEq` and `Eq`",
+                    ).span_label(
+                        hir_ty.span,
+                        format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
+                    ).emit();
+                }
                 ty
             }
             x => {
@@ -2198,7 +2209,7 @@ fn explicit_predicates_of(
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: tcx.hir().local_def_id(param.hir_id),
             index,
-            name: param.name.ident().as_interned_str(),
+            name: param.name.ident().name,
         }));
         index += 1;
 
@@ -2221,7 +2232,7 @@ fn explicit_predicates_of(
     // type parameter (e.g., `<T: Foo>`).
     for param in &ast_generics.params {
         if let GenericParamKind::Type { .. } = param.kind {
-            let name = param.name.ident().as_interned_str();
+            let name = param.name.ident().name;
             let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
             index += 1;
 
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index 3ecbf620cbc..75b508a1bbf 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -194,7 +194,7 @@ a guard.
 ```compile_fail,E0029
 let string = "salutations !";
 
-// The ordering relation for strings can't be evaluated at compile time,
+// The ordering relation for strings cannot be evaluated at compile time,
 // so this doesn't work:
 match string {
     "hello" ..= "world" => {}
@@ -348,7 +348,7 @@ fn main() {
 "##,
 
 E0044: r##"
-You can't use type or const parameters on foreign items.
+You cannot use type or const parameters on foreign items.
 Example of erroneous code:
 
 ```compile_fail,E0044
@@ -788,7 +788,7 @@ fn some_other_func() {}
 fn some_function() {
     SOME_CONST = 14; // error : a constant value cannot be changed!
     1 = 3; // error : 1 isn't a valid place!
-    some_other_func() = 4; // error : we can't assign value to a function!
+    some_other_func() = 4; // error : we cannot assign value to a function!
     SomeStruct.x = 12; // error : SomeStruct a structure name but it is used
                        // like a variable!
 }
@@ -3891,6 +3891,33 @@ details.
 [issue #33685]: https://github.com/rust-lang/rust/issues/33685
 "##,
 
+E0588: r##"
+A type with `packed` representation hint has a field with `align`
+representation hint.
+
+Erroneous code example:
+
+```compile_fail,E0588
+#[repr(align(16))]
+struct Aligned(i32);
+
+#[repr(packed)] // error!
+struct Packed(Aligned);
+```
+
+Just like you cannot have both `align` and `packed` representation hints on a
+same type, a `packed` type cannot contain another type with the `align`
+representation hint. However, you can do the opposite:
+
+```
+#[repr(packed)]
+struct Packed(i32);
+
+#[repr(align(16))] // ok!
+struct Aligned(Packed);
+```
+"##,
+
 E0592: r##"
 This error occurs when you defined methods or associated functions with same
 name.
@@ -4299,7 +4326,7 @@ extern {
 
 unsafe {
     printf(::std::ptr::null(), 0f32);
-    // error: can't pass an `f32` to variadic function, cast to `c_double`
+    // error: cannot pass an `f32` to variadic function, cast to `c_double`
 }
 ```
 
@@ -4978,6 +5005,30 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC.
 [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
 "##,
 
+E0741: r##"
+Only `structural_match` types (that is, types that derive `PartialEq` and `Eq`)
+may be used as the types of const generic parameters.
+
+```compile_fail,E0741
+#![feature(const_generics)]
+
+struct A;
+
+struct B<const X: A>; // error!
+```
+
+To fix this example, we derive `PartialEq` and `Eq`.
+
+```
+#![feature(const_generics)]
+
+#[derive(PartialEq, Eq)]
+struct A;
+
+struct B<const X: A>; // ok!
+```
+"##,
+
 ;
 //  E0035, merged into E0087/E0089
 //  E0036, merged into E0087/E0089
@@ -5000,7 +5051,7 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC.
 //  E0174,
 //  E0182, // merged into E0229
     E0183,
-//  E0187, // can't infer the kind of the closure
+//  E0187, // cannot infer the kind of the closure
 //  E0188, // can not cast an immutable reference to a mutable pointer
 //  E0189, // deprecated: can only cast a boxed pointer to a boxed object
 //  E0190, // deprecated: can only cast a &-pointer to an &-object
@@ -5047,7 +5098,6 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC.
 //  E0564, // only named lifetimes are allowed in `impl Trait`,
            // but `{}` was found in the type `{}`
     E0587, // type has conflicting packed and align representation hints
-    E0588, // packed type cannot transitively contain a `[repr(align)]` type
 //  E0611, // merged into E0616
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index e7cc8b76e48..a6a8fec429e 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -479,8 +479,8 @@ fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static
 
 fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemEnum {
     let imported_from = cx.tcx.original_crate_name(did.krate);
-    match cx.cstore.load_macro_untracked(did, cx.sess()) {
-        LoadedMacro::MacroDef(def) => {
+    match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
+        LoadedMacro::MacroDef(def, _) => {
             let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.kind {
                 let tts: Vec<_> = def.stream().into_trees().collect();
                 tts.chunks(4).map(|arm| arm[0].span()).collect()
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 09c9757dc4d..abc8b831449 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -31,7 +31,6 @@ use syntax::attr;
 use syntax_expand::base::MacroKind;
 use syntax::source_map::DUMMY_SP;
 use syntax::symbol::{Symbol, kw, sym};
-use syntax::symbol::InternedString;
 use syntax_pos::{self, Pos, FileName};
 
 use std::collections::hash_map::Entry;
@@ -1682,7 +1681,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
             .filter_map(|param| match param.kind {
                 ty::GenericParamDefKind::Lifetime => None,
                 ty::GenericParamDefKind::Type { synthetic, .. } => {
-                    if param.name.as_symbol() == kw::SelfUpper {
+                    if param.name == kw::SelfUpper {
                         assert_eq!(param.index, 0);
                         return None;
                     }
@@ -3701,13 +3700,6 @@ impl Clean<String> for ast::Name {
     }
 }
 
-impl Clean<String> for InternedString {
-    #[inline]
-    fn clean(&self, _: &DocContext<'_>) -> String {
-        self.to_string()
-    }
-}
-
 #[derive(Clone, Debug)]
 pub struct Typedef {
     pub type_: Type,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 2337ec5a52c..b227f432a4e 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -5,14 +5,13 @@ use rustc::hir::HirId;
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{Ty, TyCtxt};
-use rustc::lint::{self, LintPass};
+use rustc::lint;
 use rustc::session::config::ErrorOutputType;
 use rustc::session::DiagnosticOutput;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_interface::interface;
 use rustc_driver::abort_on_err;
 use rustc_resolve as resolve;
-use rustc_metadata::cstore::CStore;
 
 use syntax::source_map;
 use syntax::attr;
@@ -43,7 +42,6 @@ pub struct DocContext<'tcx> {
 
     pub tcx: TyCtxt<'tcx>,
     pub resolver: Rc<RefCell<interface::BoxedResolver>>,
-    pub cstore: Lrc<CStore>,
     /// Later on moved into `html::render::CACHE_KEY`
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
@@ -117,9 +115,7 @@ impl<'tcx> DocContext<'tcx> {
                     .def_path_table()
                     .next_id()
             } else {
-                self.cstore
-                    .def_path_table(crate_num)
-                    .next_id()
+                self.enter_resolver(|r| r.cstore().def_path_table(crate_num).next_id())
             };
 
             DefId {
@@ -273,10 +269,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
     whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
 
     let lints = || {
-        lint::builtin::HardwiredLints
-            .get_lints()
+        lint::builtin::HardwiredLints::get_lints()
             .into_iter()
-            .chain(rustc_lint::SoftLints.get_lints().into_iter())
+            .chain(rustc_lint::SoftLints::get_lints().into_iter())
     };
 
     let lint_opts = lints().filter_map(|lint| {
@@ -339,6 +334,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         stderr: None,
         crate_name,
         lint_caps,
+        register_lints: None,
     };
 
     interface::run_compiler_in_existing_thread_pool(config, |compiler| {
@@ -376,7 +372,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
             let mut ctxt = DocContext {
                 tcx,
                 resolver,
-                cstore: compiler.cstore().clone(),
                 external_traits: Default::default(),
                 active_extern_traits: Default::default(),
                 renderinfo: RefCell::new(renderinfo),
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 0dc094ae329..bbc00147ee1 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -59,7 +59,7 @@ impl Module<'hir> {
             fns        :   Vec::new(),
             mods       :   Vec::new(),
             typedefs   :   Vec::new(),
-            opaque_tys :  Vec::new(),
+            opaque_tys :   Vec::new(),
             statics    :   Vec::new(),
             constants  :   Vec::new(),
             traits     :   Vec::new(),
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 72a72e89281..414c3137376 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1241,6 +1241,7 @@ fn settings(root_path: &str, suffix: &str) -> String {
         ("go-to-only-result", "Directly go to item in search if there is only one result",
             false),
         ("line-numbers", "Show line numbers on code examples", false),
+        ("disable-shortcuts", "Disable keyboard shortcuts", false),
     ];
     format!(
 "<h1 class='fqn'>\
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 17a940cc4c9..f0104c9156d 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -79,6 +79,7 @@ function getSearchElement() {
                      "derive",
                      "traitalias"];
 
+    var disableShortcuts = getCurrentValue("rustdoc-disable-shortcuts") !== "true";
     var search_input = getSearchInput();
 
     // On the search screen, so you remain on the last tab you opened.
@@ -294,7 +295,7 @@ function getSearchElement() {
 
     function handleShortcut(ev) {
         // Don't interfere with browser shortcuts
-        if (ev.ctrlKey || ev.altKey || ev.metaKey) {
+        if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) {
             return;
         }
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 4270b162baf..caa7f08f68c 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -432,13 +432,13 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
     let path = ast::Path::from_ident(Ident::from_str(path_str));
     cx.enter_resolver(|resolver| {
         if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
-            &path, None, &ParentScope::module(resolver.graph_root), false, false
+            &path, None, &ParentScope::module(resolver.graph_root()), false, false
         ) {
             if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
                 return Some(res.map_id(|_| panic!("unexpected id")));
             }
         }
-        if let Some(res) = resolver.all_macros.get(&Symbol::intern(path_str)) {
+        if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
             return Some(res.map_id(|_| panic!("unexpected id")));
         }
         None
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 8afc50f83bf..07dc1e4e915 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -77,6 +77,7 @@ pub fn run(options: Options) -> i32 {
         stderr: None,
         crate_name: options.crate_name.clone(),
         lint_caps: Default::default(),
+        register_lints: None,
     };
 
     let mut test_args = options.test_args.clone();
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 9bf5caf0363..c55911a33f5 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -23,7 +23,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of
 compiler_builtins = { version = "0.1.16" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
-hashbrown = { version = "0.6.1", default-features = false, features = ['rustc-dep-of-std'] }
+hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-dep-of-std'] }
 
 [dependencies.backtrace_rs]
 package = "backtrace"
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 93d3e4ea3df..d0cb0104f6c 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -276,6 +276,7 @@
 #![feature(linkage)]
 #![feature(log_syntax)]
 #![feature(manually_drop_take)]
+#![feature(matches_macro)]
 #![feature(maybe_uninit_ref)]
 #![feature(maybe_uninit_slice)]
 #![feature(needs_panic_runtime)]
@@ -527,6 +528,7 @@ pub use core::{
     writeln,
     // Unstable
     todo,
+    matches,
 };
 
 // Re-export built-in macros defined through libcore.
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 2dde81bb0ec..619b1820190 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -217,7 +217,7 @@ pub fn update_panic_count(amt: isize) -> usize {
     PANIC_COUNT.with(|c| {
         let next = (c.get() as isize + amt) as usize;
         c.set(next);
-        return next
+        next
     })
 }
 
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index c5be1763302..be112f6fc03 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -8,7 +8,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
                                              mem::size_of_val(&v));
         imp::fill_bytes(view);
     }
-    return v
+    v
 }
 
 #[cfg(all(unix,
diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
index 28a504f1979..6ce41420284 100644
--- a/src/libstd/sys/wasi/thread.rs
+++ b/src/libstd/sys/wasi/thread.rs
@@ -31,10 +31,10 @@ impl Thread {
         let nanos = dur.as_nanos();
         assert!(nanos <= u64::max_value() as u128);
 
-        const CLOCK_ID: wasi::Userdata = 0x0123_45678;
+        const USERDATA: wasi::Userdata = 0x0123_45678;
 
         let clock = wasi::raw::__wasi_subscription_u_clock_t {
-            identifier: CLOCK_ID,
+            identifier: 0,
             clock_id: wasi::CLOCK_MONOTONIC,
             timeout: nanos as u64,
             precision: 0,
@@ -42,7 +42,7 @@ impl Thread {
         };
 
         let in_ = [wasi::Subscription {
-            userdata: 0,
+            userdata: USERDATA,
             type_: wasi::EVENTTYPE_CLOCK,
             u: wasi::raw::__wasi_subscription_u { clock: clock },
         }];
@@ -53,7 +53,7 @@ impl Thread {
         };
         match (res, event) {
             (Ok(1), wasi::Event {
-                userdata: CLOCK_ID,
+                userdata: USERDATA,
                 error: 0,
                 type_: wasi::EVENTTYPE_CLOCK,
                 ..
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 3e5aa693354..3986cda1a50 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -46,7 +46,7 @@ impl Handle {
     pub fn into_raw(self) -> c::HANDLE {
         let ret = self.raw();
         mem::forget(self);
-        return ret;
+        ret
     }
 }
 
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 37cbdcefced..79dec1adf4b 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -144,7 +144,7 @@ fn kind() -> Kind {
         Some(..) => Kind::SRWLock,
     };
     KIND.store(ret as usize, Ordering::SeqCst);
-    return ret;
+    ret
 }
 
 pub struct ReentrantMutex { inner: UnsafeCell<MaybeUninit<c::CRITICAL_SECTION>> }
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 8658deb8546..096b7bea8a5 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -257,7 +257,7 @@ impl Stdio {
                         let ret = io.duplicate(0, true,
                                                c::DUPLICATE_SAME_ACCESS);
                         io.into_raw();
-                        return ret
+                        ret
                     }
                     Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)),
                 }
@@ -472,9 +472,8 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
             cmd.push('"' as u16);
         }
 
-        let mut iter = arg.encode_wide();
         let mut backslashes: usize = 0;
-        while let Some(x) = iter.next() {
+        for x in arg.encode_wide() {
             if x == '\\' as u16 {
                 backslashes += 1;
             } else {
diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs
index c9bcb5d7415..993831bec18 100644
--- a/src/libstd/sys/windows/rand.rs
+++ b/src/libstd/sys/windows/rand.rs
@@ -13,7 +13,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
         panic!("couldn't generate random bytes: {}",
                io::Error::last_os_error());
     }
-    return v
+    v
 }
 
 #[cfg(target_vendor = "uwp")]
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index 4c9734fa0aa..728257cdd4b 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -52,7 +52,7 @@ pub unsafe fn create(dtor: Option<Dtor>) -> Key {
     if let Some(f) = dtor {
         register_dtor(key, f);
     }
-    return key;
+    key
 }
 
 #[inline]
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index e0f0e3a1a45..bd533c93d43 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -80,7 +80,7 @@ impl SystemTime {
         unsafe {
             let mut t: SystemTime = mem::zeroed();
             c::GetSystemTimeAsFileTime(&mut t.t);
-            return t
+            t
         }
     }
 
@@ -228,7 +228,7 @@ mod perf_counter {
                 FREQUENCY = frequency;
                 STATE.store(2, SeqCst);
             }
-            return frequency;
+            frequency
         }
     }
 
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index e92c0d1c58e..cfaab4e22e9 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -509,9 +509,8 @@ pub mod os {
         pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> {
             let ptr = self.os.get() as *mut Value<T>;
             if ptr as usize > 1 {
-                match (*ptr).inner.get() {
-                    Some(ref value) => return Some(value),
-                    None => {},
+                if let Some(ref value) = (*ptr).inner.get() {
+                    return Some(value);
                 }
             }
             self.try_initialize(init)
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 8be7f4478fa..51a62cd0658 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1305,7 +1305,8 @@ impl MacroDef {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+// Clippy uses Hash and PartialEq
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)]
 pub enum StrStyle {
     /// A regular string, like `"foo"`.
     Cooked,
@@ -1327,7 +1328,8 @@ pub struct Lit {
     pub span: Span,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+// Clippy uses Hash and PartialEq
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)]
 pub enum LitIntType {
     Signed(IntTy),
     Unsigned(UintTy),
@@ -1337,7 +1339,8 @@ pub enum LitIntType {
 /// Literal kind.
 ///
 /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+// Clippy uses Hash and PartialEq
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
 pub enum LitKind {
     /// A string literal (`"foo"`).
     Str(Symbol, StrStyle),
diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs
index 94f0995566f..1386eac48da 100644
--- a/src/libsyntax/feature_gate/active.rs
+++ b/src/libsyntax/feature_gate/active.rs
@@ -528,6 +528,9 @@ declare_features! (
     /// Enable accurate caller location reporting during panic (RFC 2091).
     (active, track_caller, "1.40.0", Some(47809), None),
 
+    /// Non-object safe trait objects safe to use but cannot be created in safe rust
+    (active, object_safe_for_dispatch, "1.40.0", Some(43561), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 6bbd8be0cb9..2ce0046ca27 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -86,13 +86,6 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
     }
 }
 
-fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
-    if let Some(ref mut rhs) = rhs {
-        lhs.append(rhs);
-    }
-    lhs
-}
-
 #[derive(Debug, Clone, Copy, PartialEq)]
 enum PrevTokenKind {
     DocComment,
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 0acfd1450d8..73bd80e2a21 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -10,7 +10,6 @@ use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem,
 use crate::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField};
 use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfKind, Param};
 use crate::parse::token;
-use crate::parse::parser::maybe_append;
 use crate::tokenstream::{TokenTree, TokenStream};
 use crate::symbol::{kw, sym};
 use crate::source_map::{self, respan, Span};
@@ -416,10 +415,17 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Option<P<Item>>> {
         let (ident, item, extra_attrs) = info;
         let span = lo.to(self.prev_span);
-        let attrs = maybe_append(attrs, extra_attrs);
+        let attrs = Self::maybe_append(attrs, extra_attrs);
         Ok(Some(self.mk_item(span, ident, item, vis, attrs)))
     }
 
+    fn maybe_append<T>(mut lhs: Vec<T>, mut rhs: Option<Vec<T>>) -> Vec<T> {
+        if let Some(ref mut rhs) = rhs {
+            lhs.append(rhs);
+        }
+        lhs
+    }
+
     /// This is the fall-through for parsing items.
     fn parse_macro_use_or_failure(
         &mut self,
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index ac155556cda..0559f224f1f 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -19,7 +19,6 @@ use syntax_pos::{BytePos, Span, DUMMY_SP};
 #[cfg(target_arch = "x86_64")]
 use rustc_data_structures::static_assert_size;
 use rustc_data_structures::sync::Lrc;
-use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
 use smallvec::{SmallVec, smallvec};
 
 use std::{iter, mem};
@@ -136,7 +135,7 @@ impl TokenTree {
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)]
 pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
 
 pub type TreeAndJoint = (TokenTree, IsJoint);
@@ -145,7 +144,7 @@ pub type TreeAndJoint = (TokenTree, IsJoint);
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(TokenStream, 8);
 
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum IsJoint {
     Joint,
     NonJoint
@@ -460,18 +459,6 @@ impl Cursor {
     }
 }
 
-impl Encodable for TokenStream {
-    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
-        self.trees().collect::<Vec<_>>().encode(encoder)
-    }
-}
-
-impl Decodable for TokenStream {
-    fn decode<D: Decoder>(decoder: &mut D) -> Result<TokenStream, D::Error> {
-        Vec::<TokenTree>::decode(decoder).map(|vec| vec.into_iter().collect())
-    }
-}
-
 #[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub struct DelimSpan {
     pub open: Span,
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 45d9f79c28f..37310f46f7e 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -278,7 +278,7 @@ impl<'a, 'b> Context<'a, 'b> {
     /// format string.
     fn report_invalid_references(&self, numbered_position_args: bool) {
         let mut e;
-        let sp = if self.is_literal {
+        let sp = if self.is_literal { // Point at the formatting arguments.
             MultiSpan::from_spans(self.arg_spans.clone())
         } else {
             MultiSpan::from_span(self.fmtsp)
@@ -304,6 +304,9 @@ impl<'a, 'b> Context<'a, 'b> {
                     self.describe_num_args(),
                 ),
             );
+            for arg in &self.args { // Point at the arguments that will be formatted.
+                e.span_label(arg.span, "");
+            }
         } else {
             let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip();
             // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)`
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index fa9567fb62c..377d2f877b3 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -9,7 +9,7 @@ use rustc_macros::symbols;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
 
-use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
+use std::cmp::{PartialEq, PartialOrd, Ord};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::str;
@@ -459,6 +459,7 @@ symbols! {
         no_std,
         not,
         note,
+        object_safe_for_dispatch,
         Ok,
         omit_gdb_pretty_printer_section,
         on,
@@ -766,11 +767,6 @@ impl Ident {
         Ident::with_dummy_span(kw::Invalid)
     }
 
-    /// Maps an interned string to an identifier with an empty syntax context.
-    pub fn from_interned_str(string: InternedString) -> Ident {
-        Ident::with_dummy_span(string.as_symbol())
-    }
-
     /// Maps a string to an identifier with a dummy span.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_dummy_span(Symbol::intern(string))
@@ -813,11 +809,6 @@ impl Ident {
     pub fn as_str(self) -> LocalInternedString {
         self.name.as_str()
     }
-
-    /// Convert the name to an `InternedString`.
-    pub fn as_interned_str(self) -> InternedString {
-        self.name.as_interned_str()
-    }
 }
 
 impl PartialEq for Ident {
@@ -903,15 +894,6 @@ impl Symbol {
         })
     }
 
-    /// Access two symbols' chars. This is a slowish operation because it
-    /// requires locking the symbol interner, but it is faster than calling
-    /// `with()` twice.
-    fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: Symbol, f: F) -> R {
-        with_interner(|interner| {
-            f(interner.get(self), interner.get(other))
-        })
-    }
-
     /// Convert to a `LocalInternedString`. This is a slowish operation because
     /// it requires locking the symbol interner.
     pub fn as_str(self) -> LocalInternedString {
@@ -922,11 +904,6 @@ impl Symbol {
         })
     }
 
-    /// Convert to an `InternedString`.
-    pub fn as_interned_str(self) -> InternedString {
-        InternedString { symbol: self }
-    }
-
     pub fn as_u32(self) -> u32 {
         self.0.as_u32()
     }
@@ -1105,9 +1082,9 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
     GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
 }
 
-/// An alternative to `Symbol` and `InternedString`, useful when the chars
-/// within the symbol need to be accessed. It deliberately has limited
-/// functionality and should only be used for temporary values.
+/// An alternative to `Symbol`, useful when the chars within the symbol need to
+/// be accessed. It deliberately has limited functionality and should only be
+/// used for temporary values.
 ///
 /// Because the interner outlives any thread which uses this type, we can
 /// safely treat `string` which points to interner data, as an immortal string,
@@ -1116,7 +1093,7 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
 // FIXME: ensure that the interner outlives any thread which uses
 // `LocalInternedString`, by creating a new thread right after constructing the
 // interner.
-#[derive(Eq, PartialOrd, Ord)]
+#[derive(Clone, Eq, PartialOrd, Ord)]
 pub struct LocalInternedString {
     string: &'static str,
 }
@@ -1157,89 +1134,3 @@ impl fmt::Display for LocalInternedString {
         fmt::Display::fmt(self.string, f)
     }
 }
-
-/// An alternative to `Symbol` that is focused on string contents.
-///
-/// Its implementations of `Hash`, `PartialOrd` and `Ord` work with the
-/// string chars rather than the symbol integer. This is useful when hash
-/// stability is required across compile sessions, or a guaranteed sort
-/// ordering is required.
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct InternedString {
-    symbol: Symbol,
-}
-
-impl InternedString {
-    /// Maps a string to its interned representation.
-    pub fn intern(string: &str) -> Self {
-        InternedString {
-            symbol: Symbol::intern(string)
-        }
-    }
-
-    pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
-        self.symbol.with(f)
-    }
-
-    fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: &InternedString, f: F) -> R {
-        self.symbol.with2(other.symbol, f)
-    }
-
-    pub fn as_symbol(self) -> Symbol {
-        self.symbol
-    }
-
-    /// Convert to a `LocalInternedString`. This is a slowish operation because it
-    /// requires locking the symbol interner.
-    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.with2(other, |self_str, 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.with2(other, |self_str, other_str| self_str.cmp(other_str))
-    }
-}
-
-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(InternedString::intern(&d.read_str()?))
-    }
-}
-
-impl Encodable for InternedString {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        self.with(|string| s.emit_str(string))
-    }
-}
diff --git a/src/libtest/bench.rs b/src/libtest/bench.rs
index c142c5213d2..c86bfd16c21 100644
--- a/src/libtest/bench.rs
+++ b/src/libtest/bench.rs
@@ -48,7 +48,7 @@ impl Bencher {
         F: FnMut(&mut Bencher),
     {
         f(self);
-        return self.summary;
+        self.summary
     }
 }
 
@@ -116,7 +116,7 @@ where
     for _ in 0..k {
         black_box(inner());
     }
-    return ns_from_dur(start.elapsed());
+    ns_from_dur(start.elapsed())
 }
 
 pub fn iter<T, F>(inner: &mut F) -> stats::Summary
diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs
index f95d5aad18a..a34426305be 100644
--- a/src/libtest/cli.rs
+++ b/src/libtest/cli.rs
@@ -149,7 +149,7 @@ fn optgroups() -> getopts::Options {
             `CRITICAL_TIME` here means the limit that should not be exceeded by test.
             "
         );
-    return opts;
+    opts
 }
 
 fn usage(binary: &str, options: &getopts::Options) {
diff --git a/src/libtest/console.rs b/src/libtest/console.rs
index e17030726ce..244cbd2cf5f 100644
--- a/src/libtest/console.rs
+++ b/src/libtest/console.rs
@@ -296,7 +296,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
 
     assert!(st.current_test_count() == st.total);
 
-    return out.write_run_finish(&st);
+    out.write_run_finish(&st)
 }
 
 // Calculates padding for given test description.
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 179558e8f9a..8c1e9f1722a 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -34,8 +34,10 @@
 pub use self::ColorConfig::*;
 pub use self::types::*;
 pub use self::types::TestName::*;
-pub use self::options::{Options, ShouldPanic};
+pub use self::options::{ColorConfig, Options, OutputFormat, RunIgnored, ShouldPanic};
 pub use self::bench::{Bencher, black_box};
+pub use self::console::run_tests_console;
+pub use cli::TestOpts;
 
 // Module to be used by rustc to compile tests in libtest
 pub mod test {
@@ -84,9 +86,8 @@ mod tests;
 
 use test_result::*;
 use time::TestExecTime;
-use options::{RunStrategy, Concurrent, RunIgnored, ColorConfig};
+use options::{RunStrategy, Concurrent};
 use event::{CompletedTest, TestEvent};
-use cli::TestOpts;
 use helpers::sink::Sink;
 use helpers::concurrency::get_concurrency;
 use helpers::exit_code::get_exit_code;
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 1566a153ec0..eb96c61060b 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -9,14 +9,14 @@ extern crate rustc_target;
 extern crate rustc_driver;
 
 use std::any::Any;
-use std::sync::{Arc, mpsc};
+use std::sync::Arc;
 use std::path::Path;
 use syntax::symbol::Symbol;
 use rustc::session::Session;
 use rustc::session::config::OutputFilenames;
 use rustc::ty::TyCtxt;
 use rustc::ty::query::Providers;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
 use rustc::dep_graph::DepGraph;
 use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
@@ -41,7 +41,7 @@ impl MetadataLoader for NoLlvmMetadataLoader {
 struct TheBackend;
 
 impl CodegenBackend for TheBackend {
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
+    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
         Box::new(NoLlvmMetadataLoader)
     }
 
diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs
index e290f7fa6b1..9582137eae9 100644
--- a/src/test/run-make-fulldeps/issue-19371/foo.rs
+++ b/src/test/run-make-fulldeps/issue-19371/foo.rs
@@ -59,6 +59,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
         stderr: None,
         crate_name: None,
         lint_caps: Default::default(),
+        register_lints: None,
     };
 
     interface::run_compiler(config, |compiler| {
diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs
index 85ee6d3376b..2d506787b3b 100644
--- a/src/test/rustdoc/const-generics/const-impl.rs
+++ b/src/test/rustdoc/const-generics/const-impl.rs
@@ -4,6 +4,7 @@
 
 #![crate_name = "foo"]
 
+#[derive(PartialEq, Eq)]
 pub enum Order {
     Sorted,
     Unsorted,
diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index bb0ebf693d0..6b914f501ca 100644
--- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -15,15 +15,14 @@ use syntax::symbol::Symbol;
 
 use rustc::hir;
 use rustc::hir::intravisit;
-use rustc::hir::map as hir_map;
 use hir::Node;
 use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
-use rustc::ty;
-use syntax::{ast, source_map};
+use syntax::source_map;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_late_lint_pass(box MissingWhitelistedAttrPass);
+    reg.lint_store.register_lints(&[&MISSING_WHITELISTED_ATTR]);
+    reg.lint_store.register_late_pass(|| box MissingWhitelistedAttrPass);
     reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted);
 }
 
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
index 17386d7e1aa..6874c921c1c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
@@ -7,24 +7,20 @@
 extern crate rustc_driver;
 extern crate syntax;
 
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
+use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass};
 use rustc_driver::plugin::Registry;
 use rustc::hir;
 use syntax::attr;
 use syntax::symbol::Symbol;
 
 macro_rules! fake_lint_pass {
-    ($struct:ident, $lints:expr, $($attr:expr),*) => {
+    ($struct:ident, $($attr:expr),*) => {
         struct $struct;
 
         impl LintPass for $struct {
             fn name(&self) -> &'static str {
                 stringify!($struct)
             }
-
-            fn get_lints(&self) -> LintArray {
-                $lints
-            }
         }
 
         impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
@@ -49,25 +45,29 @@ declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]");
 
 fake_lint_pass! {
     PassOkay,
-    lint_array!(CRATE_NOT_OKAY), // Single lint
     Symbol::intern("rustc_crate_okay")
 }
 
 fake_lint_pass! {
     PassRedBlue,
-    lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints
     Symbol::intern("rustc_crate_red"), Symbol::intern("rustc_crate_blue")
 }
 
 fake_lint_pass! {
     PassGreyGreen,
-    lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma
     Symbol::intern("rustc_crate_grey"), Symbol::intern("rustc_crate_green")
 }
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_late_lint_pass(box PassOkay);
-    reg.register_late_lint_pass(box PassRedBlue);
-    reg.register_late_lint_pass(box PassGreyGreen);
+    reg.lint_store.register_lints(&[
+        &CRATE_NOT_OKAY,
+        &CRATE_NOT_RED,
+        &CRATE_NOT_BLUE,
+        &CRATE_NOT_GREY,
+        &CRATE_NOT_GREEN,
+    ]);
+    reg.lint_store.register_late_pass(|| box PassOkay);
+    reg.lint_store.register_late_pass(|| box PassRedBlue);
+    reg.lint_store.register_late_pass(|| box PassGreyGreen);
 }
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 000e10392e8..1cd3e7b28db 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -7,7 +7,7 @@
 extern crate rustc_driver;
 extern crate syntax;
 
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
+use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray};
 use rustc_driver::plugin::Registry;
 use rustc::hir;
 use syntax::attr;
@@ -32,5 +32,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_late_lint_pass(box Pass);
+    reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]);
+    reg.lint_store.register_late_pass(|| box Pass);
 }
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index a377b07bd3d..cb793b43498 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -9,7 +9,7 @@ extern crate rustc;
 extern crate rustc_driver;
 
 use rustc::hir;
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
+use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId};
 use rustc_driver::plugin::Registry;
 
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
@@ -30,6 +30,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_late_lint_pass(box Pass);
-    reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]);
+    reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]);
+    reg.lint_store.register_late_pass(|| box Pass);
+    reg.lint_store.register_group(true, "lint_me", None,
+        vec![LintId::of(&TEST_LINT), LintId::of(&PLEASE_LINT)]);
 }
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index 02675191f78..40c37eb570e 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -10,8 +10,7 @@ extern crate syntax;
 extern crate rustc;
 extern crate rustc_driver;
 
-use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
-                  EarlyLintPassObject, LintArray};
+use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
 use rustc_driver::plugin::Registry;
 use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
@@ -28,5 +27,6 @@ impl EarlyLintPass for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
+    reg.lint_store.register_lints(&[&TEST_LINT]);
+    reg.lint_store.register_early_pass(|| box Pass);
 }
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index 40f8d490ac8..67135d595f4 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -8,7 +8,7 @@ extern crate syntax;
 extern crate rustc;
 extern crate rustc_driver;
 
-use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
 use rustc_driver::plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
@@ -40,6 +40,8 @@ impl EarlyLintPass for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_early_lint_pass(box Pass);
-    reg.register_lint_group("clippy::group", Some("clippy_group"), vec![TEST_LINT, TEST_GROUP]);
+    reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]);
+    reg.lint_store.register_early_pass(|| box Pass);
+    reg.lint_store.register_group(true, "clippy::group", Some("clippy_group"),
+        vec![LintId::of(&TEST_LINT), LintId::of(&TEST_GROUP)]);
 }
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
index 48dd5b122b5..0bfb32c6dc4 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
@@ -6,7 +6,7 @@
 extern crate rustc;
 
 use rustc::lint::{LintArray, LintPass};
-use rustc::{declare_lint, declare_lint_pass, impl_lint_pass, lint_array};
+use rustc::{declare_lint, declare_lint_pass, impl_lint_pass};
 
 declare_lint! {
     pub TEST_LINT,
@@ -17,10 +17,6 @@ declare_lint! {
 struct Foo;
 
 impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
-    }
-
     fn name(&self) -> &'static str {
         "Foo"
     }
@@ -31,10 +27,6 @@ macro_rules! custom_lint_pass_macro {
         struct Custom;
 
         impl LintPass for Custom { //~ERROR implementing `LintPass` by hand
-            fn get_lints(&self) -> LintArray {
-                lint_array!(TEST_LINT)
-            }
-
             fn name(&self) -> &'static str {
                 "Custom"
             }
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
index b439ae2cd14..0dbdf4f5aa9 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
@@ -12,7 +12,7 @@ LL | #![deny(rustc::lint_pass_impl_without_macro)]
    = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:33:14
+  --> $DIR/lint_pass_impl_without_macro.rs:29:14
    |
 LL |         impl LintPass for Custom {
    |              ^^^^^^^^
diff --git a/src/test/ui/asm/issue-51431.rs b/src/test/ui/asm/issue-51431.rs
new file mode 100644
index 00000000000..d29c31fafc2
--- /dev/null
+++ b/src/test/ui/asm/issue-51431.rs
@@ -0,0 +1,10 @@
+// ignore-emscripten no asm! support
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)}
+        //~^ ERROR: invalid value for constraint in inline assembly
+    }
+}
diff --git a/src/test/ui/asm/issue-51431.stderr b/src/test/ui/asm/issue-51431.stderr
new file mode 100644
index 00000000000..132eea126d6
--- /dev/null
+++ b/src/test/ui/asm/issue-51431.stderr
@@ -0,0 +1,8 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/issue-51431.rs:7:32
+   |
+LL |         asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)}
+   |                                ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs
new file mode 100644
index 00000000000..311c48b5e48
--- /dev/null
+++ b/src/test/ui/associated-const/issue-63496.rs
@@ -0,0 +1,9 @@
+trait A {
+    const C: usize;
+
+    fn f() -> ([u8; A::C], [u8; A::C]);
+    //~^ ERROR: type annotations needed: cannot resolve
+    //~| ERROR: type annotations needed: cannot resolve
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr
new file mode 100644
index 00000000000..70bb12de1fb
--- /dev/null
+++ b/src/test/ui/associated-const/issue-63496.stderr
@@ -0,0 +1,21 @@
+error[E0283]: type annotations needed: cannot resolve `_: A`
+  --> $DIR/issue-63496.rs:4:21
+   |
+LL |     const C: usize;
+   |     --------------- required by `A::C`
+LL | 
+LL |     fn f() -> ([u8; A::C], [u8; A::C]);
+   |                     ^^^^
+
+error[E0283]: type annotations needed: cannot resolve `_: A`
+  --> $DIR/issue-63496.rs:4:33
+   |
+LL |     const C: usize;
+   |     --------------- required by `A::C`
+LL | 
+LL |     fn f() -> ([u8; A::C], [u8; A::C]);
+   |                                 ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index 563885133a4..64c9f693115 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]}]}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}
diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
index 7caa9f26bc2..4b5e2d59e38 100644
--- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
+++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
@@ -244,4 +244,5 @@ LL |     let _ = await bar()?;
 
 error: aborting due to 35 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0728.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr
index 6c3c8889da7..5b9adb253d9 100644
--- a/src/test/ui/async-await/issues/issue-51719.stderr
+++ b/src/test/ui/async-await/issues/issue-51719.stderr
@@ -8,3 +8,4 @@ LL |     let _gen = || foo().await;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0728`.
diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr
index e50c78534f8..f120bd119c5 100644
--- a/src/test/ui/async-await/issues/issue-51751.stderr
+++ b/src/test/ui/async-await/issues/issue-51751.stderr
@@ -9,3 +9,4 @@ LL |     let finished = result.await;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0728`.
diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr
index f63eaa4c48a..538430290d2 100644
--- a/src/test/ui/async-await/issues/issue-62009-1.stderr
+++ b/src/test/ui/async-await/issues/issue-62009-1.stderr
@@ -40,4 +40,5 @@ LL |     F: Future
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0728.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr
index 79b6803263e..47b74b5574f 100644
--- a/src/test/ui/async-await/issues/issue-62009-2.stderr
+++ b/src/test/ui/async-await/issues/issue-62009-2.stderr
@@ -8,3 +8,4 @@ LL |     (async || 2333)().await;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0728`.
diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr
index 49ebf414c55..f826a86f089 100644
--- a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr
+++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr
@@ -9,3 +9,4 @@ LL |     let y = do_the_thing().await;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0728`.
diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs
index c424c25c646..a6f9d0423d0 100644
--- a/src/test/ui/break-outside-loop.rs
+++ b/src/test/ui/break-outside-loop.rs
@@ -22,4 +22,12 @@ fn main() {
     let rs: Foo = Foo{t: pth};
 
     let unconstrained = break; //~ ERROR: `break` outside of a loop
+
+    // This used to ICE because `target_id` passed to `check_expr_break` would be the closure and
+    // not the `loop`, which failed in the call to `find_breakable`. (#65383)
+    'lab: loop {
+        || {
+            break 'lab; //~ ERROR `break` inside of a closure
+        };
+    }
 }
diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/break-outside-loop.stderr
index 8b686356055..8e300fd848d 100644
--- a/src/test/ui/break-outside-loop.stderr
+++ b/src/test/ui/break-outside-loop.stderr
@@ -33,7 +33,15 @@ error[E0268]: `break` outside of a loop
 LL |     let unconstrained = break;
    |                         ^^^^^ cannot `break` outside of a loop
 
-error: aborting due to 5 previous errors
+error[E0267]: `break` inside of a closure
+  --> $DIR/break-outside-loop.rs:30:13
+   |
+LL |         || {
+   |         -- enclosing closure
+LL |             break 'lab;
+   |             ^^^^^^^^^^ cannot `break` inside of a closure
+
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0267, E0268.
 For more information about an error, try `rustc --explain E0267`.
diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs
new file mode 100644
index 00000000000..5cae0e76d1a
--- /dev/null
+++ b/src/test/ui/closures/issue-41366.rs
@@ -0,0 +1,13 @@
+trait T<'x> {
+    type V;
+}
+
+impl<'g> T<'g> for u32 {
+    type V = u16;
+}
+
+fn main() {
+    (&|_|()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+    //~^ ERROR: type mismatch in closure arguments
+    //~| ERROR: type mismatch resolving
+}
diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr
new file mode 100644
index 00000000000..91d26efbc4f
--- /dev/null
+++ b/src/test/ui/closures/issue-41366.stderr
@@ -0,0 +1,22 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-41366.rs:10:5
+   |
+LL |     (&|_|()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+   |     ^^-----^
+   |     | |
+   |     | found signature of `fn(_) -> _`
+   |     expected signature of `for<'x> fn(<u32 as T<'x>>::V) -> _`
+   |
+   = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(<u32 as T<'x>>::V)`
+
+error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(<u32 as T<'x>>::V,)>>::Output == ()`
+  --> $DIR/issue-41366.rs:10:5
+   |
+LL |     (&|_|()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+   |     ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
+   |
+   = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(<u32 as T<'x>>::V)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/closures/issue-52437.rs b/src/test/ui/closures/issue-52437.rs
new file mode 100644
index 00000000000..6ac5380a5aa
--- /dev/null
+++ b/src/test/ui/closures/issue-52437.rs
@@ -0,0 +1,5 @@
+fn main() {
+    [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
+    //~^ ERROR: invalid label name `'static`
+    //~| ERROR: type annotations needed
+}
diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr
new file mode 100644
index 00000000000..e76f942e9ba
--- /dev/null
+++ b/src/test/ui/closures/issue-52437.stderr
@@ -0,0 +1,15 @@
+error: invalid label name `'static`
+  --> $DIR/issue-52437.rs:2:13
+   |
+LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
+   |             ^^^^^^^
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-52437.rs:2:30
+   |
+LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
+   |                              ^ consider giving this closure parameter a type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs
new file mode 100644
index 00000000000..9859a226efd
--- /dev/null
+++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs
@@ -0,0 +1,18 @@
+// Check that unsafe trait object do not implement themselves
+// automatically
+
+#![feature(object_safe_for_dispatch)]
+
+trait Trait: Sized {
+    fn call(&self);
+}
+
+fn takes_t<S: Trait>(s: S) {
+    s.call();
+}
+
+fn takes_t_obj(t: &dyn Trait) {
+    takes_t(t); //~ ERROR E0277
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
new file mode 100644
index 00000000000..b5a86acfb97
--- /dev/null
+++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
+  --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13
+   |
+LL | fn takes_t<S: Trait>(s: S) {
+   |    -------    ----- required by this bound in `takes_t`
+...
+LL |     takes_t(t);
+   |             ^ the trait `Trait` is not implemented for `&dyn Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.rs b/src/test/ui/coherence/impl-foreign-for-foreign.rs
new file mode 100644
index 00000000000..de0b66a35eb
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign.rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote for i32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.stderr b/src/test/ui/coherence/impl-foreign-for-foreign.stderr
new file mode 100644
index 00000000000..b03a75a77c3
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign.rs:12:1
+   |
+LL | impl Remote for i32 {
+   | ^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs
new file mode 100644
index 00000000000..5146263d991
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs
@@ -0,0 +1,25 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote1<Rc<i32>> for i32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl Remote1<Rc<Local>> for f64 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl<T> Remote1<Rc<T>> for f32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr
new file mode 100644
index 00000000000..bfaec790b20
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr
@@ -0,0 +1,30 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign[foreign].rs:12:1
+   |
+LL | impl Remote1<Rc<i32>> for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign[foreign].rs:16:1
+   |
+LL | impl Remote1<Rc<Local>> for f64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign[foreign].rs:20:1
+   |
+LL | impl<T> Remote1<Rc<T>> for f32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[local].rs b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs
new file mode 100644
index 00000000000..050769dcf4c
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local<T>(Rc<T>);
+
+impl Remote1<Local<i32>> for i32 {}
+impl<T> Remote1<Local<T>> for f32 {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs
new file mode 100644
index 00000000000..03b11edf98b
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs
@@ -0,0 +1,21 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote for Box<i32> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl<T> Remote for Box<Rc<T>> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
new file mode 100644
index 00000000000..2ce4921cf93
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-fundamental[foreign].rs:12:1
+   |
+LL | impl Remote for Box<i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-fundamental[foreign].rs:16:1
+   |
+LL | impl<T> Remote for Box<Rc<T>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs
new file mode 100644
index 00000000000..ae03ce6a440
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<T>(Rc<T>);
+
+impl Remote for Box<Local> {}
+impl<T> Remote for Box<Local1<T>> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-local.rs b/src/test/ui/coherence/impl-foreign-for-local.rs
new file mode 100644
index 00000000000..c9dddeba18d
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-local.rs
@@ -0,0 +1,15 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote for Local {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs
new file mode 100644
index 00000000000..06efb6c2ad7
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs
@@ -0,0 +1,26 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<T>(Rc<T>);
+
+impl Remote1<Box<String>> for i32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl Remote1<Box<Rc<i32>>> for f64 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl<T> Remote1<Box<Rc<T>>> for f32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
new file mode 100644
index 00000000000..bf2361a1718
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
@@ -0,0 +1,30 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:13:1
+   |
+LL | impl Remote1<Box<String>> for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:17:1
+   |
+LL | impl Remote1<Box<Rc<i32>>> for f64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:21:1
+   |
+LL | impl<T> Remote1<Box<Rc<T>>> for f32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs
new file mode 100644
index 00000000000..d47e0a36a56
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs
@@ -0,0 +1,18 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<T>(Rc<T>);
+
+impl Remote1<Box<Local>> for i32 {}
+impl Remote1<Box<Local1<i32>>> for f64 {}
+impl<T> Remote1<Box<Local1<T>>> for f32 {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs
new file mode 100644
index 00000000000..db7a2ae8076
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs
@@ -0,0 +1,23 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Local;
+
+impl Remote for Rc<Local> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+impl<T> Remote for Arc<T> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
new file mode 100644
index 00000000000..d7ffcaf76f9
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl[t]-foreign-for-foreign[t].rs:13:1
+   |
+LL | impl Remote for Rc<Local> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl[t]-foreign-for-foreign[t].rs:18:1
+   |
+LL | impl<T> Remote for Arc<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs
new file mode 100644
index 00000000000..4cc19e1a526
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote for Box<T> {
+    //~^ ERROR type parameter `T` must be used as the type parameter for
+    // | some local type (e.g., `MyStruct<T>`)
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
new file mode 100644
index 00000000000..20ce11ef975
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign-for-fundamental[t].rs:12:1
+   |
+LL | impl<T> Remote for Box<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs
new file mode 100644
index 00000000000..914680f191a
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<S>(Rc<S>);
+
+impl<T> Remote1<Box<Local>> for Rc<T> {}
+impl<S, T> Remote1<Box<Local1<S>>> for Rc<T> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs
new file mode 100644
index 00000000000..1e84ff40c62
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<S>(Rc<S>);
+
+impl<T> Remote1<Local> for Rc<T> {}
+impl<T, S> Remote1<Local1<S>> for Rc<T> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs
new file mode 100644
index 00000000000..ea6aa101d20
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs
@@ -0,0 +1,19 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<S>(Rc<S>);
+
+impl<T> Remote1<Local> for Box<Rc<T>> {}
+impl<T, S> Remote1<Local1<S>> for Box<Rc<T>> {}
+impl<T> Remote1<Box<Local>> for Box<Rc<T>> {}
+impl<T, S> Remote1<Box<Local1<S>>> for Box<Rc<T>> {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
index af5e8f49754..78bd549ba79 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
@@ -1,6 +1,6 @@
 use std::marker::PhantomData;
 
 struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
-//~^ ERROR const parameters cannot depend on type parameters
+//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq`
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
index c659074a091..a2872ab982d 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -1,9 +1,3 @@
-error[E0671]: const parameters cannot depend on type parameters
-  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
-   |
-LL | struct B<T, const N: T>(PhantomData<[T; N]>);
-   |                      ^ const parameter depends on type parameter
-
 error[E0658]: const generics are unstable
   --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
    |
@@ -13,7 +7,13 @@ LL | struct B<T, const N: T>(PhantomData<[T; N]>);
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
+error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq`
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
+   |
+LL | struct B<T, const N: T>(PhantomData<[T; N]>);
+   |                      ^ `T` doesn't derive both `PartialEq` and `Eq`
+
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0658, E0671.
+Some errors have detailed explanations: E0658, E0741.
 For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
index 28e0d6c2bb7..b76209571b0 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
@@ -7,7 +7,6 @@
 // details.
 
 pub struct Dependent<T, const X: T>([(); X]);
-//~^ ERROR const parameters cannot depend on type parameters
-//~^^ ERROR parameter `T` is never used
+//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq`
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
index db14f9c9bf6..c9d6db7e2c2 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
@@ -1,9 +1,3 @@
-error[E0671]: const parameters cannot depend on type parameters
-  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
-   |
-LL | pub struct Dependent<T, const X: T>([(); X]);
-   |                                  ^ const parameter depends on type parameter
-
 warning: the feature `const_generics` is incomplete and may cause the compiler to crash
   --> $DIR/const-param-type-depends-on-type-param.rs:1:12
    |
@@ -12,15 +6,12 @@ LL | #![feature(const_generics)]
    |
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0392]: parameter `T` is never used
-  --> $DIR/const-param-type-depends-on-type-param.rs:9:22
+error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq`
+  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
    |
 LL | pub struct Dependent<T, const X: T>([(); X]);
-   |                      ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
+   |                                  ^ `T` doesn't derive both `PartialEq` and `Eq`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0392, E0671.
-For more information about an error, try `rustc --explain E0392`.
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs
new file mode 100644
index 00000000000..7bc4f3986eb
--- /dev/null
+++ b/src/test/ui/const-generics/forbid-non-structural_match-types.rs
@@ -0,0 +1,13 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+#[derive(PartialEq, Eq)]
+struct A;
+
+struct B<const X: A>; // ok
+
+struct C;
+
+struct D<const X: C>; //~ ERROR the types of const generic parameters must derive
+
+fn main() {}
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr
new file mode 100644
index 00000000000..0fd9e0599e8
--- /dev/null
+++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/forbid-non-structural_match-types.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq`
+  --> $DIR/forbid-non-structural_match-types.rs:11:19
+   |
+LL | struct D<const X: C>;
+   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs
new file mode 100644
index 00000000000..0ff7ddc41fe
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+#[derive(PartialEq, Eq)]
+struct NoMatch;
+
+fn foo<const T: NoMatch>() -> bool {
+    true
+}
+
+fn main() {
+    foo::<{NoMatch}>();
+}
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr
new file mode 100644
index 00000000000..759d5fdeb4c
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-62579-no-match.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs
new file mode 100644
index 00000000000..3ca527313f9
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-65675.rs
@@ -0,0 +1,10 @@
+// run-pass
+// compile-flags: -Z chalk
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+pub struct Foo<T, const N: usize>([T; N]);
+impl<T, const N: usize> Foo<T, {N}> {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr
new file mode 100644
index 00000000000..60b388e6278
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-65675.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-65675.rs:4:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs
new file mode 100644
index 00000000000..8945360b7be
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs
@@ -0,0 +1,41 @@
+// Test that the use of the non object-safe trait objects
+// are gated by `object_safe_for_dispatch` feature gate.
+
+trait NonObjectSafe1: Sized {}
+
+trait NonObjectSafe2 {
+    fn static_fn() {}
+}
+
+trait NonObjectSafe3 {
+    fn foo<T>(&self);
+}
+
+trait NonObjectSafe4 {
+    fn foo(&self, &Self);
+}
+
+fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
+    //~^ ERROR E0038
+}
+
+fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 {
+    //~^ ERROR E0038
+    loop {}
+}
+
+fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
+    //~^ ERROR E0038
+}
+
+fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
+    //~^ ERROR E0038
+    loop {}
+}
+
+trait Trait {}
+
+impl Trait for dyn NonObjectSafe1 {}
+//~^ ERROR E0038
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..54e64e2fc1b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
@@ -0,0 +1,46 @@
+error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:1
+   |
+LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error[E0038]: the trait `NonObjectSafe2` cannot be made into an object
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:1
+   |
+LL |     fn static_fn() {}
+   |        --------- associated function `static_fn` has no `self` parameter
+...
+LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object
+
+error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:1
+   |
+LL |     fn foo<T>(&self);
+   |        --- method `foo` has generic type parameters
+...
+LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe3` cannot be made into an object
+
+error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:1
+   |
+LL |     fn foo(&self, &Self);
+   |        --- method `foo` references the `Self` type in its parameters or return type
+...
+LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object
+
+error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6
+   |
+LL | impl Trait for dyn NonObjectSafe1 {}
+   |      ^^^^^ the trait `NonObjectSafe1` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs
index cca949aab63..691c06a2402 100644
--- a/src/test/ui/fmt/format-string-error.rs
+++ b/src/test/ui/fmt/format-string-error.rs
@@ -48,4 +48,6 @@ fn main() {
 
 "###);
     //~^^^ ERROR invalid format string: unmatched `}` found
+    println!("{} {} {}", 1, 2);
+    //~^ ERROR 3 positional arguments in format string, but there are 2 arguments
 }
diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr
index 3dc122a7399..32119b18774 100644
--- a/src/test/ui/fmt/format-string-error.stderr
+++ b/src/test/ui/fmt/format-string-error.stderr
@@ -107,5 +107,11 @@ LL |         }
    |
    = note: if you intended to print `}`, you can escape it using `}}`
 
-error: aborting due to 12 previous errors
+error: 3 positional arguments in format string, but there are 2 arguments
+  --> $DIR/format-string-error.rs:51:15
+   |
+LL |     println!("{} {} {}", 1, 2);
+   |               ^^ ^^ ^^   -  -
+
+error: aborting due to 13 previous errors
 
diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr
index 336ea2254bf..c58cbc31233 100644
--- a/src/test/ui/if/ifmt-bad-arg.stderr
+++ b/src/test/ui/if/ifmt-bad-arg.stderr
@@ -224,8 +224,9 @@ error: 4 positional arguments in format string, but there are 3 arguments
   --> $DIR/ifmt-bad-arg.rs:78:15
    |
 LL |     println!("{} {:.*} {}", 1, 3.2, 4);
-   |               ^^ ^^--^ ^^      --- this parameter corresponds to the precision flag
-   |                    |
+   |               ^^ ^^--^ ^^   -  ---  -
+   |                    |           |
+   |                    |           this parameter corresponds to the precision flag
    |                    this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
    |
    = note: positional arguments are zero-based
@@ -235,8 +236,9 @@ error: 4 positional arguments in format string, but there are 3 arguments
   --> $DIR/ifmt-bad-arg.rs:81:15
    |
 LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
-   |               ^^ ^^^----^ ^^      --- this parameter corresponds to the precision flag
-   |                     | |
+   |               ^^ ^^^----^ ^^   -  ---  -
+   |                     | |           |
+   |                     | |           this parameter corresponds to the precision flag
    |                     | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
    |                     this width flag expects an `usize` argument at position 7, but there are 3 arguments
    |
diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs
index 6a67d04a54c..02e3139d294 100644
--- a/src/test/ui/intrinsics/intrinsic-alignment.rs
+++ b/src/test/ui/intrinsics/intrinsic-alignment.rs
@@ -19,7 +19,8 @@ mod rusti {
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "vxworks"))]
 mod m {
     #[main]
     #[cfg(target_arch = "x86")]
diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr
index 5415a45f7d6..83c03b514dd 100644
--- a/src/test/ui/issues/issue-19538.stderr
+++ b/src/test/ui/issues/issue-19538.stderr
@@ -17,6 +17,7 @@ LL |     let test: &mut dyn Bar = &mut thing;
    |                              ^^^^^^^^^^ the trait `Bar` cannot be made into an object
    |
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
+   = note: required by cast to type `&mut dyn Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr
index 66309394a42..06c83f65be2 100644
--- a/src/test/ui/issues/issue-20692.stderr
+++ b/src/test/ui/issues/issue-20692.stderr
@@ -14,6 +14,7 @@ LL |     let _ = x
    |
    = note: the trait cannot require that `Self : Sized`
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
+   = note: required by cast to type `&dyn Array`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/issues/issue-38604.stderr
index 8ef7d346cb3..8b923a2c6b2 100644
--- a/src/test/ui/issues/issue-38604.stderr
+++ b/src/test/ui/issues/issue-38604.stderr
@@ -14,6 +14,7 @@ LL |         Box::new(());
    |
    = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<()>`
+   = note: required by cast to type `std::boxed::Box<dyn Foo>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/issues/issue-65611.rs
new file mode 100644
index 00000000000..b74ee1b0c6e
--- /dev/null
+++ b/src/test/ui/issues/issue-65611.rs
@@ -0,0 +1,63 @@
+use std::mem::MaybeUninit;
+use std::ops::Deref;
+
+pub unsafe trait Array {
+    /// The array’s element type
+    type Item;
+    #[doc(hidden)]
+    /// The smallest index type that indexes the array.
+    type Index: Index;
+    #[doc(hidden)]
+    fn as_ptr(&self) -> *const Self::Item;
+    #[doc(hidden)]
+    fn as_mut_ptr(&mut self) -> *mut Self::Item;
+    #[doc(hidden)]
+    fn capacity() -> usize;
+}
+
+pub trait Index : PartialEq + Copy {
+    fn to_usize(self) -> usize;
+    fn from(usize) -> Self;
+}
+
+impl Index for usize {
+    fn to_usize(self) -> usize { self }
+    fn from(val: usize) -> Self {
+        val
+    }
+}
+
+unsafe impl<T> Array for [T; 1] {
+    type Item = T;
+    type Index = usize;
+    fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
+    fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
+    fn capacity() -> usize { 1 }
+}
+
+impl<A: Array> Deref for ArrayVec<A> {
+    type Target = [A::Item];
+    #[inline]
+    fn deref(&self) -> &[A::Item] {
+        panic!()
+    }
+}
+
+pub struct ArrayVec<A: Array> {
+    xs: MaybeUninit<A>,
+    len: usize,
+}
+
+impl<A: Array> ArrayVec<A> {
+    pub fn new() -> ArrayVec<A> {
+        panic!()
+    }
+}
+
+fn main() {
+    let mut buffer = ArrayVec::new();
+    let x = buffer.last().unwrap().0.clone();
+    //~^ ERROR type annotations needed
+    //~| ERROR no field `0` on type `&_`
+    buffer.reverse();
+}
diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr
new file mode 100644
index 00000000000..cb441c13c6b
--- /dev/null
+++ b/src/test/ui/issues/issue-65611.stderr
@@ -0,0 +1,18 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-65611.rs:59:20
+   |
+LL |     let x = buffer.last().unwrap().0.clone();
+   |                    ^^^^ cannot infer type for `T`
+   |
+   = note: type must be known at this point
+
+error[E0609]: no field `0` on type `&_`
+  --> $DIR/issue-65611.rs:59:36
+   |
+LL |     let x = buffer.last().unwrap().0.clone();
+   |                                    ^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0609.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index 27901d06927..a93f4686496 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
-  --> $DIR/kindck-inherited-copy-bound.rs:18:16
+  --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL | fn take_param<T:Foo>(foo: &T) { }
    |    ----------   --- required by this bound in `take_param`
@@ -10,7 +10,7 @@ LL |     take_param(&x);
    = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
 
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/kindck-inherited-copy-bound.rs:24:19
+  --> $DIR/kindck-inherited-copy-bound.rs:28:19
    |
 LL |     let z = &x as &dyn Foo;
    |                   ^^^^^^^^ the trait `Foo` cannot be made into an object
@@ -18,13 +18,14 @@ LL |     let z = &x as &dyn Foo;
    = note: the trait cannot require that `Self : Sized`
 
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/kindck-inherited-copy-bound.rs:24:13
+  --> $DIR/kindck-inherited-copy-bound.rs:28:13
    |
 LL |     let z = &x as &dyn Foo;
    |             ^^ the trait `Foo` cannot be made into an object
    |
    = note: the trait cannot require that `Self : Sized`
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>`
+   = note: required by cast to type `&dyn Foo`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..7c67c5f9e95
--- /dev/null
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
+  --> $DIR/kindck-inherited-copy-bound.rs:21:16
+   |
+LL | fn take_param<T:Foo>(foo: &T) { }
+   |    ----------   --- required by this bound in `take_param`
+...
+LL |     take_param(&x);
+   |                ^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>`
+   |
+   = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/kindck-inherited-copy-bound.rs:28:13
+   |
+LL |     let z = &x as &dyn Foo;
+   |             ^^ the trait `Foo` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<i32>`
+   = note: required by cast to type `&dyn Foo`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0038, E0277.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.rs b/src/test/ui/kindck/kindck-inherited-copy-bound.rs
index 61e72908248..aad693e5b19 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.rs
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.rs
@@ -1,5 +1,8 @@
 // Test that Copy bounds inherited by trait are checked.
+//
+// revisions: curr object_safe_for_dispatch
 
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
 #![feature(box_syntax)]
 
 use std::any::Any;
@@ -15,15 +18,17 @@ fn take_param<T:Foo>(foo: &T) { }
 
 fn a() {
     let x: Box<_> = box 3;
-    take_param(&x); //~ ERROR E0277
+    take_param(&x); //[curr]~ ERROR E0277
+    //[object_safe_for_dispatch]~^ ERROR E0277
 }
 
 fn b() {
     let x: Box<_> = box 3;
     let y = &x;
     let z = &x as &dyn Foo;
-    //~^ ERROR E0038
-    //~| ERROR E0038
+    //[curr]~^ ERROR E0038
+    //[curr]~| ERROR E0038
+    //[object_safe_for_dispatch]~^^^ ERROR E0038
 }
 
 fn main() { }
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.fixed b/src/test/ui/lint/unused_parens_json_suggestion.fixed
index 42740711910..15ee19755bf 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.fixed
+++ b/src/test/ui/lint/unused_parens_json_suggestion.fixed
@@ -1,5 +1,4 @@
-// compile-flags: --error-format pretty-json -Zunstable-options
-// build-pass (FIXME(62277): could be check-pass?)
+// compile-flags: --error-format json -Zunstable-options
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
@@ -8,13 +7,13 @@
 // stripping away any starting or ending parenthesis characters—hence this
 // test of the JSON error format.
 
-#![warn(unused_parens)]
+#![deny(unused_parens)]
 #![allow(unreachable_code)]
 
 fn main() {
     // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
     // the malformed `1 / (2 + 3`
-    let _a = 1 / (2 + 3);
+    let _a = 1 / (2 + 3); //~ERROR unnecessary parentheses
     f();
 }
 
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
index 87192503986..d72df21e09a 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.rs
+++ b/src/test/ui/lint/unused_parens_json_suggestion.rs
@@ -1,5 +1,4 @@
-// compile-flags: --error-format pretty-json -Zunstable-options
-// build-pass (FIXME(62277): could be check-pass?)
+// compile-flags: --error-format json -Zunstable-options
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
@@ -8,13 +7,13 @@
 // stripping away any starting or ending parenthesis characters—hence this
 // test of the JSON error format.
 
-#![warn(unused_parens)]
+#![deny(unused_parens)]
 #![allow(unreachable_code)]
 
 fn main() {
     // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
     // the malformed `1 / (2 + 3`
-    let _a = (1 / (2 + 3));
+    let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses
     f();
 }
 
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
index 256c7555c90..c503c100808 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -1,106 +1,16 @@
-{
-  "message": "unnecessary parentheses around assigned value",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_json_suggestion.rs",
-      "byte_start": 654,
-      "byte_end": 667,
-      "line_start": 17,
-      "line_end": 17,
-      "column_start": 14,
-      "column_end": 27,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    let _a = (1 / (2 + 3));",
-          "highlight_start": 14,
-          "highlight_end": 27
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "lint level defined here",
-      "code": null,
-      "level": "note",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_json_suggestion.rs",
-          "byte_start": 472,
-          "byte_end": 485,
-          "line_start": 11,
-          "line_end": 11,
-          "column_start": 9,
-          "column_end": 22,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "#![warn(unused_parens)]",
-              "highlight_start": 9,
-              "highlight_end": 22
-            }
-          ],
-          "label": null,
-          "suggested_replacement": null,
-          "suggestion_applicability": null,
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    },
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_json_suggestion.rs",
-          "byte_start": 654,
-          "byte_end": 667,
-          "line_start": 17,
-          "line_end": 17,
-          "column_start": 14,
-          "column_end": 27,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    let _a = (1 / (2 + 3));",
-              "highlight_start": 14,
-              "highlight_end": 27
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "1 / (2 + 3)",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around assigned value
-  --> $DIR/unused_parens_json_suggestion.rs:17:14
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
+  --> $DIR/unused_parens_json_suggestion.rs:16:14
    |
 LL |     let _a = (1 / (2 + 3));
    |              ^^^^^^^^^^^^^ help: remove these parentheses
    |
 note: lint level defined here
-  --> $DIR/unused_parens_json_suggestion.rs:11:9
+  --> $DIR/unused_parens_json_suggestion.rs:10:9
    |
-LL | #![warn(unused_parens)]
+LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
 
-"
-}
+"}
+{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
+
+"}
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
index 2459eb1ac5c..1d891d328dd 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed
@@ -1,5 +1,4 @@
-// compile-flags: --error-format pretty-json -Zunstable-options
-// build-pass
+// compile-flags: --error-format json -Zunstable-options
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
@@ -8,14 +7,14 @@
 // stripping away any starting or ending parenthesis characters—hence this
 // test of the JSON error format.
 
-#![warn(unused_parens)]
+#![deny(unused_parens)]
 #![allow(unreachable_code)]
 
 fn main() {
 
     let _b = false;
 
-    if _b {
+    if _b { //~ ERROR unnecessary parentheses
         println!("hello");
     }
 
@@ -26,29 +25,29 @@ fn main() {
 fn f() -> bool {
     let c = false;
 
-    if c {
+    if c { //~ ERROR unnecessary parentheses
         println!("next");
     }
 
-    if c {
+    if c { //~ ERROR unnecessary parentheses
         println!("prev");
     }
 
     while false && true {
-        if c {
+        if c { //~ ERROR unnecessary parentheses
             println!("norm");
         }
 
     }
 
-    while true && false {
-        for _ in 0 .. 3 {
+    while true && false { //~ ERROR unnecessary parentheses
+        for _ in 0 .. 3 { //~ ERROR unnecessary parentheses
             println!("e~")
         }
     }
 
-    for _ in 0 .. 3 {
-        while true && false {
+    for _ in 0 .. 3 { //~ ERROR unnecessary parentheses
+        while true && false { //~ ERROR unnecessary parentheses
             println!("e~")
         }
     }
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs
index 0e9869b67d5..494cd184506 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs
@@ -1,5 +1,4 @@
-// compile-flags: --error-format pretty-json -Zunstable-options
-// build-pass
+// compile-flags: --error-format json -Zunstable-options
 // run-rustfix
 
 // The output for humans should just highlight the whole span without showing
@@ -8,14 +7,14 @@
 // stripping away any starting or ending parenthesis characters—hence this
 // test of the JSON error format.
 
-#![warn(unused_parens)]
+#![deny(unused_parens)]
 #![allow(unreachable_code)]
 
 fn main() {
 
     let _b = false;
 
-    if (_b) {
+    if (_b) { //~ ERROR unnecessary parentheses
         println!("hello");
     }
 
@@ -26,29 +25,29 @@ fn main() {
 fn f() -> bool {
     let c = false;
 
-    if(c) {
+    if(c) { //~ ERROR unnecessary parentheses
         println!("next");
     }
 
-    if (c){
+    if (c){ //~ ERROR unnecessary parentheses
         println!("prev");
     }
 
     while (false && true){
-        if (c) {
+        if (c) { //~ ERROR unnecessary parentheses
             println!("norm");
         }
 
     }
 
-    while(true && false) {
-        for _ in (0 .. 3){
+    while(true && false) { //~ ERROR unnecessary parentheses
+        for _ in (0 .. 3){ //~ ERROR unnecessary parentheses
             println!("e~")
         }
     }
 
-    for _ in (0 .. 3) {
-        while (true && false) {
+    for _ in (0 .. 3) { //~ ERROR unnecessary parentheses
+        while (true && false) { //~ ERROR unnecessary parentheses
             println!("e~")
         }
     }
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
index b4eab200dd0..873f105435e 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
@@ -1,666 +1,72 @@
-{
-  "message": "unnecessary parentheses around `if` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 521,
-      "byte_end": 525,
-      "line_start": 18,
-      "line_end": 18,
-      "column_start": 8,
-      "column_end": 12,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    if (_b) {",
-          "highlight_start": 8,
-          "highlight_end": 12
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "lint level defined here",
-      "code": null,
-      "level": "note",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 435,
-          "byte_end": 448,
-          "line_start": 11,
-          "line_end": 11,
-          "column_start": 9,
-          "column_end": 22,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "#![warn(unused_parens)]",
-              "highlight_start": 9,
-              "highlight_end": 22
-            }
-          ],
-          "label": null,
-          "suggested_replacement": null,
-          "suggestion_applicability": null,
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    },
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 521,
-          "byte_end": 525,
-          "line_start": 18,
-          "line_end": 18,
-          "column_start": 8,
-          "column_end": 12,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    if (_b) {",
-              "highlight_start": 8,
-              "highlight_end": 12
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "_b",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `if` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:18:8
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":"    if (_b) {
+  --> $DIR/unused_parens_remove_json_suggestion.rs:17:8
    |
 LL |     if (_b) {
    |        ^^^^ help: remove these parentheses
    |
 note: lint level defined here
-  --> $DIR/unused_parens_remove_json_suggestion.rs:11:9
+  --> $DIR/unused_parens_remove_json_suggestion.rs:10:9
    |
-LL | #![warn(unused_parens)]
+LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
 
-"
-}
-{
-  "message": "unnecessary parentheses around `if` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 618,
-      "byte_end": 621,
-      "line_start": 29,
-      "line_end": 29,
-      "column_start": 7,
-      "column_end": 10,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    if(c) {",
-          "highlight_start": 7,
-          "highlight_end": 10
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 618,
-          "byte_end": 621,
-          "line_start": 29,
-          "line_end": 29,
-          "column_start": 7,
-          "column_end": 10,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    if(c) {",
-              "highlight_start": 7,
-              "highlight_end": 10
-            }
-          ],
-          "label": null,
-          "suggested_replacement": " c",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `if` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:29:7
+"}
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":"    if(c) {
+  --> $DIR/unused_parens_remove_json_suggestion.rs:28:7
    |
 LL |     if(c) {
    |       ^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `if` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 664,
-      "byte_end": 667,
-      "line_start": 33,
-      "line_end": 33,
-      "column_start": 8,
-      "column_end": 11,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    if (c){",
-          "highlight_start": 8,
-          "highlight_end": 11
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 664,
-          "byte_end": 667,
-          "line_start": 33,
-          "line_end": 33,
-          "column_start": 8,
-          "column_end": 11,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    if (c){",
-              "highlight_start": 8,
-              "highlight_end": 11
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "c ",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `if` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:33:8
+"}
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":"    if (c){
+  --> $DIR/unused_parens_remove_json_suggestion.rs:32:8
    |
 LL |     if (c){
    |        ^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `while` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 712,
-      "byte_end": 727,
-      "line_start": 37,
-      "line_end": 37,
-      "column_start": 11,
-      "column_end": 26,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    while (false && true){",
-          "highlight_start": 11,
-          "highlight_end": 26
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 712,
-          "byte_end": 727,
-          "line_start": 37,
-          "line_end": 37,
-          "column_start": 11,
-          "column_end": 26,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    while (false && true){",
-              "highlight_start": 11,
-              "highlight_end": 26
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "false && true ",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `while` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:37:11
+"}
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+  --> $DIR/unused_parens_remove_json_suggestion.rs:36:11
    |
 LL |     while (false && true){
    |           ^^^^^^^^^^^^^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `if` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 740,
-      "byte_end": 743,
-      "line_start": 38,
-      "line_end": 38,
-      "column_start": 12,
-      "column_end": 15,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "        if (c) {",
-          "highlight_start": 12,
-          "highlight_end": 15
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 740,
-          "byte_end": 743,
-          "line_start": 38,
-          "line_end": 38,
-          "column_start": 12,
-          "column_end": 15,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "        if (c) {",
-              "highlight_start": 12,
-              "highlight_end": 15
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "c",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `if` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:38:12
+"}
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":"        if (c) {
+  --> $DIR/unused_parens_remove_json_suggestion.rs:37:12
    |
 LL |         if (c) {
    |            ^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `while` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 803,
-      "byte_end": 818,
-      "line_start": 44,
-      "line_end": 44,
-      "column_start": 10,
-      "column_end": 25,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    while(true && false) {",
-          "highlight_start": 10,
-          "highlight_end": 25
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 803,
-          "byte_end": 818,
-          "line_start": 44,
-          "line_end": 44,
-          "column_start": 10,
-          "column_end": 25,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    while(true && false) {",
-              "highlight_start": 10,
-              "highlight_end": 25
-            }
-          ],
-          "label": null,
-          "suggested_replacement": " true && false",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `while` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:44:10
+"}
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":"    while(true && false) {
+  --> $DIR/unused_parens_remove_json_suggestion.rs:43:10
    |
 LL |     while(true && false) {
    |          ^^^^^^^^^^^^^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `for` head expression",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 838,
-      "byte_end": 846,
-      "line_start": 45,
-      "line_end": 45,
-      "column_start": 18,
-      "column_end": 26,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "        for _ in (0 .. 3){",
-          "highlight_start": 18,
-          "highlight_end": 26
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 838,
-          "byte_end": 846,
-          "line_start": 45,
-          "line_end": 45,
-          "column_start": 18,
-          "column_end": 26,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "        for _ in (0 .. 3){",
-              "highlight_start": 18,
-              "highlight_end": 26
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "0 .. 3 ",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `for` head expression
-  --> $DIR/unused_parens_remove_json_suggestion.rs:45:18
+"}
+{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
+  --> $DIR/unused_parens_remove_json_suggestion.rs:44:18
    |
 LL |         for _ in (0 .. 3){
    |                  ^^^^^^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `for` head expression",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 905,
-      "byte_end": 913,
-      "line_start": 50,
-      "line_end": 50,
-      "column_start": 14,
-      "column_end": 22,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "    for _ in (0 .. 3) {",
-          "highlight_start": 14,
-          "highlight_end": 22
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 905,
-          "byte_end": 913,
-          "line_start": 50,
-          "line_end": 50,
-          "column_start": 14,
-          "column_end": 22,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "    for _ in (0 .. 3) {",
-              "highlight_start": 14,
-              "highlight_end": 22
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "0 .. 3",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `for` head expression
-  --> $DIR/unused_parens_remove_json_suggestion.rs:50:14
+"}
+{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
+  --> $DIR/unused_parens_remove_json_suggestion.rs:49:14
    |
 LL |     for _ in (0 .. 3) {
    |              ^^^^^^^^ help: remove these parentheses
 
-"
-}
-{
-  "message": "unnecessary parentheses around `while` condition",
-  "code": {
-    "code": "unused_parens",
-    "explanation": null
-  },
-  "level": "warning",
-  "spans": [
-    {
-      "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-      "byte_start": 930,
-      "byte_end": 945,
-      "line_start": 51,
-      "line_end": 51,
-      "column_start": 15,
-      "column_end": 30,
-      "is_primary": true,
-      "text": [
-        {
-          "text": "        while (true && false) {",
-          "highlight_start": 15,
-          "highlight_end": 30
-        }
-      ],
-      "label": null,
-      "suggested_replacement": null,
-      "suggestion_applicability": null,
-      "expansion": null
-    }
-  ],
-  "children": [
-    {
-      "message": "remove these parentheses",
-      "code": null,
-      "level": "help",
-      "spans": [
-        {
-          "file_name": "$DIR/unused_parens_remove_json_suggestion.rs",
-          "byte_start": 930,
-          "byte_end": 945,
-          "line_start": 51,
-          "line_end": 51,
-          "column_start": 15,
-          "column_end": 30,
-          "is_primary": true,
-          "text": [
-            {
-              "text": "        while (true && false) {",
-              "highlight_start": 15,
-              "highlight_end": 30
-            }
-          ],
-          "label": null,
-          "suggested_replacement": "true && false",
-          "suggestion_applicability": "MachineApplicable",
-          "expansion": null
-        }
-      ],
-      "children": [],
-      "rendered": null
-    }
-  ],
-  "rendered": "warning: unnecessary parentheses around `while` condition
-  --> $DIR/unused_parens_remove_json_suggestion.rs:51:15
+"}
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":"        while (true && false) {
+  --> $DIR/unused_parens_remove_json_suggestion.rs:50:15
    |
 LL |         while (true && false) {
    |               ^^^^^^^^^^^^^^^ help: remove these parentheses
 
-"
-}
+"}
+{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors
+
+"}
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr
index 7d5aa00356e..67ef7a62f10 100644
--- a/src/test/ui/object-safety/object-safety-associated-consts.stderr
+++ b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/object-safety-associated-consts.rs:9:1
+  --> $DIR/object-safety-associated-consts.rs:12:1
    |
 LL |     const X: usize;
    |           - the trait cannot contain associated consts like `X`
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..20993a680ba
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
@@ -0,0 +1,15 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-associated-consts.rs:14:5
+   |
+LL |     const X: usize;
+   |           - the trait cannot contain associated consts like `X`
+...
+LL |     t
+   |     ^ the trait `Bar` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required by cast to type `&dyn Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.rs b/src/test/ui/object-safety/object-safety-associated-consts.rs
index 5900019ea91..e1a772e5ab2 100644
--- a/src/test/ui/object-safety/object-safety-associated-consts.rs
+++ b/src/test/ui/object-safety/object-safety-associated-consts.rs
@@ -1,14 +1,18 @@
 // Check that we correctly prevent users from making trait objects
 // from traits with associated consts.
+//
+// revisions: curr object_safe_for_dispatch
 
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
 
 trait Bar {
     const X: usize;
 }
 
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
-    //~^ ERROR E0038
+    //[curr]~^ ERROR E0038
     t
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn main() {
diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.curr.stderr
index b25e0052e41..8ae9236a5c3 100644
--- a/src/test/ui/object-safety/object-safety-generics.stderr
+++ b/src/test/ui/object-safety/object-safety-generics.curr.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/object-safety-generics.rs:14:1
+  --> $DIR/object-safety-generics.rs:18:1
    |
 LL |     fn bar<T>(&self, t: T);
    |        --- method `bar` has generic type parameters
@@ -8,7 +8,7 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
 
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/object-safety-generics.rs:19:1
+  --> $DIR/object-safety-generics.rs:24:1
    |
 LL |     fn bar<T>(&self, t: T);
    |        --- method `bar` has generic type parameters
diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..d3d8d368888
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
@@ -0,0 +1,27 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-generics.rs:20:5
+   |
+LL |     fn bar<T>(&self, t: T);
+   |        --- method `bar` has generic type parameters
+...
+LL |     t
+   |     ^ the trait `Bar` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required by cast to type `&dyn Bar`
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-generics.rs:26:5
+   |
+LL |     fn bar<T>(&self, t: T);
+   |        --- method `bar` has generic type parameters
+...
+LL |     t as &dyn Bar
+   |     ^ the trait `Bar` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required by cast to type `&dyn Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-generics.rs b/src/test/ui/object-safety/object-safety-generics.rs
index d63ea28c8f2..63dcd169925 100644
--- a/src/test/ui/object-safety/object-safety-generics.rs
+++ b/src/test/ui/object-safety/object-safety-generics.rs
@@ -1,6 +1,10 @@
 // Check that we correctly prevent users from making trait objects
 // from traits with generic methods, unless `where Self : Sized` is
 // present.
+// revisions: curr object_safe_for_dispatch
+
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
+
 
 trait Bar {
     fn bar<T>(&self, t: T);
@@ -12,13 +16,15 @@ trait Quux {
 }
 
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
-        //~^ ERROR E0038
+    //[curr]~^ ERROR E0038
     t
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
-    //~^ ERROR E0038
+    //[curr]~^ ERROR E0038
     t as &dyn Bar
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
index 971e79cb021..297cd876187 100644
--- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/object-safety-mentions-Self.rs:17:1
+  --> $DIR/object-safety-mentions-Self.rs:22:1
    |
 LL |     fn bar(&self, x: &Self);
    |        --- method `bar` references the `Self` type in its parameters or return type
@@ -8,10 +8,10 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
 
 error[E0038]: the trait `Baz` cannot be made into an object
-  --> $DIR/object-safety-mentions-Self.rs:22:1
+  --> $DIR/object-safety-mentions-Self.rs:28:1
    |
-LL |     fn bar(&self) -> Self;
-   |        --- method `bar` references the `Self` type in its parameters or return type
+LL |     fn baz(&self) -> Self;
+   |        --- method `baz` references the `Self` type in its parameters or return type
 ...
 LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..03b2b8da075
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
@@ -0,0 +1,27 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-mentions-Self.rs:24:5
+   |
+LL |     fn bar(&self, x: &Self);
+   |        --- method `bar` references the `Self` type in its parameters or return type
+...
+LL |     t
+   |     ^ the trait `Bar` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required by cast to type `&dyn Bar`
+
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/object-safety-mentions-Self.rs:30:5
+   |
+LL |     fn baz(&self) -> Self;
+   |        --- method `baz` references the `Self` type in its parameters or return type
+...
+LL |     t
+   |     ^ the trait `Baz` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Baz>` for `&T`
+   = note: required by cast to type `&dyn Baz`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.rs b/src/test/ui/object-safety/object-safety-mentions-Self.rs
index f13ffe53626..412d16ff3c7 100644
--- a/src/test/ui/object-safety/object-safety-mentions-Self.rs
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.rs
@@ -1,27 +1,34 @@
 // Check that we correctly prevent users from making trait objects
 // form traits that make use of `Self` in an argument or return
 // position, unless `where Self : Sized` is present..
+//
+// revisions: curr object_safe_for_dispatch
+
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
+
 
 trait Bar {
     fn bar(&self, x: &Self);
 }
 
 trait Baz {
-    fn bar(&self) -> Self;
+    fn baz(&self) -> Self;
 }
 
 trait Quux {
-    fn get(&self, s: &Self) -> Self where Self : Sized;
+    fn quux(&self, s: &Self) -> Self where Self : Sized;
 }
 
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
-        //~^ ERROR E0038
-    loop { }
+    //[curr]~^ ERROR E0038
+    t
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
-        //~^ ERROR E0038
+    //[curr]~^ ERROR E0038
     t
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
@@ -32,5 +39,4 @@ fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
     t as &dyn Quux
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/object-safety/object-safety-no-static.curr.stderr b/src/test/ui/object-safety/object-safety-no-static.curr.stderr
new file mode 100644
index 00000000000..1641ce57771
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-no-static.curr.stderr
@@ -0,0 +1,12 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-no-static.rs:12:1
+   |
+LL |     fn foo() {}
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn diverges() -> Box<dyn Foo> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..91a9285b63c
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
@@ -0,0 +1,15 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-no-static.rs:22:27
+   |
+LL |     fn foo() {}
+   |        --- associated function `foo` has no `self` parameter
+...
+LL |     let b: Box<dyn Foo> = Box::new(Bar);
+   |                           ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<Bar>`
+   = note: required by cast to type `std::boxed::Box<dyn Foo>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-no-static.rs b/src/test/ui/object-safety/object-safety-no-static.rs
index 55d31ce8087..03b62217483 100644
--- a/src/test/ui/object-safety/object-safety-no-static.rs
+++ b/src/test/ui/object-safety/object-safety-no-static.rs
@@ -1,14 +1,24 @@
 // Check that we correctly prevent users from making trait objects
 // from traits with static methods.
+//
+// revisions: curr object_safe_for_dispatch
+
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
 
 trait Foo {
-    fn foo();
+    fn foo() {}
 }
 
-fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
-    //~^ ERROR E0038
+fn diverges() -> Box<dyn Foo> {
+    //[curr]~^ ERROR E0038
     loop { }
 }
 
+struct Bar;
+
+impl Foo for Bar {}
+
 fn main() {
+    let b: Box<dyn Foo> = Box::new(Bar);
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
diff --git a/src/test/ui/object-safety/object-safety-sized-2.stderr b/src/test/ui/object-safety/object-safety-sized-2.curr.stderr
index dcaf2ff0bc2..1e1d2bf64c4 100644
--- a/src/test/ui/object-safety/object-safety-sized-2.stderr
+++ b/src/test/ui/object-safety/object-safety-sized-2.curr.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/object-safety-sized-2.rs:10:1
+  --> $DIR/object-safety-sized-2.rs:14:1
    |
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
diff --git a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..06ecfd019c8
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
@@ -0,0 +1,13 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-sized-2.rs:16:5
+   |
+LL |     t
+   |     ^ the trait `Bar` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required by cast to type `&dyn Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-sized-2.rs b/src/test/ui/object-safety/object-safety-sized-2.rs
index 7235b22404e..1e79b8cd917 100644
--- a/src/test/ui/object-safety/object-safety-sized-2.rs
+++ b/src/test/ui/object-safety/object-safety-sized-2.rs
@@ -1,5 +1,9 @@
 // Check that we correctly prevent users from making trait objects
 // from traits where `Self : Sized`.
+//
+// revisions: curr object_safe_for_dispatch
+
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
 
 trait Bar
     where Self : Sized
@@ -8,8 +12,9 @@ trait Bar
 }
 
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
-        //~^ ERROR E0038
-    loop { }
+    //[curr]~^ ERROR E0038
+    t
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn main() {
diff --git a/src/test/ui/object-safety/object-safety-sized.stderr b/src/test/ui/object-safety/object-safety-sized.curr.stderr
index 98bc73e38d4..1a67e79e83d 100644
--- a/src/test/ui/object-safety/object-safety-sized.stderr
+++ b/src/test/ui/object-safety/object-safety-sized.curr.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/object-safety-sized.rs:8:1
+  --> $DIR/object-safety-sized.rs:12:1
    |
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
diff --git a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..3d88dfc40ed
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
@@ -0,0 +1,13 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/object-safety-sized.rs:14:5
+   |
+LL |     t
+   |     ^ the trait `Bar` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required by cast to type `&dyn Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/object-safety-sized.rs b/src/test/ui/object-safety/object-safety-sized.rs
index 1312bb34717..b424b892d3b 100644
--- a/src/test/ui/object-safety/object-safety-sized.rs
+++ b/src/test/ui/object-safety/object-safety-sized.rs
@@ -1,13 +1,18 @@
 // Check that we correctly prevent users from making trait objects
 // from traits where `Self : Sized`.
+//
+// revisions: curr object_safe_for_dispatch
+
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
 
 trait Bar : Sized {
     fn bar<T>(&self, t: T);
 }
 
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
-        //~^ ERROR E0038
+    //[curr]~^ ERROR E0038
     t
+    //[object_safe_for_dispatch]~^ ERROR E0038
 }
 
 fn main() {
diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr
index 219516d8abc..df001d6b5f2 100644
--- a/src/test/ui/repr/repr-packed-contains-align.stderr
+++ b/src/test/ui/repr/repr-packed-contains-align.stderr
@@ -56,3 +56,4 @@ LL | | }
 
 error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0588`.
diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs
new file mode 100644
index 00000000000..fa04f4b12d5
--- /dev/null
+++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs
@@ -0,0 +1,23 @@
+// Check that we if we get ahold of an object unsafe trait
+// object with auto traits and lifetimes, we can downcast it
+//
+// check-pass
+
+#![feature(object_safe_for_dispatch)]
+
+trait Trait: Sized {}
+
+fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait {
+    t
+}
+
+fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't))
+                                 -> &'b (dyn Trait + 't)
+where
+    'a: 'b,
+    't: 'a + 'b,
+{
+    t
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
new file mode 100644
index 00000000000..1dea4012265
--- /dev/null
+++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
@@ -0,0 +1,69 @@
+// Check that we can manually implement an object
+// unsafe trait for its trait object
+//
+// run-pass
+
+#![feature(object_safe_for_dispatch)]
+
+trait Bad {
+    fn stat() -> char {
+        'A'
+    }
+    fn virt(&self) -> char {
+        'B'
+    }
+    fn indirect(&self) -> char {
+        Self::stat()
+    }
+}
+
+trait Good {
+    fn good_virt(&self) -> char {
+        panic!()
+    }
+    fn good_indirect(&self) -> char {
+        panic!()
+    }
+}
+
+impl<'a> Bad for dyn Bad + 'a {
+    fn stat() -> char {
+        'C'
+    }
+    fn virt(&self) -> char {
+        'D'
+    }
+}
+
+struct Struct {}
+
+impl Bad for Struct {}
+
+impl Good for Struct {}
+
+fn main() {
+    let s = Struct {};
+
+    let mut res = String::new();
+
+    // Directly call static
+    res.push(Struct::stat()); // "A"
+    res.push(<dyn Bad>::stat()); // "AC"
+
+    let good: &dyn Good = &s;
+
+    // These look similar enough...
+    let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) };
+
+    // Call virtual
+    res.push(s.virt()); // "ACB"
+    res.push(bad.virt()); // "ACBD"
+
+    // Indirectly call static
+    res.push(s.indirect()); // "ACBDA"
+    res.push(bad.indirect()); // "ACBDAC"
+
+    if &res != "ACBDAC" {
+        panic!();
+    }
+}
diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs
new file mode 100644
index 00000000000..df97d2c1327
--- /dev/null
+++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs
@@ -0,0 +1,37 @@
+// Check that we can statically dispatch methods for object
+// unsafe trait objects, directly and indirectly
+//
+// check-pass
+
+#![feature(object_safe_for_dispatch)]
+
+trait Statics {
+    fn plain() {}
+    fn generic<T>() {}
+}
+
+trait Trait: Sized {}
+
+impl<'a> Statics for dyn Trait + 'a {}
+
+fn static_poly<T: Statics + ?Sized>() {
+    T::plain();
+    T::generic::<usize>();
+}
+
+fn inferred_poly<T: Statics + ?Sized>(t: &T) {
+    static_poly::<T>();
+    T::plain();
+    T::generic::<usize>();
+}
+
+fn call(t: &dyn Trait) {
+    static_poly::<dyn Trait>();
+    inferred_poly(t);
+}
+
+fn main() {
+    static_poly::<dyn Trait>();
+    <dyn Trait>::plain();
+    <dyn Trait>::generic::<usize>()
+}
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
new file mode 100644
index 00000000000..cdffc1d86ed
--- /dev/null
+++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
@@ -0,0 +1,24 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:34:32
+   |
+LL |     fn foo(self: &Rc<Self>) -> usize;
+   |        --- method `foo`'s `self` parameter cannot be dispatched on
+...
+LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
+   |                                ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
+   |
+LL |     fn foo(self: &Rc<Self>) -> usize;
+   |        --- method `foo`'s `self` parameter cannot be dispatched on
+...
+LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
+   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
+   = note: required by cast to type `std::rc::Rc<dyn Foo>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
new file mode 100644
index 00000000000..725632a1212
--- /dev/null
+++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
@@ -0,0 +1,15 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
+   |
+LL |     fn foo(self: &Rc<Self>) -> usize;
+   |        --- method `foo`'s `self` parameter cannot be dispatched on
+...
+LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
+   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+   |
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
+   = note: required by cast to type `std::rc::Rc<dyn Foo>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs
index 7443d888c9e..2eeabad28db 100644
--- a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs
+++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs
@@ -1,3 +1,6 @@
+// revisions: curr object_safe_for_dispatch
+
+#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
 #![feature(arbitrary_self_types)]
 
 use std::rc::Rc;
@@ -29,8 +32,9 @@ impl Bar for usize {
 
 fn make_foo() {
     let x = Rc::new(5usize) as Rc<dyn Foo>;
-    //~^ ERROR E0038
-    //~| ERROR E0038
+    //[curr]~^ ERROR E0038
+    //[curr]~| ERROR E0038
+    //[object_safe_for_dispatch]~^^^ ERROR E0038
 }
 
 fn make_bar() {
diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/signal-alternate-stack-cleanup.rs
index 787ff51799a..8fef66eac8d 100644
--- a/src/test/ui/signal-alternate-stack-cleanup.rs
+++ b/src/test/ui/signal-alternate-stack-cleanup.rs
@@ -7,6 +7,7 @@
 // ignore-wasm32-bare no libc
 // ignore-windows
 // ignore-sgx no libc
+// ignore-vxworks no SIGWINCH in user space
 
 #![feature(rustc_private)]
 extern crate libc;
diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs
index c4e9e9ea5ee..680a690ba34 100644
--- a/src/test/ui/structs-enums/rec-align-u64.rs
+++ b/src/test/ui/structs-enums/rec-align-u64.rs
@@ -40,7 +40,8 @@ struct Outer {
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "vxworks"))]
 mod m {
     #[cfg(target_arch = "x86")]
     pub mod m {
diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr
index 3ac1e96b30c..028e9eedd64 100644
--- a/src/test/ui/traits/trait-object-safety.stderr
+++ b/src/test/ui/traits/trait-object-safety.stderr
@@ -8,6 +8,7 @@ LL |     let _: &dyn Tr = &St;
    |                      ^^^ the trait `Tr` cannot be made into an object
    |
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
+   = note: required by cast to type `&dyn Tr`
 
 error[E0038]: the trait `Tr` cannot be made into an object
   --> $DIR/trait-object-safety.rs:15:12
diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr
index 83c2c065274..9b750d382ec 100644
--- a/src/test/ui/traits/trait-test-2.stderr
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -33,6 +33,7 @@ LL |     (box 10 as Box<dyn bar>).dup();
    |      ^^^^^^ the trait `bar` cannot be made into an object
    |
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
+   = note: required by cast to type `std::boxed::Box<dyn bar>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
new file mode 100644
index 00000000000..12eb75ae4c0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type T = impl Sized;
+// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed
+// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive;
+// so difference assertion should not be declared on impl-trait-type-alias's instances.
+// for details, check RFC-2515:
+// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md
+
+fn take(_: fn() -> T) {}
+
+fn main() {
+    take(|| {});
+    take(|| {});
+}
diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs
new file mode 100644
index 00000000000..ffdb49a3be5
--- /dev/null
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs
@@ -0,0 +1,18 @@
+// Check that we do not allow casts or coercions
+// to object unsafe trait objects inside a Box
+
+#![feature(object_safe_for_dispatch)]
+
+trait Trait: Sized {}
+
+struct S;
+
+impl Trait for S {}
+
+fn takes_box(t: Box<dyn Trait>) {}
+
+fn main() {
+    Box::new(S) as Box<dyn Trait>; //~ ERROR E0038
+    let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038
+    takes_box(Box::new(S)); //~ ERROR E0038
+}
diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
new file mode 100644
index 00000000000..0b63aef2bce
--- /dev/null
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
@@ -0,0 +1,33 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33
+   |
+LL |     let t_box: Box<dyn Trait> = Box::new(S);
+   |                                 ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
+   = note: required by cast to type `std::boxed::Box<dyn Trait>`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15
+   |
+LL |     takes_box(Box::new(S));
+   |               ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
+   = note: required by cast to type `std::boxed::Box<(dyn Trait + 'static)>`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5
+   |
+LL |     Box::new(S) as Box<dyn Trait>;
+   |     ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
+   = note: required by cast to type `std::boxed::Box<dyn Trait>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs
new file mode 100644
index 00000000000..143b854ed6b
--- /dev/null
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs
@@ -0,0 +1,18 @@
+// Check that we do not allow casts or coercions
+// to object unsafe trait objects by ref
+
+#![feature(object_safe_for_dispatch)]
+
+trait Trait: Sized {}
+
+struct S;
+
+impl Trait for S {}
+
+fn takes_trait(t: &dyn Trait) {}
+
+fn main() {
+    &S as &dyn Trait; //~ ERROR E0038
+    let t: &dyn Trait = &S; //~ ERROR E0038
+    takes_trait(&S); //~ ERROR E0038
+}
diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
new file mode 100644
index 00000000000..7aeefd731fb
--- /dev/null
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
@@ -0,0 +1,33 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25
+   |
+LL |     let t: &dyn Trait = &S;
+   |                         ^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required by cast to type `&dyn Trait`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17
+   |
+LL |     takes_trait(&S);
+   |                 ^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required by cast to type `&dyn Trait`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5
+   |
+LL |     &S as &dyn Trait;
+   |     ^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required by cast to type `&dyn Trait`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.rs b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs
new file mode 100644
index 00000000000..c8731a8ecaf
--- /dev/null
+++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs
@@ -0,0 +1,29 @@
+// Check that we do not allow coercions to object
+// unsafe trait objects in match arms
+
+#![feature(object_safe_for_dispatch)]
+
+trait Trait: Sized {}
+
+struct S;
+
+impl Trait for S {}
+
+struct R;
+
+impl Trait for R {}
+
+fn opt() -> Option<()> {
+    Some(())
+}
+
+fn main() {
+    match opt() {
+        Some(()) => &S,
+        None => &R,  //~ ERROR E0308
+    }
+    let t: &dyn Trait = match opt() { //~ ERROR E0038
+        Some(()) => &S, //~ ERROR E0038
+        None => &R,
+    };
+}
diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
new file mode 100644
index 00000000000..185b1e6c36b
--- /dev/null
+++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -0,0 +1,38 @@
+error[E0308]: match arms have incompatible types
+  --> $DIR/wf-unsafe-trait-obj-match.rs:23:17
+   |
+LL | /     match opt() {
+LL | |         Some(()) => &S,
+   | |                     -- this is found to be of type `&S`
+LL | |         None => &R,
+   | |                 ^^ expected struct `S`, found struct `R`
+LL | |     }
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `&S`
+              found type `&R`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-unsafe-trait-obj-match.rs:26:21
+   |
+LL |         Some(()) => &S,
+   |                     ^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required by cast to type `&dyn Trait`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/wf-unsafe-trait-obj-match.rs:25:25
+   |
+LL |     let t: &dyn Trait = match opt() {
+   |                         ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
+   |
+   = note: the trait cannot require that `Self : Sized`
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&R`
+   = note: required by cast to type `&dyn Trait`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0308.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index bc6c1973870..2a189a92f4b 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -401,6 +401,7 @@ impl Builder {
     fn add_packages_to(&mut self, manifest: &mut Manifest) {
         let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets);
         package("rustc", HOSTS);
+        package("rustc-dev", HOSTS);
         package("cargo", HOSTS);
         package("rust-mingw", MINGW);
         package("rust-std", TARGETS);
@@ -428,6 +429,13 @@ impl Builder {
             "rls-preview", "rust-src", "llvm-tools-preview",
             "lldb-preview", "rust-analysis", "miri-preview"
         ]);
+
+        // The compiler libraries are not stable for end users, but `rustc-dev` was only recently
+        // split out of `rust-std`. We'll include it by default as a transition for nightly users.
+        if self.rust_release == "nightly" {
+            self.extend_profile("default", &mut manifest.profiles, &["rustc-dev"]);
+            self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]);
+        }
     }
 
     fn add_renames_to(&self, manifest: &mut Manifest) {
@@ -483,6 +491,15 @@ impl Builder {
             components.push(host_component("rust-mingw"));
         }
 
+        // The compiler libraries are not stable for end users, but `rustc-dev` was only recently
+        // split out of `rust-std`. We'll include it by default as a transition for nightly users,
+        // but ship it as an optional component on the beta and stable channels.
+        if self.rust_release == "nightly" {
+            components.push(host_component("rustc-dev"));
+        } else {
+            extensions.push(host_component("rustc-dev"));
+        }
+
         // Tools are always present in the manifest,
         // but might be marked as unavailable if they weren't built.
         extensions.extend(vec![
@@ -500,6 +517,11 @@ impl Builder {
                 .filter(|&&target| target != host)
                 .map(|target| Component::from_str("rust-std", target))
         );
+        extensions.extend(
+            HOSTS.iter()
+                .filter(|&&target| target != host)
+                .map(|target| Component::from_str("rustc-dev", target))
+        );
         extensions.push(Component::from_str("rust-src", "*"));
 
         // If the components/extensions don't actually exist for this
@@ -536,6 +558,14 @@ impl Builder {
         dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect());
     }
 
+    fn extend_profile(&mut self,
+               profile_name: &str,
+               dst: &mut BTreeMap<String, Vec<String>>,
+               pkgs: &[&str]) {
+        dst.get_mut(profile_name).expect("existing profile")
+            .extend(pkgs.iter().map(|s| (*s).to_owned()));
+    }
+
     fn package(&mut self,
                pkgname: &str,
                dst: &mut BTreeMap<String, Package>,
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 3a9abe3f065554a7fbc59f440df2baba4a6e47e
+Subproject 3ba5f27170db10af7a92f2b682e049397197b8f
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject cbedd97b3a58023eff365a2fa74700d06115144
+Subproject e8d5a9e95c145a3a9be89c582d8a6f88d4ea703
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index e8a7252cb76..79c98b780eb 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -126,7 +126,6 @@ fn check(cache: &mut Cache,
     // FIXME(#32129)
     if file.ends_with("std/string/struct.String.html") ||
        file.ends_with("interpret/struct.ImmTy.html") ||
-       file.ends_with("symbol/struct.InternedString.html") ||
        file.ends_with("ast/struct.ThinVec.html") ||
        file.ends_with("util/struct.ThinVec.html") ||
        file.ends_with("layout/struct.TyLayout.html") ||