about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock78
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/check.rs2
-rw-r--r--src/bootstrap/compile.rs80
-rw-r--r--src/bootstrap/config.rs8
-rw-r--r--src/bootstrap/dist.rs4
-rw-r--r--src/bootstrap/doc.rs90
-rw-r--r--src/bootstrap/flags.rs13
-rw-r--r--src/bootstrap/native.rs115
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/bootstrap/tool.rs20
-rw-r--r--src/build_helper/lib.rs104
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md163
-rw-r--r--src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md5
-rw-r--r--src/libcore/result.rs38
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/libcore/tests/result.rs22
-rw-r--r--src/libpanic_unwind/emcc.rs2
-rw-r--r--src/librustc/Cargo.toml3
-rw-r--r--src/librustc/dep_graph/graph.rs38
-rw-r--r--src/librustc/hir/check_attr.rs2
-rw-r--r--src/librustc/infer/error_reporting/mod.rs10
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs12
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs2
-rw-r--r--src/librustc/infer/error_reporting/note.rs2
-rw-r--r--src/librustc/infer/mod.rs2
-rw-r--r--src/librustc/infer/opaque_types/mod.rs2
-rw-r--r--src/librustc/lint/context.rs140
-rw-r--r--src/librustc/lint/internal.rs8
-rw-r--r--src/librustc/lint/levels.rs6
-rw-r--r--src/librustc/lint/mod.rs106
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc/middle/stability.rs9
-rw-r--r--src/librustc/middle/weak_lang_items.rs2
-rw-r--r--src/librustc/mir/interpret/error.rs2
-rw-r--r--src/librustc/query/mod.rs4
-rw-r--r--src/librustc/traits/coherence.rs2
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc/traits/on_unimplemented.rs2
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs2
-rw-r--r--src/librustc/traits/select.rs2
-rw-r--r--src/librustc/traits/specialize/mod.rs2
-rw-r--r--src/librustc/traits/util.rs2
-rw-r--r--src/librustc/ty/context.rs4
-rw-r--r--src/librustc/ty/error.rs4
-rw-r--r--src/librustc/ty/query/config.rs5
-rw-r--r--src/librustc/ty/query/mod.rs3
-rw-r--r--src/librustc/ty/query/on_disk_cache.rs2
-rw-r--r--src/librustc/ty/query/plumbing.rs147
-rw-r--r--src/librustc/ty/query/profiling_support.rs235
-rw-r--r--src/librustc/ty/util.rs95
-rw-r--r--src/librustc/util/common.rs2
-rw-r--r--src/librustc_asan/Cargo.toml20
-rw-r--r--src/librustc_asan/build.rs30
-rw-r--r--src/librustc_asan/lib.rs10
-rw-r--r--src/librustc_ast_lowering/lib.rs8
-rw-r--r--src/librustc_ast_lowering/pat.rs13
-rw-r--r--src/librustc_ast_lowering/path.rs7
-rw-r--r--src/librustc_ast_passes/Cargo.toml20
-rw-r--r--src/librustc_ast_passes/ast_validation.rs (renamed from src/librustc_passes/ast_validation.rs)27
-rw-r--r--src/librustc_ast_passes/feature_gate.rs (renamed from src/libsyntax/feature_gate/check.rs)252
-rw-r--r--src/librustc_ast_passes/lib.rs9
-rw-r--r--src/librustc_ast_passes/show_span.rs (renamed from src/libsyntax/show_span.rs)10
-rw-r--r--src/librustc_builtin_macros/Cargo.toml3
-rw-r--r--src/librustc_builtin_macros/asm.rs2
-rw-r--r--src/librustc_builtin_macros/assert.rs2
-rw-r--r--src/librustc_builtin_macros/cfg.rs8
-rw-r--r--src/librustc_builtin_macros/deriving/default.rs2
-rw-r--r--src/librustc_builtin_macros/format.rs7
-rw-r--r--src/librustc_builtin_macros/global_asm.rs20
-rw-r--r--src/librustc_builtin_macros/proc_macro_harness.rs4
-rw-r--r--src/librustc_builtin_macros/source_util.rs4
-rw-r--r--src/librustc_builtin_macros/test_harness.rs4
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs15
-rw-r--r--src/librustc_codegen_ssa/back/link.rs138
-rw-r--r--src/librustc_codegen_ssa/back/write.rs9
-rw-r--r--src/librustc_codegen_ssa/base.rs23
-rw-r--r--src/librustc_codegen_ssa/lib.rs1
-rw-r--r--src/librustc_data_structures/Cargo.toml2
-rw-r--r--src/librustc_data_structures/profiling.rs226
-rw-r--r--src/librustc_driver/Cargo.toml2
-rw-r--r--src/librustc_driver/lib.rs16
-rw-r--r--src/librustc_expand/Cargo.toml4
-rw-r--r--src/librustc_expand/base.rs13
-rw-r--r--src/librustc_expand/expand.rs10
-rw-r--r--src/librustc_expand/lib.rs2
-rw-r--r--src/librustc_expand/mbe/macro_check.rs8
-rw-r--r--src/librustc_expand/mbe/macro_parser.rs2
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs9
-rw-r--r--src/librustc_expand/mbe/transcribe.rs12
-rw-r--r--src/librustc_expand/parse/lexer/tests.rs2
-rw-r--r--src/librustc_expand/parse/tests.rs2
-rw-r--r--src/librustc_expand/proc_macro.rs7
-rw-r--r--src/librustc_expand/proc_macro_server.rs17
-rw-r--r--src/librustc_expand/tests.rs4
-rw-r--r--src/librustc_feature/active.rs6
-rw-r--r--src/librustc_feature/builtin_attrs.rs5
-rw-r--r--src/librustc_feature/removed.rs2
-rw-r--r--src/librustc_hir/hir.rs2
-rw-r--r--src/librustc_hir/intravisit.rs4
-rw-r--r--src/librustc_hir/print.rs10
-rw-r--r--src/librustc_incremental/persist/fs.rs4
-rw-r--r--src/librustc_incremental/persist/load.rs2
-rw-r--r--src/librustc_interface/Cargo.toml2
-rw-r--r--src/librustc_interface/interface.rs14
-rw-r--r--src/librustc_interface/passes.rs45
-rw-r--r--src/librustc_interface/queries.rs14
-rw-r--r--src/librustc_interface/util.rs16
-rw-r--r--src/librustc_lint/Cargo.toml1
-rw-r--r--src/librustc_lint/array_into_iter.rs5
-rw-r--r--src/librustc_lint/builtin.rs29
-rw-r--r--src/librustc_lint/early.rs8
-rw-r--r--src/librustc_lint/late.rs6
-rw-r--r--src/librustc_lint/lib.rs3
-rw-r--r--src/librustc_lint/non_ascii_idents.rs2
-rw-r--r--src/librustc_lint/nonstandard_style.rs6
-rw-r--r--src/librustc_lint/redundant_semicolon.rs4
-rw-r--r--src/librustc_lint/types.rs8
-rw-r--r--src/librustc_lint/unused.rs7
-rw-r--r--src/librustc_lsan/Cargo.toml20
-rw-r--r--src/librustc_lsan/build.rs29
-rw-r--r--src/librustc_lsan/lib.rs10
-rw-r--r--src/librustc_metadata/Cargo.toml2
-rw-r--r--src/librustc_metadata/creader.rs123
-rw-r--r--src/librustc_metadata/locator.rs2
-rw-r--r--src/librustc_metadata/native_libs.rs4
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs4
-rw-r--r--src/librustc_metadata/rmeta/decoder/cstore_impl.rs1
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs1
-rw-r--r--src/librustc_metadata/rmeta/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs3
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs2
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs162
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs2
-rw-r--r--src/librustc_msan/Cargo.toml20
-rw-r--r--src/librustc_msan/build.rs29
-rw-r--r--src/librustc_msan/lib.rs10
-rw-r--r--src/librustc_parse/Cargo.toml1
-rw-r--r--src/librustc_parse/config.rs184
-rw-r--r--src/librustc_parse/lexer/unescape_error_reporting.rs3
-rw-r--r--src/librustc_parse/parser/diagnostics.rs6
-rw-r--r--src/librustc_parse/parser/expr.rs4
-rw-r--r--src/librustc_parse/parser/pat.rs319
-rw-r--r--src/librustc_parse/validate_attr.rs4
-rw-r--r--src/librustc_passes/Cargo.toml4
-rw-r--r--src/librustc_passes/check_const.rs4
-rw-r--r--src/librustc_passes/entry.rs2
-rw-r--r--src/librustc_passes/intrinsicck.rs2
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_passes/lib_features.rs2
-rw-r--r--src/librustc_passes/liveness.rs4
-rw-r--r--src/librustc_passes/loops.rs2
-rw-r--r--src/librustc_passes/stability.rs4
-rw-r--r--src/librustc_resolve/Cargo.toml6
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs18
-rw-r--r--src/librustc_resolve/check_unused.rs5
-rw-r--r--src/librustc_resolve/diagnostics.rs2
-rw-r--r--src/librustc_resolve/imports.rs6
-rw-r--r--src/librustc_resolve/late.rs6
-rw-r--r--src/librustc_resolve/late/diagnostics.rs10
-rw-r--r--src/librustc_resolve/lib.rs28
-rw-r--r--src/librustc_resolve/lifetimes.rs2
-rw-r--r--src/librustc_resolve/macros.rs2
-rw-r--r--src/librustc_session/Cargo.toml1
-rw-r--r--src/librustc_session/lint.rs123
-rw-r--r--src/librustc_session/lint/builtin.rs (renamed from src/librustc/lint/builtin.rs)175
-rw-r--r--src/librustc_session/parse.rs94
-rw-r--r--src/librustc_session/session.rs26
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/librustc_target/spec/mod.rs6
-rw-r--r--src/librustc_tsan/Cargo.toml20
-rw-r--r--src/librustc_tsan/build.rs30
-rw-r--r--src/librustc_tsan/lib.rs10
-rw-r--r--src/librustc_typeck/Cargo.toml2
-rw-r--r--src/librustc_typeck/astconv.rs13
-rw-r--r--src/librustc_typeck/check/autoderef.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs12
-rw-r--r--src/librustc_typeck/check/cast.rs2
-rw-r--r--src/librustc_typeck/check/coercion.rs9
-rw-r--r--src/librustc_typeck/check/compare_method.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs2
-rw-r--r--src/librustc_typeck/check/dropck.rs2
-rw-r--r--src/librustc_typeck/check/expr.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs2
-rw-r--r--src/librustc_typeck/check/method/mod.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/method/suggest.rs7
-rw-r--r--src/librustc_typeck/check/mod.rs6
-rw-r--r--src/librustc_typeck/check/op.rs8
-rw-r--r--src/librustc_typeck/check/pat.rs110
-rw-r--r--src/librustc_typeck/check/wfcheck.rs6
-rw-r--r--src/librustc_typeck/check_unused.rs8
-rw-r--r--src/librustc_typeck/coherence/builtin.rs2
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs2
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs2
-rw-r--r--src/librustc_typeck/coherence/mod.rs7
-rw-r--r--src/librustc_typeck/coherence/orphan.rs2
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs2
-rw-r--r--src/librustc_typeck/collect.rs10
-rw-r--r--src/librustc_typeck/impl_wf_check.rs2
-rw-r--r--src/librustc_typeck/lib.rs2
-rw-r--r--src/librustc_typeck/outlives/test.rs2
-rw-r--r--src/librustc_typeck/structured_errors.rs6
-rw-r--r--src/librustc_typeck/variance/test.rs2
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/core.rs13
-rw-r--r--src/librustdoc/docfs.rs4
-rw-r--r--src/librustdoc/externalfiles.rs7
-rw-r--r--src/librustdoc/html/render.rs5
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/markdown.rs5
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
-rw-r--r--src/librustdoc/test.rs4
-rw-r--r--src/librustdoc/theme.rs2
-rw-r--r--src/libstd/Cargo.toml10
-rw-r--r--src/libstd/sys/hermit/os.rs9
-rw-r--r--src/libstd/sys/hermit/thread_local.rs4
-rw-r--r--src/libstd/sys/sgx/abi/tls.rs2
-rw-r--r--src/libstd/sys/unix/os.rs10
-rw-r--r--src/libstd/sys/vxworks/os.rs7
-rw-r--r--src/libstd/sys/wasi/os.rs11
-rw-r--r--src/libstd/sys/windows/os.rs2
-rw-r--r--src/libsyntax/Cargo.toml2
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/attr/builtin.rs5
-rw-r--r--src/libsyntax/attr/mod.rs2
-rw-r--r--src/libsyntax/early_buffered_lints.rs30
-rw-r--r--src/libsyntax/lib.rs8
-rw-r--r--src/libsyntax/mut_visit.rs4
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/test/run-make-fulldeps/sanitizer-address/Makefile2
-rw-r--r--src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile16
-rw-r--r--src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs3
-rw-r--r--src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile2
-rw-r--r--src/test/run-make-fulldeps/sanitizer-leak/Makefile2
-rw-r--r--src/test/run-make-fulldeps/sanitizer-memory/Makefile4
-rw-r--r--src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs5
-rw-r--r--src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr4
-rw-r--r--src/test/ui/associated-const/associated-const-no-item.rs2
-rw-r--r--src/test/ui/associated-item/associated-item-enum.stderr6
-rw-r--r--src/test/ui/auto-ref-slice-plus-ref.stderr8
-rw-r--r--src/test/ui/block-result/issue-3563.rs2
-rw-r--r--src/test/ui/block-result/issue-3563.stderr2
-rw-r--r--src/test/ui/bogus-tag.stderr2
-rw-r--r--src/test/ui/class-cast-to-trait.stderr2
-rw-r--r--src/test/ui/coherence/coherence_inherent.stderr2
-rw-r--r--src/test/ui/coherence/coherence_inherent_cc.stderr2
-rw-r--r--src/test/ui/confuse-field-and-method/issue-18343.stderr2
-rw-r--r--src/test/ui/confuse-field-and-method/issue-2392.stderr22
-rw-r--r--src/test/ui/confuse-field-and-method/issue-32128.stderr2
-rw-r--r--src/test/ui/confuse-field-and-method/issue-33784.stderr6
-rw-r--r--src/test/ui/confuse-field-and-method/private-field.stderr2
-rw-r--r--src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr2
-rw-r--r--src/test/ui/consts/too_generic_eval_ice.stderr2
-rw-r--r--src/test/ui/copy-a-resource.stderr2
-rw-r--r--src/test/ui/derives/derive-assoc-type-not-impl.stderr2
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-pat.rs12
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-pat.stderr6
-rw-r--r--src/test/ui/did_you_mean/issue-40006.rs2
-rw-r--r--src/test/ui/did_you_mean/issue-40006.stderr2
-rw-r--r--src/test/ui/dont-suggest-private-trait-method.rs2
-rw-r--r--src/test/ui/dont-suggest-private-trait-method.stderr2
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.rs6
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr6
-rw-r--r--src/test/ui/error-codes/E0599.stderr2
-rw-r--r--src/test/ui/error-festival.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs3
-rw-r--r--src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr11
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs (renamed from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs)4
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr (renamed from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr)10
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs (renamed from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs)4
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr (renamed from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr)12
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs (renamed from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs)4
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr (renamed from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr)14
-rw-r--r--src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs21
-rw-r--r--src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr74
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs8
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr21
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs168
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr547
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs49
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs54
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr159
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs15
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr35
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs24
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr43
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs160
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs32
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-4.rs13
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-5.rs10
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-5.stderr14
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.stderr2
-rw-r--r--src/test/ui/hygiene/trait_items.rs2
-rw-r--r--src/test/ui/hygiene/trait_items.stderr2
-rw-r--r--src/test/ui/impl-trait/bindings-opaque.stderr6
-rw-r--r--src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr2
-rw-r--r--src/test/ui/impl-trait/method-suggestion-no-duplication.stderr2
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.rs2
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.stderr38
-rw-r--r--src/test/ui/infinite/infinite-autoderef.stderr2
-rw-r--r--src/test/ui/issues/issue-10465.stderr2
-rw-r--r--src/test/ui/issues/issue-13853.stderr2
-rw-r--r--src/test/ui/issues/issue-19521.stderr2
-rw-r--r--src/test/ui/issues/issue-19692.stderr2
-rw-r--r--src/test/ui/issues/issue-21596.stderr2
-rw-r--r--src/test/ui/issues/issue-22933-2.rs2
-rw-r--r--src/test/ui/issues/issue-22933-2.stderr2
-rw-r--r--src/test/ui/issues/issue-22933-3.rs2
-rw-r--r--src/test/ui/issues/issue-23173.rs6
-rw-r--r--src/test/ui/issues/issue-23173.stderr8
-rw-r--r--src/test/ui/issues/issue-23217.rs2
-rw-r--r--src/test/ui/issues/issue-23217.stderr2
-rw-r--r--src/test/ui/issues/issue-25385.rs4
-rw-r--r--src/test/ui/issues/issue-2823.stderr2
-rw-r--r--src/test/ui/issues/issue-28344.stderr4
-rw-r--r--src/test/ui/issues/issue-28586.rs2
-rw-r--r--src/test/ui/issues/issue-28971.rs2
-rw-r--r--src/test/ui/issues/issue-28971.stderr2
-rw-r--r--src/test/ui/issues/issue-29124.rs4
-rw-r--r--src/test/ui/issues/issue-29124.stderr4
-rw-r--r--src/test/ui/issues/issue-30123.rs2
-rw-r--r--src/test/ui/issues/issue-30123.stderr2
-rw-r--r--src/test/ui/issues/issue-31173.stderr2
-rw-r--r--src/test/ui/issues/issue-33575.rs2
-rw-r--r--src/test/ui/issues/issue-33575.stderr2
-rw-r--r--src/test/ui/issues/issue-34209.rs2
-rw-r--r--src/test/ui/issues/issue-34209.stderr3
-rw-r--r--src/test/ui/issues/issue-34334.rs2
-rw-r--r--src/test/ui/issues/issue-34334.stderr2
-rw-r--r--src/test/ui/issues/issue-35677.stderr2
-rw-r--r--src/test/ui/issues/issue-3707.rs2
-rw-r--r--src/test/ui/issues/issue-3707.stderr2
-rw-r--r--src/test/ui/issues/issue-38919.rs2
-rw-r--r--src/test/ui/issues/issue-38919.stderr2
-rw-r--r--src/test/ui/issues/issue-39175.stderr2
-rw-r--r--src/test/ui/issues/issue-39559.rs2
-rw-r--r--src/test/ui/issues/issue-39559.stderr2
-rw-r--r--src/test/ui/issues/issue-3973.rs2
-rw-r--r--src/test/ui/issues/issue-3973.stderr2
-rw-r--r--src/test/ui/issues/issue-41255.rs17
-rw-r--r--src/test/ui/issues/issue-41255.stderr94
-rw-r--r--src/test/ui/issues/issue-41880.rs2
-rw-r--r--src/test/ui/issues/issue-41880.stderr2
-rw-r--r--src/test/ui/issues/issue-42880.stderr2
-rw-r--r--src/test/ui/issues/issue-43189.rs2
-rw-r--r--src/test/ui/issues/issue-43189.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr2
-rw-r--r--src/test/ui/issues/issue-5153.rs2
-rw-r--r--src/test/ui/issues/issue-5153.stderr2
-rw-r--r--src/test/ui/issues/issue-54062.stderr2
-rw-r--r--src/test/ui/issues/issue-57362-1.stderr2
-rw-r--r--src/test/ui/issues/issue-57362-2.stderr2
-rw-r--r--src/test/ui/issues/issue-58734.rs2
-rw-r--r--src/test/ui/issues/issue-58734.stderr2
-rw-r--r--src/test/ui/issues/issue-64430.stderr2
-rw-r--r--src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs2
-rw-r--r--src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr2
-rw-r--r--src/test/ui/issues/issue-7950.rs2
-rw-r--r--src/test/ui/issues/issue-7950.stderr2
-rw-r--r--src/test/ui/lexical-scopes.stderr2
-rw-r--r--src/test/ui/methods/method-call-err-msg.rs2
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr2
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr2
-rw-r--r--src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs2
-rw-r--r--src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr2
-rw-r--r--src/test/ui/never_type/issue-2149.rs2
-rw-r--r--src/test/ui/never_type/issue-2149.stderr2
-rw-r--r--src/test/ui/non-copyable-void.stderr2
-rw-r--r--src/test/ui/noncopyable-class.stderr2
-rw-r--r--src/test/ui/object-pointer-types.stderr6
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.rs8
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.stderr133
-rw-r--r--src/test/ui/parser/issue-63115-range-pat-interpolated.rs6
-rw-r--r--src/test/ui/parser/issue-66357-unexpected-unreachable.rs4
-rw-r--r--src/test/ui/parser/issue-66357-unexpected-unreachable.stderr6
-rw-r--r--src/test/ui/parser/pat-tuple-4.rs11
-rw-r--r--src/test/ui/parser/pat-tuple-4.stderr25
-rw-r--r--src/test/ui/parser/pat-tuple-5.rs10
-rw-r--r--src/test/ui/parser/pat-tuple-5.stderr30
-rw-r--r--src/test/ui/parser/recover-range-pats.rs70
-rw-r--r--src/test/ui/parser/recover-range-pats.stderr349
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-method.stderr2
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr2
-rw-r--r--src/test/ui/self/suggest-self-2.rs2
-rw-r--r--src/test/ui/self/suggest-self-2.stderr2
-rw-r--r--src/test/ui/shadowed/shadowed-trait-methods.stderr2
-rw-r--r--src/test/ui/span/issue-7575.rs6
-rw-r--r--src/test/ui/span/issue-7575.stderr4
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr2
-rw-r--r--src/test/ui/suggestions/constrain-trait.fixed4
-rw-r--r--src/test/ui/suggestions/constrain-trait.rs4
-rw-r--r--src/test/ui/suggestions/constrain-trait.stderr4
-rw-r--r--src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr2
-rw-r--r--src/test/ui/suggestions/issue-21673.stderr4
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.rs2
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr2
-rw-r--r--src/test/ui/suggestions/remove-as_str.rs8
-rw-r--r--src/test/ui/suggestions/remove-as_str.stderr8
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs2
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs2
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-methods.stderr4
-rw-r--r--src/test/ui/suggestions/suggest-variants.rs6
-rw-r--r--src/test/ui/suggestions/suggest-variants.stderr12
-rw-r--r--src/test/ui/traits/trait-impl-1.rs2
-rw-r--r--src/test/ui/traits/trait-impl-1.stderr2
-rw-r--r--src/test/ui/traits/trait-item-privacy.rs12
-rw-r--r--src/test/ui/traits/trait-item-privacy.stderr12
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.rs4
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr2
-rw-r--r--src/test/ui/underscore-imports/hygiene.stderr4
-rw-r--r--src/test/ui/underscore-imports/shadow.stderr2
-rw-r--r--src/test/ui/union/union-derive-clone.rs2
-rw-r--r--src/test/ui/union/union-derive-clone.stderr2
-rw-r--r--src/test/ui/unique-object-noncopyable.stderr2
-rw-r--r--src/test/ui/unique-pinned-nocopy.stderr2
-rw-r--r--src/test/ui/unspecified-self-in-trait-ref.stderr8
m---------src/tools/clippy16
-rw-r--r--src/tools/compiletest/src/main.rs4
440 files changed, 4586 insertions, 3013 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2a222381491..54ad60e7150 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1995,9 +1995,9 @@ dependencies = [
 
 [[package]]
 name = "measureme"
-version = "0.5.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8"
+checksum = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932"
 dependencies = [
  "byteorder",
  "memmap",
@@ -3079,6 +3079,7 @@ dependencies = [
  "graphviz",
  "jobserver",
  "log",
+ "measureme",
  "parking_lot",
  "polonius-engine",
  "rustc-rayon",
@@ -3345,17 +3346,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_asan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_ast_lowering"
 version = "0.0.0"
 dependencies = [
@@ -3374,6 +3364,21 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_ast_passes"
+version = "0.0.0"
+dependencies = [
+ "log",
+ "rustc_data_structures",
+ "rustc_error_codes",
+ "rustc_errors",
+ "rustc_feature",
+ "rustc_parse",
+ "rustc_session",
+ "rustc_span",
+ "syntax",
+]
+
+[[package]]
 name = "rustc_builtin_macros"
 version = "0.0.0"
 dependencies = [
@@ -3385,6 +3390,7 @@ dependencies = [
  "rustc_expand",
  "rustc_feature",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "smallvec 1.0.0",
@@ -3538,11 +3544,13 @@ name = "rustc_expand"
 version = "0.0.0"
 dependencies = [
  "log",
+ "rustc_ast_passes",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "serialize",
  "smallvec 1.0.0",
@@ -3612,6 +3620,7 @@ dependencies = [
  "rustc",
  "rustc-rayon",
  "rustc_ast_lowering",
+ "rustc_ast_passes",
  "rustc_builtin_macros",
  "rustc_codegen_llvm",
  "rustc_codegen_ssa",
@@ -3629,6 +3638,7 @@ dependencies = [
  "rustc_plugin_impl",
  "rustc_privacy",
  "rustc_resolve",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "rustc_traits",
@@ -3653,6 +3663,7 @@ dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
+ "rustc_errors",
  "rustc_feature",
  "rustc_hir",
  "rustc_index",
@@ -3673,17 +3684,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_lsan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_macros"
 version = "0.1.0"
 dependencies = [
@@ -3745,17 +3745,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_msan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_parse"
 version = "0.0.0"
 dependencies = [
@@ -3766,6 +3755,7 @@ dependencies = [
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
+ "rustc_session",
  "rustc_span",
  "smallvec 1.0.0",
  "syntax",
@@ -3784,7 +3774,7 @@ dependencies = [
  "rustc_feature",
  "rustc_hir",
  "rustc_index",
- "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "syntax",
@@ -3864,6 +3854,7 @@ dependencies = [
  "log",
  "num_cpus",
  "rustc_data_structures",
+ "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_fs_util",
@@ -3928,17 +3919,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_tsan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_typeck"
 version = "0.0.0"
 dependencies = [
@@ -4299,10 +4279,6 @@ dependencies = [
  "panic_unwind",
  "profiler_builtins",
  "rand 0.7.0",
- "rustc_asan",
- "rustc_lsan",
- "rustc_msan",
- "rustc_tsan",
  "unwind",
  "wasi 0.9.0+wasi-snapshot-preview1",
 ]
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 3a14b3e71c4..00c8e72a8f6 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -343,6 +343,7 @@ impl<'a> Builder<'a> {
                 tool::Rustdoc,
                 tool::Clippy,
                 native::Llvm,
+                native::Sanitizers,
                 tool::Rustfmt,
                 tool::Miri,
                 native::Lld
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index d4016f16fa9..b76515763fb 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -45,7 +45,7 @@ impl Step for Std {
         let compiler = builder.compiler(0, builder.config.build);
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind));
-        std_cargo(builder, &compiler, target, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
         run_cargo(
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 7f0bb5813a4..eced03506ab 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -87,7 +87,7 @@ impl Step for Std {
         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);
+        std_cargo(builder, target, &mut cargo);
 
         builder.info(&format!(
             "Building stage{} std artifacts ({} -> {})",
@@ -153,17 +153,18 @@ fn copy_third_party_objects(
         copy_and_stamp(Path::new(&src), "libunwind.a");
     }
 
+    if builder.config.sanitizers && compiler.stage != 0 {
+        // The sanitizers are only copied in stage1 or above,
+        // to avoid creating dependency on LLVM.
+        target_deps.extend(copy_sanitizers(builder, &compiler, target));
+    }
+
     target_deps
 }
 
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
-pub fn std_cargo(
-    builder: &Builder<'_>,
-    compiler: &Compiler,
-    target: Interned<String>,
-    cargo: &mut Cargo,
-) {
+pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, cargo: &mut Cargo) {
     if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
@@ -206,19 +207,6 @@ pub fn std_cargo(
         let mut features = builder.std_features();
         features.push_str(&compiler_builtins_c_feature);
 
-        if compiler.stage != 0 && builder.config.sanitizers {
-            // This variable is used by the sanitizer runtime crates, e.g.
-            // rustc_lsan, to build the sanitizer runtime from C code
-            // When this variable is missing, those crates won't compile the C code,
-            // so we don't set this variable during stage0 where llvm-config is
-            // missing
-            // We also only build the runtimes when --enable-sanitizers (or its
-            // config.toml equivalent) is used
-            let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
-            cargo.env("LLVM_CONFIG", llvm_config);
-            cargo.env("RUSTC_BUILD_SANITIZERS", "1");
-        }
-
         cargo
             .arg("--features")
             .arg(features)
@@ -276,31 +264,43 @@ impl Step for StdLink {
         let libdir = builder.sysroot_libdir(target_compiler, target);
         let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
         add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
-
-        if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
-            // The sanitizers are only built in stage1 or above, so the dylibs will
-            // be missing in stage0 and causes panic. See the `std()` function above
-            // for reason why the sanitizers are not built in stage0.
-            copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
-        }
     }
 }
 
-fn copy_apple_sanitizer_dylibs(
+/// Copies sanitizer runtime libraries into target libdir.
+fn copy_sanitizers(
     builder: &Builder<'_>,
-    native_dir: &Path,
-    platform: &str,
-    into: &Path,
-) {
-    for &sanitizer in &["asan", "tsan"] {
-        let filename = format!("lib__rustc__clang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
-        let mut src_path = native_dir.join(sanitizer);
-        src_path.push("build");
-        src_path.push("lib");
-        src_path.push("darwin");
-        src_path.push(&filename);
-        builder.copy(&src_path, &into.join(filename));
+    compiler: &Compiler,
+    target: Interned<String>,
+) -> Vec<PathBuf> {
+    let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
+
+    if builder.config.dry_run {
+        return Vec::new();
+    }
+
+    let mut target_deps = Vec::new();
+    let libdir = builder.sysroot_libdir(*compiler, target);
+
+    for runtime in &runtimes {
+        let dst = libdir.join(&runtime.name);
+        builder.copy(&runtime.path, &dst);
+
+        if target == "x86_64-apple-darwin" {
+            // Update the library install name reflect the fact it has been renamed.
+            let status = Command::new("install_name_tool")
+                .arg("-id")
+                .arg(format!("@rpath/{}", runtime.name))
+                .arg(&dst)
+                .status()
+                .expect("failed to execute `install_name_tool`");
+            assert!(status.success());
+        }
+
+        target_deps.push(dst);
     }
+
+    target_deps
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 944df66431f..110c8b844d5 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -493,9 +493,13 @@ impl Config {
             config.mandir = install.mandir.clone().map(PathBuf::from);
         }
 
+        // We want the llvm-skip-rebuild flag to take precedence over the
+        // skip-rebuild config.toml option so we store it separately
+        // so that we can infer the right value
+        let mut llvm_skip_rebuild = flags.llvm_skip_rebuild;
+
         // Store off these values as options because if they're not provided
         // we'll infer default values for them later
-        let mut llvm_skip_rebuild = None;
         let mut llvm_assertions = None;
         let mut debug = None;
         let mut debug_assertions = None;
@@ -517,7 +521,7 @@ impl Config {
             }
             set(&mut config.ninja, llvm.ninja);
             llvm_assertions = llvm.assertions;
-            llvm_skip_rebuild = llvm.skip_rebuild;
+            llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild);
             set(&mut config.llvm_optimize, llvm.optimize);
             set(&mut config.llvm_thin_lto, llvm.thin_lto);
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index e64d4c8637d..8d13df3ee21 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -984,10 +984,6 @@ impl Step for Src {
             "src/libcore",
             "src/libpanic_abort",
             "src/libpanic_unwind",
-            "src/librustc_asan",
-            "src/librustc_lsan",
-            "src/librustc_msan",
-            "src/librustc_tsan",
             "src/libstd",
             "src/libunwind",
             "src/libtest",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 8cd7fc2c172..204056598d9 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -49,7 +49,7 @@ macro_rules! book {
                 builder.ensure(RustbookSrc {
                     target: self.target,
                     name: INTERNER.intern_str($book_name),
-                    src: doc_src(builder),
+                    src: INTERNER.intern_path(builder.src.join($path)),
                 })
             }
         }
@@ -60,6 +60,7 @@ macro_rules! book {
 // NOTE: When adding a book here, make sure to ALSO build the book by
 // adding a build step in `src/bootstrap/builder.rs`!
 book!(
+    CargoBook, "src/tools/cargo/src/doc", "cargo";
     EditionGuide, "src/doc/edition-guide", "edition-guide";
     EmbeddedBook, "src/doc/embedded-book", "embedded-book";
     Nomicon, "src/doc/nomicon", "nomicon";
@@ -69,10 +70,6 @@ book!(
     RustdocBook, "src/doc/rustdoc", "rustdoc";
 );
 
-fn doc_src(builder: &Builder<'_>) -> Interned<PathBuf> {
-    INTERNER.intern_path(builder.src.join("src/doc"))
-}
-
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct UnstableBook {
     target: Interned<String>,
@@ -96,49 +93,12 @@ impl Step for UnstableBook {
         builder.ensure(RustbookSrc {
             target: self.target,
             name: INTERNER.intern_str("unstable-book"),
-            src: builder.md_doc_out(self.target),
+            src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
         })
     }
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct CargoBook {
-    target: Interned<String>,
-    name: Interned<String>,
-}
-
-impl Step for CargoBook {
-    type Output = ();
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let builder = run.builder;
-        run.path("src/tools/cargo/src/doc/book").default_condition(builder.config.docs)
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(CargoBook { target: run.target, name: INTERNER.intern_str("cargo") });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        let target = self.target;
-        let name = self.name;
-        let src = builder.src.join("src/tools/cargo/src/doc");
-
-        let out = builder.doc_out(target);
-        t!(fs::create_dir_all(&out));
-
-        let out = out.join(name);
-
-        builder.info(&format!("Cargo Book ({}) - {}", target, name));
-
-        let _ = fs::remove_dir_all(&out);
-
-        builder.run(builder.tool_cmd(Tool::Rustbook).arg("build").arg(&src).arg("-d").arg(out));
-    }
-}
-
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 struct RustbookSrc {
     target: Interned<String>,
     name: Interned<String>,
@@ -164,7 +124,6 @@ impl Step for RustbookSrc {
         t!(fs::create_dir_all(&out));
 
         let out = out.join(name);
-        let src = src.join(name);
         let index = out.join("index.html");
         let rustbook = builder.tool_exe(Tool::Rustbook);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
@@ -182,7 +141,6 @@ impl Step for RustbookSrc {
 pub struct TheBook {
     compiler: Compiler,
     target: Interned<String>,
-    name: &'static str,
 }
 
 impl Step for TheBook {
@@ -198,7 +156,6 @@ impl Step for TheBook {
         run.builder.ensure(TheBook {
             compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
-            name: "book",
         });
     }
 
@@ -206,45 +163,30 @@ impl Step for TheBook {
     ///
     /// We need to build:
     ///
-    /// * Book (first edition)
-    /// * Book (second edition)
+    /// * Book
+    /// * Older edition redirects
     /// * Version info and CSS
     /// * Index page
     /// * Redirect pages
     fn run(self, builder: &Builder<'_>) {
         let compiler = self.compiler;
         let target = self.target;
-        let name = self.name;
 
         // build book
         builder.ensure(RustbookSrc {
             target,
-            name: INTERNER.intern_string(name.to_string()),
-            src: doc_src(builder),
+            name: INTERNER.intern_str("book"),
+            src: INTERNER.intern_path(builder.src.join("src/doc/book")),
         });
 
         // building older edition redirects
-
-        let source_name = format!("{}/first-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
-
-        let source_name = format!("{}/second-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
-
-        let source_name = format!("{}/2018-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
+        for edition in &["first-edition", "second-edition", "2018-edition"] {
+            builder.ensure(RustbookSrc {
+                target,
+                name: INTERNER.intern_string(format!("book/{}", edition)),
+                src: INTERNER.intern_path(builder.src.join("src/doc/book").join(edition)),
+            });
+        }
 
         // build the version info page and CSS
         builder.ensure(Standalone { compiler, target });
@@ -449,7 +391,7 @@ impl Step for Std {
 
         let run_cargo_rustdoc_for = |package: &str| {
             let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc");
-            compile::std_cargo(builder, &compiler, target, &mut cargo);
+            compile::std_cargo(builder, target, &mut cargo);
 
             // Keep a whitelist so we do not build internal stdlib crates, these will be
             // build by the rustc step later if enabled.
@@ -531,7 +473,7 @@ impl Step for Rustc {
 
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
-        cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden");
+        cargo.env("RUSTDOCFLAGS", "--document-private-items");
         compile::rustc_cargo(builder, &mut cargo, target);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index ffc24367db6..1fbdd50a511 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -38,6 +38,8 @@ pub struct Flags {
     //
     // true => deny, false => warn
     pub deny_warnings: Option<bool>,
+
+    pub llvm_skip_rebuild: Option<bool>,
 }
 
 pub enum Subcommand {
@@ -150,6 +152,14 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
             "VALUE",
         );
         opts.optopt("", "error-format", "rustc error format", "FORMAT");
+        opts.optopt(
+            "",
+            "llvm-skip-rebuild",
+            "whether rebuilding llvm should be skipped \
+             a VALUE of TRUE indicates that llvm will not be rebuilt \
+             VALUE overrides the skip-rebuild option in config.toml.",
+            "VALUE",
+        );
 
         // fn usage()
         let usage =
@@ -487,6 +497,9 @@ Arguments:
                 .map(|p| p.into())
                 .collect::<Vec<_>>(),
             deny_warnings: parse_deny_warnings(&matches),
+            llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map(
+                |s| s.parse::<bool>().expect("`llvm-skip-rebuild` should be either true or false"),
+            ),
         }
     }
 }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 2a4e9903e55..ce977f1bbc4 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -546,3 +546,118 @@ impl Step for TestHelpers {
             .compile("rust_test_helpers");
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Sanitizers {
+    pub target: Interned<String>,
+}
+
+impl Step for Sanitizers {
+    type Output = Vec<SanitizerRuntime>;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/llvm-project/compiler-rt").path("src/sanitizers")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Sanitizers { target: run.target });
+    }
+
+    /// Builds sanitizer runtime libraries.
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let compiler_rt_dir = builder.src.join("src/llvm-project/compiler-rt");
+        if !compiler_rt_dir.exists() {
+            return Vec::new();
+        }
+
+        let out_dir = builder.native_dir(self.target).join("sanitizers");
+        let runtimes = supported_sanitizers(&out_dir, self.target);
+        if runtimes.is_empty() {
+            return runtimes;
+        }
+
+        let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+        if builder.config.dry_run {
+            return runtimes;
+        }
+
+        let done_stamp = out_dir.join("sanitizers-finished-building");
+        if done_stamp.exists() {
+            builder.info(&format!(
+                "Assuming that sanitizers rebuild is not necessary. \
+                To force a rebuild, remove the file `{}`",
+                done_stamp.display()
+            ));
+            return runtimes;
+        }
+
+        builder.info(&format!("Building sanitizers for {}", self.target));
+        let _time = util::timeit(&builder);
+
+        let mut cfg = cmake::Config::new(&compiler_rt_dir);
+        cfg.target(&self.target);
+        cfg.host(&builder.config.build);
+        cfg.profile("Release");
+
+        cfg.define("CMAKE_C_COMPILER_TARGET", self.target);
+        cfg.define("COMPILER_RT_BUILD_BUILTINS", "OFF");
+        cfg.define("COMPILER_RT_BUILD_CRT", "OFF");
+        cfg.define("COMPILER_RT_BUILD_LIBFUZZER", "OFF");
+        cfg.define("COMPILER_RT_BUILD_PROFILE", "OFF");
+        cfg.define("COMPILER_RT_BUILD_SANITIZERS", "ON");
+        cfg.define("COMPILER_RT_BUILD_XRAY", "OFF");
+        cfg.define("COMPILER_RT_DEFAULT_TARGET_ONLY", "ON");
+        cfg.define("COMPILER_RT_USE_LIBCXX", "OFF");
+        cfg.define("LLVM_CONFIG_PATH", &llvm_config);
+
+        t!(fs::create_dir_all(&out_dir));
+        cfg.out_dir(out_dir);
+
+        for runtime in &runtimes {
+            cfg.build_target(&runtime.cmake_target);
+            cfg.build();
+        }
+
+        t!(fs::write(&done_stamp, b""));
+
+        runtimes
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct SanitizerRuntime {
+    /// CMake target used to build the runtime.
+    pub cmake_target: String,
+    /// Path to the built runtime library.
+    pub path: PathBuf,
+    /// Library filename that will be used rustc.
+    pub name: String,
+}
+
+/// Returns sanitizers available on a given target.
+fn supported_sanitizers(out_dir: &Path, target: Interned<String>) -> Vec<SanitizerRuntime> {
+    let mut result = Vec::new();
+    match &*target {
+        "x86_64-apple-darwin" => {
+            for s in &["asan", "lsan", "tsan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}_osx_dynamic", s),
+                    path: out_dir
+                        .join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)),
+                    name: format!("librustc_rt.{}.dylib", s),
+                });
+            }
+        }
+        "x86_64-unknown-linux-gnu" => {
+            for s in &["asan", "lsan", "msan", "tsan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}-x86_64", s),
+                    path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)),
+                    name: format!("librustc_rt.{}.a", s),
+                });
+            }
+        }
+        _ => {}
+    }
+    result
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index b5c8de057d0..10e07489e12 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1659,7 +1659,7 @@ impl Step for Crate {
         let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
         match mode {
             Mode::Std => {
-                compile::std_cargo(builder, &compiler, target, &mut cargo);
+                compile::std_cargo(builder, target, &mut cargo);
             }
             Mode::Rustc => {
                 builder.ensure(compile::Rustc { compiler, target });
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 9fd20386e36..7f24768a4f1 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -289,8 +289,8 @@ fn rustbook_features() -> Vec<String> {
 macro_rules! bootstrap_tool {
     ($(
         $name:ident, $path:expr, $tool_name:expr
-        $(,llvm_tools = $llvm:expr)*
         $(,is_external_tool = $external:expr)*
+        $(,is_unstable_tool = $unstable:expr)*
         $(,features = $features:expr)*
         ;
     )+) => {
@@ -301,15 +301,6 @@ macro_rules! bootstrap_tool {
             )+
         }
 
-        impl Tool {
-            /// Whether this tool requires LLVM to run
-            pub fn uses_llvm_tools(&self) -> bool {
-                match self {
-                    $(Tool::$name => false $(|| $llvm)*,)+
-                }
-            }
-        }
-
         impl<'a> Builder<'a> {
             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                 match tool {
@@ -350,7 +341,12 @@ macro_rules! bootstrap_tool {
                     compiler: self.compiler,
                     target: self.target,
                     tool: $tool_name,
-                    mode: Mode::ToolBootstrap,
+                    mode: if false $(|| $unstable)* {
+                        // use in-tree libraries for unstable features
+                        Mode::ToolStd
+                    } else {
+                        Mode::ToolBootstrap
+                    },
                     path: $path,
                     is_optional_tool: false,
                     source_type: if false $(|| $external)* {
@@ -377,7 +373,7 @@ bootstrap_tool!(
     Tidy, "src/tools/tidy", "tidy";
     Linkchecker, "src/tools/linkchecker", "linkchecker";
     CargoTest, "src/tools/cargotest", "cargotest";
-    Compiletest, "src/tools/compiletest", "compiletest", llvm_tools = true;
+    Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true;
     BuildManifest, "src/tools/build-manifest", "build-manifest";
     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
     RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true;
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 3f42533238a..43c3c5773ce 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -1,7 +1,5 @@
-use std::fs::File;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
-use std::thread;
 use std::time::{SystemTime, UNIX_EPOCH};
 use std::{env, fs};
 
@@ -181,108 +179,6 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool {
     }
 }
 
-#[must_use]
-pub struct NativeLibBoilerplate {
-    pub src_dir: PathBuf,
-    pub out_dir: PathBuf,
-}
-
-impl NativeLibBoilerplate {
-    /// On macOS we don't want to ship the exact filename that compiler-rt builds.
-    /// This conflicts with the system and ours is likely a wildly different
-    /// version, so they can't be substituted.
-    ///
-    /// As a result, we rename it here but we need to also use
-    /// `install_name_tool` on macOS to rename the commands listed inside of it to
-    /// ensure it's linked against correctly.
-    pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) {
-        if env::var("TARGET").unwrap() != "x86_64-apple-darwin" {
-            return;
-        }
-
-        let dir = self.out_dir.join("build/lib/darwin");
-        let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name);
-        let src = dir.join(&format!("lib{}.dylib", name));
-        let new_name = format!("lib__rustc__{}.dylib", name);
-        let dst = dir.join(&new_name);
-
-        println!("{} => {}", src.display(), dst.display());
-        fs::rename(&src, &dst).unwrap();
-        let status = Command::new("install_name_tool")
-            .arg("-id")
-            .arg(format!("@rpath/{}", new_name))
-            .arg(&dst)
-            .status()
-            .expect("failed to execute `install_name_tool`");
-        assert!(status.success());
-    }
-}
-
-impl Drop for NativeLibBoilerplate {
-    fn drop(&mut self) {
-        if !thread::panicking() {
-            t!(File::create(self.out_dir.join("rustbuild.timestamp")));
-        }
-    }
-}
-
-// Perform standard preparations for native libraries that are build only once for all stages.
-// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are
-// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler.
-// If Err is returned, then everything is up-to-date and further build actions can be skipped.
-// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
-// of scope, so all the build actions should be completed until then.
-pub fn native_lib_boilerplate(
-    src_dir: &Path,
-    out_name: &str,
-    link_name: &str,
-    search_subdir: &str,
-) -> Result<NativeLibBoilerplate, ()> {
-    rerun_if_changed_anything_in_dir(src_dir);
-
-    let out_dir =
-        env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| env::var_os("OUT_DIR").unwrap());
-    let out_dir = PathBuf::from(out_dir).join(out_name);
-    t!(fs::create_dir_all(&out_dir));
-    if link_name.contains('=') {
-        println!("cargo:rustc-link-lib={}", link_name);
-    } else {
-        println!("cargo:rustc-link-lib=static={}", link_name);
-    }
-    println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display());
-
-    let timestamp = out_dir.join("rustbuild.timestamp");
-    if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(src_dir, &timestamp) {
-        Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), out_dir })
-    } else {
-        Err(())
-    }
-}
-
-pub fn sanitizer_lib_boilerplate(
-    sanitizer_name: &str,
-) -> Result<(NativeLibBoilerplate, String), ()> {
-    let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() {
-        "x86_64-unknown-linux-gnu" => {
-            (format!("clang_rt.{}-x86_64", sanitizer_name), "build/lib/linux", false)
-        }
-        "x86_64-apple-darwin" => {
-            (format!("clang_rt.{}_osx_dynamic", sanitizer_name), "build/lib/darwin", true)
-        }
-        _ => return Err(()),
-    };
-    let to_link = if apple {
-        format!("dylib=__rustc__{}", link_name)
-    } else {
-        format!("static={}", link_name)
-    };
-    // This env var is provided by rustbuild to tell us where `compiler-rt`
-    // lives.
-    let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
-    let lib = native_lib_boilerplate(dir.as_ref(), sanitizer_name, &to_link, search_path)?;
-    Ok((lib, link_name))
-}
-
 fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
     t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
         let meta = t!(e.metadata());
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
new file mode 100644
index 00000000000..cbb90bd3bb3
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -0,0 +1,163 @@
+# `sanitizer`
+
+The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699).
+
+------------------------
+
+This feature allows for use of one of following sanitizers:
+
+* [AddressSanitizer][clang-asan] a faster memory error detector. Can
+  detect out-of-bounds access to heap, stack, and globals, use after free, use
+  after return, double free, invalid free, memory leaks.
+* [LeakSanitizer][clang-lsan] a run-time memory leak detector.
+* [MemorySanitizer][clang-msan] a detector of uninitialized reads.
+* [ThreadSanitizer][clang-tsan] a fast data race detector.
+
+To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one
+of `address`, `leak`, `memory` or `thread`.
+
+# Examples
+
+This sections show various issues that can be detected with sanitizers.  For
+simplicity, the examples are prepared under assumption that optimization level
+used is zero.
+
+## AddressSanitizer
+
+Stack buffer overflow:
+
+```shell
+$ cat a.rs
+fn main() {
+    let xs = [0, 1, 2, 3];
+    let _y = unsafe { *xs.as_ptr().offset(4) };
+}
+$ rustc -Zsanitizer=address a.rs
+$ ./a
+=================================================================
+==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388
+READ of size 4 at 0x7ffcc15f43d0 thread T0
+    #0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4)
+    #1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb)
+    #2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12
+    #3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39
+    #4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7
+    #5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12
+    #6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8
+    #7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24
+    #8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61)
+    #9 0x55f77dc0163a in main (/tmp/a+0xa63a)
+    #10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
+    #11 0x55f77dc01289 in _start (/tmp/a+0xa289)
+
+Address 0x7ffcc15f43d0 is located in stack of thread T0 at offset 48 in frame
+    #0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f)
+
+  This frame has 1 object(s):
+    [32, 48) 'xs' <== Memory access at offset 48 overflows this variable
+HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
+      (longjmp and C++ exceptions *are* supported)
+SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4) in a::main::hab3bd2a745c2d0ac
+Shadow bytes around the buggy address:
+  0x1000182b6820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6860: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=>0x1000182b6870: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
+  0x1000182b6880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Shadow byte legend (one shadow byte represents 8 application bytes):
+  Addressable:           00
+  Partially addressable: 01 02 03 04 05 06 07 
+  Heap left redzone:       fa
+  Freed heap region:       fd
+  Stack left redzone:      f1
+  Stack mid redzone:       f2
+  Stack right redzone:     f3
+  Stack after return:      f5
+  Stack use after scope:   f8
+  Global redzone:          f9
+  Global init order:       f6
+  Poisoned by user:        f7
+  Container overflow:      fc
+  Array cookie:            ac
+  Intra object redzone:    bb
+  ASan internal:           fe
+  Left alloca redzone:     ca
+  Right alloca redzone:    cb
+  Shadow gap:              cc
+==10029==ABORTING
+```
+
+## MemorySanitizer
+
+Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument
+standard library, and passing `-msan-track-origins=2` to the LLVM to track
+origins of uninitialized memory:
+
+```shell
+$ cat src/main.rs
+use std::mem::MaybeUninit;
+
+fn main() {
+    unsafe {
+        let a = MaybeUninit::<[usize; 4]>::uninit();
+        let a = a.assume_init();
+        println!("{}", a[2]);
+    }
+}
+
+$ env RUSTFLAGS="-Zsanitizer=memory -Cllvm-args=-msan-track-origins=2" cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
+==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
+    #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
+...
+  Uninitialized value was stored to memory at
+    #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3
+    #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16
+
+  Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E'
+    #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
+```
+
+
+# Instrumentation of external dependencies and std
+
+The sanitizers to varying degrees work correctly with partially instrumented
+code. On the one extreme is LeakSanitizer that doesn't use any compile time
+instrumentation, on the other is MemorySanitizer that requires that all program
+code to be instrumented (failing to achieve that will inevitably result in
+false positives).
+
+It is strongly recommended to combine sanitizers with recompiled and
+instrumented standard library, for example using [cargo `-Zbuild-std`
+functionality][build-std].
+
+[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+
+# Build scripts and procedural macros
+
+Use of sanitizers together with build scripts and procedural macros is
+technically possible, but in almost all cases it would be best avoided.  This
+is especially true for procedural macros which would require an instrumented
+version of rustc.
+
+In more practical terms when using cargo always remember to pass `--target`
+flag, so that rustflags will not be applied to build scripts and procedural
+macros.
+
+# Additional Information
+
+* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
+* [AddressSanitizer in Clang][clang-asan]
+* [LeakSanitizer in Clang][clang-lsan]
+* [MemorySanitizer in Clang][clang-msan]
+* [ThreadSanitizer in Clang][clang-tsan]
+
+[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
+[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
+[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
+[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
diff --git a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
deleted file mode 100644
index 82ae67fc05a..00000000000
--- a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `sanitizer_runtime_lib`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index c6062493b86..aa57c7788c6 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -1092,6 +1092,44 @@ impl<T: Default, E> Result<T, E> {
     }
 }
 
+#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
+impl<T, E: Into<!>> Result<T, E> {
+    /// Unwraps a result that can never be an [`Err`], yielding the content of the [`Ok`].
+    ///
+    /// Unlike [`unwrap`], this method is known to never panic on the
+    /// result types it is implemented for. Therefore, it can be used
+    /// instead of `unwrap` as a maintainability safeguard that will fail
+    /// to compile if the error type of the `Result` is later changed
+    /// to an error that can actually occur.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    /// [`unwrap`]: enum.Result.html#method.unwrap
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// # #![feature(never_type)]
+    /// # #![feature(unwrap_infallible)]
+    ///
+    /// fn only_good_news() -> Result<String, !> {
+    ///     Ok("this is fine".into())
+    /// }
+    ///
+    /// let s: String = only_good_news().into_ok();
+    /// println!("{}", s);
+    /// ```
+    #[inline]
+    pub fn into_ok(self) -> T {
+        match self {
+            Ok(x) => x,
+            Err(e) => e.into(),
+        }
+    }
+}
+
 #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: Deref, E> Result<T, E> {
     /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 39f6133f2a6..09b54857f7d 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -40,6 +40,8 @@
 #![feature(slice_from_raw_parts)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_raw_ptr_deref)]
+#![feature(never_type)]
+#![feature(unwrap_infallible)]
 
 extern crate test;
 
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index 499a5613bd2..254d4539eac 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -184,6 +184,28 @@ pub fn test_unwrap_or_default() {
 }
 
 #[test]
+pub fn test_into_ok() {
+    fn infallible_op() -> Result<isize, !> {
+        Ok(666)
+    }
+
+    assert_eq!(infallible_op().into_ok(), 666);
+
+    enum MyNeverToken {}
+    impl From<MyNeverToken> for ! {
+        fn from(never: MyNeverToken) -> ! {
+            match never {}
+        }
+    }
+
+    fn infallible_op2() -> Result<isize, MyNeverToken> {
+        Ok(667)
+    }
+
+    assert_eq!(infallible_op2().into_ok(), 667);
+}
+
+#[test]
 fn test_try() {
     fn try_result_some() -> Option<u8> {
         let val = Ok(1)?;
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index 2098404ee1b..9d3fe5254f8 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -63,7 +63,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     let sz = mem::size_of_val(&data);
     let exception = __cxa_allocate_exception(sz);
-    if exception == ptr::null_mut() {
+    if exception.is_null() {
         return uw::_URC_FATAL_PHASE1_ERROR as u32;
     }
     ptr::write(exception as *mut _, data);
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 1a04a9d86b5..323ce3b6cbb 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -26,8 +26,8 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_index = { path = "../librustc_index" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
@@ -36,5 +36,6 @@ parking_lot = "0.9"
 byteorder = { version = "1.3" }
 chalk-engine = { version = "0.9.0", default-features=false }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+measureme = "0.7.1"
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 0d03c834e0f..8d1efc7bc04 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -1,17 +1,18 @@
 use crate::ty::{self, TyCtxt};
-use errors::Diagnostic;
 use parking_lot::{Condvar, Mutex};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::profiling::QueryInvocationId;
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
+use rustc_errors::Diagnostic;
 use rustc_index::vec::{Idx, IndexVec};
 use smallvec::SmallVec;
 use std::collections::hash_map::Entry;
 use std::env;
 use std::hash::Hash;
 use std::mem;
-use std::sync::atomic::Ordering::SeqCst;
+use std::sync::atomic::Ordering::Relaxed;
 
 use crate::ich::{Fingerprint, StableHashingContext, StableHashingContextProvider};
 
@@ -25,6 +26,12 @@ use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
 #[derive(Clone)]
 pub struct DepGraph {
     data: Option<Lrc<DepGraphData>>,
+
+    /// This field is used for assigning DepNodeIndices when running in
+    /// non-incremental mode. Even in non-incremental mode we make sure that
+    /// each task has a `DepNodeIndex` that uniquely identifies it. This unique
+    /// ID is used for self-profiling.
+    virtual_dep_node_index: Lrc<AtomicU32>,
 }
 
 rustc_index::newtype_index! {
@@ -35,6 +42,13 @@ impl DepNodeIndex {
     pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
 }
 
+impl std::convert::From<DepNodeIndex> for QueryInvocationId {
+    #[inline]
+    fn from(dep_node_index: DepNodeIndex) -> Self {
+        QueryInvocationId(dep_node_index.as_u32())
+    }
+}
+
 #[derive(PartialEq)]
 pub enum DepNodeColor {
     Red,
@@ -105,11 +119,12 @@ impl DepGraph {
                 previous: prev_graph,
                 colors: DepNodeColorMap::new(prev_graph_node_count),
             })),
+            virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
         }
     }
 
     pub fn new_disabled() -> DepGraph {
-        DepGraph { data: None }
+        DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
     }
 
     /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
@@ -322,7 +337,7 @@ impl DepGraph {
 
             (result, dep_node_index)
         } else {
-            (task(cx, arg), DepNodeIndex::INVALID)
+            (task(cx, arg), self.next_virtual_depnode_index())
         }
     }
 
@@ -352,7 +367,7 @@ impl DepGraph {
             let dep_node_index = data.current.complete_anon_task(dep_kind, task_deps);
             (result, dep_node_index)
         } else {
-            (op(), DepNodeIndex::INVALID)
+            (op(), self.next_virtual_depnode_index())
         }
     }
 
@@ -478,8 +493,8 @@ impl DepGraph {
             let current_dep_graph = &self.data.as_ref().unwrap().current;
 
             Some((
-                current_dep_graph.total_read_count.load(SeqCst),
-                current_dep_graph.total_duplicate_read_count.load(SeqCst),
+                current_dep_graph.total_read_count.load(Relaxed),
+                current_dep_graph.total_duplicate_read_count.load(Relaxed),
             ))
         } else {
             None
@@ -877,6 +892,11 @@ impl DepGraph {
             }
         }
     }
+
+    fn next_virtual_depnode_index(&self) -> DepNodeIndex {
+        let index = self.virtual_dep_node_index.fetch_add(1, Relaxed);
+        DepNodeIndex::from_u32(index)
+    }
 }
 
 /// A "work product" is an intermediate result that we save into the
@@ -1087,7 +1107,7 @@ impl DepGraphData {
             if let Some(task_deps) = icx.task_deps {
                 let mut task_deps = task_deps.lock();
                 if cfg!(debug_assertions) {
-                    self.current.total_read_count.fetch_add(1, SeqCst);
+                    self.current.total_read_count.fetch_add(1, Relaxed);
                 }
                 if task_deps.read_set.insert(source) {
                     task_deps.reads.push(source);
@@ -1105,7 +1125,7 @@ impl DepGraphData {
                         }
                     }
                 } else if cfg!(debug_assertions) {
-                    self.current.total_duplicate_read_count.fetch_add(1, SeqCst);
+                    self.current.total_duplicate_read_count.fetch_add(1, Relaxed);
                 }
             }
         })
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 06b7b3194de..c6a996f84f4 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -9,8 +9,8 @@ use crate::lint::builtin::UNUSED_ATTRIBUTES;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
 
-use errors::struct_span_err;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 5e5f39e6c7a..c52d4335ea1 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -64,15 +64,13 @@ use crate::ty::{
     subst::{Subst, SubstsRef},
     Region, Ty, TyCtxt, TypeFoldable,
 };
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_error_codes::*;
+use rustc_errors::{pluralize, struct_span_err};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
-
-use errors::{
-    pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticStyledString,
-};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_error_codes::*;
 use rustc_span::{DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::{cmp, fmt};
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 16cfaec5ee9..70f7987faf4 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -3,7 +3,7 @@ use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::infer::InferCtxt;
 use crate::ty::print::Print;
 use crate::ty::{self, DefIdTree, Infer, Ty, TyVar};
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -151,12 +151,12 @@ pub enum TypeAnnotationNeeded {
     E0284,
 }
 
-impl Into<errors::DiagnosticId> for TypeAnnotationNeeded {
-    fn into(self) -> errors::DiagnosticId {
+impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
+    fn into(self) -> rustc_errors::DiagnosticId {
         match self {
-            Self::E0282 => errors::error_code!(E0282),
-            Self::E0283 => errors::error_code!(E0283),
-            Self::E0284 => errors::error_code!(E0284),
+            Self::E0282 => rustc_errors::error_code!(E0282),
+            Self::E0283 => rustc_errors::error_code!(E0283),
+            Self::E0284 => rustc_errors::error_code!(E0284),
         }
     }
 }
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index b73fb40f637..d6e50209f72 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -5,8 +5,8 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::util::common::ErrorReported;
 
-use errors::struct_span_err;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when both the concerned regions are anonymous.
diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
index 5da65a30193..8749d6cd34b 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
@@ -3,7 +3,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError::*;
 use crate::infer::InferCtxt;
 use crate::ty::{self, TyCtxt};
 use crate::util::common::ErrorReported;
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_span::source_map::Span;
 
 mod different_lifetimes;
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index dacd2025da5..2344d408a43 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -2,7 +2,7 @@
 //! where one region is named and the other is anonymous.
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::ty;
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir::{FunctionRetTy, TyKind};
 
 use rustc_error_codes::*;
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index f276dab5000..7b31fe7cd7e 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -7,7 +7,7 @@ use crate::ty::error::ExpectedFound;
 use crate::ty::print::{FmtPrinter, Print, RegionHighlightMode};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, TyCtxt};
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 6c78e70a444..c6fc4cd3c15 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -5,7 +5,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::ty::{BoundRegion, FreeRegion, RegionKind};
 use crate::util::common::ErrorReported;
-use errors::Applicability;
+use rustc_errors::Applicability;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index a3fdcb44f99..6303104e39d 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -3,7 +3,7 @@ use crate::infer::{self, InferCtxt, SubregionOrigin};
 use crate::middle::region;
 use crate::ty::error::TypeError;
 use crate::ty::{self, Region};
-use errors::{struct_span_err, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 
 use rustc_error_codes::*;
 
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 4eb8d79a067..f67669e367f 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -21,10 +21,10 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use crate::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
 use crate::ty::{ConstVid, FloatVid, IntVid, TyVid};
 
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unify as ut;
+use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::Symbol;
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 839e8588ff0..a1afb1a86be 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -6,10 +6,10 @@ use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::free_region_map::FreeRegionRelations;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_hir::Node;
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index ea96b15a162..3f18f4dbd1f 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -17,20 +17,21 @@
 use self::TargetLint::*;
 
 use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
-use crate::lint::builtin::BuiltinLintDiagnostics;
 use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
 use crate::lint::{EarlyLintPassObject, LateLintPassObject};
-use crate::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use crate::middle::privacy::AccessLevels;
+use crate::middle::stability;
 use crate::session::Session;
 use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
 use crate::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
-use errors::{struct_span_err, DiagnosticBuilder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
 use rustc_error_codes::*;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
@@ -64,17 +65,6 @@ pub struct LintStore {
     lint_groups: FxHashMap<&'static str, LintGroup>,
 }
 
-/// Lints that are buffered up early on in the `Session` before the
-/// `LintLevels` is calculated
-#[derive(PartialEq, Debug)]
-pub struct BufferedEarlyLint {
-    pub lint_id: LintId,
-    pub ast_id: ast::NodeId,
-    pub span: MultiSpan,
-    pub msg: String,
-    pub diagnostic: BuiltinLintDiagnostics,
-}
-
 /// The target of the `by_name` map, which accounts for renaming/deprecation.
 enum TargetLint {
     /// A direct lint target
@@ -477,6 +467,48 @@ impl LintPassObject for EarlyLintPassObject {}
 
 impl LintPassObject for LateLintPassObject {}
 
+pub fn add_elided_lifetime_in_path_suggestion(
+    sess: &Session,
+    db: &mut DiagnosticBuilder<'_>,
+    n: usize,
+    path_span: Span,
+    incl_angl_brckt: bool,
+    insertion_span: Span,
+    anon_lts: String,
+) {
+    let (replace_span, suggestion) = if incl_angl_brckt {
+        (insertion_span, anon_lts)
+    } else {
+        // When possible, prefer a suggestion that replaces the whole
+        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
+        // at a point (which makes for an ugly/confusing label)
+        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
+            // But our spans can get out of whack due to macros; if the place we think
+            // we want to insert `'_` isn't even within the path expression's span, we
+            // should bail out of making any suggestion rather than panicking on a
+            // subtract-with-overflow or string-slice-out-out-bounds (!)
+            // FIXME: can we do better?
+            if insertion_span.lo().0 < path_span.lo().0 {
+                return;
+            }
+            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
+            if insertion_index > snippet.len() {
+                return;
+            }
+            let (before, after) = snippet.split_at(insertion_index);
+            (path_span, format!("{}{}{}", before, anon_lts, after))
+        } else {
+            (insertion_span, anon_lts)
+        }
+    };
+    db.span_suggestion(
+        replace_span,
+        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
+        suggestion,
+        Applicability::MachineApplicable,
+    );
+}
+
 pub trait LintContext: Sized {
     type PassObject: LintPassObject;
 
@@ -495,7 +527,85 @@ pub trait LintContext: Sized {
         diagnostic: BuiltinLintDiagnostics,
     ) {
         let mut db = self.lookup(lint, span, msg);
-        diagnostic.run(self.sess(), &mut db);
+
+        let sess = self.sess();
+        match diagnostic {
+            BuiltinLintDiagnostics::Normal => (),
+            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
+                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                    Ok(s) if is_global => {
+                        (format!("dyn ({})", s), Applicability::MachineApplicable)
+                    }
+                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
+                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
+                };
+                db.span_suggestion(span, "use `dyn`", sugg, app);
+            }
+            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
+                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                    Ok(ref s) => {
+                        // FIXME(Manishearth) ideally the emitting code
+                        // can tell us whether or not this is global
+                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
+
+                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
+                    }
+                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
+                };
+                db.span_suggestion(span, "use `crate`", sugg, app);
+            }
+            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
+                db.span_label(
+                    span,
+                    "names from parent modules are not accessible without an explicit import",
+                );
+            }
+            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
+                db.span_note(span_def, "the macro is defined here");
+            }
+            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                n,
+                path_span,
+                incl_angl_brckt,
+                insertion_span,
+                anon_lts,
+            ) => {
+                add_elided_lifetime_in_path_suggestion(
+                    sess,
+                    &mut db,
+                    n,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_span,
+                    anon_lts,
+                );
+            }
+            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
+                db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
+            }
+            BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
+                if !replaces.is_empty() {
+                    db.tool_only_multipart_suggestion(
+                        &message,
+                        replaces,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
+                for (span, is_imported) in spans {
+                    let introduced = if is_imported { "imported" } else { "defined" };
+                    db.span_label(
+                        span,
+                        format!("the item `{}` is already {} here", ident, introduced),
+                    );
+                }
+            }
+            BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
+                stability::deprecation_suggestion(&mut db, suggestion, span)
+            }
+        }
+
         db.emit();
     }
 
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
index 69f212a9a30..30679226b9b 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc/lint/internal.rs
@@ -1,13 +1,11 @@
 //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
 //! Clippy.
 
-use crate::lint::{
-    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
-};
-use errors::Applicability;
+use crate::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
 use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
-use rustc_session::declare_tool_lint;
+use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast::{Ident, Item, ItemKind};
 
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index abd52a9de50..e586ad1836c 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -5,16 +5,16 @@ use crate::lint::builtin;
 use crate::lint::context::{CheckLintNameResult, LintStore};
 use crate::lint::{self, Level, Lint, LintId, LintSource};
 use crate::session::Session;
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir::HirId;
 use rustc_span::source_map::MultiSpan;
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast;
 use syntax::attr;
-use syntax::feature_gate;
 use syntax::print::pprust;
+use syntax::sess::feature_err;
 
 use rustc_error_codes::*;
 
@@ -223,7 +223,7 @@ impl<'a> LintLevelsBuilder<'a> {
                             // don't have any lint names (`#[level(reason = "foo")]`)
                             if let ast::LitKind::Str(rationale, _) = name_value.kind {
                                 if !self.sess.features_untracked().lint_reasons {
-                                    feature_gate::feature_err(
+                                    feature_err(
                                         &self.sess.parse_sess,
                                         sym::lint_reasons,
                                         item.span,
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 3f438005903..4afeb144948 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -21,12 +21,11 @@
 pub use self::Level::*;
 pub use self::LintSource::*;
 
-use crate::lint::builtin::BuiltinLintDiagnostics;
 use crate::ty::TyCtxt;
-use errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_data_structures::sync;
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
-use rustc_session::node_id::NodeMap;
+use rustc_session::lint::builtin::HardwiredLints;
 use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
@@ -35,48 +34,13 @@ use rustc_span::Span;
 use syntax::ast;
 
 pub use crate::lint::context::{
-    BufferedEarlyLint, CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore,
+    add_elided_lifetime_in_path_suggestion, CheckLintNameResult, EarlyContext, LateContext,
+    LintContext, LintStore,
 };
 
-pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
-
-/// Declares a static `LintArray` and return it as an expression.
-#[macro_export]
-macro_rules! lint_array {
-    ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
-    ($( $lint:expr ),*) => {{
-        vec![$($lint),*]
-    }}
-}
-
-pub type LintArray = Vec<&'static Lint>;
-
-pub trait LintPass {
-    fn name(&self) -> &'static str;
-}
-
-/// Implements `LintPass for $name` with the given list of `Lint` statics.
-#[macro_export]
-macro_rules! impl_lint_pass {
-    ($name:ident => [$($lint:expr),* $(,)?]) => {
-        impl LintPass for $name {
-            fn name(&self) -> &'static str { stringify!($name) }
-        }
-        impl $name {
-            pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) }
-        }
-    };
-}
-
-/// Declares a type named `$name` which implements `LintPass`.
-/// To the right of `=>` a comma separated list of `Lint` statics is given.
-#[macro_export]
-macro_rules! declare_lint_pass {
-    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
-        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
-        $crate::impl_lint_pass!($name => [$($lint),*]);
-    };
-}
+pub use rustc_session::lint::builtin;
+pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Level, Lint, LintId};
+pub use rustc_session::lint::{LintArray, LintPass};
 
 #[macro_export]
 macro_rules! late_lint_methods {
@@ -168,6 +132,8 @@ macro_rules! declare_late_lint_pass {
 
 late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
 
+impl LateLintPass<'_, '_> for HardwiredLints {}
+
 #[macro_export]
 macro_rules! expand_combined_late_lint_pass_method {
     ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
@@ -366,66 +332,12 @@ pub enum LintSource {
 
 pub type LevelSource = (Level, LintSource);
 
-pub mod builtin;
 mod context;
 pub mod internal;
 mod levels;
 
 pub use self::levels::{LintLevelMap, LintLevelSets, LintLevelsBuilder};
 
-#[derive(Default)]
-pub struct LintBuffer {
-    pub map: NodeMap<Vec<BufferedEarlyLint>>,
-}
-
-impl LintBuffer {
-    pub fn add_lint(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: MultiSpan,
-        msg: &str,
-        diagnostic: BuiltinLintDiagnostics,
-    ) {
-        let early_lint = BufferedEarlyLint {
-            lint_id: LintId::of(lint),
-            ast_id: id,
-            span: sp,
-            msg: msg.to_string(),
-            diagnostic,
-        };
-        let arr = self.map.entry(id).or_default();
-        if !arr.contains(&early_lint) {
-            arr.push(early_lint);
-        }
-    }
-
-    pub fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> {
-        self.map.remove(&id).unwrap_or_default()
-    }
-
-    pub fn buffer_lint<S: Into<MultiSpan>>(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: S,
-        msg: &str,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
-    }
-
-    pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: S,
-        msg: &str,
-        diagnostic: BuiltinLintDiagnostics,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, diagnostic)
-    }
-}
-
 pub fn struct_lint_level<'a>(
     sess: &'a Session,
     lint: &'static Lint,
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6f59df01a52..42fc3e030e7 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -14,8 +14,8 @@ use crate::middle::cstore::ExternCrate;
 use crate::middle::weak_lang_items;
 use crate::ty::{self, TyCtxt};
 
-use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index f2474faa75e..17e84c24881 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -3,23 +3,22 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::lint::builtin::BuiltinLintDiagnostics;
 use crate::lint::{self, in_derive_expansion, Lint};
 use crate::session::{DiagnosticMessageId, Session};
 use crate::ty::{self, TyCtxt};
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_hir::{self, HirId};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::CRATE_NODE_ID;
 use syntax::attr::{self, ConstStability, Deprecation, RustcDeprecation, Stability};
-use syntax::errors::Applicability;
-use syntax::feature_gate::feature_err_issue;
+use syntax::sess::feature_err_issue;
 
 use std::num::NonZeroU32;
 
@@ -196,7 +195,7 @@ pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String
 }
 
 pub fn early_report_deprecation(
-    lint_buffer: &'a mut lint::LintBuffer,
+    lint_buffer: &'a mut LintBuffer,
     message: &str,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index 89f385a51bc..fdffd1251ce 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -5,8 +5,8 @@ use crate::session::config;
 
 use crate::hir::map::Map;
 use crate::ty::TyCtxt;
-use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index cb11ac49cec..ed61534d545 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -7,8 +7,8 @@ use crate::ty::query::TyCtxtAt;
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
-use errors::{struct_span_err, DiagnosticBuilder};
 use hir::GeneratorKind;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_macros::HashStable;
 use rustc_span::symbol::Symbol;
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 4a2ec9b9687..9de46f86200 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -686,10 +686,6 @@ rustc_queries! {
             fatal_cycle
             desc { "checking if the crate has_panic_handler" }
         }
-        query is_sanitizer_runtime(_: CrateNum) -> bool {
-            fatal_cycle
-            desc { "query a crate is `#![sanitizer_runtime]`" }
-        }
         query is_profiler_runtime(_: CrateNum) -> bool {
             fatal_cycle
             desc { "query a crate is `#![profiler_runtime]`" }
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index db7cda3b95b..29ea47809a0 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -38,7 +38,7 @@ pub struct OverlapResult<'tcx> {
     pub involves_placeholder: bool,
 }
 
-pub fn add_placeholder_note(err: &mut errors::DiagnosticBuilder<'_>) {
+pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
     err.note(&format!(
         "this behavior recently changed as a result of a bug fix; \
          see rust-lang/rust#56105 for details"
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b9bb68798e5..0c9a73d78a5 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -21,8 +21,8 @@ use crate::ty::SubtypePredicate;
 use crate::ty::TypeckTables;
 use crate::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index f1b830e43fc..1afe153bb13 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -3,8 +3,8 @@ use fmt_macros::{Parser, Piece, Position};
 use crate::ty::{self, GenericParamDefKind, TyCtxt};
 use crate::util::common::ErrorReported;
 
-use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 370acb53896..34866b684de 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -76,7 +76,7 @@ pub struct DropckOutlivesResult<'tcx> {
 impl<'tcx> DropckOutlivesResult<'tcx> {
     pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
         if let Some(overflow_ty) = self.overflows.iter().next() {
-            errors::struct_span_err!(
+            rustc_errors::struct_span_err!(
                 tcx.sess,
                 span,
                 E0320,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 1b1cb1b36e0..8b66f4926e0 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -102,7 +102,7 @@ pub enum IntercrateAmbiguityCause {
 impl IntercrateAmbiguityCause {
     /// Emits notes when the overlap is caused by complex intercrate ambiguities.
     /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint(&self, err: &mut errors::DiagnosticBuilder<'_>) {
+    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
         err.note(&self.intercrate_ambiguity_hint());
     }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index d1897148838..7b66341ef1c 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -17,8 +17,8 @@ use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::{self, TyCtxt, TypeFoldable};
-use errors::struct_span_err;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
 use rustc_span::DUMMY_SP;
 
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 8355239af87..65fd809657b 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -1,4 +1,4 @@
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_span::Span;
 use smallvec::SmallVec;
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 17f5b98ab20..1b0b5fc4d07 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -51,7 +51,6 @@ use rustc_hir::{HirId, Node, TraitCandidate};
 use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
 
 use arena::SyncDroplessArena;
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::ShardedHashMap;
@@ -59,6 +58,7 @@ use rustc_data_structures::stable_hasher::{
     hash_stable_hashmap, HashStable, StableHasher, StableVec,
 };
 use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
+use rustc_errors::DiagnosticBuilder;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_session::node_id::NodeMap;
@@ -1613,10 +1613,10 @@ pub mod tls {
 
     use crate::dep_graph::TaskDeps;
     use crate::ty::query;
-    use errors::Diagnostic;
     use rustc_data_structures::sync::{self, Lock, Lrc};
     use rustc_data_structures::thin_vec::ThinVec;
     use rustc_data_structures::OnDrop;
+    use rustc_errors::Diagnostic;
     use std::mem;
 
     #[cfg(not(parallel_compiler))]
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 25fc484cd53..f7612874e05 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -1,12 +1,10 @@
 use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-
-use errors::{Applicability, DiagnosticBuilder};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast;
-use syntax::errors::pluralize;
 
 use std::borrow::Cow;
 use std::fmt;
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index c77cf8c41be..dbb6a1080e6 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -2,8 +2,7 @@ use crate::dep_graph::SerializedDepNodeIndex;
 use crate::dep_graph::{DepKind, DepNode};
 use crate::ty::query::plumbing::CycleError;
 use crate::ty::query::queries;
-use crate::ty::query::QueryCache;
-use crate::ty::query::{Query, QueryName};
+use crate::ty::query::{Query, QueryCache};
 use crate::ty::TyCtxt;
 use rustc_data_structures::profiling::ProfileCategory;
 use rustc_hir::def_id::{CrateNum, DefId};
@@ -20,7 +19,7 @@ use std::hash::Hash;
 // FIXME(eddyb) false positive, the lifetime parameter is used for `Key`/`Value`.
 #[allow(unused_lifetimes)]
 pub trait QueryConfig<'tcx> {
-    const NAME: QueryName;
+    const NAME: &'static str;
     const CATEGORY: ProfileCategory;
 
     type Key: Eq + Hash + Clone + Debug;
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index b163d23e239..6b272ab3d4a 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -81,6 +81,9 @@ pub(crate) use self::config::QueryDescription;
 mod on_disk_cache;
 pub use self::on_disk_cache::OnDiskCache;
 
+mod profiling_support;
+pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder};
+
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 5d968811add..a81fe33831c 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -7,10 +7,10 @@ use crate::session::{CrateDisambiguator, Session};
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
-use errors::Diagnostic;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 35608540383..84efbe21f10 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -9,13 +9,15 @@ use crate::ty::query::Query;
 use crate::ty::tls;
 use crate::ty::{self, TyCtxt};
 
-use errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level};
 #[cfg(not(parallel_compiler))]
 use rustc_data_structures::cold_path;
 use rustc_data_structures::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::profiling::TimingGuard;
 use rustc_data_structures::sharded::Sharded;
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::Span;
 use std::collections::hash_map::Entry;
@@ -82,6 +84,19 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
     /// for some compile-time benchmarks.
     #[inline(always)]
     pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> {
+        // Handling the `query_blocked_prof_timer` is a bit weird because of the
+        // control flow in this function: Blocking is implemented by
+        // awaiting a running job and, once that is done, entering the loop below
+        // again from the top. In that second iteration we will hit the
+        // cache which provides us with the information we need for
+        // finishing the "query-blocked" event.
+        //
+        // We thus allocate `query_blocked_prof_timer` outside the loop,
+        // initialize it during the first iteration and finish it during the
+        // second iteration.
+        #[cfg(parallel_compiler)]
+        let mut query_blocked_prof_timer: Option<TimingGuard<'_>> = None;
+
         let cache = Q::query_cache(tcx);
         loop {
             // We compute the key's hash once and then use it for both the
@@ -95,7 +110,17 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
             if let Some((_, value)) =
                 lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key)
             {
-                tcx.prof.query_cache_hit(Q::NAME);
+                if unlikely!(tcx.prof.enabled()) {
+                    tcx.prof.query_cache_hit(value.index.into());
+
+                    #[cfg(parallel_compiler)]
+                    {
+                        if let Some(prof_timer) = query_blocked_prof_timer.take() {
+                            prof_timer.finish_with_query_invocation_id(value.index.into());
+                        }
+                    }
+                }
+
                 let result = (value.value.clone(), value.index);
                 #[cfg(debug_assertions)]
                 {
@@ -104,9 +129,6 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
                 return TryGetJob::JobCompleted(result);
             }
 
-            #[cfg(parallel_compiler)]
-            let query_blocked_prof_timer;
-
             let job = match lock.active.entry((*key).clone()) {
                 Entry::Occupied(entry) => {
                     match *entry.get() {
@@ -116,7 +138,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
                             // self-profiler.
                             #[cfg(parallel_compiler)]
                             {
-                                query_blocked_prof_timer = tcx.prof.query_blocked(Q::NAME);
+                                query_blocked_prof_timer = Some(tcx.prof.query_blocked());
                             }
 
                             job.clone()
@@ -153,11 +175,6 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
             {
                 let result = job.r#await(tcx, span);
 
-                // This `drop()` is not strictly necessary as the binding
-                // would go out of scope anyway. But it's good to have an
-                // explicit marker of how far the measurement goes.
-                drop(query_blocked_prof_timer);
-
                 if let Err(cycle) = result {
                     return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle));
                 }
@@ -347,7 +364,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline(never)]
     pub(super) fn get_query<Q: QueryDescription<'tcx>>(self, span: Span, key: Q::Key) -> Q::Value {
-        debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME.as_str(), key, span);
+        debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
 
         let job = match JobOwner::try_get(self, span, &key) {
             TryGetJob::NotYetStarted(job) => job,
@@ -366,7 +383,7 @@ impl<'tcx> TyCtxt<'tcx> {
         }
 
         if Q::ANON {
-            let prof_timer = self.prof.query_provider(Q::NAME);
+            let prof_timer = self.prof.query_provider();
 
             let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
                 self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -374,7 +391,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 })
             });
 
-            drop(prof_timer);
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             self.dep_graph.read_index(dep_node_index);
 
@@ -436,8 +453,9 @@ impl<'tcx> TyCtxt<'tcx> {
         let result = if Q::cache_on_disk(self, key.clone(), None)
             && self.sess.opts.debugging_opts.incremental_queries
         {
-            let _prof_timer = self.prof.incr_cache_loading(Q::NAME);
+            let prof_timer = self.prof.incr_cache_loading();
             let result = Q::try_load_from_disk(self, prev_dep_node_index);
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             // We always expect to find a cached result for things that
             // can be forced from `DepNode`.
@@ -457,11 +475,13 @@ impl<'tcx> TyCtxt<'tcx> {
         } else {
             // We could not load a result from the on-disk cache, so
             // recompute.
-            let _prof_timer = self.prof.query_provider(Q::NAME);
+            let prof_timer = self.prof.query_provider();
 
             // The dep-graph for this computation is already in-place.
             let result = self.dep_graph.with_ignore(|| Q::compute(self, key));
 
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+
             result
         };
 
@@ -523,7 +543,7 @@ impl<'tcx> TyCtxt<'tcx> {
             dep_node
         );
 
-        let prof_timer = self.prof.query_provider(Q::NAME);
+        let prof_timer = self.prof.query_provider();
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
             self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -541,7 +561,7 @@ impl<'tcx> TyCtxt<'tcx> {
             })
         });
 
-        drop(prof_timer);
+        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if unlikely!(!diagnostics.is_empty()) {
             if dep_node.kind != crate::dep_graph::DepKind::Null {
@@ -572,17 +592,19 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let dep_node = Q::to_dep_node(self, &key);
 
-        if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
-            // A None return from `try_mark_green_and_read` means that this is either
-            // a new dep node or that the dep node has already been marked red.
-            // Either way, we can't call `dep_graph.read()` as we don't have the
-            // DepNodeIndex. We must invoke the query itself. The performance cost
-            // this introduces should be negligible as we'll immediately hit the
-            // in-memory cache, or another query down the line will.
-
-            let _ = self.get_query::<Q>(DUMMY_SP, key);
-        } else {
-            self.prof.query_cache_hit(Q::NAME);
+        match self.dep_graph.try_mark_green_and_read(self, &dep_node) {
+            None => {
+                // A None return from `try_mark_green_and_read` means that this is either
+                // a new dep node or that the dep node has already been marked red.
+                // Either way, we can't call `dep_graph.read()` as we don't have the
+                // DepNodeIndex. We must invoke the query itself. The performance cost
+                // this introduces should be negligible as we'll immediately hit the
+                // in-memory cache, or another query down the line will.
+                let _ = self.get_query::<Q>(DUMMY_SP, key);
+            }
+            Some((_, dep_node_index)) => {
+                self.prof.query_cache_hit(dep_node_index.into());
+            }
         }
     }
 
@@ -814,36 +836,6 @@ macro_rules! define_queries_inner {
         }
 
         #[allow(nonstandard_style)]
-        #[derive(Clone, Copy)]
-        pub enum QueryName {
-            $($name),*
-        }
-
-        impl rustc_data_structures::profiling::QueryName for QueryName {
-            fn discriminant(self) -> std::mem::Discriminant<QueryName> {
-                std::mem::discriminant(&self)
-            }
-
-            fn as_str(self) -> &'static str {
-                QueryName::as_str(&self)
-            }
-        }
-
-        impl QueryName {
-            pub fn register_with_profiler(
-                profiler: &rustc_data_structures::profiling::SelfProfiler,
-            ) {
-                $(profiler.register_query_name(QueryName::$name);)*
-            }
-
-            pub fn as_str(&self) -> &'static str {
-                match self {
-                    $(QueryName::$name => stringify!($name),)*
-                }
-            }
-        }
-
-        #[allow(nonstandard_style)]
         #[derive(Clone, Debug)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
@@ -883,12 +875,6 @@ macro_rules! define_queries_inner {
                     $(Query::$name(key) => key.default_span(tcx),)*
                 }
             }
-
-            pub fn query_name(&self) -> QueryName {
-                match self {
-                    $(Query::$name(_) => QueryName::$name,)*
-                }
-            }
         }
 
         impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> {
@@ -923,7 +909,7 @@ macro_rules! define_queries_inner {
             type Key = $K;
             type Value = $V;
 
-            const NAME: QueryName = QueryName::$name;
+            const NAME: &'static str = stringify!($name);
             const CATEGORY: ProfileCategory = $category;
         }
 
@@ -1035,6 +1021,35 @@ macro_rules! define_queries_inner {
             pub fn $name(self, key: $K) -> $V {
                 self.at(DUMMY_SP).$name(key)
             })*
+
+            /// All self-profiling events generated by the query engine use
+            /// virtual `StringId`s for their `event_id`. This method makes all
+            /// those virtual `StringId`s point to actual strings.
+            ///
+            /// If we are recording only summary data, the ids will point to
+            /// just the query names. If we are recording query keys too, we
+            /// allocate the corresponding strings here.
+            pub fn alloc_self_profile_query_strings(self) {
+                use crate::ty::query::profiling_support::{
+                    alloc_self_profile_query_strings_for_query_cache,
+                    QueryKeyStringCache,
+                };
+
+                if !self.prof.enabled() {
+                    return;
+                }
+
+                let mut string_cache = QueryKeyStringCache::new();
+
+                $({
+                    alloc_self_profile_query_strings_for_query_cache(
+                        self,
+                        stringify!($name),
+                        &self.queries.$name,
+                        &mut string_cache,
+                    );
+                })*
+            }
         }
 
         impl TyCtxtAt<$tcx> {
diff --git a/src/librustc/ty/query/profiling_support.rs b/src/librustc/ty/query/profiling_support.rs
new file mode 100644
index 00000000000..79b32ba83ae
--- /dev/null
+++ b/src/librustc/ty/query/profiling_support.rs
@@ -0,0 +1,235 @@
+use crate::hir::map::definitions::DefPathData;
+use crate::ty::context::TyCtxt;
+use crate::ty::query::config::QueryConfig;
+use crate::ty::query::plumbing::QueryCache;
+use measureme::{StringComponent, StringId};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::profiling::SelfProfiler;
+use rustc_data_structures::sharded::Sharded;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use std::fmt::Debug;
+use std::io::Write;
+
+pub struct QueryKeyStringCache {
+    def_id_cache: FxHashMap<DefId, StringId>,
+}
+
+impl QueryKeyStringCache {
+    pub fn new() -> QueryKeyStringCache {
+        QueryKeyStringCache { def_id_cache: Default::default() }
+    }
+}
+
+pub struct QueryKeyStringBuilder<'p, 'c, 'tcx> {
+    profiler: &'p SelfProfiler,
+    tcx: TyCtxt<'tcx>,
+    string_cache: &'c mut QueryKeyStringCache,
+}
+
+impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+    pub fn new(
+        profiler: &'p SelfProfiler,
+        tcx: TyCtxt<'tcx>,
+        string_cache: &'c mut QueryKeyStringCache,
+    ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+        QueryKeyStringBuilder { profiler, tcx, string_cache }
+    }
+
+    // The current implementation is rather crude. In the future it might be a
+    // good idea to base this on `ty::print` in order to get nicer and more
+    // efficient query keys.
+    fn def_id_to_string_id(&mut self, def_id: DefId) -> StringId {
+        if let Some(&string_id) = self.string_cache.def_id_cache.get(&def_id) {
+            return string_id;
+        }
+
+        let def_key = self.tcx.def_key(def_id);
+
+        let (parent_string_id, start_index) = match def_key.parent {
+            Some(parent_index) => {
+                let parent_def_id = DefId { index: parent_index, krate: def_id.krate };
+
+                (self.def_id_to_string_id(parent_def_id), 0)
+            }
+            None => (StringId::INVALID, 2),
+        };
+
+        let dis_buffer = &mut [0u8; 16];
+        let name;
+        let dis;
+        let end_index;
+
+        match def_key.disambiguated_data.data {
+            DefPathData::CrateRoot => {
+                name = self.tcx.original_crate_name(def_id.krate).as_str();
+                dis = "";
+                end_index = 3;
+            }
+            other => {
+                name = other.as_symbol().as_str();
+                if def_key.disambiguated_data.disambiguator == 0 {
+                    dis = "";
+                    end_index = 3;
+                } else {
+                    write!(&mut dis_buffer[..], "[{}]", def_key.disambiguated_data.disambiguator)
+                        .unwrap();
+                    let end_of_dis = dis_buffer.iter().position(|&c| c == b']').unwrap();
+                    dis = std::str::from_utf8(&dis_buffer[..end_of_dis + 1]).unwrap();
+                    end_index = 4;
+                }
+            }
+        }
+
+        let components = [
+            StringComponent::Ref(parent_string_id),
+            StringComponent::Value("::"),
+            StringComponent::Value(&name[..]),
+            StringComponent::Value(dis),
+        ];
+
+        let string_id = self.profiler.alloc_string(&components[start_index..end_index]);
+
+        self.string_cache.def_id_cache.insert(def_id, string_id);
+
+        string_id
+    }
+}
+
+pub trait IntoSelfProfilingString {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId;
+}
+
+// The default implementation of `IntoSelfProfilingString` just uses `Debug`
+// which is slow and causes lots of duplication of string data.
+// The specialized impls below take care of making the `DefId` case more
+// efficient.
+impl<T: Debug> IntoSelfProfilingString for T {
+    default fn to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        let s = format!("{:?}", self);
+        builder.profiler.alloc_string(&s[..])
+    }
+}
+
+impl IntoSelfProfilingString for DefId {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(*self)
+    }
+}
+
+impl IntoSelfProfilingString for CrateNum {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
+    }
+}
+
+impl IntoSelfProfilingString for DefIndex {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
+    }
+}
+
+impl<T0, T1> IntoSelfProfilingString for (T0, T1)
+where
+    T0: IntoSelfProfilingString + Debug,
+    T1: IntoSelfProfilingString + Debug,
+{
+    default fn to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        let val0 = self.0.to_self_profile_string(builder);
+        let val1 = self.1.to_self_profile_string(builder);
+
+        let components = &[
+            StringComponent::Value("("),
+            StringComponent::Ref(val0),
+            StringComponent::Value(","),
+            StringComponent::Ref(val1),
+            StringComponent::Value(")"),
+        ];
+
+        builder.profiler.alloc_string(components)
+    }
+}
+
+/// Allocate the self-profiling query strings for a single query cache. This
+/// method is called from `alloc_self_profile_query_strings` which knows all
+/// the queries via macro magic.
+pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>(
+    tcx: TyCtxt<'tcx>,
+    query_name: &'static str,
+    query_cache: &Sharded<QueryCache<'tcx, Q>>,
+    string_cache: &mut QueryKeyStringCache,
+) where
+    Q: QueryConfig<'tcx>,
+{
+    tcx.prof.with_profiler(|profiler| {
+        let event_id_builder = profiler.event_id_builder();
+
+        // Walk the entire query cache and allocate the appropriate
+        // string representations. Each cache entry is uniquely
+        // identified by its dep_node_index.
+        if profiler.query_key_recording_enabled() {
+            let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);
+
+            let query_name = profiler.get_or_alloc_cached_string(query_name);
+
+            // Since building the string representation of query keys might
+            // need to invoke queries itself, we cannot keep the query caches
+            // locked while doing so. Instead we copy out the
+            // `(query_key, dep_node_index)` pairs and release the lock again.
+            let query_keys_and_indices = {
+                let shards = query_cache.lock_shards();
+                let len = shards.iter().map(|shard| shard.results.len()).sum();
+
+                let mut query_keys_and_indices = Vec::with_capacity(len);
+
+                for shard in &shards {
+                    query_keys_and_indices.extend(
+                        shard.results.iter().map(|(q_key, q_val)| (q_key.clone(), q_val.index)),
+                    );
+                }
+
+                query_keys_and_indices
+            };
+
+            // Now actually allocate the strings. If allocating the strings
+            // generates new entries in the query cache, we'll miss them but
+            // we don't actually care.
+            for (query_key, dep_node_index) in query_keys_and_indices {
+                // Translate the DepNodeIndex into a QueryInvocationId
+                let query_invocation_id = dep_node_index.into();
+
+                // Create the string version of the query-key
+                let query_key = query_key.to_self_profile_string(&mut query_string_builder);
+                let event_id = event_id_builder.from_label_and_arg(query_name, query_key);
+
+                // Doing this in bulk might be a good idea:
+                profiler.map_query_invocation_id_to_string(
+                    query_invocation_id,
+                    event_id.to_string_id(),
+                );
+            }
+        } else {
+            // In this branch we don't allocate query keys
+            let query_name = profiler.get_or_alloc_cached_string(query_name);
+            let event_id = event_id_builder.from_label(query_name).to_string_id();
+
+            let shards = query_cache.lock_shards();
+
+            for shard in shards.iter() {
+                let query_invocation_ids = shard
+                    .results
+                    .values()
+                    .map(|v| v.index)
+                    .map(|dep_node_index| dep_node_index.into());
+
+                profiler
+                    .bulk_map_query_invocation_id_to_single_string(query_invocation_ids, event_id);
+            }
+        }
+    });
+}
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index ddff8258c6d..8d22ac9dbbe 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -3,18 +3,18 @@
 use crate::hir::map::DefPathData;
 use crate::ich::NodeIdHashingMode;
 use crate::mir::interpret::{sign_extend, truncate};
-use crate::ty::layout::{Integer, IntegerExt};
+use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use crate::ty::TyKind::*;
 use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable};
 use crate::util::common::ErrorReported;
+use rustc_apfloat::Float as _;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_span::Span;
 use std::{cmp, fmt};
@@ -43,26 +43,38 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
     }
 }
 
+fn signed_min(size: Size) -> i128 {
+    sign_extend(1_u128 << (size.bits() - 1), size) as i128
+}
+
+fn signed_max(size: Size) -> i128 {
+    i128::max_value() >> (128 - size.bits())
+}
+
+fn unsigned_max(size: Size) -> u128 {
+    u128::max_value() >> (128 - size.bits())
+}
+
+fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
+    let (int, signed) = match ty.kind {
+        Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
+        Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
+        _ => bug!("non integer discriminant"),
+    };
+    (int.size(), signed)
+}
+
 impl<'tcx> Discr<'tcx> {
     /// Adds `1` to the value and wraps around if the maximum for the type is reached.
     pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self {
         self.checked_add(tcx, 1).0
     }
     pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
-        let (int, signed) = match self.ty.kind {
-            Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
-            Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
-            _ => bug!("non integer discriminant"),
-        };
-
-        let size = int.size();
-        let bit_size = int.size().bits();
-        let shift = 128 - bit_size;
-        if signed {
-            let sext = |u| sign_extend(u, size) as i128;
-            let min = sext(1_u128 << (bit_size - 1));
-            let max = i128::max_value() >> shift;
-            let val = sext(self.val);
+        let (size, signed) = int_size_and_signed(tcx, self.ty);
+        let (val, oflo) = if signed {
+            let min = signed_min(size);
+            let max = signed_max(size);
+            let val = sign_extend(self.val, size) as i128;
             assert!(n < (i128::max_value() as u128));
             let n = n as i128;
             let oflo = val > max - n;
@@ -70,14 +82,15 @@ impl<'tcx> Discr<'tcx> {
             // zero the upper bits
             let val = val as u128;
             let val = truncate(val, size);
-            (Self { val: val as u128, ty: self.ty }, oflo)
+            (val, oflo)
         } else {
-            let max = u128::max_value() >> shift;
+            let max = unsigned_max(size);
             let val = self.val;
             let oflo = val > max - n;
             let val = if oflo { n - (max - val) - 1 } else { val + n };
-            (Self { val: val, ty: self.ty }, oflo)
-        }
+            (val, oflo)
+        };
+        (Self { val, ty: self.ty }, oflo)
     }
 }
 
@@ -621,6 +634,44 @@ impl<'tcx> TyCtxt<'tcx> {
 }
 
 impl<'tcx> ty::TyS<'tcx> {
+    /// Returns the maximum value for the given numeric type (including `char`s)
+    /// or returns `None` if the type is not numeric.
+    pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
+        let val = match self.kind {
+            ty::Int(_) | ty::Uint(_) => {
+                let (size, signed) = int_size_and_signed(tcx, self);
+                let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
+                Some(val)
+            }
+            ty::Char => Some(std::char::MAX as u128),
+            ty::Float(fty) => Some(match fty {
+                ast::FloatTy::F32 => ::rustc_apfloat::ieee::Single::INFINITY.to_bits(),
+                ast::FloatTy::F64 => ::rustc_apfloat::ieee::Double::INFINITY.to_bits(),
+            }),
+            _ => None,
+        };
+        val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
+    }
+
+    /// Returns the minimum value for the given numeric type (including `char`s)
+    /// or returns `None` if the type is not numeric.
+    pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
+        let val = match self.kind {
+            ty::Int(_) | ty::Uint(_) => {
+                let (size, signed) = int_size_and_signed(tcx, self);
+                let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
+                Some(val)
+            }
+            ty::Char => Some(0),
+            ty::Float(fty) => Some(match fty {
+                ast::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(),
+                ast::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(),
+            }),
+            _ => None,
+        };
+        val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
+    }
+
     /// Checks whether values of this type `T` are *moved* or *copied*
     /// when referenced -- this amounts to a check for whether `T:
     /// Copy`, but note that we **don't** consider lifetimes when
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 9324b26a09b..19b43bfd162 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -8,7 +8,7 @@ use std::time::{Duration, Instant};
 #[cfg(test)]
 mod tests;
 
-pub use errors::ErrorReported;
+pub use rustc_errors::ErrorReported;
 
 pub fn to_readable_str(mut val: usize) -> String {
     let mut groups = vec![];
diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml
deleted file mode 100644
index df117de8720..00000000000
--- a/src/librustc_asan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_asan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_asan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
deleted file mode 100644
index e276dc16c35..00000000000
--- a/src/librustc_asan/build.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("asan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-        native.fixup_sanitizer_lib_name("asan");
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs
deleted file mode 100644
index bdbc154f4e8..00000000000
--- a/src/librustc_asan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 527aa6796bc..58b8e8a089a 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -37,7 +37,6 @@ use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
 use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions};
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::lint::builtin;
 use rustc::{bug, span_bug};
 use rustc_data_structures::captures::Captures;
@@ -52,6 +51,7 @@ use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::IndexVec;
 use rustc_session::config::nightly_options;
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::node_id::NodeMap;
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
@@ -198,7 +198,7 @@ pub trait Resolver {
         ns: Namespace,
     ) -> (ast::Path, Res<NodeId>);
 
-    fn lint_buffer(&mut self) -> &mut lint::LintBuffer;
+    fn lint_buffer(&mut self) -> &mut LintBuffer;
 
     fn next_node_id(&mut self) -> NodeId;
 }
@@ -268,7 +268,7 @@ pub fn lower_crate<'a, 'hir>(
     // incr. comp. yet.
     dep_graph.assert_ignored();
 
-    let _prof_timer = sess.prof.generic_activity("hir_lowering");
+    let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
 
     LoweringContext {
         crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
@@ -2617,7 +2617,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 id,
                 span,
                 "trait objects without an explicit `dyn` are deprecated",
-                builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
+                BuiltinLintDiagnostics::BareTraitObject(span, is_global),
             )
         }
     }
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index cd69646d0c5..6cf640a0e98 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -65,9 +65,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
             PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
             PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
-                self.lower_expr(e1),
-                self.lower_expr(e2),
-                self.lower_range_end(end),
+                e1.as_deref().map(|e| self.lower_expr(e)),
+                e2.as_deref().map(|e| self.lower_expr(e)),
+                self.lower_range_end(end, e2.is_some()),
             ),
             PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
             PatKind::Rest => {
@@ -253,10 +253,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         hir::PatKind::Wild
     }
 
-    fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
+    fn lower_range_end(&mut self, e: &RangeEnd, has_end: bool) -> hir::RangeEnd {
         match *e {
-            RangeEnd::Included(_) => hir::RangeEnd::Included,
-            RangeEnd::Excluded => hir::RangeEnd::Excluded,
+            RangeEnd::Excluded if has_end => hir::RangeEnd::Excluded,
+            // No end; so `X..` behaves like `RangeFrom`.
+            RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included,
         }
     }
 }
diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs
index 9b504704ae0..65347d379bd 100644
--- a/src/librustc_ast_lowering/path.rs
+++ b/src/librustc_ast_lowering/path.rs
@@ -1,7 +1,7 @@
 use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
 use super::{GenericArgsCtor, ParenthesizedGenericArgs};
 
-use rustc::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
+use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
 use rustc::span_bug;
 use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability};
@@ -9,6 +9,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::Span;
 use syntax::ast::{self, *};
 
@@ -304,7 +305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             E0726,
                             "implicit elided lifetime not allowed here"
                         );
-                        crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
+                        rustc::lint::add_elided_lifetime_in_path_suggestion(
                             &self.sess,
                             &mut err,
                             expected_lifetimes,
@@ -321,7 +322,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             CRATE_NODE_ID,
                             path_span,
                             "hidden lifetime parameters in types are deprecated",
-                            builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
                                 expected_lifetimes,
                                 path_span,
                                 incl_angl_brckt,
diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml
new file mode 100644
index 00000000000..dced4a0d15b
--- /dev/null
+++ b/src/librustc_ast_passes/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_ast_passes"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_ast_passes"
+path = "lib.rs"
+
+[dependencies]
+log = "0.4"
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_error_codes = { path = "../librustc_error_codes" }
+rustc_feature = { path = "../librustc_feature" }
+rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
+syntax = { path = "../libsyntax" }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 724d717304c..c915b7ba216 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -6,11 +6,12 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
-use errors::{struct_span_err, Applicability, FatalError};
-use rustc::lint;
-use rustc::session::Session;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, Applicability, FatalError};
 use rustc_parse::validate_attr;
+use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
+use rustc_session::lint::LintBuffer;
+use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -65,7 +66,7 @@ struct AstValidator<'a> {
     /// certain positions.
     is_assoc_ty_bound_banned: bool,
 
-    lint_buffer: &'a mut lint::LintBuffer,
+    lint_buffer: &'a mut LintBuffer,
 }
 
 impl<'a> AstValidator<'a> {
@@ -158,7 +159,7 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn err_handler(&self) -> &errors::Handler {
+    fn err_handler(&self) -> &rustc_errors::Handler {
         &self.session.diagnostic()
     }
 
@@ -409,7 +410,7 @@ enum GenericPosition {
 
 fn validate_generics_order<'a>(
     sess: &Session,
-    handler: &errors::Handler,
+    handler: &rustc_errors::Handler,
     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
     pos: GenericPosition,
     span: Span,
@@ -906,7 +907,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     }
                 }
 
-                Some(Constness::Const) => bug!("Parser should reject bare `const` on bounds"),
+                Some(Constness::Const) => panic!("Parser should reject bare `const` on bounds"),
                 None => {}
             }
         }
@@ -920,8 +921,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.check_expr_within_pat(expr, false);
             }
             PatKind::Range(ref start, ref end, _) => {
-                self.check_expr_within_pat(start, true);
-                self.check_expr_within_pat(end, true);
+                if let Some(expr) = start {
+                    self.check_expr_within_pat(expr, true);
+                }
+                if let Some(expr) = end {
+                    self.check_expr_within_pat(expr, true);
+                }
             }
             _ => {}
         }
@@ -988,7 +993,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
                     if mut_ident {
                         self.lint_buffer.buffer_lint(
-                            lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                            PATTERNS_IN_FNS_WITHOUT_BODY,
                             ti.id,
                             span,
                             "patterns aren't allowed in methods without bodies",
@@ -1017,7 +1022,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 }
 
-pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
+pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
     let mut validator = AstValidator {
         session,
         has_proc_macro_decls: false,
diff --git a/src/libsyntax/feature_gate/check.rs b/src/librustc_ast_passes/feature_gate.rs
index 52eb20d320f..1e396d6fe8e 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -1,22 +1,15 @@
-use crate::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use crate::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
-use crate::attr;
-use crate::sess::ParseSess;
-use crate::visit::{self, FnKind, Visitor};
-
-use errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Handler};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_error_codes::*;
-use rustc_feature::{find_feature_issue, GateIssue};
+use rustc_errors::{struct_span_err, Handler};
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
-use rustc_feature::{Feature, Features, State as FeatureState, UnstableFeatures};
-use rustc_feature::{
-    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
-};
-use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_feature::{Features, GateIssue, UnstableFeatures};
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
+use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
+use syntax::attr;
+use syntax::sess::{feature_err, leveled_feature_err, GateStrength, ParseSess};
+use syntax::visit::{self, FnKind, Visitor};
 
 use log::debug;
 
@@ -53,70 +46,6 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features:
     PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
 }
 
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum GateStrength {
-    /// A hard error. (Most feature gates should use this.)
-    Hard,
-    /// Only a warning. (Use this only as backwards-compatibility demands.)
-    Soft,
-}
-
-pub fn feature_err<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    explain: &str,
-) -> DiagnosticBuilder<'a> {
-    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
-}
-
-pub fn feature_err_issue<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    issue: GateIssue,
-    explain: &str,
-) -> DiagnosticBuilder<'a> {
-    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
-}
-
-fn leveled_feature_err<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    issue: GateIssue,
-    explain: &str,
-    level: GateStrength,
-) -> DiagnosticBuilder<'a> {
-    let diag = &sess.span_diagnostic;
-
-    let mut err = match level {
-        GateStrength::Hard => diag.struct_span_err_with_code(span, explain, error_code!(E0658)),
-        GateStrength::Soft => diag.struct_span_warn(span, explain),
-    };
-
-    if let Some(n) = find_feature_issue(feature, issue) {
-        err.note(&format!(
-            "for more information, see https://github.com/rust-lang/rust/issues/{}",
-            n,
-        ));
-    }
-
-    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
-    if sess.unstable_features.is_nightly_build() {
-        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
-    }
-
-    // If we're on stable and only emitting a "soft" warning, add a note to
-    // clarify that the feature isn't "on" (rather than being on but
-    // warning-worthy).
-    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
-        err.help("a nightly build of the compiler is required to enable this feature");
-    }
-
-    err
-}
-
 struct PostExpansionVisitor<'a> {
     parse_sess: &'a ParseSess,
     features: &'a Features,
@@ -724,168 +653,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     }
 }
 
-pub fn get_features(
-    span_handler: &Handler,
-    krate_attrs: &[ast::Attribute],
-    crate_edition: Edition,
-    allow_features: &Option<Vec<String>>,
-) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
-        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
-        err.span_label(span, "feature has been removed");
-        if let Some(reason) = reason {
-            err.note(reason);
-        }
-        err.emit();
-    }
-
-    let mut features = Features::default();
-    let mut edition_enabled_features = FxHashMap::default();
-
-    for &edition in ALL_EDITIONS {
-        if edition <= crate_edition {
-            // The `crate_edition` implies its respective umbrella feature-gate
-            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
-            edition_enabled_features.insert(edition.feature_name(), edition);
-        }
-    }
-
-    for feature in active_features_up_to(crate_edition) {
-        feature.set(&mut features, DUMMY_SP);
-        edition_enabled_features.insert(feature.name, crate_edition);
-    }
-
-    // Process the edition umbrella feature-gates first, to ensure
-    // `edition_enabled_features` is completed before it's queried.
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        for mi in list {
-            if !mi.is_word() {
-                continue;
-            }
-
-            let name = mi.name_or_empty();
-
-            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
-            if let Some(edition) = edition {
-                if edition <= crate_edition {
-                    continue;
-                }
-
-                for feature in active_features_up_to(edition) {
-                    // FIXME(Manishearth) there is currently no way to set
-                    // lib features by edition
-                    feature.set(&mut features, DUMMY_SP);
-                    edition_enabled_features.insert(feature.name, edition);
-                }
-            }
-        }
-    }
-
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        let bad_input = |span| {
-            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
-        };
-
-        for mi in list {
-            let name = match mi.ident() {
-                Some(ident) if mi.is_word() => ident.name,
-                Some(ident) => {
-                    bad_input(mi.span())
-                        .span_suggestion(
-                            mi.span(),
-                            "expected just one word",
-                            format!("{}", ident.name),
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
-                    continue;
-                }
-                None => {
-                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
-                    continue;
-                }
-            };
-
-            if let Some(edition) = edition_enabled_features.get(&name) {
-                let msg =
-                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
-                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
-                continue;
-            }
-
-            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
-                // Handled in the separate loop above.
-                continue;
-            }
-
-            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
-            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
-            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
-                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
-                    state
-                {
-                    feature_removed(span_handler, mi.span(), *reason);
-                    continue;
-                }
-            }
-
-            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
-                let since = Some(Symbol::intern(since));
-                features.declared_lang_features.push((name, mi.span(), since));
-                continue;
-            }
-
-            if let Some(allowed) = allow_features.as_ref() {
-                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
-                    struct_span_err!(
-                        span_handler,
-                        mi.span(),
-                        E0725,
-                        "the feature `{}` is not in the list of allowed features",
-                        name
-                    )
-                    .emit();
-                    continue;
-                }
-            }
-
-            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
-                f.set(&mut features, mi.span());
-                features.declared_lang_features.push((name, mi.span(), None));
-                continue;
-            }
-
-            features.declared_lib_features.push((name, mi.span()));
-        }
-    }
-
-    features
-}
-
-fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
-    ACTIVE_FEATURES.iter().filter(move |feature| {
-        if let Some(feature_edition) = feature.edition { feature_edition <= edition } else { false }
-    })
-}
-
 pub fn check_crate(
     krate: &ast::Crate,
     parse_sess: &ParseSess,
@@ -911,6 +678,7 @@ pub fn check_crate(
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
     gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
     gate_all!(const_trait_impl, "const trait impls are experimental");
+    gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs
new file mode 100644
index 00000000000..eadbc485296
--- /dev/null
+++ b/src/librustc_ast_passes/lib.rs
@@ -0,0 +1,9 @@
+//! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
+//! parsed by `rustc_parse` and then lowered, after the passes in this crate,
+//! by `rustc_ast_lowering`.
+
+#![feature(slice_patterns)]
+
+pub mod ast_validation;
+pub mod feature_gate;
+pub mod show_span;
diff --git a/src/libsyntax/show_span.rs b/src/librustc_ast_passes/show_span.rs
index fb641239dfa..4596e8ff53d 100644
--- a/src/libsyntax/show_span.rs
+++ b/src/librustc_ast_passes/show_span.rs
@@ -5,9 +5,9 @@
 
 use std::str::FromStr;
 
-use crate::ast;
-use crate::visit;
-use crate::visit::Visitor;
+use syntax::ast;
+use syntax::visit;
+use syntax::visit::Visitor;
 
 enum Mode {
     Expression,
@@ -29,7 +29,7 @@ impl FromStr for Mode {
 }
 
 struct ShowSpanVisitor<'a> {
-    span_diagnostic: &'a errors::Handler,
+    span_diagnostic: &'a rustc_errors::Handler,
     mode: Mode,
 }
 
@@ -60,7 +60,7 @@ impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
     }
 }
 
-pub fn run(span_diagnostic: &errors::Handler, mode: &str, krate: &ast::Crate) {
+pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) {
     let mode = match mode.parse().ok() {
         Some(mode) => mode,
         None => return,
diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml
index f56cc938f4a..f291eaf9358 100644
--- a/src/librustc_builtin_macros/Cargo.toml
+++ b/src/librustc_builtin_macros/Cargo.toml
@@ -10,13 +10,14 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 fmt_macros = { path = "../libfmt_macros" }
 log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_target = { path = "../librustc_target" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 rustc_expand = { path = "../librustc_expand" }
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index 78d2d37ef56..a6b45e0567c 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -2,7 +2,7 @@
 //
 use State::*;
 
-use errors::{struct_span_err, DiagnosticBuilder, PResult};
+use rustc_errors::{struct_span_err, DiagnosticBuilder, PResult};
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
 use rustc_span::symbol::{kw, sym, Symbol};
diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs
index 9043db4742b..c96ba516f0c 100644
--- a/src/librustc_builtin_macros/assert.rs
+++ b/src/librustc_builtin_macros/assert.rs
@@ -1,4 +1,4 @@
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
diff --git a/src/librustc_builtin_macros/cfg.rs b/src/librustc_builtin_macros/cfg.rs
index 62a4dc06b1f..cee62a54f00 100644
--- a/src/librustc_builtin_macros/cfg.rs
+++ b/src/librustc_builtin_macros/cfg.rs
@@ -1,8 +1,8 @@
-/// The compiler code necessary to support the cfg! extension, which expands to
-/// a literal `true` or `false` based on whether the given cfg matches the
-/// current compilation environment.
-use errors::DiagnosticBuilder;
+//! The compiler code necessary to support the cfg! extension, which expands to
+//! a literal `true` or `false` based on whether the given cfg matches the
+//! current compilation environment.
 
+use rustc_errors::DiagnosticBuilder;
 use rustc_expand::base::{self, *};
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs
index 8d3f1951373..72c41ad9745 100644
--- a/src/librustc_builtin_macros/deriving/default.rs
+++ b/src/librustc_builtin_macros/deriving/default.rs
@@ -2,7 +2,7 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use errors::struct_span_err;
+use rustc_errors::struct_span_err;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs
index e2662faab6c..6fca74e2239 100644
--- a/src/librustc_builtin_macros/format.rs
+++ b/src/librustc_builtin_macros/format.rs
@@ -3,10 +3,8 @@ use Position::*;
 
 use fmt_macros as parse;
 
-use errors::pluralize;
-use errors::Applicability;
-use errors::DiagnosticBuilder;
-
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
@@ -15,7 +13,6 @@ use syntax::ptr::P;
 use syntax::token;
 use syntax::tokenstream::TokenStream;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 
diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs
index 2bcd76e6699..052e62ee9ff 100644
--- a/src/librustc_builtin_macros/global_asm.rs
+++ b/src/librustc_builtin_macros/global_asm.rs
@@ -1,14 +1,14 @@
-/// Module-level assembly support.
-///
-/// The macro defined here allows you to specify "top-level",
-/// "file-scoped", or "module-level" assembly. These synonyms
-/// all correspond to LLVM's module-level inline assembly instruction.
-///
-/// For example, `global_asm!("some assembly here")` codegens to
-/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
-/// therefore apply.
-use errors::DiagnosticBuilder;
+//! Module-level assembly support.
+//!
+//! The macro defined here allows you to specify "top-level",
+//! "file-scoped", or "module-level" assembly. These synonyms
+//! all correspond to LLVM's module-level inline assembly instruction.
+//!
+//! For example, `global_asm!("some assembly here")` codegens to
+//! LLVM's `module asm "some assembly here"`. All of LLVM's caveats
+//! therefore apply.
 
+use rustc_errors::DiagnosticBuilder;
 use rustc_expand::base::{self, *};
 use rustc_span::source_map::respan;
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs
index 44968d6df96..ae706085051 100644
--- a/src/librustc_builtin_macros/proc_macro_harness.rs
+++ b/src/librustc_builtin_macros/proc_macro_harness.rs
@@ -40,7 +40,7 @@ enum ProcMacro {
 struct CollectProcMacros<'a> {
     macros: Vec<ProcMacro>,
     in_root: bool,
-    handler: &'a errors::Handler,
+    handler: &'a rustc_errors::Handler,
     is_proc_macro_crate: bool,
     is_test_crate: bool,
 }
@@ -53,7 +53,7 @@ pub fn inject(
     has_proc_macro_decls: bool,
     is_test_crate: bool,
     num_crate_types: usize,
-    handler: &errors::Handler,
+    handler: &rustc_errors::Handler,
 ) -> ast::Crate {
     let ecfg = ExpansionConfig::default("proc_macro".to_string());
     let mut cx = ExtCtxt::new(sess, ecfg, resolver);
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index 19a766de1f4..dc85a92d272 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -1,15 +1,15 @@
 use rustc_expand::base::{self, *};
 use rustc_expand::panictry;
 use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
+use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
+use rustc_span::{self, Pos, Span};
 use syntax::ast;
-use syntax::early_buffered_lints::INCOMPLETE_INCLUDE;
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::token;
 use syntax::tokenstream::TokenStream;
 
-use rustc_span::{self, Pos, Span};
 use smallvec::SmallVec;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index eddf4927203..17d180da6bf 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -40,7 +40,7 @@ pub fn inject(
     resolver: &mut dyn Resolver,
     should_test: bool,
     krate: &mut ast::Crate,
-    span_diagnostic: &errors::Handler,
+    span_diagnostic: &rustc_errors::Handler,
     features: &Features,
     panic_strategy: PanicStrategy,
     platform_panic_strategy: PanicStrategy,
@@ -351,7 +351,7 @@ fn is_test_case(i: &ast::Item) -> bool {
     attr::contains_name(&i.attrs, sym::rustc_test_marker)
 }
 
-fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
+fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
     let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
     test_attr.meta_item_list().map(|meta_list| {
         if meta_list.len() != 1 {
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index b3c58b24020..52613fef7e6 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -46,7 +46,7 @@ fn require_inited() {
 }
 
 unsafe fn configure_llvm(sess: &Session) {
-    let n_args = sess.opts.cg.llvm_args.len();
+    let n_args = sess.opts.cg.llvm_args.len() + sess.target.target.options.llvm_args.len();
     let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
     let mut llvm_args = Vec::with_capacity(n_args + 1);
 
@@ -56,14 +56,11 @@ unsafe fn configure_llvm(sess: &Session) {
         full_arg.trim().split(|c: char| c == '=' || c.is_whitespace()).next().unwrap_or("")
     }
 
-    let user_specified_args: FxHashSet<_> = sess
-        .opts
-        .cg
-        .llvm_args
-        .iter()
-        .map(|s| llvm_arg_to_arg_name(s))
-        .filter(|s| s.len() > 0)
-        .collect();
+    let cg_opts = sess.opts.cg.llvm_args.iter();
+    let tg_opts = sess.target.target.options.llvm_args.iter();
+
+    let user_specified_args: FxHashSet<_> =
+        cg_opts.chain(tg_opts).map(|s| llvm_arg_to_arg_name(s)).filter(|s| s.len() > 0).collect();
 
     {
         // This adds the given argument to LLVM. Unless `force` is true
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 253225f308e..53ee5996432 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -53,6 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
     crate_name: &str,
     target_cpu: &str,
 ) {
+    let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
@@ -71,9 +72,11 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
             );
         }
 
-        for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
-            check_file_is_writeable(obj, sess);
-        }
+        sess.time("link_binary_check_files_are_writeable", || {
+            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+                check_file_is_writeable(obj, sess);
+            }
+        });
 
         let tmpdir = TempFileBuilder::new()
             .prefix("rustc")
@@ -84,6 +87,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
             let out_filename = out_filename(sess, crate_type, outputs, crate_name);
             match crate_type {
                 config::CrateType::Rlib => {
+                    let _timer = sess.timer("link_rlib");
                     link_rlib::<B>(
                         sess,
                         codegen_results,
@@ -118,29 +122,34 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
     }
 
     // Remove the temporary object file and metadata if we aren't saving temps
-    if !sess.opts.cg.save_temps {
-        if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) {
-            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
-                remove(sess, obj);
+    sess.time("link_binary_remove_temps", || {
+        if !sess.opts.cg.save_temps {
+            if sess.opts.output_types.should_codegen()
+                && !preserve_objects_for_their_debuginfo(sess)
+            {
+                for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+                    remove(sess, obj);
+                }
             }
-        }
-        for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
-            remove(sess, obj);
-        }
-        if let Some(ref metadata_module) = codegen_results.metadata_module {
-            if let Some(ref obj) = metadata_module.object {
+            for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref())
+            {
                 remove(sess, obj);
             }
-        }
-        if let Some(ref allocator_module) = codegen_results.allocator_module {
-            if let Some(ref obj) = allocator_module.object {
-                remove(sess, obj);
+            if let Some(ref metadata_module) = codegen_results.metadata_module {
+                if let Some(ref obj) = metadata_module.object {
+                    remove(sess, obj);
+                }
             }
-            if let Some(ref bc) = allocator_module.bytecode_compressed {
-                remove(sess, bc);
+            if let Some(ref allocator_module) = codegen_results.allocator_module {
+                if let Some(ref obj) = allocator_module.object {
+                    remove(sess, obj);
+                }
+                if let Some(ref bc) = allocator_module.bytecode_compressed {
+                    remove(sess, bc);
+                }
             }
         }
-    }
+    });
 }
 
 // The third parameter is for env vars, used on windows to set up the
@@ -531,6 +540,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
 
     {
         let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu);
+        link_sanitizer_runtime(sess, crate_type, &mut *linker);
         link_args::<B>(
             &mut *linker,
             flavor,
@@ -735,6 +745,47 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     }
 }
 
+fn link_sanitizer_runtime(sess: &Session, crate_type: config::CrateType, linker: &mut dyn Linker) {
+    let sanitizer = match &sess.opts.debugging_opts.sanitizer {
+        Some(s) => s,
+        None => return,
+    };
+
+    if crate_type != config::CrateType::Executable {
+        return;
+    }
+
+    let name = match sanitizer {
+        Sanitizer::Address => "asan",
+        Sanitizer::Leak => "lsan",
+        Sanitizer::Memory => "msan",
+        Sanitizer::Thread => "tsan",
+    };
+
+    let default_sysroot = filesearch::get_or_default_sysroot();
+    let default_tlib =
+        filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple());
+
+    match sess.opts.target_triple.triple() {
+        "x86_64-apple-darwin" => {
+            // On Apple platforms, the sanitizer is always built as a dylib, and
+            // LLVM will link to `@rpath/*.dylib`, so we need to specify an
+            // rpath to the library as well (the rpath should be absolute, see
+            // PR #41352 for details).
+            let libname = format!("rustc_rt.{}", name);
+            let rpath = default_tlib.to_str().expect("non-utf8 component in path");
+            linker.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]);
+            linker.link_dylib(Symbol::intern(&libname));
+        }
+        "x86_64-unknown-linux-gnu" => {
+            let filename = format!("librustc_rt.{}.a", name);
+            let path = default_tlib.join(&filename);
+            linker.link_whole_rlib(&path);
+        }
+        _ => {}
+    }
+}
+
 /// Returns a boolean indicating whether the specified crate should be ignored
 /// during LTO.
 ///
@@ -1415,12 +1466,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
             _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
                 add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
             }
-            _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum)
-                && crate_type == config::CrateType::Executable =>
-            {
-                // Link the sanitizer runtimes only if we are actually producing an executable
-                link_sanitizer_runtime::<B>(cmd, sess, codegen_results, tmpdir, cnum);
-            }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
             _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
@@ -1457,47 +1502,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
         }
     }
 
-    // We must link the sanitizer runtime using -Wl,--whole-archive but since
-    // it's packed in a .rlib, it contains stuff that are not objects that will
-    // make the linker error. So we must remove those bits from the .rlib before
-    // linking it.
-    fn link_sanitizer_runtime<'a, B: ArchiveBuilder<'a>>(
-        cmd: &mut dyn Linker,
-        sess: &'a Session,
-        codegen_results: &CodegenResults,
-        tmpdir: &Path,
-        cnum: CrateNum,
-    ) {
-        let src = &codegen_results.crate_info.used_crate_source[&cnum];
-        let cratepath = &src.rlib.as_ref().unwrap().0;
-
-        if sess.target.target.options.is_like_osx {
-            // On Apple platforms, the sanitizer is always built as a dylib, and
-            // LLVM will link to `@rpath/*.dylib`, so we need to specify an
-            // rpath to the library as well (the rpath should be absolute, see
-            // PR #41352 for details).
-            //
-            // FIXME: Remove this logic into librustc_*san once Cargo supports it
-            let rpath = cratepath.parent().unwrap();
-            let rpath = rpath.to_str().expect("non-utf8 component in path");
-            cmd.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]);
-        }
-
-        let dst = tmpdir.join(cratepath.file_name().unwrap());
-        let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
-        archive.update_symbols();
-
-        for f in archive.src_files() {
-            if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME {
-                archive.remove_file(&f);
-            }
-        }
-
-        archive.build();
-
-        cmd.link_whole_rlib(&dst);
-    }
-
     // Adds the static "rlib" versions of all crates to the command line.
     // There's a bit of magic which happens here specifically related to LTO and
     // dynamic libraries. Specifically:
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 1ce0a29d55d..4d09e23ee7f 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -479,6 +479,8 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
         return work_products;
     }
 
+    let _timer = sess.timer("incr_comp_copy_cgu_workproducts");
+
     for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
         let mut files = vec![];
 
@@ -1714,8 +1716,11 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> {
 
 impl<B: ExtraBackendMethods> OngoingCodegen<B> {
     pub fn join(self, sess: &Session) -> (CodegenResults, FxHashMap<WorkProductId, WorkProduct>) {
+        let _timer = sess.timer("finish_ongoing_codegen");
+
         self.shared_emitter_main.check(sess, true);
-        let compiled_modules = match self.future.join() {
+        let future = self.future;
+        let compiled_modules = sess.time("join_worker_thread", || match future.join() {
             Ok(Ok(compiled_modules)) => compiled_modules,
             Ok(Err(())) => {
                 sess.abort_if_errors();
@@ -1724,7 +1729,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
             Err(_) => {
                 bug!("panic during codegen/LLVM phase");
             }
-        };
+        });
 
         sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic());
 
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index c8381090727..ab5d67e5783 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -85,7 +85,7 @@ pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind, signed: bool) -> IntPredicat
         }
         op => bug!(
             "comparison_op_to_icmp_predicate: expected comparison operator, \
-                  found {:?}",
+             found {:?}",
             op
         ),
     }
@@ -102,7 +102,7 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> RealPredicate {
         op => {
             bug!(
                 "comparison_op_to_fcmp_predicate: expected comparison operator, \
-                  found {:?}",
+                 found {:?}",
                 op
             );
         }
@@ -519,7 +519,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
         ongoing_codegen.codegen_finished(tcx);
 
-        assert_and_save_dep_graph(tcx);
+        finalize_tcx(tcx);
 
         ongoing_codegen.check_for_errors(tcx.sess);
 
@@ -660,7 +660,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
     ongoing_codegen.check_for_errors(tcx.sess);
 
-    assert_and_save_dep_graph(tcx);
+    finalize_tcx(tcx);
+
     ongoing_codegen.into_inner()
 }
 
@@ -711,10 +712,16 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
     }
 }
 
-fn assert_and_save_dep_graph(tcx: TyCtxt<'_>) {
+fn finalize_tcx(tcx: TyCtxt<'_>) {
     tcx.sess.time("assert_dep_graph", || ::rustc_incremental::assert_dep_graph(tcx));
-
     tcx.sess.time("serialize_dep_graph", || ::rustc_incremental::save_dep_graph(tcx));
+
+    // We assume that no queries are run past here. If there are new queries
+    // after this point, they'll show up as "<unknown>" in self-profiling data.
+    {
+        let _prof_timer = tcx.prof.generic_activity("self_profile_alloc_query_strings");
+        tcx.alloc_self_profile_query_strings();
+    }
 }
 
 impl CrateInfo {
@@ -723,7 +730,6 @@ impl CrateInfo {
             panic_runtime: None,
             compiler_builtins: None,
             profiler_runtime: None,
-            sanitizer_runtime: None,
             is_no_builtins: Default::default(),
             native_libraries: Default::default(),
             used_libraries: tcx.native_libraries(LOCAL_CRATE),
@@ -759,9 +765,6 @@ impl CrateInfo {
             if tcx.is_profiler_runtime(cnum) {
                 info.profiler_runtime = Some(cnum);
             }
-            if tcx.is_sanitizer_runtime(cnum) {
-                info.sanitizer_runtime = Some(cnum);
-            }
             if tcx.is_no_builtins(cnum) {
                 info.is_no_builtins.insert(cnum);
             }
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index a8d051db8b4..ee527ecb509 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -122,7 +122,6 @@ pub struct CrateInfo {
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
-    pub sanitizer_runtime: Option<CrateNum>,
     pub is_no_builtins: FxHashSet<CrateNum>,
     pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
     pub crate_name: FxHashMap<CrateNum, String>,
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 7fa40b8a869..19db9834fd4 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,7 +26,7 @@ rustc-hash = "1.0.1"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
-measureme = "0.5"
+measureme = "0.7.1"
 
 [dependencies.parking_lot]
 version = "0.9"
diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs
index a9d3a2668aa..8deb43d50f9 100644
--- a/src/librustc_data_structures/profiling.rs
+++ b/src/librustc_data_structures/profiling.rs
@@ -1,6 +1,90 @@
+//! # Rust Compiler Self-Profiling
+//!
+//! This module implements the basic framework for the compiler's self-
+//! profiling support. It provides the `SelfProfiler` type which enables
+//! recording "events". An event is something that starts and ends at a given
+//! point in time and has an ID and a kind attached to it. This allows for
+//! tracing the compiler's activity.
+//!
+//! Internally this module uses the custom tailored [measureme][mm] crate for
+//! efficiently recording events to disk in a compact format that can be
+//! post-processed and analyzed by the suite of tools in the `measureme`
+//! project. The highest priority for the tracing framework is on incurring as
+//! little overhead as possible.
+//!
+//!
+//! ## Event Overview
+//!
+//! Events have a few properties:
+//!
+//! - The `event_kind` designates the broad category of an event (e.g. does it
+//!   correspond to the execution of a query provider or to loading something
+//!   from the incr. comp. on-disk cache, etc).
+//! - The `event_id` designates the query invocation or function call it
+//!   corresponds to, possibly including the query key or function arguments.
+//! - Each event stores the ID of the thread it was recorded on.
+//! - The timestamp stores beginning and end of the event, or the single point
+//!   in time it occurred at for "instant" events.
+//!
+//!
+//! ## Event Filtering
+//!
+//! Event generation can be filtered by event kind. Recording all possible
+//! events generates a lot of data, much of which is not needed for most kinds
+//! of analysis. So, in order to keep overhead as low as possible for a given
+//! use case, the `SelfProfiler` will only record the kinds of events that
+//! pass the filter specified as a command line argument to the compiler.
+//!
+//!
+//! ## `event_id` Assignment
+//!
+//! As far as `measureme` is concerned, `event_id`s are just strings. However,
+//! it would incur too much overhead to generate and persist each `event_id`
+//! string at the point where the event is recorded. In order to make this more
+//! efficient `measureme` has two features:
+//!
+//! - Strings can share their content, so that re-occurring parts don't have to
+//!   be copied over and over again. One allocates a string in `measureme` and
+//!   gets back a `StringId`. This `StringId` is then used to refer to that
+//!   string. `measureme` strings are actually DAGs of string components so that
+//!   arbitrary sharing of substrings can be done efficiently. This is useful
+//!   because `event_id`s contain lots of redundant text like query names or
+//!   def-path components.
+//!
+//! - `StringId`s can be "virtual" which means that the client picks a numeric
+//!   ID according to some application-specific scheme and can later make that
+//!   ID be mapped to an actual string. This is used to cheaply generate
+//!   `event_id`s while the events actually occur, causing little timing
+//!   distortion, and then later map those `StringId`s, in bulk, to actual
+//!   `event_id` strings. This way the largest part of the tracing overhead is
+//!   localized to one contiguous chunk of time.
+//!
+//! How are these `event_id`s generated in the compiler? For things that occur
+//! infrequently (e.g. "generic activities"), we just allocate the string the
+//! first time it is used and then keep the `StringId` in a hash table. This
+//! is implemented in `SelfProfiler::get_or_alloc_cached_string()`.
+//!
+//! For queries it gets more interesting: First we need a unique numeric ID for
+//! each query invocation (the `QueryInvocationId`). This ID is used as the
+//! virtual `StringId` we use as `event_id` for a given event. This ID has to
+//! be available both when the query is executed and later, together with the
+//! query key, when we allocate the actual `event_id` strings in bulk.
+//!
+//! We could make the compiler generate and keep track of such an ID for each
+//! query invocation but luckily we already have something that fits all the
+//! the requirements: the query's `DepNodeIndex`. So we use the numeric value
+//! of the `DepNodeIndex` as `event_id` when recording the event and then,
+//! just before the query context is dropped, we walk the entire query cache
+//! (which stores the `DepNodeIndex` along with the query key for each
+//! invocation) and allocate the corresponding strings together with a mapping
+//! for `DepNodeIndex as StringId`.
+//!
+//! [mm]: https://github.com/rust-lang/measureme/
+
+use crate::fx::FxHashMap;
+
 use std::error::Error;
 use std::fs;
-use std::mem::{self, Discriminant};
 use std::path::Path;
 use std::process;
 use std::sync::Arc;
@@ -8,7 +92,8 @@ use std::thread::ThreadId;
 use std::time::{Duration, Instant};
 use std::u32;
 
-use measureme::StringId;
+use measureme::{EventId, EventIdBuilder, SerializableString, StringId};
+use parking_lot::RwLock;
 
 /// MmapSerializatioSink is faster on macOS and Linux
 /// but FileSerializationSink is faster on Windows
@@ -19,11 +104,6 @@ type SerializationSink = measureme::FileSerializationSink;
 
 type Profiler = measureme::Profiler<SerializationSink>;
 
-pub trait QueryName: Sized + Copy {
-    fn discriminant(self) -> Discriminant<Self>;
-    fn as_str(self) -> &'static str;
-}
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
 pub enum ProfileCategory {
     Parsing,
@@ -43,6 +123,8 @@ bitflags::bitflags! {
         const QUERY_BLOCKED      = 1 << 3;
         const INCR_CACHE_LOADS   = 1 << 4;
 
+        const QUERY_KEYS         = 1 << 5;
+
         const DEFAULT = Self::GENERIC_ACTIVITIES.bits |
                         Self::QUERY_PROVIDERS.bits |
                         Self::QUERY_BLOCKED.bits |
@@ -62,12 +144,16 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("query-cache-hit", EventFilter::QUERY_CACHE_HITS),
     ("query-blocked", EventFilter::QUERY_BLOCKED),
     ("incr-cache-load", EventFilter::INCR_CACHE_LOADS),
+    ("query-keys", EventFilter::QUERY_KEYS),
 ];
 
 fn thread_id_to_u32(tid: ThreadId) -> u32 {
-    unsafe { mem::transmute::<ThreadId, u64>(tid) as u32 }
+    unsafe { std::mem::transmute::<ThreadId, u64>(tid) as u32 }
 }
 
+/// Something that uniquely identifies a query invocation.
+pub struct QueryInvocationId(pub u32);
+
 /// A reference to the SelfProfiler. It can be cloned and sent across thread
 /// boundaries at will.
 #[derive(Clone)]
@@ -138,7 +224,10 @@ impl SelfProfilerRef {
     /// a measureme event, "verbose" generic activities also print a timing entry to
     /// stdout if the compiler is invoked with -Ztime or -Ztime-passes.
     #[inline(always)]
-    pub fn verbose_generic_activity<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> {
+    pub fn verbose_generic_activity<'a>(
+        &'a self,
+        event_id: &'static str,
+    ) -> VerboseTimingGuard<'a> {
         VerboseTimingGuard::start(
             event_id,
             self.print_verbose_generic_activities,
@@ -167,9 +256,10 @@ impl SelfProfilerRef {
     /// Start profiling a generic activity. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn generic_activity(&self, event_id: &str) -> TimingGuard<'_> {
+    pub fn generic_activity(&self, event_id: &'static str) -> TimingGuard<'_> {
         self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
-            let event_id = profiler.profiler.alloc_string(event_id);
+            let event_id = profiler.get_or_alloc_cached_string(event_id);
+            let event_id = EventId::from_label(event_id);
             TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
         })
     }
@@ -177,19 +267,18 @@ impl SelfProfilerRef {
     /// Start profiling a query provider. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn query_provider(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn query_provider(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::QUERY_PROVIDERS, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.query_event_kind, event_id)
+            TimingGuard::start(profiler, profiler.query_event_kind, EventId::INVALID)
         })
     }
 
     /// Record a query in-memory cache hit.
     #[inline(always)]
-    pub fn query_cache_hit(&self, query_name: impl QueryName) {
+    pub fn query_cache_hit(&self, query_invocation_id: QueryInvocationId) {
         self.instant_query_event(
             |profiler| profiler.query_cache_hit_event_kind,
-            query_name,
+            query_invocation_id,
             EventFilter::QUERY_CACHE_HITS,
         );
     }
@@ -198,10 +287,9 @@ impl SelfProfilerRef {
     /// Profiling continues until the TimingGuard returned from this call is
     /// dropped.
     #[inline(always)]
-    pub fn query_blocked(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn query_blocked(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::QUERY_BLOCKED, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id)
+            TimingGuard::start(profiler, profiler.query_blocked_event_kind, EventId::INVALID)
         })
     }
 
@@ -209,10 +297,13 @@ impl SelfProfilerRef {
     /// incremental compilation on-disk cache. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn incr_cache_loading(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn incr_cache_loading(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.incremental_load_result_event_kind, event_id)
+            TimingGuard::start(
+                profiler,
+                profiler.incremental_load_result_event_kind,
+                EventId::INVALID,
+            )
         })
     }
 
@@ -220,29 +311,41 @@ impl SelfProfilerRef {
     fn instant_query_event(
         &self,
         event_kind: fn(&SelfProfiler) -> StringId,
-        query_name: impl QueryName,
+        query_invocation_id: QueryInvocationId,
         event_filter: EventFilter,
     ) {
         drop(self.exec(event_filter, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
+            let event_id = StringId::new_virtual(query_invocation_id.0);
             let thread_id = thread_id_to_u32(std::thread::current().id());
 
-            profiler.profiler.record_instant_event(event_kind(profiler), event_id, thread_id);
+            profiler.profiler.record_instant_event(
+                event_kind(profiler),
+                EventId::from_virtual(event_id),
+                thread_id,
+            );
 
             TimingGuard::none()
         }));
     }
 
-    pub fn register_queries(&self, f: impl FnOnce(&SelfProfiler)) {
+    pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) {
         if let Some(profiler) = &self.profiler {
             f(&profiler)
         }
     }
+
+    #[inline]
+    pub fn enabled(&self) -> bool {
+        self.profiler.is_some()
+    }
 }
 
 pub struct SelfProfiler {
     profiler: Profiler,
     event_filter_mask: EventFilter,
+
+    string_cache: RwLock<FxHashMap<&'static str, StringId>>,
+
     query_event_kind: StringId,
     generic_activity_event_kind: StringId,
     incremental_load_result_event_kind: StringId,
@@ -305,6 +408,7 @@ impl SelfProfiler {
         Ok(SelfProfiler {
             profiler,
             event_filter_mask,
+            string_cache: RwLock::new(FxHashMap::default()),
             query_event_kind,
             generic_activity_event_kind,
             incremental_load_result_event_kind,
@@ -313,16 +417,51 @@ impl SelfProfiler {
         })
     }
 
-    fn get_query_name_string_id(query_name: impl QueryName) -> StringId {
-        let discriminant =
-            unsafe { mem::transmute::<Discriminant<_>, u64>(query_name.discriminant()) };
+    /// Allocates a new string in the profiling data. Does not do any caching
+    /// or deduplication.
+    pub fn alloc_string<STR: SerializableString + ?Sized>(&self, s: &STR) -> StringId {
+        self.profiler.alloc_string(s)
+    }
+
+    /// Gets a `StringId` for the given string. This method makes sure that
+    /// any strings going through it will only be allocated once in the
+    /// profiling data.
+    pub fn get_or_alloc_cached_string(&self, s: &'static str) -> StringId {
+        // Only acquire a read-lock first since we assume that the string is
+        // already present in the common case.
+        {
+            let string_cache = self.string_cache.read();
+
+            if let Some(&id) = string_cache.get(s) {
+                return id;
+            }
+        }
+
+        let mut string_cache = self.string_cache.write();
+        // Check if the string has already been added in the small time window
+        // between dropping the read lock and acquiring the write lock.
+        *string_cache.entry(s).or_insert_with(|| self.profiler.alloc_string(s))
+    }
+
+    pub fn map_query_invocation_id_to_string(&self, from: QueryInvocationId, to: StringId) {
+        let from = StringId::new_virtual(from.0);
+        self.profiler.map_virtual_to_concrete_string(from, to);
+    }
 
-        StringId::reserved(discriminant as u32)
+    pub fn bulk_map_query_invocation_id_to_single_string<I>(&self, from: I, to: StringId)
+    where
+        I: Iterator<Item = QueryInvocationId> + ExactSizeIterator,
+    {
+        let from = from.map(|qid| StringId::new_virtual(qid.0));
+        self.profiler.bulk_map_virtual_to_single_concrete_string(from, to);
+    }
+
+    pub fn query_key_recording_enabled(&self) -> bool {
+        self.event_filter_mask.contains(EventFilter::QUERY_KEYS)
     }
 
-    pub fn register_query_name(&self, query_name: impl QueryName) {
-        let id = SelfProfiler::get_query_name_string_id(query_name);
-        self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
+    pub fn event_id_builder(&self) -> EventIdBuilder<'_, SerializationSink> {
+        EventIdBuilder::new(&self.profiler)
     }
 }
 
@@ -334,7 +473,7 @@ impl<'a> TimingGuard<'a> {
     pub fn start(
         profiler: &'a SelfProfiler,
         event_kind: StringId,
-        event_id: StringId,
+        event_id: EventId,
     ) -> TimingGuard<'a> {
         let thread_id = thread_id_to_u32(std::thread::current().id());
         let raw_profiler = &profiler.profiler;
@@ -344,9 +483,24 @@ impl<'a> TimingGuard<'a> {
     }
 
     #[inline]
+    pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) {
+        if let Some(guard) = self.0 {
+            let event_id = StringId::new_virtual(query_invocation_id.0);
+            let event_id = EventId::from_virtual(event_id);
+            guard.finish_with_override_event_id(event_id);
+        }
+    }
+
+    #[inline]
     pub fn none() -> TimingGuard<'a> {
         TimingGuard(None)
     }
+
+    #[inline(always)]
+    pub fn run<R>(self, f: impl FnOnce() -> R) -> R {
+        let _timer = self;
+        f()
+    }
 }
 
 #[must_use]
@@ -444,8 +598,8 @@ fn get_resident() -> Option<usize> {
             cb: DWORD,
         ) -> BOOL;
     }
-    let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { mem::zeroed() };
-    pmc.cb = mem::size_of_val(&pmc) as DWORD;
+    let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { std::mem::zeroed() };
+    pmc.cb = std::mem::size_of_val(&pmc) as DWORD;
     match unsafe { GetProcessMemoryInfo(GetCurrentProcess(), &mut pmc, pmc.cb) } {
         0 => None,
         _ => Some(pmc.WorkingSetSize as usize),
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 5e0c853ed24..37449f9402e 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -17,7 +17,7 @@ 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_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index a5277bcd120..3d31f240a34 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -24,7 +24,6 @@ extern crate lazy_static;
 pub extern crate rustc_plugin_impl as plugin;
 
 //use rustc_resolve as resolve;
-use errors::{registry::Registry, PResult};
 use rustc::lint;
 use rustc::lint::Lint;
 use rustc::middle::cstore::MetadataLoader;
@@ -37,6 +36,7 @@ use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::profiling::print_time_passes_entry;
 use rustc_data_structures::sync::SeqCst;
+use rustc_errors::{registry::Registry, PResult};
 use rustc_feature::{find_gated_cfg, UnstableFeatures};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::get_builtin_codegen_backend;
@@ -389,6 +389,7 @@ pub fn run_compiler(
                 })?;
             } else {
                 // Drop AST after creating GlobalCtxt to free memory
+                let _timer = sess.prof.generic_activity("drop_ast");
                 mem::drop(queries.expansion()?.take());
             }
 
@@ -413,6 +414,7 @@ pub fn run_compiler(
         })?;
 
         if let Some(linker) = linker {
+            let _timer = sess.timer("link");
             linker.link()?
         }
 
@@ -1134,7 +1136,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
 /// the panic into a `Result` instead.
 pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> {
     catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
-        if value.is::<errors::FatalErrorMarker>() {
+        if value.is::<rustc_errors::FatalErrorMarker>() {
             ErrorReported
         } else {
             panic::resume_unwind(value);
@@ -1163,20 +1165,20 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // Separate the output with an empty line
     eprintln!();
 
-    let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
-        errors::ColorConfig::Auto,
+    let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
+        rustc_errors::ColorConfig::Auto,
         None,
         false,
         false,
         None,
         false,
     ));
-    let handler = errors::Handler::with_emitter(true, None, emitter);
+    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
 
     // a .span_bug or .bug call has already printed what
     // it wants to print.
-    if !info.payload().is::<errors::ExplicitBug>() {
-        let d = errors::Diagnostic::new(errors::Level::Bug, "unexpected panic");
+    if !info.payload().is::<rustc_errors::ExplicitBug>() {
+        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
         handler.emit_diagnostic(&d);
     }
 
diff --git a/src/librustc_expand/Cargo.toml b/src/librustc_expand/Cargo.toml
index f9c15fbed36..d04dd079be7 100644
--- a/src/librustc_expand/Cargo.toml
+++ b/src/librustc_expand/Cargo.toml
@@ -14,10 +14,12 @@ doctest = false
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 log = "0.4"
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_ast_passes = { path = "../librustc_ast_passes" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index fe08c85249a..52ba14dbc3d 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -1,9 +1,15 @@
 use crate::expand::{self, AstFragment, Invocation};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{self, Lrc};
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
 use rustc_span::edition::Edition;
+use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
+use smallvec::{smallvec, SmallVec};
 use syntax::ast::{self, Attribute, Name, NodeId, PatKind};
 use syntax::attr::{self, Deprecation, HasAttrs, Stability};
 use syntax::mut_visit::{self, MutVisitor};
@@ -13,13 +19,6 @@ use syntax::token;
 use syntax::tokenstream::{self, TokenStream};
 use syntax::visit::Visitor;
 
-use errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{self, Lrc};
-use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
-use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
-
 use std::default::Default;
 use std::iter;
 use std::path::PathBuf;
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index 6eead11ccb7..3254d0c913d 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -5,6 +5,8 @@ use crate::mbe::macro_rules::annotate_err_with_kind;
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
 use rustc_parse::configure;
 use rustc_parse::parser::Parser;
@@ -16,20 +18,16 @@ use rustc_span::{FileName, Span, DUMMY_SP};
 use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
 use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
 use syntax::attr::{self, is_builtin_attr, HasAttrs};
-use syntax::feature_gate::{self, feature_err};
 use syntax::mut_visit::*;
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::sess::ParseSess;
+use syntax::sess::{feature_err, ParseSess};
 use syntax::token;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::util::map_in_place::MapInPlace;
 use syntax::visit::{self, Visitor};
 
-use errors::{Applicability, FatalError, PResult};
 use smallvec::{smallvec, SmallVec};
-
-use rustc_data_structures::sync::Lrc;
 use std::io::ErrorKind;
 use std::ops::DerefMut;
 use std::path::PathBuf;
@@ -1063,7 +1061,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
-            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
+            rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.parse_sess, features);
             validate_attr::check_meta(self.cx.parse_sess, attr);
 
             // macros are expanded before any lint passes so this warning has to be hardcoded
diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs
index feba7f633ed..4fe7c268c4f 100644
--- a/src/librustc_expand/lib.rs
+++ b/src/librustc_expand/lib.rs
@@ -13,7 +13,7 @@ extern crate proc_macro as pm;
 #[macro_export]
 macro_rules! panictry {
     ($e:expr) => {{
-        use errors::FatalError;
+        use rustc_errors::FatalError;
         use std::result::Result::{Err, Ok};
         match $e {
             Ok(e) => e,
diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs
index 992764ab6a4..47865b2fb9f 100644
--- a/src/librustc_expand/mbe/macro_check.rs
+++ b/src/librustc_expand/mbe/macro_check.rs
@@ -106,14 +106,14 @@
 //! bound.
 use crate::mbe::{KleeneToken, TokenTree};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
+use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym};
+use rustc_span::{symbol::Ident, MultiSpan, Span};
 use syntax::ast::NodeId;
-use syntax::early_buffered_lints::META_VARIABLE_MISUSE;
-use syntax::sess::ParseSess;
 use syntax::token::{DelimToken, Token, TokenKind};
 
-use rustc_data_structures::fx::FxHashMap;
-use rustc_span::{symbol::Ident, MultiSpan, Span};
 use smallvec::SmallVec;
 
 /// Stack represented as linked list.
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index c0e34a30c54..441c1b75a7c 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -85,7 +85,7 @@ use syntax::sess::ParseSess;
 use syntax::token::{self, DocComment, Nonterminal, Token};
 use syntax::tokenstream::TokenStream;
 
-use errors::{FatalError, PResult};
+use rustc_errors::{FatalError, PResult};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 6e965346d30..d72317af9eb 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -8,6 +8,9 @@ use crate::mbe::macro_parser::{Error, Failure, Success};
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult};
 use crate::mbe::transcribe::transcribe;
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
 use rustc_parse::Directory;
@@ -22,17 +25,11 @@ use syntax::sess::ParseSess;
 use syntax::token::{self, NtTT, Token, TokenKind::*};
 use syntax::tokenstream::{DelimSpan, TokenStream};
 
-use errors::{DiagnosticBuilder, FatalError};
 use log::debug;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::{mem, slice};
 
-use errors::Applicability;
-
 const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
                                         `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
                                         `literal`, `path`, `meta`, `tt`, `item` and `vis`";
diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs
index 4fd68a80de8..104a5233c9d 100644
--- a/src/librustc_expand/mbe/transcribe.rs
+++ b/src/librustc_expand/mbe/transcribe.rs
@@ -2,19 +2,17 @@ use crate::base::ExtCtxt;
 use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::pluralize;
+use rustc_span::hygiene::{ExpnId, Transparency};
+use rustc_span::Span;
 use syntax::ast::{Ident, Mac};
 use syntax::mut_visit::{self, MutVisitor};
 use syntax::token::{self, NtTT, Token};
 use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 
 use smallvec::{smallvec, SmallVec};
-
-use errors::pluralize;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
-use rustc_span::hygiene::{ExpnId, Transparency};
-use rustc_span::Span;
-
 use std::mem;
 
 // A Marker adds the given mark to the syntax context.
diff --git a/src/librustc_expand/parse/lexer/tests.rs b/src/librustc_expand/parse/lexer/tests.rs
index 835f0b0108e..2ef81d80a14 100644
--- a/src/librustc_expand/parse/lexer/tests.rs
+++ b/src/librustc_expand/parse/lexer/tests.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{emitter::EmitterWriter, Handler};
 use rustc_parse::lexer::StringReader;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::symbol::Symbol;
@@ -8,7 +9,6 @@ use syntax::token::{self, Token, TokenKind};
 use syntax::util::comments::is_doc_comment;
 use syntax::with_default_globals;
 
-use errors::{emitter::EmitterWriter, Handler};
 use std::io;
 use std::path::PathBuf;
 
diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs
index 25cd5dabe57..b79e2894126 100644
--- a/src/librustc_expand/parse/tests.rs
+++ b/src/librustc_expand/parse/tests.rs
@@ -1,6 +1,6 @@
 use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
 
-use errors::PResult;
+use rustc_errors::PResult;
 use rustc_parse::new_parser_from_source_str;
 use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::{kw, sym, Symbol};
diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs
index 25e2bbb3467..cb6249e9369 100644
--- a/src/librustc_expand/proc_macro.rs
+++ b/src/librustc_expand/proc_macro.rs
@@ -1,15 +1,14 @@
 use crate::base::{self, *};
 use crate::proc_macro_server;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, FatalError};
 use rustc_span::symbol::sym;
+use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
-use syntax::errors::{Applicability, FatalError};
 use syntax::token;
 use syntax::tokenstream::{self, TokenStream};
 
-use rustc_data_structures::sync::Lrc;
-use rustc_span::{Span, DUMMY_SP};
-
 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
 
 pub struct BangProcMacro {
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index cf5749f5068..d441613ac58 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -1,5 +1,7 @@
 use crate::base::ExtCtxt;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::Diagnostic;
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -11,9 +13,6 @@ use syntax::token;
 use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 use syntax::util::comments;
 
-use errors::Diagnostic;
-use rustc_data_structures::sync::Lrc;
-
 use pm::bridge::{server, TokenTree};
 use pm::{Delimiter, Level, LineColumn, Spacing};
 use std::ops::Bound;
@@ -265,13 +264,13 @@ impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
     }
 }
 
-impl ToInternal<errors::Level> for Level {
-    fn to_internal(self) -> errors::Level {
+impl ToInternal<rustc_errors::Level> for Level {
+    fn to_internal(self) -> rustc_errors::Level {
         match self {
-            Level::Error => errors::Level::Error,
-            Level::Warning => errors::Level::Warning,
-            Level::Note => errors::Level::Note,
-            Level::Help => errors::Level::Help,
+            Level::Error => rustc_errors::Level::Error,
+            Level::Warning => rustc_errors::Level::Warning,
+            Level::Note => rustc_errors::Level::Note,
+            Level::Help => rustc_errors::Level::Help,
             _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
         }
     }
diff --git a/src/librustc_expand/tests.rs b/src/librustc_expand/tests.rs
index 18dc605c9e7..82ab74ac150 100644
--- a/src/librustc_expand/tests.rs
+++ b/src/librustc_expand/tests.rs
@@ -6,9 +6,9 @@ use syntax::sess::ParseSess;
 use syntax::tokenstream::TokenStream;
 use syntax::with_default_globals;
 
-use errors::emitter::EmitterWriter;
-use errors::{Handler, PResult};
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::emitter::EmitterWriter;
+use rustc_errors::{Handler, PResult};
 
 use std::io;
 use std::io::prelude::*;
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 6a15cc5cb0f..319cd88f245 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -192,9 +192,6 @@ declare_features! (
     /// Allows using the `unadjusted` ABI; perma-unstable.
     (active, abi_unadjusted, "1.16.0", None, None),
 
-    /// Allows identifying crates that contain sanitizer runtimes.
-    (active, sanitizer_runtime, "1.17.0", None, None),
-
     /// Used to identify crates that contain the profiler runtime.
     (active, profiler_runtime, "1.18.0", None, None),
 
@@ -534,6 +531,9 @@ declare_features! (
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
 
+    /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
+    (active, half_open_range_patterns, "1.41.0", Some(67264), None),
+
     /// Allows using `&mut` in constant functions.
     (active, const_mut_refs, "1.41.0", Some(57349), None),
 
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index 3cbf96b6d29..a38726e3de8 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -410,11 +410,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         which contains compiler-rt intrinsics and will never be stable",
     ),
     gated!(
-        sanitizer_runtime, Whitelisted, template!(Word),
-        "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \
-        of a sanitizer and will never be stable",
-    ),
-    gated!(
         profiler_runtime, Whitelisted, template!(Word),
         "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
         which contains the profiler runtime and will never be stable",
diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs
index 1eeedd77214..d5b6fe81c7b 100644
--- a/src/librustc_feature/removed.rs
+++ b/src/librustc_feature/removed.rs
@@ -74,6 +74,8 @@ declare_features! (
     (removed, pushpop_unsafe, "1.2.0", None, None, None),
     (removed, needs_allocator, "1.4.0", Some(27389), None,
      Some("subsumed by `#![feature(allocator_internals)]`")),
+    /// Allows identifying crates that contain sanitizer runtimes.
+    (removed, sanitizer_runtime, "1.17.0", None, None, None),
     (removed, proc_macro_mod, "1.27.0", Some(54727), None,
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
     (removed, proc_macro_expr, "1.27.0", Some(54727), None,
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 603c21188e3..550e3654d08 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -905,7 +905,7 @@ pub enum PatKind<'hir> {
     Lit(&'hir Expr<'hir>),
 
     /// A range pattern (e.g., `1..=2` or `1..2`).
-    Range(&'hir Expr<'hir>, &'hir Expr<'hir>, RangeEnd),
+    Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
 
     /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
     ///
diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs
index 4664340b15f..3dbc5253a9a 100644
--- a/src/librustc_hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -766,8 +766,8 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound)
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index 571bab2cb83..759f423070a 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -1767,13 +1767,17 @@ impl<'a> State<'a> {
             }
             PatKind::Lit(ref e) => self.print_expr(&e),
             PatKind::Range(ref begin, ref end, ref end_kind) => {
-                self.print_expr(&begin);
-                self.s.space();
+                if let Some(expr) = begin {
+                    self.print_expr(expr);
+                    self.s.space();
+                }
                 match *end_kind {
                     RangeEnd::Included => self.s.word("..."),
                     RangeEnd::Excluded => self.s.word(".."),
                 }
-                self.print_expr(&end);
+                if let Some(expr) = end {
+                    self.print_expr(expr);
+                }
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
                 self.s.word("[");
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index adf8f57f01d..ba20006d73c 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -190,6 +190,8 @@ pub fn prepare_session_directory(
         return;
     }
 
+    let _timer = sess.timer("incr_comp_prepare_session_directory");
+
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
@@ -306,6 +308,8 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
         return;
     }
 
+    let _timer = sess.timer("incr_comp_finalize_session_directory");
+
     let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
 
     if sess.has_errors_or_delayed_span_bugs() {
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 0732ddd3261..6c57f79e1a7 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -102,6 +102,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
         return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() });
     }
 
+    let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
+
     // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
     // Fortunately, we just checked that this isn't the case.
     let path = dep_graph_path_from(&sess.incr_comp_session_dir());
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index be60b75bc47..eb0551c6065 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -17,10 +17,12 @@ syntax = { path = "../libsyntax" }
 rustc_builtin_macros = { path = "../librustc_builtin_macros" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc = { path = "../librustc" }
 rustc_ast_lowering = { path = "../librustc_ast_lowering" }
+rustc_ast_passes = { path = "../librustc_ast_passes" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_traits = { path = "../librustc_traits" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index c4449945dd1..d00875f6fee 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -177,11 +177,17 @@ pub fn run_compiler_in_existing_thread_pool<R>(
         override_queries: config.override_queries,
     };
 
-    let _sess_abort_error = OnDrop(|| {
-        compiler.sess.diagnostic().print_error_count(registry);
-    });
+    let r = {
+        let _sess_abort_error = OnDrop(|| {
+            compiler.sess.diagnostic().print_error_count(registry);
+        });
 
-    f(&compiler)
+        f(&compiler)
+    };
+
+    let prof = compiler.sess.prof.clone();
+    prof.generic_activity("drop_compiler").run(move || drop(compiler));
+    r
 }
 
 pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index a7e174f0455..9119466cbc0 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -29,7 +29,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental;
 use rustc_mir as mir;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
-use rustc_passes::{self, ast_validation, hir_stats, layout_test};
+use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
 use rustc_privacy;
 use rustc_resolve::{Resolver, ResolverArenas};
@@ -37,7 +37,6 @@ use rustc_span::symbol::Symbol;
 use rustc_span::FileName;
 use rustc_traits;
 use rustc_typeck as typeck;
-use syntax::early_buffered_lints::BufferedEarlyLint;
 use syntax::mut_visit::MutVisitor;
 use syntax::util::node_count::NodeCounter;
 use syntax::{self, ast, visit};
@@ -71,7 +70,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
     }
 
     if let Some(ref s) = sess.opts.debugging_opts.show_span {
-        syntax::show_span::run(sess.diagnostic(), s, &krate);
+        rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate);
     }
 
     if sess.opts.debugging_opts.hir_stats {
@@ -345,7 +344,7 @@ fn configure_and_expand_inner<'a>(
     }
 
     let has_proc_macro_decls = sess.time("AST_validation", || {
-        ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
+        rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
     });
 
     let crate_types = sess.crate_types.borrow();
@@ -400,7 +399,7 @@ fn configure_and_expand_inner<'a>(
 
     // Needs to go *after* expansion to be able to check the results of macro expansion.
     sess.time("complete_gated_feature_checking", || {
-        syntax::feature_gate::check_crate(
+        rustc_ast_passes::feature_gate::check_crate(
             &krate,
             &sess.parse_sess,
             &sess.features_untracked(),
@@ -411,8 +410,8 @@ fn configure_and_expand_inner<'a>(
     // Add all buffered lints from the `ParseSess` to the `Session`.
     sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
         info!("{} parse sess buffered_lints", buffered_lints.len());
-        for BufferedEarlyLint { id, span, msg, lint_id } in buffered_lints.drain(..) {
-            resolver.lint_buffer().buffer_lint(lint_id, id, span, &msg);
+        for early_lint in buffered_lints.drain(..) {
+            resolver.lint_buffer().add_early_lint(early_lint);
         }
     });
 
@@ -611,6 +610,8 @@ pub fn prepare_outputs(
     boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
     crate_name: &str,
 ) -> Result<OutputFilenames> {
+    let _timer = sess.timer("prepare_outputs");
+
     // FIXME: rustdoc passes &[] instead of &krate.attrs here
     let outputs = util::build_output_filenames(
         &compiler.input,
@@ -734,20 +735,22 @@ pub fn create_global_ctxt<'tcx>(
         callback(sess, &mut local_providers, &mut extern_providers);
     }
 
-    let gcx = global_ctxt.init_locking(|| {
-        TyCtxt::create_global_ctxt(
-            sess,
-            lint_store,
-            local_providers,
-            extern_providers,
-            &all_arenas,
-            arena,
-            resolver_outputs,
-            hir_map,
-            query_result_on_disk_cache,
-            &crate_name,
-            &outputs,
-        )
+    let gcx = sess.time("setup_global_ctxt", || {
+        global_ctxt.init_locking(|| {
+            TyCtxt::create_global_ctxt(
+                sess,
+                lint_store,
+                local_providers,
+                extern_providers,
+                &all_arenas,
+                arena,
+                resolver_outputs,
+                hir_map,
+                query_result_on_disk_cache,
+                &crate_name,
+                &outputs,
+            )
+        })
     });
 
     // Do some initialization of the DepGraph that can only be done with the tcx available.
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 6033569d765..7de1c36ce4b 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -176,6 +176,7 @@ impl<'tcx> Queries<'tcx> {
         self.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let (krate, lint_store) = self.register_plugins()?.take();
+            let _timer = self.session().timer("configure_and_expand");
             passes::configure_and_expand(
                 self.session().clone(),
                 lint_store.clone(),
@@ -256,6 +257,7 @@ impl<'tcx> Queries<'tcx> {
             let lint_store = self.expansion()?.peek().2.clone();
             let hir = self.lower_to_hir()?.peek();
             let (ref hir_forest, ref resolver_outputs) = &*hir;
+            let _timer = self.session().timer("create_global_ctxt");
             Ok(passes::create_global_ctxt(
                 self.compiler,
                 lint_store,
@@ -312,14 +314,19 @@ pub struct Linker {
 
 impl Linker {
     pub fn link(self) -> Result<()> {
-        self.codegen_backend
+        let r = self
+            .codegen_backend
             .join_codegen_and_link(
                 self.ongoing_codegen,
                 &self.sess,
                 &self.dep_graph,
                 &self.prepare_outputs,
             )
-            .map_err(|_| ErrorReported)
+            .map_err(|_| ErrorReported);
+        let prof = self.sess.prof.clone();
+        let dep_graph = self.dep_graph;
+        prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph));
+        r
     }
 }
 
@@ -328,6 +335,7 @@ impl Compiler {
     where
         F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T,
     {
+        let mut _timer = None;
         let queries = Queries::new(&self);
         let ret = f(&queries);
 
@@ -337,6 +345,8 @@ impl Compiler {
             }
         }
 
+        _timer = Some(self.session().timer("free_global_ctxt"));
+
         ret
     }
 
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index c15dc2fe704..2fafd3af7a5 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -1,8 +1,5 @@
 use log::info;
 use rustc::lint;
-use rustc::session::config::{ErrorOutputType, Input, OutputFilenames};
-use rustc::session::CrateDisambiguator;
-use rustc::session::{self, config, early_error, filesearch, DiagnosticOutput, Session};
 use rustc::ty;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -14,6 +11,11 @@ use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_resolve::{self, Resolver};
+use rustc_session as session;
+use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::CrateDisambiguator;
+use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
 use rustc_span::symbol::{sym, Symbol};
@@ -71,10 +73,6 @@ pub fn create_session(
         lint_caps,
     );
 
-    sess.prof.register_queries(|profiler| {
-        rustc::ty::query::QueryName::register_with_profiler(&profiler);
-    });
-
     let codegen_backend = get_codegen_backend(&sess);
 
     let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
@@ -424,7 +422,7 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat
     CrateDisambiguator::from(hasher.finish::<Fingerprint>())
 }
 
-pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) {
+pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut LintBuffer) {
     // Unconditionally collect crate types from attributes to make them used
     for a in attrs.iter() {
         if a.check_name(sym::crate_type) {
@@ -446,7 +444,7 @@ pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut
                             ast::CRATE_NODE_ID,
                             span,
                             "invalid `crate_type` value",
-                            lint::builtin::BuiltinLintDiagnostics::UnknownCrateTypes(
+                            BuiltinLintDiagnostics::UnknownCrateTypes(
                                 span,
                                 "did you mean".to_string(),
                                 format!("\"{}\"", candidate),
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 5ca8fc97ac4..7e23e705779 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -12,6 +12,7 @@ path = "lib.rs"
 log = "0.4"
 unicode-security = "0.0.2"
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs
index 46202cda16d..19d1052d1b2 100644
--- a/src/librustc_lint/array_into_iter.rs
+++ b/src/librustc_lint/array_into_iter.rs
@@ -1,10 +1,9 @@
-use crate::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
-use rustc::lint::FutureIncompatibleInfo;
+use rustc::lint::{FutureIncompatibleInfo, LateContext, LateLintPass, LintContext};
 use rustc::ty;
 use rustc::ty::adjustment::{Adjust, Adjustment};
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_span::symbol::sym;
-use syntax::errors::Applicability;
 
 declare_lint! {
     pub ARRAY_INTO_ITER,
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 23740af5259..befeb84e57c 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -21,16 +21,12 @@
 //! If you define a new `LateLintPass`, you will also need to add it to the
 //! `late_lint_methods!` invocation in `lib.rs`.
 
-use std::fmt::Write;
-
-use lint::{EarlyContext, EarlyLintPass, LateLintPass, LintPass};
-use lint::{LateContext, LintArray, LintContext};
 use rustc::hir::map::Map;
-use rustc::lint;
-use rustc::lint::FutureIncompatibleInfo;
+use rustc::lint::{self, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::traits::misc::can_type_implement_copy;
 use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::Stability;
 use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
 use rustc_hir as hir;
@@ -38,21 +34,21 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{GenericParamKind, PatKind};
 use rustc_hir::{HirIdSet, Node};
+use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
 use syntax::ast::{self, Expr};
 use syntax::attr::{self, HasAttrs};
-use syntax::errors::{Applicability, DiagnosticBuilder};
 use syntax::print::pprust::{self, expr_to_string};
-use syntax::ptr::P;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::FnKind;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
 use log::debug;
+use std::fmt::Write;
 
 // hardwired lints from librustc
 pub use lint::builtin::*;
@@ -1309,11 +1305,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
 
         /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
         /// corresponding to the ellipsis.
-        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P<Expr>, &P<Expr>, Span)> {
+        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> {
             match &pat.kind {
-                PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => {
-                    Some((a, b, *span))
-                }
+                PatKind::Range(
+                    a,
+                    Some(b),
+                    Spanned { span, node: RangeEnd::Included(DotDotDot) },
+                ) => Some((a.as_deref(), b, *span)),
                 _ => None,
             }
         }
@@ -1328,11 +1326,16 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
             let suggestion = "use `..=` for an inclusive range";
             if parenthesise {
                 self.node_id = Some(pat.id);
+                let end = expr_to_string(&end);
+                let replace = match start {
+                    Some(start) => format!("&({}..={})", expr_to_string(&start), end),
+                    None => format!("&(..={})", end),
+                };
                 let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg);
                 err.span_suggestion(
                     pat.span,
                     suggestion,
-                    format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)),
+                    replace,
                     Applicability::MachineApplicable,
                 );
                 err.emit();
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index 67c0c98b203..9a901719851 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -16,15 +16,15 @@
 
 use rustc::lint::{EarlyContext, LintStore};
 use rustc::lint::{EarlyLintPass, EarlyLintPassObject};
-use rustc::lint::{LintBuffer, LintContext, LintPass};
-use rustc::session::Session;
-
+use rustc::lint::{LintContext, LintPass};
+use rustc_session::lint::LintBuffer;
+use rustc_session::Session;
 use rustc_span::Span;
-use std::slice;
 use syntax::ast;
 use syntax::visit as ast_visit;
 
 use log::debug;
+use std::slice;
 
 macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs
index 07c3b95d699..d8e0274cf43 100644
--- a/src/librustc_lint/late.rs
+++ b/src/librustc_lint/late.rs
@@ -16,7 +16,6 @@
 
 use rustc::hir::map::Map;
 use rustc::lint::LateContext;
-use rustc::lint::LintPass;
 use rustc::lint::{LateLintPass, LateLintPassObject};
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
@@ -24,12 +23,13 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor;
+use rustc_session::lint::LintPass;
 use rustc_span::Span;
-use std::slice;
 use syntax::ast;
+use syntax::walk_list;
 
 use log::debug;
-use syntax::walk_list;
+use std::slice;
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index e272c3af468..e708ded603b 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -38,11 +38,12 @@ use rustc::lint::builtin::{
     BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
     INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS,
 };
-use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
+use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::{LintArray, LintPass};
 
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs
index f30d0bcbdd5..522aeb6b144 100644
--- a/src/librustc_lint/non_ascii_idents.rs
+++ b/src/librustc_lint/non_ascii_idents.rs
@@ -1,4 +1,4 @@
-use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use rustc::lint::{EarlyContext, EarlyLintPass, LintContext};
 use syntax::ast;
 
 declare_lint! {
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 13e57ecf146..f75bb9ba32c 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -1,7 +1,6 @@
-use lint::{EarlyContext, LateContext, LintArray, LintContext};
-use lint::{EarlyLintPass, LateLintPass, LintPass};
-use rustc::lint;
+use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::FnKind;
@@ -11,7 +10,6 @@ use rustc_span::{symbol::Ident, BytePos, Span};
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::errors::Applicability;
 
 #[derive(PartialEq)]
 pub enum MethodLateContext {
diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs
index 8dbf96a1558..dc18f15fe40 100644
--- a/src/librustc_lint/redundant_semicolon.rs
+++ b/src/librustc_lint/redundant_semicolon.rs
@@ -1,6 +1,6 @@
-use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use rustc::lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_errors::Applicability;
 use syntax::ast::{ExprKind, Stmt, StmtKind};
-use syntax::errors::Applicability;
 
 declare_lint! {
     pub REDUNDANT_SEMICOLON,
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index f740bdb2716..ab6841c0c09 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1,22 +1,20 @@
 #![allow(non_snake_case)]
 
-use crate::hir::def_id::DefId;
-use lint::{LateContext, LintArray, LintContext};
-use lint::{LateLintPass, LintPass};
-use rustc::lint;
+use rustc::lint::{LateContext, LateLintPass, LintContext};
 use rustc::mir::interpret::{sign_extend, truncate};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, ExprKind, Node};
 use rustc_index::vec::Idx;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
-use syntax::errors::Applicability;
 use syntax::{ast, attr};
 
 use log::debug;
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 184651e3ad5..da8a23f041e 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -1,21 +1,18 @@
-use lint::{EarlyContext, LateContext, LintArray, LintContext};
-use lint::{EarlyLintPass, LateLintPass, LintPass};
-use rustc::lint;
 use rustc::lint::builtin::UNUSED_ATTRIBUTES;
+use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty::adjustment;
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, Applicability};
 use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
 use syntax::ast;
 use syntax::attr;
-use syntax::errors::{pluralize, Applicability};
 use syntax::print::pprust;
 use syntax::util::parser;
 
diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml
deleted file mode 100644
index 9a24361f44e..00000000000
--- a/src/librustc_lsan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_lsan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_lsan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
deleted file mode 100644
index 6201bc9356d..00000000000
--- a/src/librustc_lsan/build.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("lsan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs
deleted file mode 100644
index bdbc154f4e8..00000000000
--- a/src/librustc_lsan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index d998e82d489..48767c377a9 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -16,8 +16,8 @@ memmap = "0.7"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_target = { path = "../librustc_target" }
 rustc_index = { path = "../librustc_index" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 30d049d143e..181f872154c 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -6,31 +6,29 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob
 use rustc::hir::map::Definitions;
 use rustc::middle::cstore::DepKind;
 use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
-use rustc::session::config::{self, Sanitizer};
+use rustc::session::config;
 use rustc::session::search_paths::PathKind;
 use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
+use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_index::vec::IndexVec;
-use rustc_target::spec::{PanicStrategy, TargetTriple};
-
-use std::path::Path;
-use std::{cmp, fs};
-
-use errors::struct_span_err;
-use log::{debug, info, log_enabled};
-use proc_macro::bridge::client::ProcMacro;
-use rustc_expand::base::SyntaxExtension;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::{PanicStrategy, TargetTriple};
 use syntax::ast;
 use syntax::attr;
 use syntax::expand::allocator::{global_allocator_spans, AllocatorKind};
 
-use rustc_error_codes::*;
+use log::{debug, info, log_enabled};
+use proc_macro::bridge::client::ProcMacro;
+use std::path::Path;
+use std::{cmp, fs};
 
 #[derive(Clone)]
 pub struct CStore {
@@ -673,108 +671,6 @@ impl<'a> CrateLoader<'a> {
         self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
     }
 
-    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`
-            const ASAN_SUPPORTED_TARGETS: &[&str] =
-                &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-            const TSAN_SUPPORTED_TARGETS: &[&str] =
-                &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-            const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-            const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-
-            let supported_targets = match *sanitizer {
-                Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
-                Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
-                Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
-                Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
-            };
-            if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) {
-                self.sess.err(&format!(
-                    "{:?}Sanitizer only works with the `{}` target",
-                    sanitizer,
-                    supported_targets.join("` or `")
-                ));
-                return;
-            }
-
-            // firstyear 2017 - during testing I was unable to access an OSX machine
-            // to make this work on different crate types. As a result, today I have
-            // only been able to test and support linux as a target.
-            if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" {
-                if !self.sess.crate_types.borrow().iter().all(|ct| {
-                    match *ct {
-                        // Link the runtime
-                        config::CrateType::Executable => true,
-                        // This crate will be compiled with the required
-                        // instrumentation pass
-                        config::CrateType::Staticlib
-                        | config::CrateType::Rlib
-                        | config::CrateType::Dylib
-                        | config::CrateType::Cdylib => false,
-                        _ => {
-                            self.sess.err(&format!(
-                                "Only executables, staticlibs, \
-                                cdylibs, dylibs and rlibs can be compiled with \
-                                `-Z sanitizer`"
-                            ));
-                            false
-                        }
-                    }
-                }) {
-                    return;
-                }
-            } else {
-                if !self.sess.crate_types.borrow().iter().all(|ct| {
-                    match *ct {
-                        // Link the runtime
-                        config::CrateType::Executable => true,
-                        // This crate will be compiled with the required
-                        // instrumentation pass
-                        config::CrateType::Rlib => false,
-                        _ => {
-                            self.sess.err(&format!(
-                                "Only executables and rlibs can be \
-                                                    compiled with `-Z sanitizer`"
-                            ));
-                            false
-                        }
-                    }
-                }) {
-                    return;
-                }
-            }
-
-            let mut uses_std = false;
-            self.cstore.iter_crate_data(|_, data| {
-                if data.name() == sym::std {
-                    uses_std = true;
-                }
-            });
-
-            if uses_std {
-                let name = Symbol::intern(match sanitizer {
-                    Sanitizer::Address => "rustc_asan",
-                    Sanitizer::Leak => "rustc_lsan",
-                    Sanitizer::Memory => "rustc_msan",
-                    Sanitizer::Thread => "rustc_tsan",
-                });
-                info!("loading sanitizer: {}", name);
-
-                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.is_sanitizer_runtime() {
-                    self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name));
-                }
-            } else {
-                self.sess.err("Must link std to be compiled with `-Z sanitizer`");
-            }
-        }
-    }
-
     fn inject_profiler_runtime(&mut self) {
         if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() {
             info!("loading profiler");
@@ -926,7 +822,6 @@ impl<'a> CrateLoader<'a> {
     }
 
     pub fn postprocess(&mut self, krate: &ast::Crate) {
-        self.inject_sanitizer_runtime();
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
         self.inject_panic_runtime(krate);
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 9f9a2187ece..4745ad02a3a 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -215,7 +215,6 @@
 use crate::creader::Library;
 use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
-use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::middle::cstore::{CrateSource, MetadataLoader};
 use rustc::session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
 use rustc::session::search_paths::PathKind;
@@ -223,6 +222,7 @@ use rustc::session::{config, CrateDisambiguator, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index c9f47475af8..9426d5e26f5 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -1,16 +1,16 @@
-use errors::struct_span_err;
 use rustc::middle::cstore::{self, NativeLibrary};
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
 use syntax::attr;
-use syntax::feature_gate::feature_err;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     let mut collector = Collector { tcx, libs: Vec::new() };
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index f5a05751f4c..eb3dcfa7227 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -1587,10 +1587,6 @@ impl<'a, 'tcx> CrateMetadata {
         self.root.panic_runtime
     }
 
-    crate fn is_sanitizer_runtime(&self) -> bool {
-        self.root.sanitizer_runtime
-    }
-
     crate fn is_profiler_runtime(&self) -> bool {
         self.root.profiler_runtime
     }
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index eb5754bf99b..c45e1994bc5 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -161,7 +161,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
     has_panic_handler => { cdata.root.has_panic_handler }
-    is_sanitizer_runtime => { cdata.root.sanitizer_runtime }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
     extern_crate => {
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 952d3bb8582..7f8791d0c34 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -514,7 +514,6 @@ impl<'tcx> EncodeContext<'tcx> {
             no_builtins: attr::contains_name(&attrs, sym::no_builtins),
             panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
             profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
-            sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime),
             symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
 
             crate_deps,
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 6309f1c260e..426ea62b8cd 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -209,7 +209,6 @@ crate struct CrateRoot<'tcx> {
     no_builtins: bool,
     panic_runtime: bool,
     profiler_runtime: bool,
-    sanitizer_runtime: bool,
     symbol_mangling_version: SymbolManglingVersion,
 }
 
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 9a301a6ad32..dc63fa80275 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -6,13 +6,12 @@ use rustc::infer::{
 };
 use rustc::mir::{Body, ConstraintCategory, Location};
 use rustc::ty::{self, RegionVid, Ty};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
 use std::collections::VecDeque;
-use syntax::errors::Applicability;
 
 use crate::util::borrowck_errors;
 
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index ce0c081bc16..0e9d16cfa56 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -6,6 +6,7 @@ use super::{PatCtxt, PatKind, PatternError};
 
 use rustc::hir::map::Map;
 use rustc::lint;
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
@@ -19,7 +20,6 @@ use rustc_hir::{HirId, Pat};
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::Mutability;
-use syntax::feature_gate::feature_err;
 
 use std::slice;
 
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 611d3f5b832..2598ce2391f 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -429,14 +429,87 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
         match self.lower_lit(expr) {
-            PatKind::AscribeUserType {
-                ascription: lo_ascription,
-                subpattern: Pat { kind: box kind, .. },
-            } => (kind, Some(lo_ascription)),
+            PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => {
+                (kind, Some(ascription))
+            }
             kind => (kind, None),
         }
     }
 
+    fn lower_pattern_range(
+        &mut self,
+        ty: Ty<'tcx>,
+        lo: &'tcx ty::Const<'tcx>,
+        hi: &'tcx ty::Const<'tcx>,
+        end: RangeEnd,
+        span: Span,
+    ) -> PatKind<'tcx> {
+        assert_eq!(lo.ty, ty);
+        assert_eq!(hi.ty, ty);
+        let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
+        match (end, cmp) {
+            // `x..y` where `x < y`.
+            // Non-empty because the range includes at least `x`.
+            (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            // `x..y` where `x >= y`. The range is empty => error.
+            (RangeEnd::Excluded, _) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0579,
+                    "lower range bound must be less than upper"
+                )
+                .emit();
+                PatKind::Wild
+            }
+            // `x..=y` where `x == y`.
+            (RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo },
+            // `x..=y` where `x < y`.
+            (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            // `x..=y` where `x > y` hence the range is empty => error.
+            (RangeEnd::Included, _) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0030,
+                    "lower range bound must be less than or equal to upper"
+                );
+                err.span_label(span, "lower bound larger than upper bound");
+                if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                    err.note(
+                        "When matching against a range, the compiler \
+                              verifies that the range is non-empty. Range \
+                              patterns include both end-points, so this is \
+                              equivalent to requiring the start of the range \
+                              to be less than or equal to the end of the range.",
+                    );
+                }
+                err.emit();
+                PatKind::Wild
+            }
+        }
+    }
+
+    fn normalize_range_pattern_ends(
+        &self,
+        ty: Ty<'tcx>,
+        lo: Option<&PatKind<'tcx>>,
+        hi: Option<&PatKind<'tcx>>,
+    ) -> Option<(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>)> {
+        match (lo, hi) {
+            (Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
+                Some((lo, hi))
+            }
+            (Some(PatKind::Constant { value: lo }), None) => {
+                Some((lo, ty.numeric_max_val(self.tcx)?))
+            }
+            (None, Some(PatKind::Constant { value: hi })) => {
+                Some((ty.numeric_min_val(self.tcx)?, hi))
+            }
+            _ => None,
+        }
+    }
+
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let mut ty = self.tables.node_type(pat.hir_id);
 
@@ -451,65 +524,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             hir::PatKind::Lit(ref value) => self.lower_lit(value),
 
             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
-                let (lo, lo_ascription) = self.lower_range_expr(lo_expr);
-                let (hi, hi_ascription) = self.lower_range_expr(hi_expr);
-
-                let mut kind = match (lo, hi) {
-                    (PatKind::Constant { value: lo }, PatKind::Constant { value: hi }) => {
-                        assert_eq!(lo.ty, ty);
-                        assert_eq!(hi.ty, ty);
-                        let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
-                        match (end, cmp) {
-                            (RangeEnd::Excluded, Some(Ordering::Less)) => {
-                                PatKind::Range(PatRange { lo, hi, end })
-                            }
-                            (RangeEnd::Excluded, _) => {
-                                struct_span_err!(
-                                    self.tcx.sess,
-                                    lo_expr.span,
-                                    E0579,
-                                    "lower range bound must be less than upper",
-                                )
-                                .emit();
-                                PatKind::Wild
-                            }
-                            (RangeEnd::Included, Some(Ordering::Equal)) => {
-                                PatKind::Constant { value: lo }
-                            }
-                            (RangeEnd::Included, Some(Ordering::Less)) => {
-                                PatKind::Range(PatRange { lo, hi, end })
-                            }
-                            (RangeEnd::Included, _) => {
-                                let mut err = struct_span_err!(
-                                    self.tcx.sess,
-                                    lo_expr.span,
-                                    E0030,
-                                    "lower range bound must be less than or equal to upper"
-                                );
-                                err.span_label(lo_expr.span, "lower bound larger than upper bound");
-                                if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                                    err.note(
-                                        "When matching against a range, the compiler \
-                                              verifies that the range is non-empty. Range \
-                                              patterns include both end-points, so this is \
-                                              equivalent to requiring the start of the range \
-                                              to be less than or equal to the end of the range.",
-                                    );
-                                }
-                                err.emit();
-                                PatKind::Wild
-                            }
-                        }
-                    }
-                    ref pats => {
-                        self.tcx.sess.delay_span_bug(
-                            pat.span,
-                            &format!(
-                                "found bad range pattern `{:?}` outside of error recovery",
-                                pats,
-                            ),
+                let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
+                let lo_span = lo_expr.map_or(pat.span, |e| e.span);
+                let lo = lo_expr.map(|e| self.lower_range_expr(e));
+                let hi = hi_expr.map(|e| self.lower_range_expr(e));
+
+                let (lp, hp) = (lo.as_ref().map(|x| &x.0), hi.as_ref().map(|x| &x.0));
+                let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) {
+                    Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span),
+                    None => {
+                        let msg = &format!(
+                            "found bad range pattern `{:?}` outside of error recovery",
+                            (&lo, &hi),
                         );
-
+                        self.tcx.sess.delay_span_bug(pat.span, msg);
                         PatKind::Wild
                     }
                 };
@@ -517,12 +545,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 // If we are handling a range with associated constants (e.g.
                 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
                 // constants somewhere. Have them on the range pattern.
-                for ascription in &[lo_ascription, hi_ascription] {
-                    if let Some(ascription) = ascription {
-                        kind = PatKind::AscribeUserType {
-                            ascription: *ascription,
-                            subpattern: Pat { span: pat.span, ty, kind: Box::new(kind) },
-                        };
+                for end in &[lo, hi] {
+                    if let Some((_, Some(ascription))) = end {
+                        let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
+                        kind = PatKind::AscribeUserType { ascription: *ascription, subpattern };
                     }
                 }
 
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index e4188092827..edb4eb4d7c3 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,12 +1,12 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
 use rustc::session::config::nightly_options;
+use rustc::session::parse::feature_err;
 use rustc::ty::TyCtxt;
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use syntax::feature_gate::feature_err;
 
 use super::{ConstKind, Item};
 
diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml
deleted file mode 100644
index bda40785725..00000000000
--- a/src/librustc_msan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_msan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_msan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
deleted file mode 100644
index dc08d51b51c..00000000000
--- a/src/librustc_msan/build.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("msan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs
deleted file mode 100644
index bdbc154f4e8..00000000000
--- a/src/librustc_msan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index d41d89902ef..aa159c55ff2 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -18,6 +18,7 @@ rustc_lexer = { path = "../librustc_lexer" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_error_codes = { path = "../librustc_error_codes" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 syntax = { path = "../libsyntax" }
 unicode-normalization = "0.1.11"
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index f2ffd9470ed..8467acc759c 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -9,18 +9,22 @@
 //! [#64197]: https://github.com/rust-lang/rust/issues/64197
 
 use crate::{parse_in, validate_attr};
-use rustc_errors::Applicability;
-use rustc_feature::Features;
-use rustc_span::edition::Edition;
-use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_error_codes::*;
+use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
+use rustc_feature::{Feature, Features, State as FeatureState};
+use rustc_feature::{
+    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
+};
+use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, AttrItem, Attribute, MetaItem};
 use syntax::attr;
 use syntax::attr::HasAttrs;
-use syntax::feature_gate::{feature_err, get_features};
 use syntax::mut_visit::*;
 use syntax::ptr::P;
-use syntax::sess::ParseSess;
+use syntax::sess::{feature_err, ParseSess};
 use syntax::util::map_in_place::MapInPlace;
 
 use smallvec::SmallVec;
@@ -31,6 +35,172 @@ pub struct StripUnconfigured<'a> {
     pub features: Option<&'a Features>,
 }
 
+fn get_features(
+    span_handler: &Handler,
+    krate_attrs: &[ast::Attribute],
+    crate_edition: Edition,
+    allow_features: &Option<Vec<String>>,
+) -> Features {
+    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
+        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
+        err.span_label(span, "feature has been removed");
+        if let Some(reason) = reason {
+            err.note(reason);
+        }
+        err.emit();
+    }
+
+    fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
+        ACTIVE_FEATURES.iter().filter(move |feature| {
+            if let Some(feature_edition) = feature.edition {
+                feature_edition <= edition
+            } else {
+                false
+            }
+        })
+    }
+
+    let mut features = Features::default();
+    let mut edition_enabled_features = FxHashMap::default();
+
+    for &edition in ALL_EDITIONS {
+        if edition <= crate_edition {
+            // The `crate_edition` implies its respective umbrella feature-gate
+            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
+            edition_enabled_features.insert(edition.feature_name(), edition);
+        }
+    }
+
+    for feature in active_features_up_to(crate_edition) {
+        feature.set(&mut features, DUMMY_SP);
+        edition_enabled_features.insert(feature.name, crate_edition);
+    }
+
+    // Process the edition umbrella feature-gates first, to ensure
+    // `edition_enabled_features` is completed before it's queried.
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        for mi in list {
+            if !mi.is_word() {
+                continue;
+            }
+
+            let name = mi.name_or_empty();
+
+            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
+            if let Some(edition) = edition {
+                if edition <= crate_edition {
+                    continue;
+                }
+
+                for feature in active_features_up_to(edition) {
+                    // FIXME(Manishearth) there is currently no way to set
+                    // lib features by edition
+                    feature.set(&mut features, DUMMY_SP);
+                    edition_enabled_features.insert(feature.name, edition);
+                }
+            }
+        }
+    }
+
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        let bad_input = |span| {
+            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
+        };
+
+        for mi in list {
+            let name = match mi.ident() {
+                Some(ident) if mi.is_word() => ident.name,
+                Some(ident) => {
+                    bad_input(mi.span())
+                        .span_suggestion(
+                            mi.span(),
+                            "expected just one word",
+                            format!("{}", ident.name),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    continue;
+                }
+                None => {
+                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+                    continue;
+                }
+            };
+
+            if let Some(edition) = edition_enabled_features.get(&name) {
+                let msg =
+                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
+                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+                continue;
+            }
+
+            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
+                // Handled in the separate loop above.
+                continue;
+            }
+
+            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
+            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
+            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
+                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
+                    state
+                {
+                    feature_removed(span_handler, mi.span(), *reason);
+                    continue;
+                }
+            }
+
+            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
+                let since = Some(Symbol::intern(since));
+                features.declared_lang_features.push((name, mi.span(), since));
+                continue;
+            }
+
+            if let Some(allowed) = allow_features.as_ref() {
+                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
+                    struct_span_err!(
+                        span_handler,
+                        mi.span(),
+                        E0725,
+                        "the feature `{}` is not in the list of allowed features",
+                        name
+                    )
+                    .emit();
+                    continue;
+                }
+            }
+
+            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
+                f.set(&mut features, mi.span());
+                features.declared_lang_features.push((name, mi.span(), None));
+                continue;
+            }
+
+            features.declared_lib_features.push((name, mi.span()));
+        }
+    }
+
+    features
+}
+
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
 pub fn features(
     mut krate: ast::Crate,
diff --git a/src/librustc_parse/lexer/unescape_error_reporting.rs b/src/librustc_parse/lexer/unescape_error_reporting.rs
index 151c63a49b5..88762dabd8a 100644
--- a/src/librustc_parse/lexer/unescape_error_reporting.rs
+++ b/src/librustc_parse/lexer/unescape_error_reporting.rs
@@ -3,11 +3,10 @@
 use std::iter::once;
 use std::ops::Range;
 
+use rustc_errors::{Applicability, Handler};
 use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
 
-use syntax::errors::{Applicability, Handler};
-
 pub(crate) fn emit_unescape_error(
     handler: &Handler,
     // interior part of the literal, without quotes
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 9abfbc698c5..d321383424c 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -51,7 +51,6 @@ pub enum Error {
         secondary_path: String,
     },
     UselessDocComment,
-    InclusiveRangeWithNoEnd,
 }
 
 impl Error {
@@ -102,11 +101,6 @@ impl Error {
                 );
                 err
             }
-            Error::InclusiveRangeWithNoEnd => {
-                let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end",);
-                err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
-                err
-            }
         }
     }
 }
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 90f15375aec..2d6a94ce620 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1,4 +1,3 @@
-use super::diagnostics::Error;
 use super::pat::{GateOr, PARAM_EXPECTED};
 use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
@@ -1967,7 +1966,8 @@ impl<'a> Parser<'a> {
         limits: RangeLimits,
     ) -> PResult<'a, ExprKind> {
         if end.is_none() && limits == RangeLimits::Closed {
-            Err(self.span_fatal_err(self.token.span, Error::InclusiveRangeWithNoEnd))
+            self.error_inclusive_range_with_no_end(self.token.span);
+            Ok(ExprKind::Err)
         } else {
             Ok(ExprKind::Range(start, end, limits))
         }
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index bf7f5735f13..50756ddec9f 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,6 +1,6 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym};
 use syntax::ast::{self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax};
@@ -281,91 +281,73 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtPat, |x| x);
 
         let lo = self.token.span;
-        let pat = match self.token.kind {
-            token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?,
-            token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?,
-            token::OpenDelim(token::Bracket) => {
-                // Parse `[pat, pat,...]` as a slice pattern.
-                let (pats, _) =
-                    self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
-                PatKind::Slice(pats)
-            }
-            token::DotDot => {
-                self.bump();
-                if self.is_pat_range_end_start() {
-                    // Parse `..42` for recovery.
-                    self.parse_pat_range_to(RangeEnd::Excluded, "..")?
-                } else {
-                    // A rest pattern `..`.
-                    PatKind::Rest
-                }
-            }
-            token::DotDotEq => {
-                // Parse `..=42` for recovery.
-                self.bump();
-                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?
-            }
-            token::DotDotDot => {
-                // Parse `...42` for recovery.
-                self.bump();
-                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?
+
+        let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
+            self.parse_pat_deref(expected)?
+        } else if self.check(&token::OpenDelim(token::Paren)) {
+            self.parse_pat_tuple_or_parens()?
+        } else if self.check(&token::OpenDelim(token::Bracket)) {
+            // Parse `[pat, pat,...]` as a slice pattern.
+            let (pats, _) =
+                self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
+            PatKind::Slice(pats)
+        } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
+            // A rest pattern `..`.
+            self.bump(); // `..`
+            PatKind::Rest
+        } else if let Some(form) = self.parse_range_end() {
+            self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
+        } else if self.eat_keyword(kw::Underscore) {
+            // Parse _
+            PatKind::Wild
+        } else if self.eat_keyword(kw::Mut) {
+            self.parse_pat_ident_mut()?
+        } else if self.eat_keyword(kw::Ref) {
+            // Parse ref ident @ pat / ref mut ident @ pat
+            let mutbl = self.parse_mutability();
+            self.parse_pat_ident(BindingMode::ByRef(mutbl))?
+        } else if self.eat_keyword(kw::Box) {
+            // Parse `box pat`
+            let pat = self.parse_pat_with_range_pat(false, None)?;
+            self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
+            PatKind::Box(pat)
+        } else if self.can_be_ident_pat() {
+            // Parse `ident @ pat`
+            // This can give false positives and parse nullary enums,
+            // they are dealt with later in resolve.
+            self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
+        } else if self.is_start_of_pat_with_path() {
+            // Parse pattern starting with a path
+            let (qself, path) = if self.eat_lt() {
+                // Parse a qualified path
+                let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+                (Some(qself), path)
+            } else {
+                // Parse an unqualified path
+                (None, self.parse_path(PathStyle::Expr)?)
+            };
+            let span = lo.to(self.prev_span);
+
+            if qself.is_none() && self.check(&token::Not) {
+                self.parse_pat_mac_invoc(path)?
+            } else if let Some(form) = self.parse_range_end() {
+                let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
+                self.parse_pat_range_begin_with(begin, form)?
+            } else if self.check(&token::OpenDelim(token::Brace)) {
+                self.parse_pat_struct(qself, path)?
+            } else if self.check(&token::OpenDelim(token::Paren)) {
+                self.parse_pat_tuple_struct(qself, path)?
+            } else {
+                PatKind::Path(qself, path)
             }
-            // At this point, token != `&`, `&&`, `(`, `[`, `..`, `..=`, or `...`.
-            _ => {
-                if self.eat_keyword(kw::Underscore) {
-                    // Parse _
-                    PatKind::Wild
-                } else if self.eat_keyword(kw::Mut) {
-                    self.parse_pat_ident_mut()?
-                } else if self.eat_keyword(kw::Ref) {
-                    // Parse ref ident @ pat / ref mut ident @ pat
-                    let mutbl = self.parse_mutability();
-                    self.parse_pat_ident(BindingMode::ByRef(mutbl))?
-                } else if self.eat_keyword(kw::Box) {
-                    // Parse `box pat`
-                    let pat = self.parse_pat_with_range_pat(false, None)?;
-                    self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
-                    PatKind::Box(pat)
-                } else if self.can_be_ident_pat() {
-                    // Parse `ident @ pat`
-                    // This can give false positives and parse nullary enums,
-                    // they are dealt with later in resolve.
-                    self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
-                } else if self.is_start_of_pat_with_path() {
-                    // Parse pattern starting with a path
-                    let (qself, path) = if self.eat_lt() {
-                        // Parse a qualified path
-                        let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
-                        (Some(qself), path)
-                    } else {
-                        // Parse an unqualified path
-                        (None, self.parse_path(PathStyle::Expr)?)
-                    };
-                    match self.token.kind {
-                        token::Not if qself.is_none() => self.parse_pat_mac_invoc(path)?,
-                        token::DotDotDot | token::DotDotEq | token::DotDot => {
-                            self.parse_pat_range_starting_with_path(lo, qself, path)?
-                        }
-                        token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
-                        token::OpenDelim(token::Paren) => {
-                            self.parse_pat_tuple_struct(qself, path)?
-                        }
-                        _ => PatKind::Path(qself, path),
-                    }
-                } else {
-                    // Try to parse everything else as literal with optional minus
-                    match self.parse_literal_maybe_minus() {
-                        Ok(begin)
-                            if self.check(&token::DotDot)
-                                || self.check(&token::DotDotEq)
-                                || self.check(&token::DotDotDot) =>
-                        {
-                            self.parse_pat_range_starting_with_lit(begin)?
-                        }
-                        Ok(begin) => PatKind::Lit(begin),
-                        Err(err) => return self.fatal_unexpected_non_pat(err, expected),
-                    }
-                }
+        } else {
+            // Try to parse everything else as literal with optional minus
+            match self.parse_literal_maybe_minus() {
+                Ok(begin) => match self.parse_range_end() {
+                    Some(form) => self.parse_pat_range_begin_with(begin, form)?,
+                    None => PatKind::Lit(begin),
+                },
+                Err(err) => return self.fatal_unexpected_non_pat(err, expected),
             }
         };
 
@@ -374,7 +356,7 @@ impl<'a> Parser<'a> {
         let pat = self.recover_intersection_pat(pat)?;
 
         if !allow_range_pat {
-            self.ban_pat_range_if_ambiguous(&pat)?
+            self.ban_pat_range_if_ambiguous(&pat)
         }
 
         Ok(pat)
@@ -441,26 +423,25 @@ impl<'a> Parser<'a> {
     }
 
     /// Ban a range pattern if it has an ambiguous interpretation.
-    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
+    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) {
         match pat.kind {
             PatKind::Range(
                 ..,
                 Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. },
-            ) => return Ok(()),
+            ) => return,
             PatKind::Range(..) => {}
-            _ => return Ok(()),
+            _ => return,
         }
 
-        let mut err =
-            self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation");
-        err.span_suggestion(
-            pat.span,
-            "add parentheses to clarify the precedence",
-            format!("({})", pprust::pat_to_string(&pat)),
-            // "ambiguous interpretation" implies that we have to be guessing
-            Applicability::MaybeIncorrect,
-        );
-        Err(err)
+        self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation")
+            .span_suggestion(
+                pat.span,
+                "add parentheses to clarify the precedence",
+                format!("({})", pprust::pat_to_string(&pat)),
+                // "ambiguous interpretation" implies that we have to be guessing
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
     }
 
     /// Parse `&pat` / `&mut pat`.
@@ -618,51 +599,6 @@ impl<'a> Parser<'a> {
         Ok(PatKind::Mac(mac))
     }
 
-    fn excluded_range_end(&self, span: Span) -> RangeEnd {
-        self.sess.gated_spans.gate(sym::exclusive_range_pattern, span);
-        RangeEnd::Excluded
-    }
-
-    /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
-    /// The `$path` has already been parsed and the next token is the `$form`.
-    fn parse_pat_range_starting_with_path(
-        &mut self,
-        lo: Span,
-        qself: Option<QSelf>,
-        path: Path,
-    ) -> PResult<'a, PatKind> {
-        let (end_kind, form) = match self.token.kind {
-            token::DotDot => (self.excluded_range_end(self.token.span), ".."),
-            token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
-            token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
-            _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
-        };
-        let op_span = self.token.span;
-        // Parse range
-        let span = lo.to(self.prev_span);
-        let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
-        self.bump();
-        let end = self.parse_pat_range_end_opt(&begin, form)?;
-        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
-    }
-
-    /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`.
-    /// The `$path` has already been parsed and the next token is the `$form`.
-    fn parse_pat_range_starting_with_lit(&mut self, begin: P<Expr>) -> PResult<'a, PatKind> {
-        let op_span = self.token.span;
-        let (end_kind, form) = if self.eat(&token::DotDotDot) {
-            (RangeEnd::Included(RangeSyntax::DotDotDot), "...")
-        } else if self.eat(&token::DotDotEq) {
-            (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
-        } else if self.eat(&token::DotDot) {
-            (self.excluded_range_end(op_span), "..")
-        } else {
-            panic!("impossible case: we already matched on a range-operator token")
-        };
-        let end = self.parse_pat_range_end_opt(&begin, form)?;
-        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
-    }
-
     fn fatal_unexpected_non_pat(
         &mut self,
         mut err: DiagnosticBuilder<'a>,
@@ -684,57 +620,66 @@ impl<'a> Parser<'a> {
         Err(err)
     }
 
-    /// Is the current token suitable as the start of a range patterns end?
-    fn is_pat_range_end_start(&self) -> bool {
-        self.token.is_path_start() // e.g. `MY_CONST`;
-            || self.token == token::Dot // e.g. `.5` for recovery;
-            || self.token.can_begin_literal_or_bool() // e.g. `42`.
-            || self.token.is_whole_expr()
-    }
-
-    /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
-    fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
-        let lo = self.prev_span;
-        let end = self.parse_pat_range_end()?;
-        let range_span = lo.to(end.span);
-        let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new());
-
-        self.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
-            .span_suggestion(
-                range_span,
-                "try using the minimum value for the type",
-                format!("MIN{}{}", form, pprust::expr_to_string(&end)),
-                Applicability::HasPlaceholders,
-            )
-            .emit();
-
-        Ok(PatKind::Range(begin, end, respan(lo, re)))
+    /// Parses the range pattern end form `".." | "..." | "..=" ;`.
+    fn parse_range_end(&mut self) -> Option<Spanned<RangeEnd>> {
+        let re = if self.eat(&token::DotDotDot) {
+            RangeEnd::Included(RangeSyntax::DotDotDot)
+        } else if self.eat(&token::DotDotEq) {
+            RangeEnd::Included(RangeSyntax::DotDotEq)
+        } else if self.eat(&token::DotDot) {
+            self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_span);
+            RangeEnd::Excluded
+        } else {
+            return None;
+        };
+        Some(respan(self.prev_span, re))
     }
 
-    /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern  or recover
-    /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
-    fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
-        if self.is_pat_range_end_start() {
+    /// Parse a range pattern `$begin $form $end?` where `$form = ".." | "..." | "..=" ;`.
+    /// `$begin $form` has already been parsed.
+    fn parse_pat_range_begin_with(
+        &mut self,
+        begin: P<Expr>,
+        re: Spanned<RangeEnd>,
+    ) -> PResult<'a, PatKind> {
+        let end = if self.is_pat_range_end_start(0) {
             // Parsing e.g. `X..=Y`.
-            self.parse_pat_range_end()
+            Some(self.parse_pat_range_end()?)
         } else {
             // Parsing e.g. `X..`.
-            let range_span = begin.span.to(self.prev_span);
+            self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span));
+            if let RangeEnd::Included(_) = re.node {
+                // FIXME(Centril): Consider semantic errors instead in `ast_validation`.
+                // Possibly also do this for `X..=` in *expression* contexts.
+                self.error_inclusive_range_with_no_end(re.span);
+            }
+            None
+        };
+        Ok(PatKind::Range(Some(begin), end, re))
+    }
 
-            self.struct_span_err(
-                range_span,
-                &format!("`X{}` range patterns are not supported", form),
-            )
-            .span_suggestion(
-                range_span,
-                "try using the maximum value for the type",
-                format!("{}{}MAX", pprust::expr_to_string(&begin), form),
-                Applicability::HasPlaceholders,
-            )
+    pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
+        use rustc_error_codes::E0586;
+        struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
+            .help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
             .emit();
+    }
 
-            Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new()))
-        }
+    /// Parse a range-to pattern, e.g. `..X` and `..=X` where `X` remains to be parsed.
+    fn parse_pat_range_to(&mut self, re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
+        let end = self.parse_pat_range_end()?;
+        self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_span));
+        Ok(PatKind::Range(None, Some(end), re))
+    }
+
+    /// Is the token `dist` away from the current suitable as the start of a range patterns end?
+    fn is_pat_range_end_start(&self, dist: usize) -> bool {
+        self.look_ahead(dist, |t| {
+            t.is_path_start() // e.g. `MY_CONST`;
+                || t.kind == token::Dot // e.g. `.5` for recovery;
+                || t.can_begin_literal_or_bool() // e.g. `42`.
+                || t.is_whole_expr()
+        })
     }
 
     fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index f0893612207..84562fbb46f 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -4,10 +4,10 @@ use crate::parse_in;
 
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
+use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Symbol};
 use syntax::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
-use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
-use syntax::sess::ParseSess;
 use syntax::tokenstream::DelimSpan;
 
 pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index ced933ba3ee..639d8639c4b 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -12,12 +12,12 @@ path = "lib.rs"
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_index = { path = "../librustc_index" }
-rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs
index 47e6e5ccc24..39ba2fbc63b 100644
--- a/src/librustc_passes/check_const.rs
+++ b/src/librustc_passes/check_const.rs
@@ -7,18 +7,18 @@
 //! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
-use errors::struct_span_err;
 use rustc::hir::map::Map;
 use rustc::session::config::nightly_options;
+use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::{sym, Span, Symbol};
 use syntax::ast::Mutability;
-use syntax::feature_gate::feature_err;
 
 use std::fmt;
 
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index 8273504715d..028d7c66275 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -1,9 +1,9 @@
-use errors::struct_span_err;
 use rustc::hir::map as hir_map;
 use rustc::session::config::EntryFnType;
 use rustc::session::{config, Session};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index ae8ac2e2c2e..2c26707a518 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -1,8 +1,8 @@
-use errors::struct_span_err;
 use rustc::hir::map::Map;
 use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index f128d3891d7..65eb07b989d 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -17,7 +17,6 @@ extern crate log;
 
 use rustc::ty::query::Providers;
 
-pub mod ast_validation;
 mod check_const;
 pub mod dead;
 mod diagnostic_items;
diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs
index e7d490d6d8d..8ae72912897 100644
--- a/src/librustc_passes/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -4,11 +4,11 @@
 // and `#[unstable (..)]`), but are not declared in one single location
 // (unlike lang features), which means we need to collect them instead.
 
-use errors::struct_span_err;
 use rustc::hir::map::Map;
 use rustc::middle::lib_features::LibFeatures;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::Symbol;
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 5c1bc4d1eaa..0426f3fbea2 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -96,12 +96,12 @@
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
-use errors::Applicability;
 use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::DefId;
@@ -1064,7 +1064,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                             .sess
                             .struct_span_err(expr.span, "`break` to unknown label")
                             .emit();
-                        errors::FatalError.raise()
+                        rustc_errors::FatalError.raise()
                     }
                 }
             }
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index 333b39c3bb3..5ad5795c777 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -2,10 +2,10 @@ use Context::*;
 
 use rustc::session::Session;
 
-use errors::{struct_span_err, Applicability};
 use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index be098543a2f..af37d218d68 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -1,16 +1,17 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
-use errors::struct_span_err;
 use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability::{DeprecationEntry, Index};
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::traits::misc::can_type_implement_copy;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -20,7 +21,6 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use syntax::ast::Attribute;
 use syntax::attr::{self, Stability};
-use syntax::feature_gate::feature_err;
 
 use std::cmp::Ordering;
 use std::mem::replace;
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 01e5d75d2b5..af37e7b5b76 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -14,16 +14,16 @@ doctest = false
 bitflags = "1.2.1"
 log = "0.4"
 syntax = { path = "../libsyntax" }
-rustc_expand = { path = "../librustc_expand" }
 arena = { path = "../libarena" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
-rustc_span = { path = "../librustc_span" }
 rustc = { path = "../librustc" }
 rustc_ast_lowering = { path = "../librustc_ast_lowering" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_expand = { path = "../librustc_expand" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 6472f39e844..291386413d6 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -20,18 +20,14 @@ use rustc::bug;
 use rustc::hir::exports::Export;
 use rustc::middle::cstore::CrateStore;
 use rustc::ty;
-use rustc_hir::def::{self, *};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_metadata::creader::LoadedMacro;
-
 use rustc_data_structures::sync::Lrc;
-use std::cell::Cell;
-use std::ptr;
-
-use errors::{struct_span_err, Applicability};
-
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
+use rustc_hir::def::{self, *};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_metadata::creader::LoadedMacro;
 use rustc_span::hygiene::{ExpnId, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym};
@@ -44,8 +40,8 @@ use syntax::token::{self, Token};
 use syntax::visit::{self, Visitor};
 
 use log::debug;
-
-use rustc_error_codes::*;
+use std::cell::Cell;
+use std::ptr;
 
 type Res = def::Res<NodeId>;
 
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 6561072a21b..4a6df92d822 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -26,9 +26,10 @@
 use crate::imports::ImportDirectiveSubclass;
 use crate::Resolver;
 
-use errors::pluralize;
 use rustc::{lint, ty};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::pluralize;
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::node_id::NodeMap;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
@@ -317,7 +318,7 @@ impl Resolver<'_> {
                 unused.use_tree_id,
                 ms,
                 &msg,
-                lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
+                BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
             );
         }
     }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index b81e71f0acf..99428049093 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,11 +1,11 @@
 use std::cmp::Reverse;
 
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use log::debug;
 use rustc::bug;
 use rustc::session::Session;
 use rustc::ty::{self, DefIdTree};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index 72de895f350..8fe17e89444 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -11,17 +11,17 @@ use crate::{BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
 use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
-use errors::{pluralize, struct_span_err, Applicability};
 use rustc::hir::exports::Export;
-use rustc::lint::builtin::BuiltinLintDiagnostics;
 use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
-use rustc::session::DiagnosticMessageId;
 use rustc::ty;
 use rustc::{bug, span_bug};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
+use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir::def::{self, PartialRes};
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span};
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 29a1be6bb74..defca4944bc 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -11,10 +11,9 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
-use errors::DiagnosticId;
-use log::debug;
 use rustc::{bug, lint, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::DiagnosticId;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
@@ -28,6 +27,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::{self, FnKind, Visitor};
 use syntax::{unwrap_or, walk_list};
 
+use log::debug;
 use std::collections::BTreeSet;
 use std::mem::replace;
 
@@ -306,7 +306,7 @@ impl<'a> PathSource<'a> {
     }
 
     fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId {
-        use errors::error_code;
+        use rustc_errors::error_code;
         match (self, has_unexpected_resolution) {
             (PathSource::Trait(_), true) => error_code!(E0404),
             (PathSource::Trait(_), false) => error_code!(E0405),
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 029f8421475..151f3e834e5 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -4,10 +4,10 @@ use crate::path_names_to_string;
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use errors::{Applicability, DiagnosticBuilder};
-use log::debug;
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_error_codes::*;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
@@ -18,7 +18,7 @@ use rustc_span::Span;
 use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind};
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
+use log::debug;
 
 type Res = def::Res<ast::NodeId>;
 
@@ -139,7 +139,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
 
         // Emit special messages for unresolved `Self` and `self`.
         if is_self_type(path, ns) {
-            err.code(errors::error_code!(E0411));
+            err.code(rustc_errors::error_code!(E0411));
             err.span_label(
                 span,
                 format!("`Self` is only available in impls, traits, and type definitions"),
@@ -149,7 +149,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
         if is_self_value(path, ns) {
             debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
 
-            err.code(errors::error_code!(E0424));
+            err.code(rustc_errors::error_code!(E0424));
             err.span_label(span, match source {
                 PathSource::Pat => format!(
                     "`self` value is a keyword and may not be bound to variables or shadowed",
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 9e4486e16f2..8e4630cf7d6 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -20,18 +20,17 @@ pub use rustc_hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
 
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::hir::exports::ExportMap;
 use rustc::hir::map::{DefKey, Definitions};
 use rustc::lint;
 use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
-use rustc::session::Session;
 use rustc::span_bug;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, DefIdTree, ResolverOutputs};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
@@ -39,7 +38,9 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}
 use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
 use rustc_hir::{GlobMap, TraitMap};
 use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::node_id::{NodeMap, NodeSet};
+use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym};
@@ -960,7 +961,7 @@ pub struct Resolver<'a> {
     /// when visiting the correspondent variants.
     variant_vis: DefIdMap<ty::Visibility>,
 
-    lint_buffer: lint::LintBuffer,
+    lint_buffer: LintBuffer,
 
     next_node_id: NodeId,
 }
@@ -1082,7 +1083,7 @@ impl rustc_ast_lowering::Resolver for Resolver<'_> {
         &mut self.definitions
     }
 
-    fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
+    fn lint_buffer(&mut self) -> &mut LintBuffer {
         &mut self.lint_buffer
     }
 
@@ -1241,7 +1242,7 @@ impl<'a> Resolver<'a> {
                 .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
                 .collect(),
             variant_vis: Default::default(),
-            lint_buffer: lint::LintBuffer::default(),
+            lint_buffer: LintBuffer::default(),
             next_node_id: NodeId::from_u32(1),
         }
     }
@@ -1256,7 +1257,7 @@ impl<'a> Resolver<'a> {
         self.next_node_id
     }
 
-    pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
+    pub fn lint_buffer(&mut self) -> &mut LintBuffer {
         &mut self.lint_buffer
     }
 
@@ -1713,10 +1714,10 @@ impl<'a> Resolver<'a> {
                     if let Some(node_id) = poisoned {
                         self.lint_buffer.buffer_lint_with_diagnostic(
                             lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-                            node_id, ident.span,
+                            node_id,
+                            ident.span,
                             &format!("cannot find {} `{}` in this scope", ns.descr(), ident),
-                            lint::builtin::BuiltinLintDiagnostics::
-                                ProcMacroDeriveResolutionFallback(ident.span),
+                            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(ident.span),
                         );
                     }
                     return Some(LexicalScopeBinding::Item(binding));
@@ -2267,7 +2268,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        let diag = lint::builtin::BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
+        let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
         self.lint_buffer.buffer_lint_with_diagnostic(
             lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             diag_id,
@@ -2562,9 +2563,10 @@ impl<'a> Resolver<'a> {
                        cannot be referred to by absolute paths";
             self.lint_buffer.buffer_lint_with_diagnostic(
                 lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
-                CRATE_NODE_ID, span_use, msg,
-                lint::builtin::BuiltinLintDiagnostics::
-                    MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+                CRATE_NODE_ID,
+                span_use,
+                msg,
+                BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
             );
         }
 
diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs
index 469e1b9aa62..d6143eec73c 100644
--- a/src/librustc_resolve/lifetimes.rs
+++ b/src/librustc_resolve/lifetimes.rs
@@ -5,7 +5,6 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
@@ -13,6 +12,7 @@ use rustc::session::Session;
 use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 1103d5b5b7c..85b5d8ef1cb 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -7,6 +7,7 @@ use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy};
 use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
 use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
 use rustc::middle::stability;
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::{lint, span_bug, ty};
 use rustc_data_structures::fx::FxHashSet;
@@ -23,7 +24,6 @@ use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, Ident, NodeId};
 use syntax::attr::{self, StabilityLevel};
-use syntax::feature_gate::feature_err;
 use syntax::print::pprust;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml
index 47c23bc4dcf..377ea141ed5 100644
--- a/src/librustc_session/Cargo.toml
+++ b/src/librustc_session/Cargo.toml
@@ -10,6 +10,7 @@ path = "lib.rs"
 
 [dependencies]
 log = "0.4"
+rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs
index 0cce7e848fd..2ba3932c7d9 100644
--- a/src/librustc_session/lint.rs
+++ b/src/librustc_session/lint.rs
@@ -1,8 +1,10 @@
 pub use self::Level::*;
-use crate::node_id::NodeId;
+use crate::node_id::{NodeId, NodeMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_span::edition::Edition;
-use rustc_span::{sym, MultiSpan, Symbol};
+use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
+
+pub mod builtin;
 
 /// Setting for how to handle a lint.
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
@@ -174,7 +176,25 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
     }
 }
 
-/// Stores buffered lint info which can later be passed to `librustc`.
+// This could be a closure, but then implementing derive trait
+// becomes hacky (and it gets allocated).
+#[derive(PartialEq)]
+pub enum BuiltinLintDiagnostics {
+    Normal,
+    BareTraitObject(Span, /* is_global */ bool),
+    AbsPathWithModule(Span),
+    ProcMacroDeriveResolutionFallback(Span),
+    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
+    ElidedLifetimesInPaths(usize, Span, bool, Span, String),
+    UnknownCrateTypes(Span, String, String),
+    UnusedImports(String, Vec<(Span, String)>),
+    RedundantImport(Vec<(Span, bool)>, Ident),
+    DeprecatedMacro(Option<Symbol>, Span),
+}
+
+/// Lints that are buffered up early on in the `Session` before the
+/// `LintLevels` is calculated. These are later passed to `librustc`.
+#[derive(PartialEq)]
 pub struct BufferedEarlyLint {
     /// The span of code that we are linting on.
     pub span: MultiSpan,
@@ -183,10 +203,65 @@ pub struct BufferedEarlyLint {
     pub msg: String,
 
     /// The `NodeId` of the AST node that generated the lint.
-    pub id: NodeId,
+    pub node_id: NodeId,
 
     /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
-    pub lint_id: &'static Lint,
+    pub lint_id: LintId,
+
+    /// Customization of the `DiagnosticBuilder<'_>` for the lint.
+    pub diagnostic: BuiltinLintDiagnostics,
+}
+
+#[derive(Default)]
+pub struct LintBuffer {
+    pub map: NodeMap<Vec<BufferedEarlyLint>>,
+}
+
+impl LintBuffer {
+    pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
+        let arr = self.map.entry(early_lint.node_id).or_default();
+        if !arr.contains(&early_lint) {
+            arr.push(early_lint);
+        }
+    }
+
+    pub fn add_lint(
+        &mut self,
+        lint: &'static Lint,
+        node_id: NodeId,
+        span: MultiSpan,
+        msg: &str,
+        diagnostic: BuiltinLintDiagnostics,
+    ) {
+        let lint_id = LintId::of(lint);
+        let msg = msg.to_string();
+        self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
+    }
+
+    pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
+        self.map.remove(&id).unwrap_or_default()
+    }
+
+    pub fn buffer_lint(
+        &mut self,
+        lint: &'static Lint,
+        id: NodeId,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+    ) {
+        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
+    }
+
+    pub fn buffer_lint_with_diagnostic(
+        &mut self,
+        lint: &'static Lint,
+        id: NodeId,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+        diagnostic: BuiltinLintDiagnostics,
+    ) {
+        self.add_lint(lint, id, sp.into(), msg, diagnostic)
+    }
 }
 
 /// Declares a static item of type `&'static Lint`.
@@ -253,3 +328,41 @@ macro_rules! declare_tool_lint {
         };
     );
 }
+
+/// Declares a static `LintArray` and return it as an expression.
+#[macro_export]
+macro_rules! lint_array {
+    ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
+    ($( $lint:expr ),*) => {{
+        vec![$($lint),*]
+    }}
+}
+
+pub type LintArray = Vec<&'static Lint>;
+
+pub trait LintPass {
+    fn name(&self) -> &'static str;
+}
+
+/// Implements `LintPass for $name` with the given list of `Lint` statics.
+#[macro_export]
+macro_rules! impl_lint_pass {
+    ($name:ident => [$($lint:expr),* $(,)?]) => {
+        impl $crate::lint::LintPass for $name {
+            fn name(&self) -> &'static str { stringify!($name) }
+        }
+        impl $name {
+            pub fn get_lints() -> $crate::lint::LintArray { $crate::lint_array!($($lint),*) }
+        }
+    };
+}
+
+/// Declares a type named `$name` which implements `LintPass`.
+/// To the right of `=>` a comma separated list of `Lint` statics is given.
+#[macro_export]
+macro_rules! declare_lint_pass {
+    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
+        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
+        $crate::impl_lint_pass!($name => [$($lint),*]);
+    };
+}
diff --git a/src/librustc/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index 3726e6ace54..3e8503ef661 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -4,16 +4,31 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::lint::{FutureIncompatibleInfo, LateLintPass, LintArray, LintPass};
-use crate::middle::stability;
-use crate::session::Session;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc_session::declare_lint;
+use crate::lint::FutureIncompatibleInfo;
+use crate::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
-use rustc_span::source_map::Span;
-use rustc_span::symbol::Symbol;
-use syntax::ast;
-use syntax::early_buffered_lints::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
+
+declare_lint! {
+    pub ILL_FORMED_ATTRIBUTE_INPUT,
+    Deny,
+    "ill-formed attribute inputs that were previously accepted and used in practice",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
+        edition: None,
+    };
+}
+
+declare_lint! {
+    pub META_VARIABLE_MISUSE,
+    Allow,
+    "possible meta-variable misuse at macro definition"
+}
+
+declare_lint! {
+    pub INCOMPLETE_INCLUDE,
+    Deny,
+    "trailing content in included file"
+}
 
 declare_lint! {
     pub EXCEEDING_BITSHIFTS,
@@ -513,145 +528,3 @@ declare_lint_pass! {
         SOFT_UNSTABLE,
     ]
 }
-
-// this could be a closure, but then implementing derive traits
-// becomes hacky (and it gets allocated)
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
-pub enum BuiltinLintDiagnostics {
-    Normal,
-    BareTraitObject(Span, /* is_global */ bool),
-    AbsPathWithModule(Span),
-    ProcMacroDeriveResolutionFallback(Span),
-    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
-    ElidedLifetimesInPaths(usize, Span, bool, Span, String),
-    UnknownCrateTypes(Span, String, String),
-    UnusedImports(String, Vec<(Span, String)>),
-    RedundantImport(Vec<(Span, bool)>, ast::Ident),
-    DeprecatedMacro(Option<Symbol>, Span),
-}
-
-pub fn add_elided_lifetime_in_path_suggestion(
-    sess: &Session,
-    db: &mut DiagnosticBuilder<'_>,
-    n: usize,
-    path_span: Span,
-    incl_angl_brckt: bool,
-    insertion_span: Span,
-    anon_lts: String,
-) {
-    let (replace_span, suggestion) = if incl_angl_brckt {
-        (insertion_span, anon_lts)
-    } else {
-        // When possible, prefer a suggestion that replaces the whole
-        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
-        // at a point (which makes for an ugly/confusing label)
-        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
-            // But our spans can get out of whack due to macros; if the place we think
-            // we want to insert `'_` isn't even within the path expression's span, we
-            // should bail out of making any suggestion rather than panicking on a
-            // subtract-with-overflow or string-slice-out-out-bounds (!)
-            // FIXME: can we do better?
-            if insertion_span.lo().0 < path_span.lo().0 {
-                return;
-            }
-            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
-            if insertion_index > snippet.len() {
-                return;
-            }
-            let (before, after) = snippet.split_at(insertion_index);
-            (path_span, format!("{}{}{}", before, anon_lts, after))
-        } else {
-            (insertion_span, anon_lts)
-        }
-    };
-    db.span_suggestion(
-        replace_span,
-        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
-        suggestion,
-        Applicability::MachineApplicable,
-    );
-}
-
-impl BuiltinLintDiagnostics {
-    pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
-        match self {
-            BuiltinLintDiagnostics::Normal => (),
-            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
-                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
-                    Ok(ref s) if is_global => {
-                        (format!("dyn ({})", s), Applicability::MachineApplicable)
-                    }
-                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
-                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
-                };
-                db.span_suggestion(span, "use `dyn`", sugg, app);
-            }
-            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
-                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
-                    Ok(ref s) => {
-                        // FIXME(Manishearth) ideally the emitting code
-                        // can tell us whether or not this is global
-                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
-
-                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
-                    }
-                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
-                };
-                db.span_suggestion(span, "use `crate`", sugg, app);
-            }
-            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
-                db.span_label(
-                    span,
-                    "names from parent modules are not \
-                                     accessible without an explicit import",
-                );
-            }
-            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
-                db.span_note(span_def, "the macro is defined here");
-            }
-            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                n,
-                path_span,
-                incl_angl_brckt,
-                insertion_span,
-                anon_lts,
-            ) => {
-                add_elided_lifetime_in_path_suggestion(
-                    sess,
-                    db,
-                    n,
-                    path_span,
-                    incl_angl_brckt,
-                    insertion_span,
-                    anon_lts,
-                );
-            }
-            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
-                db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
-            }
-            BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
-                if !replaces.is_empty() {
-                    db.tool_only_multipart_suggestion(
-                        &message,
-                        replaces,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
-                for (span, is_imported) in spans {
-                    let introduced = if is_imported { "imported" } else { "defined" };
-                    db.span_label(
-                        span,
-                        format!("the item `{}` is already {} here", ident, introduced),
-                    );
-                }
-            }
-            BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
-                stability::deprecation_suggestion(db, suggestion, span)
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 6cc6a1ec276..946e77d3559 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -1,15 +1,15 @@
 //! Contains `ParseSess` which holds state living beyond what one `Parser` might.
 //! It also serves as an input to the parser itself.
 
-use crate::lint::BufferedEarlyLint;
+use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
 use crate::node_id::NodeId;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{Lock, Lrc, Once};
-use rustc_errors::{
-    emitter::SilentEmitter, Applicability, ColorConfig, DiagnosticBuilder, Handler,
-};
-use rustc_feature::UnstableFeatures;
+use rustc_error_codes::E0658;
+use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
+use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
+use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
@@ -62,6 +62,81 @@ impl GatedSpans {
     }
 }
 
+/// The strenght of a feature gate.
+/// Either it is a `Hard` error, or only a `Soft` warning.
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum GateStrength {
+    /// A hard error. (Most feature gates should use this.)
+    Hard,
+    /// Only a warning. (Use this only as backwards-compatibility demands.)
+    Soft,
+}
+
+/// Construct a diagnostic for a language feature error due to the given `span`.
+/// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
+pub fn feature_err<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
+    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
+}
+
+/// Construct a diagnostic for a feature gate error.
+///
+/// This variant allows you to control whether it is a library or language feature.
+/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
+pub fn feature_err_issue<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    issue: GateIssue,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
+    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
+}
+
+/// Construct a diagnostic for a feature gate error / warning.
+///
+/// You should typically just use `feature_err` instead.
+pub fn leveled_feature_err<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    issue: GateIssue,
+    explain: &str,
+    level: GateStrength,
+) -> DiagnosticBuilder<'a> {
+    let diag = &sess.span_diagnostic;
+
+    let mut err = match level {
+        GateStrength::Hard => diag.struct_span_err_with_code(span, explain, error_code!(E0658)),
+        GateStrength::Soft => diag.struct_span_warn(span, explain),
+    };
+
+    if let Some(n) = find_feature_issue(feature, issue) {
+        err.note(&format!(
+            "for more information, see https://github.com/rust-lang/rust/issues/{}",
+            n,
+        ));
+    }
+
+    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
+    if sess.unstable_features.is_nightly_build() {
+        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
+    }
+
+    // If we're on stable and only emitting a "soft" warning, add a note to
+    // clarify that the feature isn't "on" (rather than being on but
+    // warning-worthy).
+    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
+        err.help("a nightly build of the compiler is required to enable this feature");
+    }
+
+    err
+}
+
 /// Info about a parsing session.
 pub struct ParseSess {
     pub span_diagnostic: Handler,
@@ -123,17 +198,18 @@ impl ParseSess {
 
     pub fn buffer_lint(
         &self,
-        lint_id: &'static crate::lint::Lint,
+        lint: &'static Lint,
         span: impl Into<MultiSpan>,
-        id: NodeId,
+        node_id: NodeId,
         msg: &str,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
                 span: span.into(),
-                id,
+                node_id,
                 msg: msg.into(),
-                lint_id,
+                lint_id: LintId::of(lint),
+                diagnostic: BuiltinLintDiagnostics::Normal,
             });
         });
     }
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index dba5b9f3f14..d979247b46d 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -1124,6 +1124,32 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
                   See https://github.com/rust-lang/rust/issues/61002 for details.",
         );
     }
+
+    // Sanitizers can only be used on some tested platforms.
+    if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
+        const ASAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const TSAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const LSAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
+
+        let supported_targets = match *sanitizer {
+            Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
+            Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
+            Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
+            Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
+        };
+
+        if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
+            sess.err(&format!(
+                "{:?}Sanitizer only works with the `{}` target",
+                sanitizer,
+                supported_targets.join("` or `")
+            ));
+        }
+    }
 }
 
 /// Hash value constructed out of all the `-C metadata` arguments passed to the
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index d9f4b72560c..a8b2db300a4 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -343,6 +343,7 @@ symbols! {
         global_allocator,
         global_asm,
         globs,
+        half_open_range_patterns,
         hash,
         Hash,
         HashSet,
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f08634cc770..528ffdf93a0 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -805,6 +805,9 @@ pub struct TargetOptions {
 
     /// Whether or not RelaxElfRelocation flag will be passed to the linker
     pub relax_elf_relocations: bool,
+
+    /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
+    pub llvm_args: Vec<String>,
 }
 
 impl Default for TargetOptions {
@@ -893,6 +896,7 @@ impl Default for TargetOptions {
             target_mcount: "mcount".to_string(),
             llvm_abiname: "".to_string(),
             relax_elf_relocations: false,
+            llvm_args: vec![],
         }
     }
 }
@@ -1206,6 +1210,7 @@ impl Target {
         key!(target_mcount);
         key!(llvm_abiname);
         key!(relax_elf_relocations, bool);
+        key!(llvm_args, list);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1433,6 +1438,7 @@ impl ToJson for Target {
         target_option_val!(target_mcount);
         target_option_val!(llvm_abiname);
         target_option_val!(relax_elf_relocations);
+        target_option_val!(llvm_args);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert(
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
deleted file mode 100644
index 82045dd0cdd..00000000000
--- a/src/librustc_tsan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_tsan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_tsan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
deleted file mode 100644
index 570642a2eaa..00000000000
--- a/src/librustc_tsan/build.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
-    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
-        return;
-    }
-    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        build_helper::restore_library_path();
-
-        let (native, target) = match sanitizer_lib_boilerplate("tsan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-        native.fixup_sanitizer_lib_name("tsan");
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs
deleted file mode 100644
index bdbc154f4e8..00000000000
--- a/src/librustc_tsan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index a489d0cd02b..84e5f56d9c2 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -15,8 +15,8 @@ arena = { path = "../libarena" }
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 7c7480339a5..c15bcd81443 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -9,8 +9,8 @@ use crate::middle::resolve_lifetime as rl;
 use crate::namespace::Namespace;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
-use errors::{struct_span_err, Applicability, DiagnosticId};
 use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
+use rustc::session::parse::feature_err;
 use rustc::traits;
 use rustc::traits::astconv_object_safety_violations;
 use rustc::traits::error_reporting::report_object_safety_error;
@@ -19,6 +19,7 @@ use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
 use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -30,8 +31,6 @@ use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use smallvec::SmallVec;
 use syntax::ast;
-use syntax::errors::pluralize;
-use syntax::feature_gate::feature_err;
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use std::collections::BTreeSet;
@@ -2125,9 +2124,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     let msg = format!("expected type, found variant `{}`", assoc_ident);
                     tcx.sess.span_err(span, &msg);
                 } else if qself_ty.is_enum() {
-                    let mut err = tcx.sess.struct_span_err(
+                    let mut err = struct_span_err!(
+                        tcx.sess,
                         assoc_ident.span,
-                        &format!("no variant `{}` in enum `{}`", assoc_ident, qself_ty),
+                        E0599,
+                        "no variant named `{}` found for enum `{}`",
+                        assoc_ident,
+                        qself_ty,
                     );
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 3d02889d2dd..8d6b74c3015 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -1,13 +1,13 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs, PlaceOp};
 
-use errors::struct_span_err;
 use rustc::infer::{InferCtxt, InferOk};
 use rustc::session::DiagnosticMessageId;
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc::ty::{self, TraitRef, Ty, TyCtxt};
 use rustc::ty::{ToPredicate, TypeFoldable};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 
 use rustc_span::Span;
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index a1915bc025f..bff6765314a 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -3,22 +3,20 @@ use super::method::MethodCallee;
 use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
 use crate::type_error_struct;
 
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
-use hir::def::Res;
-use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::{infer, traits};
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast::Ident;
 
-use rustc_hir as hir;
-
-use rustc_error_codes::*;
-
 /// Checks that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called).
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 9dbf55c4948..ba5e5fd8ac1 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -34,7 +34,6 @@ use crate::hir::def_id::DefId;
 use crate::lint;
 use crate::type_error_struct;
 use crate::util::common::ErrorReported;
-use errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::traits;
@@ -45,6 +44,7 @@ use rustc::ty::cast::{CastKind, CastTy};
 use rustc::ty::error::TypeError;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index ec298ca6971..1afb703ca15 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -51,9 +51,9 @@
 //! we may want to adjust precisely when coercions occur.
 
 use crate::check::{FnCtxt, Needs};
-use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{Coercion, InferOk, InferResult};
+use rustc::session::parse::feature_err;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -63,6 +63,8 @@ use rustc::ty::fold::TypeFoldable;
 use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut};
+use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span;
@@ -70,9 +72,6 @@ use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
-use syntax::feature_gate;
-
-use rustc_error_codes::*;
 
 struct Coerce<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -627,7 +626,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         }
 
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
-            feature_gate::feature_err(
+            feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::unsized_tuple_coercion,
                 self.cause.span,
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 449c2e90ff2..c35661ac649 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1,4 +1,3 @@
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc::hir::map::Map;
 use rustc::infer::{self, InferOk};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
@@ -7,6 +6,7 @@ use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::ExplicitSelf;
 use rustc::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc::util::common::ErrorReported;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 1be65b5f189..e0f9fcc6932 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -2,9 +2,9 @@ use crate::check::FnCtxt;
 use rustc::infer::InferOk;
 use rustc::traits::{self, ObligationCause};
 
-use errors::{Applicability, DiagnosticBuilder};
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::{self, AssocItem, Ty};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, print, Node};
 use rustc_span::symbol::sym;
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 33a07423c25..88e7a265ebb 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -2,7 +2,6 @@ use crate::check::regionck::RegionCtxt;
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::util::common::ErrorReported;
-use errors::struct_span_err;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::{InferOk, SuppressRegionErrors};
 use rustc::middle::region;
@@ -11,6 +10,7 @@ use rustc::ty::error::TypeError;
 use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, Predicate, Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 
 use rustc_span::Span;
 
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 01795ef3966..35342de59a0 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -17,7 +17,6 @@ use crate::check::TupleArgumentsFlag::DontTupleArguments;
 use crate::type_error_struct;
 use crate::util::common::ErrorReported;
 
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::middle::lang_items;
@@ -28,6 +27,7 @@ use rustc::ty::Ty;
 use rustc::ty::TypeFoldable;
 use rustc::ty::{AdtKind, Visibility};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 2b731947aa0..0441514c83c 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -3,11 +3,11 @@
 
 use crate::require_same_types;
 
-use errors::struct_span_err;
 use rustc::traits::{ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::abi::Abi;
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index e9356a04c01..711c285d17e 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -12,7 +12,6 @@ pub use self::MethodError::*;
 
 use crate::check::FnCtxt;
 use crate::namespace::Namespace;
-use errors::{Applicability, DiagnosticBuilder};
 use rustc::infer::{self, InferOk};
 use rustc::traits;
 use rustc::ty::subst::Subst;
@@ -20,6 +19,7 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::GenericParamDefKind;
 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable};
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind};
 use rustc_hir::def_id::DefId;
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4f0467b78b2..b2542cc27a5 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -9,7 +9,6 @@ use crate::hir::def::DefKind;
 use crate::hir::def_id::DefId;
 use crate::namespace::Namespace;
 
-use errors::struct_span_err;
 use rustc::infer::canonical::OriginalQueryValues;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -29,6 +28,7 @@ use rustc::ty::{
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
 use std::cmp::max;
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 4f55d9ab70e..b84e1d37b06 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -4,7 +4,6 @@
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
 use crate::namespace::Namespace;
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::hir::map as hir_map;
 use rustc::hir::map::Map;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -12,6 +11,7 @@ use rustc::traits::Obligation;
 use rustc::ty::print::with_crate_prefix;
 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -360,10 +360,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             tcx.sess,
                             span,
                             E0599,
-                            "no {} named `{}` found for type `{}` in the current scope",
+                            "no {} named `{}` found for {} `{}` in the current scope",
                             item_kind,
                             item_name,
-                            ty_str
+                            actual.prefix_string(),
+                            ty_str,
                         );
                         if let Some(span) =
                             tcx.sess.confused_type_with_std_module.borrow().get(&span)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 5e73f8e3e12..dea1be7641a 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -90,7 +90,6 @@ pub mod writeback;
 use crate::astconv::{AstConv, PathSeg};
 use crate::middle::lang_items;
 use crate::namespace::Namespace;
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::hir::map::Map;
 use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
@@ -100,6 +99,7 @@ use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc::infer::{self, InferCtxt, InferOk, InferResult};
 use rustc::middle::region;
 use rustc::mir::interpret::ConstValue;
+use rustc::session::parse::feature_err;
 use rustc::traits::error_reporting::recursive_type_with_infinite_size_error;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::adjustment::{
@@ -116,6 +116,7 @@ use rustc::ty::{
 };
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
@@ -130,7 +131,6 @@ use rustc_span::{self, BytePos, MultiSpan, Span};
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::feature_gate::feature_err;
 use syntax::util::parser::ExprPrecedence;
 
 use rustc_error_codes::*;
@@ -164,7 +164,7 @@ macro_rules! type_error_struct {
         if $typ.references_error() {
             $session.diagnostic().struct_dummy()
         } else {
-            errors::struct_span_err!($session, $span, $code, $($message)*)
+            rustc_errors::struct_span_err!($session, $span, $code, $($message)*)
         }
     })
 }
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index d746b974727..edf9d19dea3 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -2,11 +2,11 @@
 
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs};
-use errors::{self, struct_span_err, Applicability};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint};
 use rustc::ty::{self, Ty, TypeFoldable};
+use rustc_errors::{self, struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_span::Span;
 use syntax::ast::Ident;
@@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                             lhs_expr.span,
                                             msg,
                                             format!("*{}", lstring),
-                                            errors::Applicability::MachineApplicable,
+                                            rustc_errors::Applicability::MachineApplicable,
                                         );
                                         suggested_deref = true;
                                     }
@@ -482,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// suggest calling the function. Returns wether a suggestion was given.
     fn add_type_neq_err_label(
         &self,
-        err: &mut errors::DiagnosticBuilder<'_>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_>,
         span: Span,
         ty: Ty<'tcx>,
         other_ty: Ty<'tcx>,
@@ -565,7 +565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rhs_expr: &'tcx hir::Expr<'tcx>,
         lhs_ty: Ty<'tcx>,
         rhs_ty: Ty<'tcx>,
-        err: &mut errors::DiagnosticBuilder<'_>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_>,
         is_assign: bool,
         op: hir::BinOp,
     ) -> bool {
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 58c722f1da6..1478b35a25d 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1,11 +1,11 @@
 use crate::check::FnCtxt;
-use errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Pattern;
 use rustc::ty::subst::GenericArg;
 use rustc::ty::{self, BindingMode, Ty, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -135,12 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = match pat.kind {
             PatKind::Wild => expected,
             PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
-            PatKind::Range(begin, end, _) => {
-                match self.check_pat_range(pat.span, begin, end, expected, ti) {
-                    None => return,
-                    Some(ty) => ty,
-                }
-            }
+            PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
             PatKind::Binding(ba, var_id, _, sub) => {
                 self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti)
             }
@@ -395,39 +390,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_range(
         &self,
         span: Span,
-        lhs: &'tcx hir::Expr<'tcx>,
-        rhs: &'tcx hir::Expr<'tcx>,
+        lhs: Option<&'tcx hir::Expr<'tcx>>,
+        rhs: Option<&'tcx hir::Expr<'tcx>>,
         expected: Ty<'tcx>,
         ti: TopInfo<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        let lhs_ty = self.check_expr(lhs);
-        let rhs_ty = self.check_expr(rhs);
-
-        // Check that both end-points are of numeric or char type.
-        let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char() || ty.references_error();
-        let lhs_fail = !numeric_or_char(lhs_ty);
-        let rhs_fail = !numeric_or_char(rhs_ty);
-
-        if lhs_fail || rhs_fail {
-            self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
-            return None;
+    ) -> Ty<'tcx> {
+        let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
+            None => (None, None),
+            Some(expr) => {
+                let ty = self.check_expr(expr);
+                // Check that the end-point is of numeric or char type.
+                let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error());
+                (Some(ty), Some((fail, ty, expr.span)))
+            }
+        };
+        let (lhs_ty, lhs) = calc_side(lhs);
+        let (rhs_ty, rhs) = calc_side(rhs);
+
+        if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
+            // There exists a side that didn't meet our criteria that the end-point
+            // be of a numeric or char type, as checked in `calc_side` above.
+            self.emit_err_pat_range(span, lhs, rhs);
+            return self.tcx.types.err;
         }
 
-        // Now that we know the types can be unified we find the unified type and use
-        // it to type the entire expression.
-        let common_type = self.resolve_vars_if_possible(&lhs_ty);
+        // Now that we know the types can be unified we find the unified type
+        // and use it to type the entire expression.
+        let common_type = self.resolve_vars_if_possible(&lhs_ty.or(rhs_ty).unwrap_or(expected));
 
         // Subtyping doesn't matter here, as the value is some kind of scalar.
-        let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
-            self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
-                self.endpoint_has_type(&mut err, y_span, y_ty);
-                err.emit();
-            });
+        let demand_eqtype = |x, y| {
+            if let Some((_, x_ty, x_span)) = x {
+                self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
+                    if let Some((_, y_ty, y_span)) = y {
+                        self.endpoint_has_type(&mut err, y_span, y_ty);
+                    }
+                    err.emit();
+                });
+            }
         };
-        demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty);
-        demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty);
+        demand_eqtype(lhs, rhs);
+        demand_eqtype(rhs, lhs);
 
-        Some(common_type)
+        common_type
     }
 
     fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
@@ -439,21 +444,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn emit_err_pat_range(
         &self,
         span: Span,
-        begin_span: Span,
-        end_span: Span,
-        lhs_fail: bool,
-        rhs_fail: bool,
-        lhs_ty: Ty<'tcx>,
-        rhs_ty: Ty<'tcx>,
+        lhs: Option<(bool, Ty<'tcx>, Span)>,
+        rhs: Option<(bool, Ty<'tcx>, Span)>,
     ) {
-        let span = if lhs_fail && rhs_fail {
-            span
-        } else if lhs_fail {
-            begin_span
-        } else {
-            end_span
+        let span = match (lhs, rhs) {
+            (Some((true, ..)), Some((true, ..))) => span,
+            (Some((true, _, sp)), _) => sp,
+            (_, Some((true, _, sp))) => sp,
+            _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"),
         };
-
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
@@ -461,17 +460,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             "only char and numeric types are allowed in range patterns"
         );
         let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
-        let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
+        let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
             err.span_label(first_span, &msg(first_ty));
-            self.endpoint_has_type(&mut err, second_span, second_ty);
+            if let Some((_, ty, sp)) = second {
+                self.endpoint_has_type(&mut err, sp, ty);
+            }
         };
-        if lhs_fail && rhs_fail {
-            err.span_label(begin_span, &msg(lhs_ty));
-            err.span_label(end_span, &msg(rhs_ty));
-        } else if lhs_fail {
-            one_side_err(begin_span, lhs_ty, end_span, rhs_ty);
-        } else {
-            one_side_err(end_span, rhs_ty, begin_span, lhs_ty);
+        match (lhs, rhs) {
+            (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => {
+                err.span_label(lhs_sp, &msg(lhs_ty));
+                err.span_label(rhs_sp, &msg(rhs_ty));
+            }
+            (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs),
+            (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
+            _ => span_bug!(span, "Impossible, verified above."),
         }
         if self.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index c57eb672189..a496a6e12ce 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -1,19 +1,19 @@
 use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
-use errors::{struct_span_err, DiagnosticBuilder};
 use rustc::infer::opaque_types::may_define_opaque_type;
 use rustc::middle::lang_items;
+use rustc::session::parse::feature_err;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
-use syntax::feature_gate;
 
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
@@ -821,7 +821,7 @@ fn check_method_receiver<'fcx, 'tcx>(
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
             if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
                 // Report error; would have worked with `arbitrary_self_types`.
-                feature_gate::feature_err(
+                feature_err(
                     &fcx.tcx.sess.parse_sess,
                     sym::arbitrary_self_types,
                     span,
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index ab8e4ce6975..ec098c1d896 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -1,15 +1,13 @@
 use crate::lint;
 use rustc::ty::TyCtxt;
-
-use errors::Applicability;
-use rustc_span::Span;
-use syntax::ast;
-
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::visibility_qualified;
+use rustc_span::Span;
+use syntax::ast;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports = DefIdSet::default();
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 5af5acda143..8b3db15c02b 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -1,7 +1,6 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
-use errors::struct_span_err;
 use rustc::infer;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::SuppressRegionErrors;
@@ -14,6 +13,7 @@ use rustc::ty::adjustment::CoerceUnsizedInfo;
 use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 73d03f92447..673c1bd9fd8 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -7,8 +7,8 @@
 //! `tcx.inherent_impls(def_id)`). That value, however,
 //! is computed by selecting an idea from this table.
 
-use errors::struct_span_err;
 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 01d2f528d45..a9228c7f6bb 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -1,7 +1,7 @@
 use crate::namespace::Namespace;
-use errors::struct_span_err;
 use rustc::traits::{self, IntercrateMode};
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index ca10601f413..fd685e77b41 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -5,14 +5,13 @@
 // done by the orphan and overlap modules. Then we build up various
 // mappings. That mapping code resides here.
 
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
-use crate::hir::HirId;
-use errors::struct_span_err;
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
-
 use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::HirId;
 
 mod builtin;
 mod inherent_impls;
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index cf9935143b2..1878f9385a8 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -1,9 +1,9 @@
 //! Orphan checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use errors::struct_span_err;
 use rustc::traits;
 use rustc::ty::{self, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 9257aa759b4..3f4035b0998 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -1,8 +1,8 @@
 //! Unsafety checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use errors::struct_span_err;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Unsafety;
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3bb06d76349..ad750d5ab83 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -20,10 +20,10 @@ use crate::constrained_generic_params as cgp;
 use crate::lint;
 use crate::middle::resolve_lifetime as rl;
 use crate::middle::weak_lang_items;
-use errors::{struct_span_err, Applicability, StashKey};
 use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
+use rustc::session::parse::feature_err;
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::GenericArgKind;
@@ -34,6 +34,7 @@ use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::{ReprOptions, ToPredicate};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, Applicability, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -45,7 +46,6 @@ use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
-use syntax::feature_gate;
 
 use rustc_error_codes::*;
 
@@ -255,7 +255,7 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
 fn bad_placeholder_type(
     tcx: TyCtxt<'tcx>,
     mut spans: Vec<Span>,
-) -> errors::DiagnosticBuilder<'tcx> {
+) -> rustc_errors::DiagnosticBuilder<'tcx> {
     spans.sort();
     let mut err = struct_span_err!(
         tcx.sess,
@@ -1537,7 +1537,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         _ => None,
                     };
                     if let Some(unsupported_type) = err {
-                        feature_gate::feature_err(
+                        feature_err(
                             &tcx.sess.parse_sess,
                             sym::const_compare_raw_pointers,
                             hir_ty.span,
@@ -2633,7 +2633,7 @@ fn from_target_feature(
                 None => true,
             };
             if !allowed && id.is_local() {
-                feature_gate::feature_err(
+                feature_err(
                     &tcx.sess.parse_sess,
                     feature_gate.unwrap(),
                     item.span(),
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index e3e61ebb936..fb87b285fa2 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -9,10 +9,10 @@
 //! fixed, but for the moment it's easier to do these checks early.
 
 use crate::constrained_generic_params as cgp;
-use errors::struct_span_err;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 0d9940cbf92..b951883ac19 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -91,7 +91,6 @@ mod outlives;
 mod structured_errors;
 mod variance;
 
-use errors::struct_span_err;
 use rustc::infer::InferOk;
 use rustc::lint;
 use rustc::middle;
@@ -103,6 +102,7 @@ use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util;
 use rustc::util::common::ErrorReported;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index b693743e474..908429c8dc4 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -1,5 +1,5 @@
-use errors::struct_span_err;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs
index dc6c45b4184..068814723f5 100644
--- a/src/librustc_typeck/structured_errors.rs
+++ b/src/librustc_typeck/structured_errors.rs
@@ -1,6 +1,6 @@
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::session::Session;
 use rustc::ty::{Ty, TypeFoldable};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_span::Span;
 
 use rustc_error_codes::*;
@@ -50,7 +50,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
     }
 
     fn code(&self) -> DiagnosticId {
-        errors::error_code!(E0617)
+        rustc_errors::error_code!(E0617)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
@@ -111,7 +111,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
     }
 
     fn code(&self) -> DiagnosticId {
-        errors::error_code!(E0607)
+        rustc_errors::error_code!(E0607)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs
index 860bfe79395..2f41bee1819 100644
--- a/src/librustc_typeck/variance/test.rs
+++ b/src/librustc_typeck/variance/test.rs
@@ -1,5 +1,5 @@
-use errors::struct_span_err;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index c8f1dff703f..5d8e27ecadb 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -497,7 +497,7 @@ impl Attributes {
         false
     }
 
-    pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
+    pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
         let mut doc_strings = vec![];
         let mut sp = None;
         let mut cfg = Cfg::True;
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 26b49d2f962..22f5d0dc2c0 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -3,7 +3,6 @@ use std::ffi::OsStr;
 use std::fmt;
 use std::path::PathBuf;
 
-use errors;
 use getopts;
 use rustc::lint::Level;
 use rustc::session;
@@ -566,7 +565,7 @@ impl Options {
 }
 
 /// Prints deprecation warnings for deprecated options
-fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) {
+fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Handler) {
     let deprecated_flags = ["input-format", "output-format", "no-defaults", "passes"];
 
     for flag in deprecated_flags.iter() {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index be7f7ea364f..3cda1b3be75 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -15,8 +15,8 @@ use rustc_interface::interface;
 use rustc_lint;
 use rustc_resolve as resolve;
 
-use errors::emitter::{Emitter, EmitterWriter};
-use errors::json::JsonEmitter;
+use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::json::JsonEmitter;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
@@ -171,7 +171,7 @@ pub fn new_handler(
     error_format: ErrorOutputType,
     source_map: Option<Lrc<source_map::SourceMap>>,
     debugging_opts: &DebuggingOptions,
-) -> errors::Handler {
+) -> rustc_errors::Handler {
     let emitter: Box<dyn Emitter + sync::Send> = match error_format {
         ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -198,7 +198,10 @@ pub fn new_handler(
         }
     };
 
-    errors::Handler::with_emitter_and_flags(emitter, debugging_opts.diagnostic_handler_flags(true))
+    rustc_errors::Handler::with_emitter_and_flags(
+        emitter,
+        debugging_opts.diagnostic_handler_flags(true),
+    )
 }
 
 pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) {
@@ -409,7 +412,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
 
                 let mut krate = clean::krate(&mut ctxt);
 
-                fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
+                fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) {
                     let mut msg = diag.struct_warn(&format!(
                         "the `#![doc({})]` attribute is \
                                                          considered deprecated",
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 2a107e828f7..ecc394a2bc9 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -9,8 +9,6 @@
 //! needs to read-after-write from a file, then it would be added to this
 //! abstraction.
 
-use errors;
-
 use std::fs;
 use std::io;
 use std::path::Path;
@@ -42,7 +40,7 @@ impl ErrorStorage {
     }
 
     /// Prints all stored errors. Returns the number of printed errors.
-    pub fn write_errors(&mut self, diag: &errors::Handler) -> usize {
+    pub fn write_errors(&mut self, diag: &rustc_errors::Handler) -> usize {
         let mut printed = 0;
         // In order to drop the sender part of the channel.
         self.sender = None;
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index e0ed02c11c7..8b5a3a2ba61 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -1,6 +1,5 @@
 use crate::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};
 use crate::rustc_span::edition::Edition;
-use errors;
 use rustc_feature::UnstableFeatures;
 use std::fs;
 use std::path::Path;
@@ -26,7 +25,7 @@ impl ExternalHtml {
         after_content: &[String],
         md_before_content: &[String],
         md_after_content: &[String],
-        diag: &errors::Handler,
+        diag: &rustc_errors::Handler,
         id_map: &mut IdMap,
         edition: Edition,
         playground: &Option<Playground>,
@@ -58,7 +57,7 @@ pub enum LoadStringError {
 
 pub fn load_string<P: AsRef<Path>>(
     file_path: P,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
 ) -> Result<String, LoadStringError> {
     let file_path = file_path.as_ref();
     let contents = match fs::read(file_path) {
@@ -77,7 +76,7 @@ pub fn load_string<P: AsRef<Path>>(
     }
 }
 
-fn load_external_files(names: &[String], diag: &errors::Handler) -> Option<String> {
+fn load_external_files(names: &[String], diag: &rustc_errors::Handler) -> Option<String> {
     let mut out = String::new();
     for name in names {
         let s = match load_string(name, diag) {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index a01e2f79394..2d932eb7668 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -42,7 +42,6 @@ use std::rc::Rc;
 use std::str;
 use std::sync::Arc;
 
-use errors;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
 use rustc_data_structures::flock;
@@ -394,7 +393,7 @@ pub fn run(
     mut krate: clean::Crate,
     options: RenderOptions,
     renderinfo: RenderInfo,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
     edition: Edition,
 ) -> Result<(), Error> {
     // need to save a copy of the options for rendering the index page
@@ -528,7 +527,7 @@ fn write_shared(
     krate: &clean::Crate,
     search_index: String,
     options: &RenderOptions,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
 ) -> Result<(), Error> {
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 91150899877..b15dae452ff 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -24,6 +24,7 @@ extern crate rustc;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_error_codes;
+extern crate rustc_errors;
 extern crate rustc_expand;
 extern crate rustc_feature;
 extern crate rustc_hir;
@@ -42,7 +43,6 @@ extern crate syntax;
 extern crate test as testing;
 #[macro_use]
 extern crate log;
-extern crate rustc_errors as errors;
 
 use std::default::Default;
 use std::env;
@@ -518,6 +518,6 @@ where
 
     match result {
         Ok(output) => output,
-        Err(_) => panic::resume_unwind(Box::new(errors::FatalErrorMarker)),
+        Err(_) => panic::resume_unwind(Box::new(rustc_errors::FatalErrorMarker)),
     }
 }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 69aa248aa8e..912a40722b8 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -2,7 +2,6 @@ use std::fs::File;
 use std::io::prelude::*;
 use std::path::PathBuf;
 
-use errors;
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::DUMMY_SP;
@@ -39,7 +38,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
 pub fn render(
     input: PathBuf,
     options: RenderOptions,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
     edition: Edition,
 ) -> i32 {
     let mut output = options.output;
@@ -128,7 +127,7 @@ pub fn render(
 }
 
 /// Runs any tests/code examples in the markdown file `input`.
-pub fn test(mut options: Options, diag: &errors::Handler) -> i32 {
+pub fn test(mut options: Options, diag: &rustc_errors::Handler) -> i32 {
     let input_str = match load_string(&options.input, diag) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 79548eb6d64..0bab4423b3d 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -1,5 +1,5 @@
-use errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
 use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
 use rustc_parse::lexer::StringReader as Lexer;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::{FileName, InnerSpan};
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index b1cd3deecb4..50d5f70f488 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,6 +1,6 @@
-use errors::Applicability;
 use rustc::lint;
 use rustc::ty;
+use rustc_errors::Applicability;
 use rustc_expand::base::SyntaxExtensionKind;
 use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 94e31108901..cc5359b53d1 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -389,8 +389,8 @@ pub fn make_test(
     // crate already is included.
     let result = rustc_driver::catch_fatal_errors(|| {
         with_globals(edition, || {
-            use errors::emitter::EmitterWriter;
-            use errors::Handler;
+            use rustc_errors::emitter::EmitterWriter;
+            use rustc_errors::Handler;
             use rustc_parse::maybe_new_parser_from_source_str;
             use rustc_span::source_map::FilePathMapping;
             use syntax::sess::ParseSess;
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index b45531d7252..af1c50acb0a 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -3,7 +3,7 @@ use std::fs;
 use std::hash::{Hash, Hasher};
 use std::path::Path;
 
-use errors::Handler;
+use rustc_errors::Handler;
 
 #[cfg(test)]
 mod tests;
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index a22e162bbff..c9ff93eac02 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -34,16 +34,6 @@ features = [ "rustc-dep-of-std" ] # enable build support for integrating into li
 [dev-dependencies]
 rand = "0.7"
 
-[target.x86_64-apple-darwin.dependencies]
-rustc_asan = { path = "../librustc_asan" }
-rustc_tsan = { path = "../librustc_tsan" }
-
-[target.x86_64-unknown-linux-gnu.dependencies]
-rustc_asan = { path = "../librustc_asan" }
-rustc_lsan = { path = "../librustc_lsan" }
-rustc_msan = { path = "../librustc_msan" }
-rustc_tsan = { path = "../librustc_tsan" }
-
 [target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 
diff --git a/src/libstd/sys/hermit/os.rs b/src/libstd/sys/hermit/os.rs
index 5999fdd4f8d..78eabf8f81e 100644
--- a/src/libstd/sys/hermit/os.rs
+++ b/src/libstd/sys/hermit/os.rs
@@ -6,7 +6,6 @@ use crate::io;
 use crate::marker::PhantomData;
 use crate::memchr;
 use crate::path::{self, PathBuf};
-use crate::ptr;
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
@@ -77,13 +76,17 @@ pub fn init_environment(env: *const *const i8) {
     unsafe {
         ENV = Some(Mutex::new(HashMap::new()));
 
+        if env.is_null() {
+            return;
+        }
+
         let mut guard = ENV.as_ref().unwrap().lock().unwrap();
         let mut environ = env;
-        while environ != ptr::null() && *environ != ptr::null() {
+        while !(*environ).is_null() {
             if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 guard.insert(key, value);
             }
-            environ = environ.offset(1);
+            environ = environ.add(1);
         }
     }
 
diff --git a/src/libstd/sys/hermit/thread_local.rs b/src/libstd/sys/hermit/thread_local.rs
index ba967c7676c..c6f8adb2162 100644
--- a/src/libstd/sys/hermit/thread_local.rs
+++ b/src/libstd/sys/hermit/thread_local.rs
@@ -18,14 +18,14 @@ static KEYS_LOCK: Mutex = Mutex::new();
 static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
 
 unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
-    if KEYS == ptr::null_mut() {
+    if KEYS.is_null() {
         KEYS = Box::into_raw(Box::new(BTreeMap::new()));
     }
     &mut *KEYS
 }
 
 unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
-    if LOCALS == ptr::null_mut() {
+    if LOCALS.is_null() {
         LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
     }
     &mut *LOCALS
diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs
index 81a766e367d..2b0485c4f03 100644
--- a/src/libstd/sys/sgx/abi/tls.rs
+++ b/src/libstd/sys/sgx/abi/tls.rs
@@ -70,7 +70,7 @@ impl<'a> Drop for ActiveTls<'a> {
             any_non_null_dtor = false;
             for (value, dtor) in TLS_KEY_IN_USE.iter().filter_map(&value_with_destructor) {
                 let value = value.replace(ptr::null_mut());
-                if value != ptr::null_mut() {
+                if !value.is_null() {
                     any_non_null_dtor = true;
                     unsafe { dtor(value) }
                 }
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index b277b3d5899..91f7d1524cc 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -480,11 +480,13 @@ pub fn env() -> Env {
         let _guard = env_lock();
         let mut environ = *environ();
         let mut result = Vec::new();
-        while environ != ptr::null() && *environ != ptr::null() {
-            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                result.push(key_value);
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
             }
-            environ = environ.offset(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs
index d4219154499..1fadf716135 100644
--- a/src/libstd/sys/vxworks/os.rs
+++ b/src/libstd/sys/vxworks/os.rs
@@ -7,7 +7,6 @@ use crate::marker::PhantomData;
 use crate::mem;
 use crate::memchr;
 use crate::path::{self, Path, PathBuf};
-use crate::ptr;
 use crate::slice;
 use crate::str;
 use crate::sys::cvt;
@@ -226,15 +225,15 @@ pub fn env() -> Env {
     unsafe {
         let _guard = env_lock();
         let mut environ = *environ();
-        if environ == ptr::null() {
+        if environ.is_null() {
             panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error());
         }
         let mut result = Vec::new();
-        while *environ != ptr::null() {
+        while !(*environ).is_null() {
             if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 result.push(key_value);
             }
-            environ = environ.offset(1);
+            environ = environ.add(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs
index 3baec6bf099..8052c0aa8a8 100644
--- a/src/libstd/sys/wasi/os.rs
+++ b/src/libstd/sys/wasi/os.rs
@@ -6,7 +6,6 @@ use crate::io;
 use crate::marker::PhantomData;
 use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::ptr;
 use crate::str;
 use crate::sys::memchr;
 use crate::sys::{unsupported, Void};
@@ -107,11 +106,13 @@ pub fn env() -> Env {
         let _guard = env_lock();
         let mut environ = libc::environ;
         let mut result = Vec::new();
-        while environ != ptr::null_mut() && *environ != ptr::null_mut() {
-            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                result.push(key_value);
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
             }
-            environ = environ.offset(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index c5354671c98..cc4ae405906 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -43,7 +43,7 @@ pub fn error_string(mut errnum: i32) -> String {
             ];
             module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
 
-            if module != ptr::null_mut() {
+            if !module.is_null() {
                 errnum ^= c::FACILITY_NT_BIT as i32;
                 flags = c::FORMAT_MESSAGE_FROM_HMODULE;
             }
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index e4f0398fb42..7d9f715e9fe 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -13,8 +13,8 @@ doctest = false
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 log = "0.4"
 scoped-tls = "1.0"
+rustc_errors = { path = "../librustc_errors" }
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1d3bb7d8768..33acba8eba0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -649,7 +649,7 @@ pub enum PatKind {
     Lit(P<Expr>),
 
     /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
-    Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
+    Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
 
     /// A slice pattern `[a, b, c]`.
     Slice(Vec<P<Pat>>),
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index b308d479545..70f4f47621a 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -2,11 +2,10 @@
 
 use super::{mark_used, MetaItemKind};
 use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
-use crate::feature_gate::feature_err;
 use crate::print::pprust;
-use crate::sess::ParseSess;
+use crate::sess::{feature_err, ParseSess};
 
-use errors::{struct_span_err, Applicability, Handler};
+use rustc_errors::{struct_span_err, Applicability, Handler};
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
 use rustc_macros::HashStable_Generic;
 use rustc_span::hygiene::Transparency;
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 8449b61f7b0..ec05dab451a 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -384,7 +384,7 @@ pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> {
 
 pub fn allow_internal_unstable<'a>(
     attrs: &[Attribute],
-    span_diagnostic: &'a errors::Handler,
+    span_diagnostic: &'a rustc_errors::Handler,
 ) -> Option<impl Iterator<Item = Symbol> + 'a> {
     find_by_name(attrs, sym::allow_internal_unstable).and_then(|attr| {
         attr.meta_item_list()
diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs
deleted file mode 100644
index 7724107888a..00000000000
--- a/src/libsyntax/early_buffered_lints.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! Allows the buffering of lints for later.
-//!
-//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat
-//! redundant. Later, these types can be converted to types for use by the rest of the compiler.
-
-use rustc_session::declare_lint;
-pub use rustc_session::lint::BufferedEarlyLint;
-use rustc_session::lint::FutureIncompatibleInfo;
-
-declare_lint! {
-    pub ILL_FORMED_ATTRIBUTE_INPUT,
-    Deny,
-    "ill-formed attribute inputs that were previously accepted and used in practice",
-    @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
-        edition: None,
-    };
-}
-
-declare_lint! {
-    pub META_VARIABLE_MISUSE,
-    Allow,
-    "possible meta-variable misuse at macro definition"
-}
-
-declare_lint! {
-    pub INCOMPLETE_INCLUDE,
-    Deny,
-    "trailing content in included file"
-}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index b197eab7394..a96fee0cf8f 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -18,7 +18,6 @@
 #![recursion_limit = "256"]
 
 use ast::AttrId;
-pub use errors;
 use rustc_data_structures::sync::Lock;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
@@ -76,13 +75,8 @@ pub mod ast;
 pub mod attr;
 pub mod entry;
 pub mod expand;
-pub mod feature_gate {
-    mod check;
-    pub use check::{check_attribute, check_crate, feature_err, feature_err_issue, get_features};
-}
 pub mod mut_visit;
 pub mod ptr;
-pub mod show_span;
 pub use rustc_session::parse as sess;
 pub mod token;
 pub mod tokenstream;
@@ -94,8 +88,6 @@ pub mod print {
     pub mod pprust;
 }
 
-pub mod early_buffered_lints;
-
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 264ba25cede..58d4e46111b 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -1075,8 +1075,8 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
         PatKind::Box(inner) => vis.visit_pat(inner),
         PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
         PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
-            vis.visit_expr(e1);
-            vis.visit_expr(e2);
+            visit_opt(e1, |e| vis.visit_expr(e));
+            visit_opt(e2, |e| vis.visit_expr(e));
             vis.visit_span(span);
         }
         PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index dd9976510dc..11c8cb8ef75 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2329,14 +2329,18 @@ impl<'a> State<'a> {
             }
             PatKind::Lit(ref e) => self.print_expr(&**e),
             PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
-                self.print_expr(begin);
-                self.s.space();
+                if let Some(e) = begin {
+                    self.print_expr(e);
+                    self.s.space();
+                }
                 match *end_kind {
                     RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."),
                     RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="),
                     RangeEnd::Excluded => self.s.word(".."),
                 }
-                self.print_expr(end);
+                if let Some(e) = end {
+                    self.print_expr(e);
+                }
             }
             PatKind::Slice(ref elts) => {
                 self.s.word("[");
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ebb49abebb0..3c2ebacbc4e 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -492,8 +492,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound);
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild | PatKind::Rest => {}
         PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => {
diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile
index 3a377c32993..7f5e9049b2f 100644
--- a/src/test/run-make-fulldeps/sanitizer-address/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile
@@ -23,7 +23,7 @@ endif
 endif
 
 all:
-	$(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan
+	$(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) rustc_rt.asan
 	# Verify that stack buffer overflow is detected:
 	$(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow
 	# Verify that variable name is included in address sanitizer report:
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile
deleted file mode 100644
index 9581ac565ea..00000000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# needs-sanitizer-support
-
--include ../tools.mk
-
-# NOTE the address sanitizer only supports x86_64 linux and macOS
-
-ifeq ($(TARGET),x86_64-apple-darwin)
-EXTRA_RUSTFLAG=-C rpath
-else
-ifeq ($(TARGET),x86_64-unknown-linux-gnu)
-EXTRA_RUSTFLAG=
-endif
-endif
-
-all:
-	$(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | $(CGREP) '-Z sanitizer'
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs
deleted file mode 100644
index e7a11a969c0..00000000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    println!("Hello, world!");
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
index df8afee15ce..2a23f0fe3d4 100644
--- a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
@@ -2,4 +2,4 @@
 
 all:
 	$(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \
-		$(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` target'
+		$(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target'
diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile
index 101e8272ab9..d8598b8ac93 100644
--- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile
@@ -7,5 +7,5 @@
 # FIXME(#46126) ThinLTO for libstd broke this test
 
 all:
-	$(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_lsan
+	$(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) rustc_rt.lsan
 	$(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks'
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile
index f5787903a2b..8bc9df1b4ba 100644
--- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-memory/Makefile
@@ -5,7 +5,7 @@
 # only-x86_64
 
 all:
-	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan
+	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) rustc_rt.msan
 	$(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value
-	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) librustc_msan
+	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) rustc_rt.msan
 	$(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value
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 7ce2a1dd9a6..8d9cbe45fc6 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,9 +6,8 @@
 extern crate rustc;
 extern crate rustc_session;
 
-use rustc::lint::{LintArray, LintPass};
-use rustc::{declare_lint_pass, impl_lint_pass};
-use rustc_session::declare_lint;
+use rustc_session::lint::{LintArray, LintPass};
+use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 
 declare_lint! {
     pub TEST_LINT,
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 ad8670c6c83..39ac0019aac 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
@@ -1,5 +1,5 @@
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:21:6
+  --> $DIR/lint_pass_impl_without_macro.rs:20:6
    |
 LL | impl LintPass for Foo {
    |      ^^^^^^^^
@@ -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:31:14
+  --> $DIR/lint_pass_impl_without_macro.rs:30:14
    |
 LL |         impl LintPass for Custom {
    |              ^^^^^^^^
diff --git a/src/test/ui/associated-const/associated-const-no-item.rs b/src/test/ui/associated-const/associated-const-no-item.rs
index 35fb662f63a..024d14e21b5 100644
--- a/src/test/ui/associated-const/associated-const-no-item.rs
+++ b/src/test/ui/associated-const/associated-const-no-item.rs
@@ -3,7 +3,7 @@ trait Foo {
 }
 
 const X: i32 = <i32>::ID;
-//~^ ERROR no associated item named `ID` found for type `i32`
+//~^ ERROR no associated item named `ID` found
 
 fn main() {
     assert_eq!(1, X);
diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr
index 5a62b9736de..6f89530eac9 100644
--- a/src/test/ui/associated-item/associated-item-enum.stderr
+++ b/src/test/ui/associated-item/associated-item-enum.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `mispellable` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `mispellable` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:17:11
    |
 LL | enum Enum { Variant }
@@ -10,7 +10,7 @@ LL |     Enum::mispellable();
    |           variant or associated item not found in `Enum`
    |           help: there is a method with a similar name: `misspellable`
 
-error[E0599]: no variant or associated item named `mispellable_trait` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:18:11
    |
 LL | enum Enum { Variant }
@@ -19,7 +19,7 @@ LL | enum Enum { Variant }
 LL |     Enum::mispellable_trait();
    |           ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum`
 
-error[E0599]: no variant or associated item named `MISPELLABLE` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:19:11
    |
 LL | enum Enum { Variant }
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index 3e36f2402a9..a0739a7a90b 100644
--- a/src/test/ui/auto-ref-slice-plus-ref.stderr
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}>` in the current scope
+error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
@@ -8,7 +8,7 @@ LL |     a.test_mut();
    = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
+error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
    |
 LL |     a.test();
@@ -18,7 +18,7 @@ LL |     a.test();
    = note: the following trait defines an item `test`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `[{integer}; 1]` in the current scope
+error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:10:11
    |
 LL |     ([1]).test();
@@ -28,7 +28,7 @@ LL |     ([1]).test();
    = note: the following trait defines an item `test`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `&[{integer}; 1]` in the current scope
+error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:11:12
    |
 LL |     (&[1]).test();
diff --git a/src/test/ui/block-result/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs
index 9b313d3e9b2..0b652a1f54b 100644
--- a/src/test/ui/block-result/issue-3563.rs
+++ b/src/test/ui/block-result/issue-3563.rs
@@ -1,7 +1,7 @@
 trait A {
     fn a(&self) {
         || self.b()
-        //~^ ERROR no method named `b` found for type `&Self` in the current scope
+        //~^ ERROR no method named `b` found
     }
 }
 fn main() {}
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index 237b8c54ce3..be551f6e889 100644
--- a/src/test/ui/block-result/issue-3563.stderr
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `b` found for type `&Self` in the current scope
+error[E0599]: no method named `b` found for reference `&Self` in the current scope
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr
index 890f6800c22..cb3199e7c88 100644
--- a/src/test/ui/bogus-tag.stderr
+++ b/src/test/ui/bogus-tag.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Hsl` found for type `Color` in the current scope
+error[E0599]: no variant or associated item named `Hsl` found for enum `Color` in the current scope
   --> $DIR/bogus-tag.rs:7:16
    |
 LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
diff --git a/src/test/ui/class-cast-to-trait.stderr b/src/test/ui/class-cast-to-trait.stderr
index 4cab52e3e97..0f932cda07f 100644
--- a/src/test/ui/class-cast-to-trait.stderr
+++ b/src/test/ui/class-cast-to-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `eat` found for type `std::boxed::Box<dyn Noisy>` in the current scope
+error[E0599]: no method named `eat` found for struct `std::boxed::Box<dyn Noisy>` in the current scope
   --> $DIR/class-cast-to-trait.rs:53:8
    |
 LL |   nyan.eat();
diff --git a/src/test/ui/coherence/coherence_inherent.stderr b/src/test/ui/coherence/coherence_inherent.stderr
index e719d5254f6..3d37d8af31d 100644
--- a/src/test/ui/coherence/coherence_inherent.stderr
+++ b/src/test/ui/coherence/coherence_inherent.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the current scope
+error[E0599]: no method named `the_fn` found for reference `&Lib::TheStruct` in the current scope
   --> $DIR/coherence_inherent.rs:31:11
    |
 LL |         s.the_fn();
diff --git a/src/test/ui/coherence/coherence_inherent_cc.stderr b/src/test/ui/coherence/coherence_inherent_cc.stderr
index c666c1a3d1b..d968c8b4680 100644
--- a/src/test/ui/coherence/coherence_inherent_cc.stderr
+++ b/src/test/ui/coherence/coherence_inherent_cc.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_lib::TheStruct` in the current scope
+error[E0599]: no method named `the_fn` found for reference `&coherence_inherent_cc_lib::TheStruct` in the current scope
   --> $DIR/coherence_inherent_cc.rs:23:11
    |
 LL |         s.the_fn();
diff --git a/src/test/ui/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr
index 79ba93130a7..d6b399acb73 100644
--- a/src/test/ui/confuse-field-and-method/issue-18343.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
   --> $DIR/issue-18343.rs:7:7
    |
 LL | struct Obj<F> where F: FnMut() -> u32 {
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
index a44b9718415..f9dfdddad9d 100644
--- a/src/test/ui/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
   --> $DIR/issue-2392.rs:36:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -12,7 +12,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (o_closure.closure)();
    |     ^                 ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
   --> $DIR/issue-2392.rs:38:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -23,7 +23,7 @@ LL |     o_closure.not_closure();
    |               |
    |               field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:42:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -37,7 +37,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (o_func.closure)();
    |     ^              ^
 
-error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope
   --> $DIR/issue-2392.rs:45:14
    |
 LL | struct BoxedObj {
@@ -51,7 +51,7 @@ help: to call the function stored in `boxed_closure`, surround the field access
 LL |     (boxed_fn.boxed_closure)();
    |     ^                      ^
 
-error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope
   --> $DIR/issue-2392.rs:48:19
    |
 LL | struct BoxedObj {
@@ -65,7 +65,7 @@ help: to call the function stored in `boxed_closure`, surround the field access
 LL |     (boxed_closure.boxed_closure)();
    |     ^                           ^
 
-error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:53:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -79,7 +79,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (w.wrap.closure)();
    |     ^              ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:55:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -90,7 +90,7 @@ LL |     w.wrap.not_closure();
    |            |
    |            field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
   --> $DIR/issue-2392.rs:58:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -104,7 +104,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (check_expression().closure)();
    |     ^                          ^
 
-error[E0599]: no method named `f1` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f1` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:64:31
    |
 LL | struct FuncContainer {
@@ -118,7 +118,7 @@ help: to call the function stored in `f1`, surround the field access with parent
 LL |             ((*self.container).f1)(1);
    |             ^                    ^
 
-error[E0599]: no method named `f2` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f2` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:65:31
    |
 LL | struct FuncContainer {
@@ -132,7 +132,7 @@ help: to call the function stored in `f2`, surround the field access with parent
 LL |             ((*self.container).f2)(1);
    |             ^                    ^
 
-error[E0599]: no method named `f3` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f3` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:66:31
    |
 LL | struct FuncContainer {
diff --git a/src/test/ui/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr
index b2f7894ba05..a8d97bdfe2f 100644
--- a/src/test/ui/confuse-field-and-method/issue-32128.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `example` found for type `Example` in the current scope
+error[E0599]: no method named `example` found for struct `Example` in the current scope
   --> $DIR/issue-32128.rs:12:10
    |
 LL | struct Example {
diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr
index af29a9963e1..c109896e825 100644
--- a/src/test/ui/confuse-field-and-method/issue-33784.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
   --> $DIR/issue-33784.rs:27:7
    |
 LL |     p.closure();
@@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (p.closure)();
    |     ^         ^
 
-error[E0599]: no method named `fn_ptr` found for type `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
   --> $DIR/issue-33784.rs:29:7
    |
 LL |     q.fn_ptr();
@@ -20,7 +20,7 @@ help: to call the function stored in `fn_ptr`, surround the field access with pa
 LL |     (q.fn_ptr)();
    |     ^        ^
 
-error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scope
+error[E0599]: no method named `c_fn_ptr` found for reference `&D` in the current scope
   --> $DIR/issue-33784.rs:32:7
    |
 LL |     s.c_fn_ptr();
diff --git a/src/test/ui/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr
index 97c949e32e3..82cb235d47a 100644
--- a/src/test/ui/confuse-field-and-method/private-field.stderr
+++ b/src/test/ui/confuse-field-and-method/private-field.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `dog_age` found for type `animal::Dog` in the current scope
+error[E0599]: no method named `dog_age` found for struct `animal::Dog` in the current scope
   --> $DIR/private-field.rs:16:23
    |
 LL |     pub struct Dog {
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
index 47b090cb886..19e7d2036bf 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -4,7 +4,7 @@ error[E0107]: wrong number of const arguments: expected 0, found 1
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
    |                                  ^^ unexpected const argument
 
-error[E0599]: no method named `f` found for type `S` in the current scope
+error[E0599]: no method named `f` found for struct `S` in the current scope
   --> $DIR/invalid-const-arg-for-type-param.rs:7:7
    |
 LL | struct S;
diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr
index 2fb9977f4d7..599d1d79e75 100644
--- a/src/test/ui/consts/too_generic_eval_ice.stderr
+++ b/src/test/ui/consts/too_generic_eval_ice.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `HOST_SIZE` found for type `Foo<A, B>` in the current scope
+error[E0599]: no associated item named `HOST_SIZE` found for struct `Foo<A, B>` in the current scope
   --> $DIR/too_generic_eval_ice.rs:7:19
    |
 LL | pub struct Foo<A, B>(A, B);
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index 054bd0914d3..c95e8d239d2 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Foo` in the current scope
+error[E0599]: no method named `clone` found for struct `Foo` in the current scope
   --> $DIR/copy-a-resource.rs:18:16
    |
 LL | struct Foo {
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index 038de80508a..2083a1d6522 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Bar<NotClone>` in the current scope
+error[E0599]: no method named `clone` found for struct `Bar<NotClone>` in the current scope
   --> $DIR/derive-assoc-type-not-impl.rs:18:30
    |
 LL | struct Bar<T: Foo> {
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.rs b/src/test/ui/did_you_mean/bad-assoc-pat.rs
index 7e7ba59dca8..3f912f7ffc6 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.rs
@@ -2,25 +2,25 @@ fn main() {
     match 0u8 {
         [u8]::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `[u8]` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
         (u8, u8)::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `(u8, u8)` in the current sco
+        //~| ERROR no associated item named `AssocItem` found
         _::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `_` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
     match &0u8 {
         &(u8,)::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `(u8,)` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
 }
 
 macro_rules! pat {
     ($ty: ty) => ($ty::AssocItem)
     //~^ ERROR missing angle brackets in associated item path
-    //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+    //~| ERROR no associated item named `AssocItem` found
 }
 macro_rules! ty {
     () => (u8)
@@ -31,6 +31,6 @@ fn check_macros() {
         pat!(u8) => {}
         ty!()::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
 }
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
index 59b865437a2..3f1946b94f6 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
@@ -37,13 +37,13 @@ LL |     ($ty: ty) => ($ty::AssocItem)
 LL |         pat!(u8) => {}
    |         -------- in this macro invocation
 
-error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope
+error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope
   --> $DIR/bad-assoc-pat.rs:3:15
    |
 LL |         [u8]::AssocItem => {}
    |               ^^^^^^^^^ associated item not found in `[u8]`
 
-error[E0599]: no associated item named `AssocItem` found for type `(u8, u8)` in the current scope
+error[E0599]: no associated item named `AssocItem` found for tuple `(u8, u8)` in the current scope
   --> $DIR/bad-assoc-pat.rs:6:19
    |
 LL |         (u8, u8)::AssocItem => {}
@@ -55,7 +55,7 @@ error[E0599]: no associated item named `AssocItem` found for type `_` in the cur
 LL |         _::AssocItem => {}
    |            ^^^^^^^^^ associated item not found in `_`
 
-error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope
+error[E0599]: no associated item named `AssocItem` found for tuple `(u8,)` in the current scope
   --> $DIR/bad-assoc-pat.rs:14:17
    |
 LL |         &(u8,)::AssocItem => {}
diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs
index ea21592997b..60633c6930c 100644
--- a/src/test/ui/did_you_mean/issue-40006.rs
+++ b/src/test/ui/did_you_mean/issue-40006.rs
@@ -35,5 +35,5 @@ impl S {
 }
 
 fn main() {
-    S.hello_method(); //~ no method named `hello_method` found for type `S` in the current scope
+    S.hello_method(); //~ no method named `hello_method` found
 }
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index d1e995013cb..072e61f6a3c 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -56,7 +56,7 @@ error: missing `fn`, `type`, or `const` for associated-item declaration
 LL |     pub hello_method(&self) {
    |        ^ missing `fn`, `type`, or `const`
 
-error[E0599]: no method named `hello_method` found for type `S` in the current scope
+error[E0599]: no method named `hello_method` found for struct `S` in the current scope
   --> $DIR/issue-40006.rs:38:7
    |
 LL | struct S;
diff --git a/src/test/ui/dont-suggest-private-trait-method.rs b/src/test/ui/dont-suggest-private-trait-method.rs
index ef0904c1a2d..6e2b1abd137 100644
--- a/src/test/ui/dont-suggest-private-trait-method.rs
+++ b/src/test/ui/dont-suggest-private-trait-method.rs
@@ -2,5 +2,5 @@ struct T;
 
 fn main() {
     T::new();
-    //~^ ERROR no function or associated item named `new` found for type `T` in the current scope
+    //~^ ERROR no function or associated item named `new` found
 }
diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr
index 5189ffa62d1..fd7fdb4f722 100644
--- a/src/test/ui/dont-suggest-private-trait-method.stderr
+++ b/src/test/ui/dont-suggest-private-trait-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new` found for type `T` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `T` in the current scope
   --> $DIR/dont-suggest-private-trait-method.rs:4:8
    |
 LL | struct T;
diff --git a/src/test/ui/empty/empty-struct-braces-expr.rs b/src/test/ui/empty/empty-struct-braces-expr.rs
index 1a38d3d7601..f4144277f16 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.rs
+++ b/src/test/ui/empty/empty-struct-braces-expr.rs
@@ -22,8 +22,8 @@ fn main() {
     let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
     let xe1 = XEmpty1();
     //~^ ERROR expected function, tuple struct or tuple variant, found struct `XEmpty1`
-    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for type
-    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for type
+    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for enum
+    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for enum
 
-    XE::Empty1 {}; //~ ERROR no variant `Empty1` in enum `empty_struct::XE`
+    XE::Empty1 {}; //~ ERROR no variant named `Empty1` found for enum `empty_struct::XE`
 }
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index f427c1ba0ad..20f4c320e66 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -58,7 +58,7 @@ LL |     let xe1 = XEmpty1();
    |               did you mean `XEmpty1 { /* fields */ }`?
    |               help: a unit struct with a similar name exists: `XEmpty2`
 
-error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
@@ -67,7 +67,7 @@ LL |     let xe3 = XE::Empty3;
    |                   variant or associated item not found in `empty_struct::XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
@@ -76,7 +76,7 @@ LL |     let xe3 = XE::Empty3();
    |                   variant or associated item not found in `empty_struct::XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error: no variant `Empty1` in enum `empty_struct::XE`
+error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
   --> $DIR/empty-struct-braces-expr.rs:28:9
    |
 LL |     XE::Empty1 {};
diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr
index 89bfccf2fbc..a78a003661d 100644
--- a/src/test/ui/error-codes/E0599.stderr
+++ b/src/test/ui/error-codes/E0599.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope
+error[E0599]: no associated item named `NotEvenReal` found for struct `Foo` in the current scope
   --> $DIR/E0599.rs:4:20
    |
 LL | struct Foo;
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 73571a375b5..6b80d99b3af 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -20,7 +20,7 @@ LL |     x += 2;
    |
    = note: an implementation of `std::ops::AddAssign` might be missing for `&str`
 
-error[E0599]: no method named `z` found for type `&str` in the current scope
+error[E0599]: no method named `z` found for reference `&str` in the current scope
   --> $DIR/error-festival.rs:16:7
    |
 LL |     x.z();
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
deleted file mode 100644
index 3b972c117a6..00000000000
--- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
deleted file mode 100644
index b13ec215f8c..00000000000
--- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
-  --> $DIR/feature-gate-sanitizer-runtime.rs:1:1
-   |
-LL | #![sanitizer_runtime]
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(sanitizer_runtime)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
index d97b693f520..3f4c17836c4 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
@@ -1,10 +1,10 @@
+#![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
         [_, 99.., _] => {},
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR mismatched types
+        //~^ ERROR mismatched types
         _ => {},
     }
 }
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
index 76ae7241ff2..a6f8563a047 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -1,11 +1,5 @@
-error: `X..` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
-   |
-LL |         [_, 99.., _] => {},
-   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
-
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -15,6 +9,6 @@ LL |         [_, 99.., _] => {},
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
index 09f459c9862..dedc85491b4 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
@@ -1,10 +1,10 @@
+#![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
         [_, 99..] => {},
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR pattern requires 2 elements but array has 3
+        //~^ ERROR pattern requires 2 elements but array has 3
         //~| ERROR mismatched types
         _ => {},
     }
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 5c96f8041fe..4e0102c930d 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -1,17 +1,11 @@
-error: `X..` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
-   |
-LL |         [_, 99..] => {},
-   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
-
 error[E0527]: pattern requires 2 elements but array has 3
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:9
    |
 LL |         [_, 99..] => {},
    |         ^^^^^^^^^ expected 3 elements
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -21,7 +15,7 @@ LL |         [_, 99..] => {},
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0308, E0527.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
index 1557f592b2a..6a9b562cc3a 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
@@ -1,10 +1,10 @@
+#![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
         [..9, 99..100, _] => {},
-        //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR mismatched types
+        //~^ ERROR mismatched types
         //~| ERROR mismatched types
         //~| ERROR mismatched types
         _ => {},
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index 17e10324db1..665eef2fcb9 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -1,11 +1,5 @@
-error: `..X` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
-   |
-LL |         [..9, 99..100, _] => {},
-   |          ^^^ help: try using the minimum value for the type: `MIN..9`
-
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -16,7 +10,7 @@ LL |         [..9, 99..100, _] => {},
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -29,7 +23,7 @@ LL |         [..9, 99..100, _] => {},
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -41,6 +35,6 @@ LL |         [..9, 99..100, _] => {},
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
new file mode 100644
index 00000000000..4cb8230a7b6
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
@@ -0,0 +1,21 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn foo() {
+    if let ..=5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let ...5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let ..5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let 5.. = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let 5..= = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR inclusive range with no end
+    if let 5... = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR inclusive range with no end
+}
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
new file mode 100644
index 00000000000..68ba654de76
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
@@ -0,0 +1,74 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/feature-gate-half-open-range-patterns.rs:15:13
+   |
+LL |     if let 5..= = 0 {}
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/feature-gate-half-open-range-patterns.rs:18:13
+   |
+LL |     if let 5... = 0 {}
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:7:12
+   |
+LL |     if let ..=5 = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
+   |
+LL |     if let ...5 = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:11:12
+   |
+LL |     if let ..5 = 0 {}
+   |            ^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:13:12
+   |
+LL |     if let 5.. = 0 {}
+   |            ^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:15:12
+   |
+LL |     if let 5..= = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:18:12
+   |
+LL |     if let 5... = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0586, E0658.
+For more information about an error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
new file mode 100644
index 00000000000..7cddf5f652a
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
@@ -0,0 +1,8 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let "a".. = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let .."a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let ..="a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
new file mode 100644
index 00000000000..68ca3637150
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
@@ -0,0 +1,21 @@
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:5:9
+   |
+LL |     let "a".. = "a";
+   |         ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:6:11
+   |
+LL |     let .."a" = "a";
+   |           ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:7:12
+   |
+LL |     let ..="a" = "a";
+   |            ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
new file mode 100644
index 00000000000..b135891d0b8
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
@@ -0,0 +1,168 @@
+// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+fn main() {}
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn floats() {
+    m!(0f32, core::f32::NEG_INFINITY..); //~ ERROR non-exhaustive patterns: `_` not covered
+    m!(0f32, ..core::f32::INFINITY); //~ ERROR non-exhaustive patterns: `_` not covered
+}
+
+fn khar() {
+    const ALMOST_MAX: char = '\u{10fffe}';
+    const ALMOST_MIN: char = '\u{1}';
+    const VAL: char = 'a';
+    const VAL_1: char = 'b';
+    const VAL_2: char = 'c';
+    m!('a', ..core::char::MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+    m!('a', ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+    m!('a', ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+}
+
+mod unsigned {
+    fn u8() {
+        const ALMOST_MAX: u8 = core::u8::MAX - 1;
+        const ALMOST_MIN: u8 = core::u8::MIN + 1;
+        const VAL: u8 = 42;
+        const VAL_1: u8 = VAL + 1;
+        const VAL_2: u8 = VAL + 2;
+        m!(0, ..core::u8::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u16() {
+        const ALMOST_MAX: u16 = core::u16::MAX - 1;
+        const ALMOST_MIN: u16 = core::u16::MIN + 1;
+        const VAL: u16 = 42;
+        const VAL_1: u16 = VAL + 1;
+        const VAL_2: u16 = VAL + 2;
+        m!(0, ..core::u16::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u32() {
+        const ALMOST_MAX: u32 = core::u32::MAX - 1;
+        const ALMOST_MIN: u32 = core::u32::MIN + 1;
+        const VAL: u32 = 42;
+        const VAL_1: u32 = VAL + 1;
+        const VAL_2: u32 = VAL + 2;
+        m!(0, ..core::u32::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u64() {
+        const ALMOST_MAX: u64 = core::u64::MAX - 1;
+        const ALMOST_MIN: u64 = core::u64::MIN + 1;
+        const VAL: u64 = 42;
+        const VAL_1: u64 = VAL + 1;
+        const VAL_2: u64 = VAL + 2;
+        m!(0, ..core::u64::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u128() {
+        const ALMOST_MAX: u128 = core::u128::MAX - 1;
+        const ALMOST_MIN: u128 = core::u128::MIN + 1;
+        const VAL: u128 = 42;
+        const VAL_1: u128 = VAL + 1;
+        const VAL_2: u128 = VAL + 2;
+        m!(0, ..core::u128::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+}
+
+mod signed {
+    fn i8() {
+        const ALMOST_MAX: i8 = core::i8::MAX - 1;
+        const ALMOST_MIN: i8 = core::i8::MIN + 1;
+        const VAL: i8 = 42;
+        const VAL_1: i8 = VAL + 1;
+        const VAL_2: i8 = VAL + 2;
+        m!(0, ..core::i8::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i16() {
+        const ALMOST_MAX: i16 = core::i16::MAX - 1;
+        const ALMOST_MIN: i16 = core::i16::MIN + 1;
+        const VAL: i16 = 42;
+        const VAL_1: i16 = VAL + 1;
+        const VAL_2: i16 = VAL + 2;
+        m!(0, ..core::i16::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i32() {
+        const ALMOST_MAX: i32 = core::i32::MAX - 1;
+        const ALMOST_MIN: i32 = core::i32::MIN + 1;
+        const VAL: i32 = 42;
+        const VAL_1: i32 = VAL + 1;
+        const VAL_2: i32 = VAL + 2;
+        m!(0, ..core::i32::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i64() {
+        const ALMOST_MAX: i64 = core::i64::MAX - 1;
+        const ALMOST_MIN: i64 = core::i64::MIN + 1;
+        const VAL: i64 = 42;
+        const VAL_1: i64 = VAL + 1;
+        const VAL_2: i64 = VAL + 2;
+        m!(0, ..core::i64::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i128() {
+        const ALMOST_MAX: i128 = core::i128::MAX - 1;
+        const ALMOST_MIN: i128 = core::i128::MIN + 1;
+        const VAL: i128 = 42;
+        const VAL_1: i128 = VAL + 1;
+        const VAL_2: i128 = VAL + 2;
+        m!(0, ..core::i128::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
new file mode 100644
index 00000000000..26d0cf9e9ec
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -0,0 +1,547 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
+   |
+LL |     m!(0f32, core::f32::NEG_INFINITY..);
+   |        ^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:17:8
+   |
+LL |     m!(0f32, ..core::f32::INFINITY);
+   |        ^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
+   |
+LL |     m!('a', ..core::char::MAX);
+   |        ^^^ pattern `'\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
+   |
+LL |     m!('a', ..ALMOST_MAX);
+   |        ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
+   |
+LL |     m!('a', ALMOST_MIN..);
+   |        ^^^ pattern `'\u{0}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
+   |
+LL |     m!('a', ..=ALMOST_MAX);
+   |        ^^^ pattern `'\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'b'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
+   |
+LL |     m!('a', ..=VAL | VAL_2..);
+   |        ^^^ pattern `'b'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'b'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:31:8
+   |
+LL |     m!('a', ..VAL_1 | VAL_2..);
+   |        ^^^ pattern `'b'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
+   |
+LL |         m!(0, ..core::u8::MAX);
+   |            ^ pattern `std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `254u8..=std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `254u8..=std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:46:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
+   |
+LL |         m!(0, ..core::u16::MAX);
+   |            ^ pattern `std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `65534u16..=std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `65534u16..=std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:59:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
+   |
+LL |         m!(0, ..core::u32::MAX);
+   |            ^ pattern `std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `4294967294u32..=std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `4294967294u32..=std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:72:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
+   |
+LL |         m!(0, ..core::u64::MAX);
+   |            ^ pattern `std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `18446744073709551614u64..=std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `18446744073709551614u64..=std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:85:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
+   |
+LL |         m!(0, ..core::u128::MAX);
+   |            ^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:98:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
+   |
+LL |         m!(0, ..core::i8::MAX);
+   |            ^ pattern `std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `126i8..=std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `126i8..=std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i8::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:114:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
+   |
+LL |         m!(0, ..core::i16::MAX);
+   |            ^ pattern `std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `32766i16..=std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `32766i16..=std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i16::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:127:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
+   |
+LL |         m!(0, ..core::i32::MAX);
+   |            ^ pattern `std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `2147483646i32..=std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `2147483646i32..=std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i32::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:140:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
+   |
+LL |         m!(0, ..core::i64::MAX);
+   |            ^ pattern `std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `9223372036854775806i64..=std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `9223372036854775806i64..=std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i64::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:153:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
+   |
+LL |         m!(0, ..core::i128::MAX);
+   |            ^ pattern `std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i128::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:166:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 68 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
new file mode 100644
index 00000000000..efac0df2a43
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
@@ -0,0 +1,49 @@
+// check-pass
+
+// Test various exhaustive matches for `X..`, `..=X` and `..X` ranges.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {}
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+macro_rules! test_int {
+    ($s:expr, $min:path, $max:path) => {
+        m!($s, $min..);
+        m!($s, $min..5 | 5..);
+        m!($s, ..5 | 5..);
+        m!($s, ..=4 | 5..);
+        m!($s, ..=$max);
+        m!($s, ..$max | $max);
+        m!(($s, true), (..5, true) | (5.., true) | ($min.., false));
+    }
+}
+
+fn unsigned_int() {
+    test_int!(0u8, core::u8::MIN, core::u8::MAX);
+    test_int!(0u16, core::u16::MIN, core::u16::MAX);
+    test_int!(0u32, core::u32::MIN, core::u32::MAX);
+    test_int!(0u64, core::u64::MIN, core::u64::MAX);
+    test_int!(0u128, core::u128::MIN, core::u128::MAX);
+}
+
+fn signed_int() {
+    test_int!(0i8, core::i8::MIN, core::i8::MAX);
+    test_int!(0i16, core::i16::MIN, core::i16::MAX);
+    test_int!(0i32, core::i32::MIN, core::i32::MAX);
+    test_int!(0i64, core::i64::MIN, core::i64::MAX);
+    test_int!(0i128, core::i128::MIN, core::i128::MAX);
+}
+
+fn khar() {
+    m!('a', ..=core::char::MAX);
+    m!('a', '\u{0}'..);
+    m!('a', ..='\u{D7FF}' | '\u{E000}'..);
+    m!('a', ..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
new file mode 100644
index 00000000000..904efda903c
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
@@ -0,0 +1,54 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    m!(0, ..core::u8::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u16::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u32::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u64::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u128::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!(0, ..core::i8::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i16::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i32::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i64::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i128::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!(0f32, ..core::f32::NEG_INFINITY);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0f64, ..core::f64::NEG_INFINITY);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!('a', ..'\u{0}');
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
new file mode 100644
index 00000000000..b536e1b5548
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
@@ -0,0 +1,159 @@
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+   |
+LL |     m!(0, ..core::u8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+   |
+LL |     m!(0, ..core::u16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+   |
+LL |     m!(0, ..core::u32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+   |
+LL |     m!(0, ..core::u64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+   |
+LL |     m!(0, ..core::u128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+   |
+LL |     m!(0, ..core::i8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+   |
+LL |     m!(0, ..core::i16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+   |
+LL |     m!(0, ..core::i32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+   |
+LL |     m!(0, ..core::i64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+   |
+LL |     m!(0, ..core::i128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+   |
+LL |     m!(0f32, ..core::f32::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+   |
+LL |     m!(0f64, ..core::f64::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+   |
+LL |     m!('a', ..'\u{0}');
+   |             ^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+   |
+LL |     m!(0, ..core::u8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+   |
+LL |     m!(0, ..core::u16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+   |
+LL |     m!(0, ..core::u32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+   |
+LL |     m!(0, ..core::u64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+   |
+LL |     m!(0, ..core::u128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+   |
+LL |     m!(0, ..core::i8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+   |
+LL |     m!(0, ..core::i16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+   |
+LL |     m!(0, ..core::i32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+   |
+LL |     m!(0, ..core::i64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+   |
+LL |     m!(0, ..core::i128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+   |
+LL |     m!(0f32, ..core::f32::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+   |
+LL |     m!(0f64, ..core::f64::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+   |
+LL |     m!('a', ..'\u{0}');
+   |             ^^^^^^^^^
+
+error: aborting due to 26 previous errors
+
+For more information about this error, try `rustc --explain E0579`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
new file mode 100644
index 00000000000..03166e36755
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
@@ -0,0 +1,15 @@
+// Test `X...` and `X..=` range patterns not being allowed syntactically.
+// FIXME(Centril): perhaps these should be semantic restrictions.
+
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn foo() {
+    if let 0... = 1 {} //~ ERROR inclusive range with no end
+    if let 0..= = 1 {} //~ ERROR inclusive range with no end
+    const X: u8 = 0;
+    if let X... = 1 {} //~ ERROR inclusive range with no end
+    if let X..= = 1 {} //~ ERROR inclusive range with no end
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
new file mode 100644
index 00000000000..2b4d95f6842
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
@@ -0,0 +1,35 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13
+   |
+LL |     if let 0... = 1 {}
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13
+   |
+LL |     if let 0..= = 1 {}
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:13:13
+   |
+LL |     if let X... = 1 {}
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:14:13
+   |
+LL |     if let X..= = 1 {}
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
new file mode 100644
index 00000000000..e9a5361e63d
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
@@ -0,0 +1,24 @@
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match &0 {
+        &0.. | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &0..= | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~| ERROR inclusive range with no end
+        &0... | _ => {}
+        //~^ ERROR inclusive range with no end
+    }
+
+    match &0 {
+        &..0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &..=0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &...0 | _ => {}
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
new file mode 100644
index 00000000000..5d3aded0222
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
@@ -0,0 +1,43 @@
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10
+   |
+LL |         &0.. | _ => {}
+   |          ^^^ help: add parentheses to clarify the precedence: `(0 ..)`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11
+   |
+LL |         &0..= | _ => {}
+   |           ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10
+   |
+LL |         &0..= | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(0 ..=)`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11
+   |
+LL |         &0... | _ => {}
+   |           ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10
+   |
+LL |         &..0 | _ => {}
+   |          ^^^ help: add parentheses to clarify the precedence: `(..0)`
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10
+   |
+LL |         &..=0 | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
new file mode 100644
index 00000000000..416c59af3fd
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
@@ -0,0 +1,160 @@
+// run-pass
+
+// Test half-open range patterns against their expression equivalents
+// via `.contains(...)` and make sure the dynamic semantics match.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+#![allow(unreachable_patterns)]
+
+macro_rules! yes {
+    ($scrutinee:expr, $($t:tt)+) => {
+        {
+            let m = match $scrutinee { $($t)+ => true, _ => false, };
+            let c = ($($t)+).contains(&$scrutinee);
+            assert_eq!(m, c);
+            m
+        }
+    }
+}
+
+fn range_to_inclusive() {
+    // `..=X` (`RangeToInclusive`-equivalent):
+    //---------------------------------------
+
+    // u8; `..=X`
+    assert!(yes!(core::u8::MIN, ..=core::u8::MIN));
+    assert!(yes!(core::u8::MIN, ..=5));
+    assert!(yes!(5u8, ..=5));
+    assert!(!yes!(6u8, ..=5));
+
+    // i16; `..=X`
+    assert!(yes!(core::i16::MIN, ..=core::i16::MIN));
+    assert!(yes!(core::i16::MIN, ..=0));
+    assert!(yes!(core::i16::MIN, ..=-5));
+    assert!(yes!(-5, ..=-5));
+    assert!(!yes!(-4, ..=-5));
+
+    // char; `..=X`
+    assert!(yes!('\u{0}', ..='\u{0}'));
+    assert!(yes!('\u{0}', ..='a'));
+    assert!(yes!('a', ..='a'));
+    assert!(!yes!('b', ..='a'));
+
+    // f32; `..=X`
+    assert!(yes!(core::f32::NEG_INFINITY, ..=core::f32::NEG_INFINITY));
+    assert!(yes!(core::f32::NEG_INFINITY, ..=1.0f32));
+    assert!(yes!(1.5f32, ..=1.5f32));
+    assert!(!yes!(1.6f32, ..=-1.5f32));
+
+    // f64; `..=X`
+    assert!(yes!(core::f64::NEG_INFINITY, ..=core::f64::NEG_INFINITY));
+    assert!(yes!(core::f64::NEG_INFINITY, ..=1.0f64));
+    assert!(yes!(1.5f64, ..=1.5f64));
+    assert!(!yes!(1.6f64, ..=-1.5f64));
+}
+
+fn range_to() {
+    // `..X` (`RangeTo`-equivalent):
+    //-----------------------------
+
+    // u8; `..X`
+    assert!(yes!(0u8, ..1));
+    assert!(yes!(0u8, ..5));
+    assert!(!yes!(5u8, ..5));
+    assert!(!yes!(6u8, ..5));
+
+    // u8; `..X`
+    const NU8: u8 = core::u8::MIN + 1;
+    assert!(yes!(core::u8::MIN, ..NU8));
+    assert!(yes!(0u8, ..5));
+    assert!(!yes!(5u8, ..5));
+    assert!(!yes!(6u8, ..5));
+
+    // i16; `..X`
+    const NI16: i16 = core::i16::MIN + 1;
+    assert!(yes!(core::i16::MIN, ..NI16));
+    assert!(yes!(core::i16::MIN, ..5));
+    assert!(yes!(-6, ..-5));
+    assert!(!yes!(-5, ..-5));
+
+    // char; `..X`
+    assert!(yes!('\u{0}', ..'\u{1}'));
+    assert!(yes!('\u{0}', ..'a'));
+    assert!(yes!('a', ..'b'));
+    assert!(!yes!('a', ..'a'));
+    assert!(!yes!('b', ..'a'));
+
+    // f32; `..X`
+    assert!(yes!(core::f32::NEG_INFINITY, ..1.0f32));
+    assert!(!yes!(1.5f32, ..1.5f32));
+    const E32: f32 = 1.5f32 + core::f32::EPSILON;
+    assert!(yes!(1.5f32, ..E32));
+    assert!(!yes!(1.6f32, ..1.5f32));
+
+    // f64; `..X`
+    assert!(yes!(core::f64::NEG_INFINITY, ..1.0f64));
+    assert!(!yes!(1.5f64, ..1.5f64));
+    const E64: f64 = 1.5f64 + core::f64::EPSILON;
+    assert!(yes!(1.5f64, ..E64));
+    assert!(!yes!(1.6f64, ..1.5f64));
+}
+
+fn range_from() {
+    // `X..` (`RangeFrom`-equivalent):
+    //--------------------------------
+
+    // u8; `X..`
+    assert!(yes!(core::u8::MIN, core::u8::MIN..));
+    assert!(yes!(core::u8::MAX, core::u8::MIN..));
+    assert!(!yes!(core::u8::MIN, 1..));
+    assert!(!yes!(4, 5..));
+    assert!(yes!(5, 5..));
+    assert!(yes!(6, 5..));
+    assert!(yes!(core::u8::MAX, core::u8::MAX..));
+
+    // i16; `X..`
+    assert!(yes!(core::i16::MIN, core::i16::MIN..));
+    assert!(yes!(core::i16::MAX, core::i16::MIN..));
+    const NI16: i16 = core::i16::MIN + 1;
+    assert!(!yes!(core::i16::MIN, NI16..));
+    assert!(!yes!(-4, 5..));
+    assert!(yes!(-4, -4..));
+    assert!(yes!(-3, -4..));
+    assert!(yes!(core::i16::MAX, core::i16::MAX..));
+
+    // char; `X..`
+    assert!(yes!('\u{0}', '\u{0}'..));
+    assert!(yes!(core::char::MAX, '\u{0}'..));
+    assert!(yes!('a', 'a'..));
+    assert!(yes!('b', 'a'..));
+    assert!(!yes!('a', 'b'..));
+    assert!(yes!(core::char::MAX, core::char::MAX..));
+
+    // f32; `X..`
+    assert!(yes!(core::f32::NEG_INFINITY, core::f32::NEG_INFINITY..));
+    assert!(yes!(core::f32::INFINITY, core::f32::NEG_INFINITY..));
+    assert!(!yes!(core::f32::NEG_INFINITY, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, 1.0f32..));
+    assert!(!yes!(1.0f32 - core::f32::EPSILON, 1.0f32..));
+    assert!(yes!(1.0f32, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, core::f32::INFINITY..));
+
+    // f64; `X..`
+    assert!(yes!(core::f64::NEG_INFINITY, core::f64::NEG_INFINITY..));
+    assert!(yes!(core::f64::INFINITY, core::f64::NEG_INFINITY..));
+    assert!(!yes!(core::f64::NEG_INFINITY, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, 1.0f64..));
+    assert!(!yes!(1.0f64 - core::f64::EPSILON, 1.0f64..));
+    assert!(yes!(1.0f64, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, core::f64::INFINITY..));
+}
+
+fn main() {
+    range_to_inclusive();
+    range_to();
+    range_from();
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
new file mode 100644
index 00000000000..a663acd2d19
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+// Test the parsing of half-open ranges.
+
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match scrutinee {
+        X.. | 0.. | 'a'.. | 0.0f32.. => {}
+        ..=X | ...X | ..X => {}
+        ..=0 | ...0 | ..0 => {}
+        ..='a' | ...'a' | ..'a' => {}
+        ..=0.0f32 | ...0.0f32 | ..0.0f32 => {}
+    }
+
+    macro_rules! mac {
+        ($e:expr) => {
+            let ..$e;
+            let ...$e;
+            let ..=$e;
+            let $e..;
+            let $e...;
+            let $e..=;
+        }
+    }
+
+    mac!(0);
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-4.rs b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
new file mode 100644
index 00000000000..bd795368205
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    const PAT: u8 = 1;
+
+    match 0 {
+        (.. PAT) => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.rs b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
new file mode 100644
index 00000000000..613d907cfe3
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
@@ -0,0 +1,10 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    const PAT: u8 = 1;
+
+    match (0, 1) {
+        (PAT ..) => {} //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
new file mode 100644
index 00000000000..307ad711b74
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-5.rs:8:10
+   |
+LL |     match (0, 1) {
+   |           ------ this expression has type `({integer}, {integer})`
+LL |         (PAT ..) => {}
+   |          ^^^ expected tuple, found `u8`
+   |
+   = note: expected tuple `({integer}, {integer})`
+               found type `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 736369dab83..5d75f5034bc 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -15,7 +15,7 @@ LL |     fn f() { ::bar::m!(); }
 LL |         Vec::new();
    |         ^^^ use of undeclared type or module `Vec`
 
-error[E0599]: no method named `clone` found for type `()` in the current scope
+error[E0599]: no method named `clone` found for unit type `()` in the current scope
   --> $DIR/no_implicit_prelude.rs:12:12
    |
 LL |     fn f() { ::bar::m!(); }
diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
index a116c5b38ce..15c4acbc939 100644
--- a/src/test/ui/hygiene/trait_items.rs
+++ b/src/test/ui/hygiene/trait_items.rs
@@ -14,7 +14,7 @@ mod bar {
 }
 
 mod baz {
-    pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
+    pub macro m() { ().f() } //~ ERROR no method named `f` found
     fn f() { ::bar::m!(); }
 }
 
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
index c3ce484edf7..8e3609292a7 100644
--- a/src/test/ui/hygiene/trait_items.stderr
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `()` in the current scope
+error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/trait_items.rs:17:24
    |
 LL |     fn f() { ::baz::m!(); }
diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr
index 644d26b3406..1605f3434cf 100644
--- a/src/test/ui/impl-trait/bindings-opaque.stderr
+++ b/src/test/ui/impl-trait/bindings-opaque.stderr
@@ -6,19 +6,19 @@ LL | #![feature(impl_trait_in_bindings)]
    |
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:11:17
    |
 LL |     let _ = FOO.count_ones();
    |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:13:17
    |
 LL |     let _ = BAR.count_ones();
    |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:15:17
    |
 LL |     let _ = foo.count_ones();
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
index 2bff01be9b8..41f48cb5693 100644
--- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
@@ -18,5 +18,5 @@ fn main() {
     let f1 = Bar;
 
     f1.foo(1usize);
-    //~^ error: method named `foo` found for type `Bar` in the current scope
+    //~^ error: method named `foo` found for struct `Bar` in the current scope
 }
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
index 441191beaf5..57417975474 100644
--- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `Bar` in the current scope
+error[E0599]: no method named `foo` found for struct `Bar` in the current scope
   --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8
    |
 LL | struct Bar;
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
index fb870d6c6f0..7f2eb0c21e6 100644
--- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `is_empty` found for type `Foo` in the current scope
+error[E0599]: no method named `is_empty` found for struct `Foo` in the current scope
   --> $DIR/method-suggestion-no-duplication.rs:7:15
    |
 LL | struct Foo;
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.rs b/src/test/ui/impl-trait/no-method-suggested-traits.rs
index c912873a6c0..c8abc2d8f8e 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.rs
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.rs
@@ -25,7 +25,7 @@ fn main() {
     //~|items from traits can only be used if the trait is in scope
     std::rc::Rc::new(&mut Box::new(&1u32)).method();
     //~^items from traits can only be used if the trait is in scope
-    //~| ERROR no method named `method` found for type
+    //~| ERROR no method named `method` found for struct
 
     'a'.method();
     //~^ ERROR no method named
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index f0a03e1be82..da25617e187 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -16,7 +16,7 @@ LL | use no_method_suggested_traits::qux::PrivPub;
 LL | use no_method_suggested_traits::Reexported;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:26:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method();
@@ -46,7 +46,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use foo::Bar;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:32:43
    |
 LL |         fn method(&self) {}
@@ -78,7 +78,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:37:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method();
@@ -90,7 +90,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 
-error[E0599]: no method named `method` found for type `Foo` in the current scope
+error[E0599]: no method named `method` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:40:9
    |
 LL | struct Foo;
@@ -106,7 +106,7 @@ LL |     Foo.method();
            candidate #3: `no_method_suggested_traits::qux::PrivPub`
            candidate #4: `no_method_suggested_traits::Reexported`
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:42:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method();
@@ -129,7 +129,7 @@ LL |     1u64.method2();
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:47:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u64)).method2();
@@ -139,7 +139,7 @@ LL |     std::rc::Rc::new(&mut Box::new(&1u64)).method2();
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
@@ -149,7 +149,7 @@ LL |     no_method_suggested_traits::Foo.method2();
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
@@ -159,7 +159,7 @@ LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).metho
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
@@ -169,7 +169,7 @@ LL |     no_method_suggested_traits::Bar::X.method2();
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
@@ -179,7 +179,7 @@ LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).me
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method3` found for type `Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:59:9
    |
 LL | struct Foo;
@@ -192,7 +192,7 @@ LL |     Foo.method3();
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:61:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method3();
@@ -202,7 +202,7 @@ LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method3();
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:63:12
    |
 LL | enum Bar { X }
@@ -215,7 +215,7 @@ LL |     Bar::X.method3();
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:65:46
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
@@ -231,31 +231,31 @@ error[E0599]: no method named `method3` found for type `usize` in the current sc
 LL |     1_usize.method3();
    |             ^^^^^^^ method not found in `usize`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:70:47
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
    |                                               ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&usize>>`
 
-error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:71:37
    |
 LL |     no_method_suggested_traits::Foo.method3();
    |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:72:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
    |                                                                       ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>`
 
-error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:74:40
    |
 LL |     no_method_suggested_traits::Bar::X.method3();
    |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:75:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index f4567554d0d..8c59fbd5301 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -37,7 +37,7 @@ LL |     Foo.bar();
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
 
-error[E0599]: no method named `bar` found for type `Foo` in the current scope
+error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/infinite-autoderef.rs:26:9
    |
 LL | struct Foo;
diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr
index 80ca051ceff..666fb6ab2bb 100644
--- a/src/test/ui/issues/issue-10465.stderr
+++ b/src/test/ui/issues/issue-10465.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&b::B` in the current scope
+error[E0599]: no method named `foo` found for reference `&b::B` in the current scope
   --> $DIR/issue-10465.rs:17:15
    |
 LL |             b.foo();
diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr
index cdb261a238e..2f31636f8ad 100644
--- a/src/test/ui/issues/issue-13853.stderr
+++ b/src/test/ui/issues/issue-13853.stderr
@@ -12,7 +12,7 @@ LL |         self.iter()
    = help: type parameters must be constrained to match other types
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error[E0599]: no method named `iter` found for type `&G` in the current scope
+error[E0599]: no method named `iter` found for reference `&G` in the current scope
   --> $DIR/issue-13853.rs:27:23
    |
 LL |     for node in graph.iter() {
diff --git a/src/test/ui/issues/issue-19521.stderr b/src/test/ui/issues/issue-19521.stderr
index c15c5392fac..b6847cd755c 100644
--- a/src/test/ui/issues/issue-19521.stderr
+++ b/src/test/ui/issues/issue-19521.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `homura` found for type `&'static str` in the current scope
+error[E0599]: no method named `homura` found for reference `&'static str` in the current scope
   --> $DIR/issue-19521.rs:2:8
    |
 LL |     "".homura()();
diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr
index fe920c16939..b412d7bc704 100644
--- a/src/test/ui/issues/issue-19692.stderr
+++ b/src/test/ui/issues/issue-19692.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `kaname` found for type `Homura` in the current scope
+error[E0599]: no method named `kaname` found for struct `Homura` in the current scope
   --> $DIR/issue-19692.rs:4:40
    |
 LL | struct Homura;
diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr
index 4e5cace5257..efde16167b7 100644
--- a/src/test/ui/issues/issue-21596.stderr
+++ b/src/test/ui/issues/issue-21596.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `to_string` found for type `*const u8` in the current scope
+error[E0599]: no method named `to_string` found for raw pointer `*const u8` in the current scope
   --> $DIR/issue-21596.rs:4:22
    |
 LL |     println!("{}", z.to_string());
diff --git a/src/test/ui/issues/issue-22933-2.rs b/src/test/ui/issues/issue-22933-2.rs
index 98a354b1bd0..dfd84b9a79d 100644
--- a/src/test/ui/issues/issue-22933-2.rs
+++ b/src/test/ui/issues/issue-22933-2.rs
@@ -2,7 +2,7 @@ enum Delicious {
     Pie      = 0x1,
     Apple    = 0x2,
     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-    //~^ ERROR no variant or associated item named `PIE` found for type `Delicious`
+    //~^ ERROR no variant or associated item named `PIE` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr
index 72038ea20a3..584b05ec44d 100644
--- a/src/test/ui/issues/issue-22933-2.stderr
+++ b/src/test/ui/issues/issue-22933-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `PIE` found for type `Delicious` in the current scope
+error[E0599]: no variant or associated item named `PIE` found for enum `Delicious` in the current scope
   --> $DIR/issue-22933-2.rs:4:55
    |
 LL | enum Delicious {
diff --git a/src/test/ui/issues/issue-22933-3.rs b/src/test/ui/issues/issue-22933-3.rs
index 8518ed34aee..fbcce4b8344 100644
--- a/src/test/ui/issues/issue-22933-3.rs
+++ b/src/test/ui/issues/issue-22933-3.rs
@@ -1,4 +1,4 @@
 const FOO: [u32; u8::MIN as usize] = [];
-//~^ ERROR no associated item named `MIN` found for type `u8`
+//~^ ERROR no associated item named `MIN` found
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23173.rs b/src/test/ui/issues/issue-23173.rs
index 7c15598448d..92f4c546440 100644
--- a/src/test/ui/issues/issue-23173.rs
+++ b/src/test/ui/issues/issue-23173.rs
@@ -7,7 +7,7 @@ fn use_token(token: &Token) { unimplemented!() }
 
 fn main() {
     use_token(&Token::Homura); //~ ERROR no variant or associated item named `Homura`
-    Struct::method(); //~ ERROR no function or associated item named `method` found for type
-    Struct::method; //~ ERROR no function or associated item named `method` found for type
-    Struct::Assoc; //~ ERROR no associated item named `Assoc` found for type `Struct` in
+    Struct::method(); //~ ERROR no function or associated item named `method` found
+    Struct::method; //~ ERROR no function or associated item named `method` found
+    Struct::Assoc; //~ ERROR no associated item named `Assoc` found
 }
diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr
index 699e41156fa..89f70fda786 100644
--- a/src/test/ui/issues/issue-23173.stderr
+++ b/src/test/ui/issues/issue-23173.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Homura` found for type `Token` in the current scope
+error[E0599]: no variant or associated item named `Homura` found for enum `Token` in the current scope
   --> $DIR/issue-23173.rs:9:23
    |
 LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
@@ -7,7 +7,7 @@ LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
 LL |     use_token(&Token::Homura);
    |                       ^^^^^^ variant or associated item not found in `Token`
 
-error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:10:13
    |
 LL | struct Struct {
@@ -16,7 +16,7 @@ LL | struct Struct {
 LL |     Struct::method();
    |             ^^^^^^ function or associated item not found in `Struct`
 
-error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:11:13
    |
 LL | struct Struct {
@@ -25,7 +25,7 @@ LL | struct Struct {
 LL |     Struct::method;
    |             ^^^^^^ function or associated item not found in `Struct`
 
-error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope
+error[E0599]: no associated item named `Assoc` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:12:13
    |
 LL | struct Struct {
diff --git a/src/test/ui/issues/issue-23217.rs b/src/test/ui/issues/issue-23217.rs
index 157f20d22d8..09f9ebccf25 100644
--- a/src/test/ui/issues/issue-23217.rs
+++ b/src/test/ui/issues/issue-23217.rs
@@ -1,5 +1,5 @@
 pub enum SomeEnum {
-    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found for type `SomeEnum`
+    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr
index 97100ed3753..a81b459a34c 100644
--- a/src/test/ui/issues/issue-23217.stderr
+++ b/src/test/ui/issues/issue-23217.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `A` found for type `SomeEnum` in the current scope
+error[E0599]: no variant or associated item named `A` found for enum `SomeEnum` in the current scope
   --> $DIR/issue-23217.rs:2:19
    |
 LL | pub enum SomeEnum {
diff --git a/src/test/ui/issues/issue-25385.rs b/src/test/ui/issues/issue-25385.rs
index adad6c35a3f..ea042a6c76b 100644
--- a/src/test/ui/issues/issue-25385.rs
+++ b/src/test/ui/issues/issue-25385.rs
@@ -1,6 +1,6 @@
 macro_rules! foo {
     ($e:expr) => { $e.foo() }
-    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+    //~^ ERROR no method named `foo` found
 }
 
 fn main() {
@@ -8,5 +8,5 @@ fn main() {
     foo!(a);
 
     foo!(1i32.foo());
-    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+    //~^ ERROR no method named `foo` found
 }
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index c9ede030034..aa720fd4589 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `C` in the current scope
+error[E0599]: no method named `clone` found for struct `C` in the current scope
   --> $DIR/issue-2823.rs:13:16
    |
 LL | struct C {
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
index e315317c98a..77bc8292094 100644
--- a/src/test/ui/issues/issue-28344.stderr
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -4,7 +4,7 @@ error[E0191]: the value of the associated type `Output` (from trait `std::ops::B
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                 ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
 
-error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+error[E0599]: no function or associated item named `bitor` found for trait object `dyn std::ops::BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:4:25
    |
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
@@ -19,7 +19,7 @@ error[E0191]: the value of the associated type `Output` (from trait `std::ops::B
 LL |     let g = BitXor::bitor;
    |             ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
 
-error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+error[E0599]: no function or associated item named `bitor` found for trait object `dyn std::ops::BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:8:21
    |
 LL |     let g = BitXor::bitor;
diff --git a/src/test/ui/issues/issue-28586.rs b/src/test/ui/issues/issue-28586.rs
index 4d286be1e33..c543ef9b0e3 100644
--- a/src/test/ui/issues/issue-28586.rs
+++ b/src/test/ui/issues/issue-28586.rs
@@ -2,6 +2,6 @@
 
 pub trait Foo {}
 impl Foo for [u8; usize::BYTES] {}
-//~^ ERROR no associated item named `BYTES` found for type `usize`
+//~^ ERROR no associated item named `BYTES` found
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-28971.rs b/src/test/ui/issues/issue-28971.rs
index 6493565d216..f0a1e2d0061 100644
--- a/src/test/ui/issues/issue-28971.rs
+++ b/src/test/ui/issues/issue-28971.rs
@@ -5,7 +5,7 @@ fn main(){
     foo(|| {
         match Foo::Bar(1) {
             Foo::Baz(..) => (),
-            //~^ ERROR no variant or associated item named `Baz` found for type `Foo`
+            //~^ ERROR no variant or associated item named `Baz` found
             _ => (),
         }
     });
diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr
index 7411896443d..2736ee881d5 100644
--- a/src/test/ui/issues/issue-28971.stderr
+++ b/src/test/ui/issues/issue-28971.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Baz` found for type `Foo` in the current scope
+error[E0599]: no variant or associated item named `Baz` found for enum `Foo` in the current scope
   --> $DIR/issue-28971.rs:7:18
    |
 LL | enum Foo {
diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/issues/issue-29124.rs
index 1cd3f84f7a2..dd278484175 100644
--- a/src/test/ui/issues/issue-29124.rs
+++ b/src/test/ui/issues/issue-29124.rs
@@ -13,7 +13,7 @@ fn func() -> Ret {
 
 fn main() {
     Obj::func.x();
-    //~^ ERROR no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+    //~^ ERROR no method named `x` found
     func.x();
-    //~^ ERROR no method named `x` found for type `fn() -> Ret {func}` in the current scope
+    //~^ ERROR no method named `x` found
 }
diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr
index c537c6118f3..fff20248b70 100644
--- a/src/test/ui/issues/issue-29124.stderr
+++ b/src/test/ui/issues/issue-29124.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+error[E0599]: no method named `x` found for fn item `fn() -> Ret {Obj::func}` in the current scope
   --> $DIR/issue-29124.rs:15:15
    |
 LL |     Obj::func.x();
@@ -6,7 +6,7 @@ LL |     Obj::func.x();
    |
    = note: Obj::func is a function, perhaps you wish to call it
 
-error[E0599]: no method named `x` found for type `fn() -> Ret {func}` in the current scope
+error[E0599]: no method named `x` found for fn item `fn() -> Ret {func}` in the current scope
   --> $DIR/issue-29124.rs:17:10
    |
 LL |     func.x();
diff --git a/src/test/ui/issues/issue-30123.rs b/src/test/ui/issues/issue-30123.rs
index 4fc32e0de8d..705355d91bf 100644
--- a/src/test/ui/issues/issue-30123.rs
+++ b/src/test/ui/issues/issue-30123.rs
@@ -5,5 +5,5 @@ use issue_30123_aux::*;
 
 fn main() {
     let ug = Graph::<i32, i32>::new_undirected();
-    //~^ ERROR no function or associated item named `new_undirected` found for type
+    //~^ ERROR no function or associated item named `new_undirected` found
 }
diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr
index 32bbd4d03d6..bc6731601f0 100644
--- a/src/test/ui/issues/issue-30123.stderr
+++ b/src/test/ui/issues/issue-30123.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new_undirected` found for type `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
   --> $DIR/issue-30123.rs:7:33
    |
 LL |     let ug = Graph::<i32, i32>::new_undirected();
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index 38cf3c4f930..a614b96ac14 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -7,7 +7,7 @@ LL |         .cloned()
    = note:   expected type `u8`
            found reference `&_`
 
-error[E0599]: no method named `collect` found for type `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
+error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
   --> $DIR/issue-31173.rs:14:10
    |
 LL |         .collect();
diff --git a/src/test/ui/issues/issue-33575.rs b/src/test/ui/issues/issue-33575.rs
index 09c499452ad..de544afae73 100644
--- a/src/test/ui/issues/issue-33575.rs
+++ b/src/test/ui/issues/issue-33575.rs
@@ -1,4 +1,4 @@
 fn main() {
-    let baz = ().foo(); //~ ERROR no method named `foo` found for type `()` in the current scope
+    let baz = ().foo(); //~ ERROR no method named `foo` found
     <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
 }
diff --git a/src/test/ui/issues/issue-33575.stderr b/src/test/ui/issues/issue-33575.stderr
index e6b74d262c3..bbd8042d1cd 100644
--- a/src/test/ui/issues/issue-33575.stderr
+++ b/src/test/ui/issues/issue-33575.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `()` in the current scope
+error[E0599]: no method named `foo` found for unit type `()` in the current scope
   --> $DIR/issue-33575.rs:2:18
    |
 LL |     let baz = ().foo();
diff --git a/src/test/ui/issues/issue-34209.rs b/src/test/ui/issues/issue-34209.rs
index fc2c3679e13..632ddb91b36 100644
--- a/src/test/ui/issues/issue-34209.rs
+++ b/src/test/ui/issues/issue-34209.rs
@@ -4,7 +4,7 @@ enum S {
 
 fn bug(l: S) {
     match l {
-        S::B {} => {}, //~ ERROR no variant `B` in enum `S`
+        S::B {} => {}, //~ ERROR no variant named `B` found for enum `S`
     }
 }
 
diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr
index 194bb2bfab8..f9a25b69ff6 100644
--- a/src/test/ui/issues/issue-34209.stderr
+++ b/src/test/ui/issues/issue-34209.stderr
@@ -1,4 +1,4 @@
-error: no variant `B` in enum `S`
+error[E0599]: no variant named `B` found for enum `S`
   --> $DIR/issue-34209.rs:7:12
    |
 LL | enum S {
@@ -9,3 +9,4 @@ LL |         S::B {} => {},
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs
index e34b5c9a0f4..afe4d42edd8 100644
--- a/src/test/ui/issues/issue-34334.rs
+++ b/src/test/ui/issues/issue-34334.rs
@@ -7,5 +7,5 @@ fn main () {
     //~| ERROR expected expression, found reserved identifier `_`
     //~| ERROR expected expression, found reserved identifier `_`
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-    //~^ ERROR no method named `iter` found for type `()` in the current scope
+    //~^ ERROR no method named `iter` found
 }
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 3055e316a08..c52ea4ef9da 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -43,7 +43,7 @@ LL |     let sr: Vec<(u32, _, _) = vec![];
    |             |
    |             cannot assign to this expression
 
-error[E0599]: no method named `iter` found for type `()` in the current scope
+error[E0599]: no method named `iter` found for unit type `()` in the current scope
   --> $DIR/issue-34334.rs:9:36
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr
index b381203856e..a998f95d306 100644
--- a/src/test/ui/issues/issue-35677.stderr
+++ b/src/test/ui/issues/issue-35677.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `is_subset` found for type `&std::collections::HashSet<T>` in the current scope
+error[E0599]: no method named `is_subset` found for reference `&std::collections::HashSet<T>` in the current scope
   --> $DIR/issue-35677.rs:4:10
    |
 LL |     this.is_subset(other)
diff --git a/src/test/ui/issues/issue-3707.rs b/src/test/ui/issues/issue-3707.rs
index 844a2dc0069..0817c51ee4e 100644
--- a/src/test/ui/issues/issue-3707.rs
+++ b/src/test/ui/issues/issue-3707.rs
@@ -7,7 +7,7 @@ impl Obj {
         return 1+1 == 2
     }
     pub fn chirp(&self) {
-        self.boom(); //~ ERROR no method named `boom` found for type `&Obj` in the current scope
+        self.boom(); //~ ERROR no method named `boom` found
     }
 }
 
diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr
index b98bc572a39..6ca2deee377 100644
--- a/src/test/ui/issues/issue-3707.stderr
+++ b/src/test/ui/issues/issue-3707.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `boom` found for type `&Obj` in the current scope
+error[E0599]: no method named `boom` found for reference `&Obj` in the current scope
   --> $DIR/issue-3707.rs:10:14
    |
 LL |         self.boom();
diff --git a/src/test/ui/issues/issue-38919.rs b/src/test/ui/issues/issue-38919.rs
index 60a8793b4e6..3d28f1936b4 100644
--- a/src/test/ui/issues/issue-38919.rs
+++ b/src/test/ui/issues/issue-38919.rs
@@ -1,5 +1,5 @@
 fn foo<T: Iterator>() {
-    T::Item; //~ ERROR no associated item named `Item` found for type `T` in the current scope
+    T::Item; //~ ERROR no associated item named `Item` found
 }
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr
index 603d42ca35e..0022065a32c 100644
--- a/src/test/ui/issues/issue-38919.stderr
+++ b/src/test/ui/issues/issue-38919.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `Item` found for type `T` in the current scope
+error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope
   --> $DIR/issue-38919.rs:2:8
    |
 LL |     T::Item;
diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr
index 8b173e1b50c..2f6e676538e 100644
--- a/src/test/ui/issues/issue-39175.stderr
+++ b/src/test/ui/issues/issue-39175.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `exec` found for type `&mut std::process::Command` in the current scope
+error[E0599]: no method named `exec` found for mutable reference `&mut std::process::Command` in the current scope
   --> $DIR/issue-39175.rs:15:39
    |
 LL |     Command::new("echo").arg("hello").exec();
diff --git a/src/test/ui/issues/issue-39559.rs b/src/test/ui/issues/issue-39559.rs
index 5af48ca4c0d..3a75956af52 100644
--- a/src/test/ui/issues/issue-39559.rs
+++ b/src/test/ui/issues/issue-39559.rs
@@ -12,7 +12,7 @@ impl Dim for Dim3 {
 
 pub struct Vector<T, D: Dim> {
     entries: [T; D::dim()],
-    //~^ ERROR no function or associated item named `dim` found for type `D` in the current scope
+    //~^ ERROR no function or associated item named `dim` found
     _dummy: D,
 }
 
diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr
index b945b5e6654..0554b232c24 100644
--- a/src/test/ui/issues/issue-39559.stderr
+++ b/src/test/ui/issues/issue-39559.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `dim` found for type `D` in the current scope
+error[E0599]: no function or associated item named `dim` found for type parameter `D` in the current scope
   --> $DIR/issue-39559.rs:14:21
    |
 LL |     entries: [T; D::dim()],
diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/issues/issue-3973.rs
index 4e00915683a..a5ed5b87051 100644
--- a/src/test/ui/issues/issue-3973.rs
+++ b/src/test/ui/issues/issue-3973.rs
@@ -20,6 +20,6 @@ impl ToString_ for Point {
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    //~^ ERROR no function or associated item named `new` found for type `Point`
+    //~^ ERROR no function or associated item named `new` found for struct `Point`
     println!("{}", p.to_string());
 }
diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr
index ee07a410a9c..63282e8d86d 100644
--- a/src/test/ui/issues/issue-3973.stderr
+++ b/src/test/ui/issues/issue-3973.stderr
@@ -7,7 +7,7 @@ LL | |         Point { x: x, y: y }
 LL | |     }
    | |_____^ not a member of trait `ToString_`
 
-error[E0599]: no function or associated item named `new` found for type `Point` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
   --> $DIR/issue-3973.rs:22:20
    |
 LL | struct Point {
diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs
index 478e13bb177..5b95a737913 100644
--- a/src/test/ui/issues/issue-41255.rs
+++ b/src/test/ui/issues/issue-41255.rs
@@ -1,6 +1,7 @@
 // Matching against float literals should result in a linter error
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 #![allow(unused)]
 #![forbid(illegal_floating_point_literal_pattern)]
 
@@ -35,6 +36,22 @@ fn main() {
                              //~| WARNING hard error
                              //~| WARNING hard error
                              //~| WARNING hard error
+
+        ..71.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
+        ..=72.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
+        71.0.. => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
         _ => {},
     };
     let y = 5.0;
diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr
index 4f24456c169..1ff58153c88 100644
--- a/src/test/ui/issues/issue-41255.stderr
+++ b/src/test/ui/issues/issue-41255.stderr
@@ -1,11 +1,11 @@
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:10:9
+  --> $DIR/issue-41255.rs:11:9
    |
 LL |         5.0 => {},
    |         ^^^
    |
 note: lint level defined here
-  --> $DIR/issue-41255.rs:5:11
+  --> $DIR/issue-41255.rs:6:11
    |
 LL | #![forbid(illegal_floating_point_literal_pattern)]
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL | #![forbid(illegal_floating_point_literal_pattern)]
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:14:9
+  --> $DIR/issue-41255.rs:15:9
    |
 LL |         5.0f32 => {},
    |         ^^^^^^
@@ -22,7 +22,7 @@ LL |         5.0f32 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:18:10
+  --> $DIR/issue-41255.rs:19:10
    |
 LL |         -5.0 => {},
    |          ^^^
@@ -31,7 +31,7 @@ LL |         -5.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:9
+  --> $DIR/issue-41255.rs:23:9
    |
 LL |         1.0 .. 33.0 => {},
    |         ^^^
@@ -40,7 +40,7 @@ LL |         1.0 .. 33.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:16
+  --> $DIR/issue-41255.rs:23:16
    |
 LL |         1.0 .. 33.0 => {},
    |                ^^^^
@@ -49,7 +49,7 @@ LL |         1.0 .. 33.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:30:9
+  --> $DIR/issue-41255.rs:31:9
    |
 LL |         39.0 ..= 70.0 => {},
    |         ^^^^
@@ -58,7 +58,7 @@ LL |         39.0 ..= 70.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:30:18
+  --> $DIR/issue-41255.rs:31:18
    |
 LL |         39.0 ..= 70.0 => {},
    |                  ^^^^
@@ -67,7 +67,34 @@ LL |         39.0 ..= 70.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:43:10
+  --> $DIR/issue-41255.rs:40:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:45:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:50:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:60:10
    |
 LL |         (3.14, 1) => {},
    |          ^^^^
@@ -76,7 +103,7 @@ LL |         (3.14, 1) => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:52:18
+  --> $DIR/issue-41255.rs:69:18
    |
 LL |         Foo { x: 2.0 } => {},
    |                  ^^^
@@ -85,7 +112,7 @@ LL |         Foo { x: 2.0 } => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:10:9
+  --> $DIR/issue-41255.rs:11:9
    |
 LL |         5.0 => {},
    |         ^^^
@@ -94,7 +121,7 @@ LL |         5.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:14:9
+  --> $DIR/issue-41255.rs:15:9
    |
 LL |         5.0f32 => {},
    |         ^^^^^^
@@ -103,7 +130,7 @@ LL |         5.0f32 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:18:10
+  --> $DIR/issue-41255.rs:19:10
    |
 LL |         -5.0 => {},
    |          ^^^
@@ -112,7 +139,7 @@ LL |         -5.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:9
+  --> $DIR/issue-41255.rs:23:9
    |
 LL |         1.0 .. 33.0 => {},
    |         ^^^
@@ -121,7 +148,7 @@ LL |         1.0 .. 33.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:16
+  --> $DIR/issue-41255.rs:23:16
    |
 LL |         1.0 .. 33.0 => {},
    |                ^^^^
@@ -130,7 +157,7 @@ LL |         1.0 .. 33.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:30:9
+  --> $DIR/issue-41255.rs:31:9
    |
 LL |         39.0 ..= 70.0 => {},
    |         ^^^^
@@ -139,7 +166,7 @@ LL |         39.0 ..= 70.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:30:18
+  --> $DIR/issue-41255.rs:31:18
    |
 LL |         39.0 ..= 70.0 => {},
    |                  ^^^^
@@ -148,7 +175,34 @@ LL |         39.0 ..= 70.0 => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:43:10
+  --> $DIR/issue-41255.rs:40:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:45:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:50:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:60:10
    |
 LL |         (3.14, 1) => {},
    |          ^^^^
@@ -157,7 +211,7 @@ LL |         (3.14, 1) => {},
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:52:18
+  --> $DIR/issue-41255.rs:69:18
    |
 LL |         Foo { x: 2.0 } => {},
    |                  ^^^
@@ -165,5 +219,5 @@ LL |         Foo { x: 2.0 } => {},
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to 18 previous errors
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/issues/issue-41880.rs b/src/test/ui/issues/issue-41880.rs
index 16facc5a78f..10cde21abd7 100644
--- a/src/test/ui/issues/issue-41880.rs
+++ b/src/test/ui/issues/issue-41880.rs
@@ -25,5 +25,5 @@ impl<T: Clone, F> Iterator for Iterate<T, F> where F: Fn(&T) -> T {
 fn main() {
     let a = iterate(0, |x| x+1);
     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-    //~^ ERROR no method named `iter` found for type `Iterate<{integer}
+    //~^ ERROR no method named `iter` found
 }
diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr
index 0e1d55c339e..09d5594f73f 100644
--- a/src/test/ui/issues/issue-41880.stderr
+++ b/src/test/ui/issues/issue-41880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `iter` found for type `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
+error[E0599]: no method named `iter` found for struct `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
   --> $DIR/issue-41880.rs:27:24
    |
 LL | pub struct Iterate<T, F> {
diff --git a/src/test/ui/issues/issue-42880.stderr b/src/test/ui/issues/issue-42880.stderr
index 763bb9ae0ea..82cdc20df2f 100644
--- a/src/test/ui/issues/issue-42880.stderr
+++ b/src/test/ui/issues/issue-42880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `String` found for type `std::string::String` in the current scope
+error[E0599]: no associated item named `String` found for struct `std::string::String` in the current scope
   --> $DIR/issue-42880.rs:4:22
    |
 LL |     let f = |&Value::String(_)| ();
diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/issues/issue-43189.rs
index f4f4dce7682..ce667a5006e 100644
--- a/src/test/ui/issues/issue-43189.rs
+++ b/src/test/ui/issues/issue-43189.rs
@@ -8,5 +8,5 @@
 extern crate xcrate_issue_43189_b;
 fn main() {
     ().a();
-    //~^ ERROR no method named `a` found for type `()` in the current scope [E0599]
+    //~^ ERROR no method named `a` found
 }
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
index 4dae6c1cd15..3f63cb8e78f 100644
--- a/src/test/ui/issues/issue-43189.stderr
+++ b/src/test/ui/issues/issue-43189.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `a` found for type `()` in the current scope
+error[E0599]: no method named `a` found for unit type `()` in the current scope
   --> $DIR/issue-43189.rs:10:8
    |
 LL |     ().a();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
index 24c61425b8e..5b6b8f8de18 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _result = &Some(42).as_deref();
-//~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>`
+//~^ ERROR no method named `as_deref` found for enum `std::option::Option<{integer}>`
 }
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
index 0eb7bf02475..f91f6e891ed 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope
+error[E0599]: no method named `as_deref` found for enum `std::option::Option<{integer}>` in the current scope
   --> $DIR/option-as_deref.rs:2:29
    |
 LL |     let _result = &Some(42).as_deref();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
index 67ad73f5847..c5fe6ea82cb 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _result = &mut Some(42).as_deref_mut();
-//~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>`
+//~^ ERROR no method named `as_deref_mut` found for enum `std::option::Option<{integer}>`
 }
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
index 845ddb52319..583236345ca 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope
+error[E0599]: no method named `as_deref_mut` found for enum `std::option::Option<{integer}>` in the current scope
   --> $DIR/option-as_deref_mut.rs:2:33
    |
 LL |     let _result = &mut Some(42).as_deref_mut();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
index 5e016748770..fae11fe62b1 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref.rs:4:27
    |
 LL |     let _result = &Ok(42).as_deref();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
index 6dc13da548b..48a662e98b5 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_err` found for type `std::result::Result<_, {integer}>` in the current scope
+error[E0599]: no method named `as_deref_err` found for enum `std::result::Result<_, {integer}>` in the current scope
   --> $DIR/result-as_deref_err.rs:4:28
    |
 LL |     let _result = &Err(41).as_deref_err();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
index f21e97388b6..2c6231fb3b5 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref_mut.rs:4:31
    |
 LL |     let _result = &mut Ok(42).as_deref_mut();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
index 44c0c954eee..8a5c2f40060 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut_err` found for type `std::result::Result<_, {integer}>` in the current scope
+error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Result<_, {integer}>` in the current scope
   --> $DIR/result-as_deref_mut_err.rs:4:32
    |
 LL |     let _result = &mut Err(41).as_deref_mut_err();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
index b8369c9b82e..af8d657999c 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut_ok` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref_mut_ok` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref_mut_ok.rs:4:31
    |
 LL |     let _result = &mut Ok(42).as_deref_mut_ok();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
index b26705a99e3..145e610d52c 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_ok` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref_ok` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref_ok.rs:4:27
    |
 LL |     let _result = &Ok(42).as_deref_ok();
diff --git a/src/test/ui/issues/issue-5153.rs b/src/test/ui/issues/issue-5153.rs
index e6737662088..5bf0579030a 100644
--- a/src/test/ui/issues/issue-5153.rs
+++ b/src/test/ui/issues/issue-5153.rs
@@ -8,5 +8,5 @@ impl Foo for isize {
 
 fn main() {
     (&5isize as &dyn Foo).foo();
-    //~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
+    //~^ ERROR: no method named `foo` found for reference `&dyn Foo` in the current scope
 }
diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr
index 5034e6d538e..4680c8b131c 100644
--- a/src/test/ui/issues/issue-5153.stderr
+++ b/src/test/ui/issues/issue-5153.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&dyn Foo` in the current scope
+error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope
   --> $DIR/issue-5153.rs:10:27
    |
 LL |     (&5isize as &dyn Foo).foo();
diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr
index 3830ad4b1e3..5222e3ee95d 100644
--- a/src/test/ui/issues/issue-54062.stderr
+++ b/src/test/ui/issues/issue-54062.stderr
@@ -4,7 +4,7 @@ error[E0616]: field `inner` of struct `std::sync::Mutex` is private
 LL |     let _ = test.comps.inner.lock().unwrap();
    |             ^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `unwrap` found for type `std::sys_common::mutex::MutexGuard<'_>` in the current scope
+error[E0599]: no method named `unwrap` found for struct `std::sys_common::mutex::MutexGuard<'_>` in the current scope
   --> $DIR/issue-54062.rs:10:37
    |
 LL |     let _ = test.comps.inner.lock().unwrap();
diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr
index c4000c8a9d4..e762b7bc0c8 100644
--- a/src/test/ui/issues/issue-57362-1.stderr
+++ b/src/test/ui/issues/issue-57362-1.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `fn(&u8)` in the current scope
+error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope
   --> $DIR/issue-57362-1.rs:20:7
    |
 LL |     a.f();
diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr
index 2e713cc0ab5..3528084f6ce 100644
--- a/src/test/ui/issues/issue-57362-2.stderr
+++ b/src/test/ui/issues/issue-57362-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `make_g` found for type `for<'r> fn(&'r ())` in the current scope
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope
   --> $DIR/issue-57362-2.rs:22:25
    |
 LL |     let x = <fn (&())>::make_g();
diff --git a/src/test/ui/issues/issue-58734.rs b/src/test/ui/issues/issue-58734.rs
index bbdfebe1577..b253c135b8c 100644
--- a/src/test/ui/issues/issue-58734.rs
+++ b/src/test/ui/issues/issue-58734.rs
@@ -18,5 +18,5 @@ fn main() {
     Trait::exists(());
     // no object safety error
     Trait::nonexistent(());
-    //~^ ERROR no function or associated item named `nonexistent` found for type `dyn Trait`
+    //~^ ERROR no function or associated item named `nonexistent` found
 }
diff --git a/src/test/ui/issues/issue-58734.stderr b/src/test/ui/issues/issue-58734.stderr
index 07f2a046b2d..5e98cfadf8a 100644
--- a/src/test/ui/issues/issue-58734.stderr
+++ b/src/test/ui/issues/issue-58734.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `nonexistent` found for type `dyn Trait` in the current scope
+error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope
   --> $DIR/issue-58734.rs:20:12
    |
 LL |     Trait::nonexistent(());
diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr
index f1b2de8d8b3..e7a244e9df5 100644
--- a/src/test/ui/issues/issue-64430.stderr
+++ b/src/test/ui/issues/issue-64430.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `bar` found for type `Foo` in the current scope
+error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/issue-64430.rs:7:9
    |
 LL | pub struct Foo;
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
index e0eaafdfc2f..018ce0459fd 100644
--- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
@@ -5,7 +5,7 @@ trait Foo {
 trait Bar {}
 
 fn do_stuff<T : Bar>(t : T) {
-    t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope
+    t.foo() //~ ERROR no method named `foo` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
index 24bf60abf6a..4807a0930e7 100644
--- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `T` in the current scope
+error[E0599]: no method named `foo` found for type parameter `T` in the current scope
   --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
    |
 LL |     t.foo()
diff --git a/src/test/ui/issues/issue-7950.rs b/src/test/ui/issues/issue-7950.rs
index 7add8afee43..d3dcb3380bb 100644
--- a/src/test/ui/issues/issue-7950.rs
+++ b/src/test/ui/issues/issue-7950.rs
@@ -4,5 +4,5 @@ struct Foo;
 
 fn main() {
     Foo::bar();
-    //~^ ERROR no function or associated item named `bar` found for type `Foo`
+    //~^ ERROR no function or associated item named `bar` found for struct `Foo`
 }
diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr
index bbeab405e29..73e13c65cf3 100644
--- a/src/test/ui/issues/issue-7950.stderr
+++ b/src/test/ui/issues/issue-7950.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `bar` found for type `Foo` in the current scope
+error[E0599]: no function or associated item named `bar` found for struct `Foo` in the current scope
   --> $DIR/issue-7950.rs:6:10
    |
 LL | struct Foo;
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index a7843a93011..6bb0877e9b9 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -9,7 +9,7 @@ help: possible better candidate is found in another module, you can import it in
 LL | use T;
    |
 
-error[E0599]: no function or associated item named `f` found for type `Foo` in the current scope
+error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope
   --> $DIR/lexical-scopes.rs:10:10
    |
 LL |     Foo::f();
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
index e0dec0a4a70..5ff4b412667 100644
--- a/src/test/ui/methods/method-call-err-msg.rs
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -15,6 +15,6 @@ fn main() {
 
     let y = Foo;
     y.zero()
-     .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
+     .take()    //~ ERROR no method named `take` found
      .one(0);
 }
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index 94c27b7d178..7efdd91708a 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -25,7 +25,7 @@ LL |     fn two(self, _: isize, _: isize) -> Foo { self }
 LL |      .two(0);
    |       ^^^ expected 2 parameters
 
-error[E0599]: no method named `take` found for type `Foo` in the current scope
+error[E0599]: no method named `take` found for struct `Foo` in the current scope
   --> $DIR/method-call-err-msg.rs:18:7
    |
 LL | pub struct Foo;
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index da018aa8948..f8d677b99d6 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `count` found for type `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
+error[E0599]: no method named `count` found for struct `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
index 83cea168465..58ceaffc964 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
@@ -3,5 +3,5 @@ struct Foo;
 fn main() {
     let a: Result<(), Foo> = Ok(());
     a.unwrap();
-    //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
+    //~^ ERROR no method named `unwrap` found
 }
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 865092e4e9c..bbfb0005056 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `unwrap` found for type `std::result::Result<(), Foo>` in the current scope
+error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope
   --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
diff --git a/src/test/ui/never_type/issue-2149.rs b/src/test/ui/never_type/issue-2149.rs
index d46f0e61793..d6426d2cfab 100644
--- a/src/test/ui/never_type/issue-2149.rs
+++ b/src/test/ui/never_type/issue-2149.rs
@@ -11,5 +11,5 @@ impl<A> VecMonad<A> for Vec<A> {
 }
 fn main() {
     ["hi"].bind(|x| [x] );
-    //~^ ERROR no method named `bind` found for type `[&str; 1]` in the current scope
+    //~^ ERROR no method named `bind` found
 }
diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr
index 8ce2ba03332..9645244751d 100644
--- a/src/test/ui/never_type/issue-2149.stderr
+++ b/src/test/ui/never_type/issue-2149.stderr
@@ -6,7 +6,7 @@ LL |         for elt in self { r = r + f(*elt); }
    |
    = help: the trait `std::ops::Add<std::vec::Vec<B>>` is not implemented for `()`
 
-error[E0599]: no method named `bind` found for type `[&str; 1]` in the current scope
+error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope
   --> $DIR/issue-2149.rs:13:12
    |
 LL |     ["hi"].bind(|x| [x] );
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
index b05c29c0d40..074ed66a261 100644
--- a/src/test/ui/non-copyable-void.stderr
+++ b/src/test/ui/non-copyable-void.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `libc::c_void` in the current scope
+error[E0599]: no method named `clone` found for enum `libc::c_void` in the current scope
   --> $DIR/non-copyable-void.rs:11:23
    |
 LL |         let _z = (*y).clone();
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index c1c50211381..6c3c4a6ac98 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Foo` in the current scope
+error[E0599]: no method named `clone` found for struct `Foo` in the current scope
   --> $DIR/noncopyable-class.rs:34:16
    |
 LL | struct Foo {
diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr
index 2df628ecf8e..855894b4495 100644
--- a/src/test/ui/object-pointer-types.stderr
+++ b/src/test/ui/object-pointer-types.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `owned` found for type `&dyn Foo` in the current scope
+error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:11:7
    |
 LL |     x.owned();
@@ -8,7 +8,7 @@ LL |     x.owned();
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error[E0599]: no method named `owned` found for type `&mut dyn Foo` in the current scope
+error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:17:7
    |
 LL |     x.owned();
@@ -18,7 +18,7 @@ LL |     x.owned();
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error[E0599]: no method named `managed` found for type `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
+error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
   --> $DIR/object-pointer-types.rs:23:7
    |
 LL |     x.managed();
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
index f6d2bee0e15..118bff8144c 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -1,3 +1,5 @@
+#![feature(half_open_range_patterns)]
+
 fn main() {}
 
 #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
@@ -90,15 +92,15 @@ fn main() {}
 // note: requires parens in patterns to allow disambiguation
 
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
 //~^ ERROR unexpected token: `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 
 #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
index 0123006418a..654b49ab620 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -1,5 +1,5 @@
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:3:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:5:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
    |                                    ^^^^^^^^
@@ -7,19 +7,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `]`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:5:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:7:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
    |                                        ^ expected expression
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:7:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
    |                                   ^ expected one of 7 possible tokens
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:9:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:11:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                    ^^^^^^^^
@@ -27,13 +27,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `)`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:9:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:11:44
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                            ^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:12:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:14:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                      ^^^^^^^^
@@ -41,13 +41,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `)`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:12:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:14:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                              ^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:15:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:17:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
    |                                    ^^^^^^^^
@@ -55,7 +55,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:17:33
+  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
    |
 LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
    |                                 ^^^^^^^^
@@ -63,7 +63,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
+  --> $DIR/attr-stmt-expr-attr-bad.rs:21:33
    |
 LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
    |                                 ^^^^^^^^
@@ -71,13 +71,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:21:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:23:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
    |                                  ^ expected one of 7 possible tokens
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:23:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:25:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
    |                                   ^^^^^^^^
@@ -85,7 +85,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:25:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:27:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
    |                                        ^^^^^^^^
@@ -93,7 +93,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:27:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:29:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
    |                                   ^^^^^^^^
@@ -101,7 +101,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:29:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    |                                        ^^^^^^^^
@@ -109,19 +109,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `..`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
    |                                        ^^ expected expression
 
 error: expected expression, found `..`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:35:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
    |                                        ^^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:35:41
+  --> $DIR/attr-stmt-expr-attr-bad.rs:37:41
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
    |                                         ^^^^^^^^
@@ -129,7 +129,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:37:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:39:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |                                             ^^^^^^^^
@@ -137,13 +137,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:39:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:41:32
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
    |                                ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
+  --> $DIR/attr-stmt-expr-attr-bad.rs:43:37
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
    |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -152,7 +152,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
    |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:45:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    |                                      ^^^^^^^^
@@ -160,13 +160,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:47:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
    |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:49:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
    |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -174,7 +174,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
    |                                             expected `{`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |                                              ^^^^^^^^
@@ -182,13 +182,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
@@ -196,7 +196,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             expected `{`
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:54:50
+  --> $DIR/attr-stmt-expr-attr-bad.rs:56:50
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
    |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -205,7 +205,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
    |                                             this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:56:51
+  --> $DIR/attr-stmt-expr-attr-bad.rs:58:51
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |                                                   ^^^^^^^^
@@ -213,13 +213,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:58:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:60:32
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
    |                                ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:60:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:62:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
    |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -228,7 +228,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
    |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:62:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:64:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    |                                              ^^^^^^^^
@@ -236,13 +236,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:64:48
+  --> $DIR/attr-stmt-expr-attr-bad.rs:66:48
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
    |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:66:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:68:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
    |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -250,7 +250,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
    |                                                     expected `{`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:68:54
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:54
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |                                                      ^^^^^^^^
@@ -258,13 +258,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
    |                                                     ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
    |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
@@ -272,7 +272,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}
    |                                                     expected `{`
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:73:66
+  --> $DIR/attr-stmt-expr-attr-bad.rs:75:66
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
    |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -281,7 +281,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}
    |                                                     this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:75:67
+  --> $DIR/attr-stmt-expr-attr-bad.rs:77:67
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
    |                                                                   ^^^^^^^^
@@ -289,7 +289,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -299,7 +299,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -309,7 +309,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -319,7 +319,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -329,7 +329,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:88:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -338,83 +338,90 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:92:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:92:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:95:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:97:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:95:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:97:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:98:39
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:39
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
    |                                       ^
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:102:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:102:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:104:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:104:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:107:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:107:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:112:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:114:44
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
    |                                            ^
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:114:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:116:45
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
    |                                             ^
 
 error: aborting due to 57 previous errors
 
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
index a7d10ca9320..8efb3c73f03 100644
--- a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
+++ b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
@@ -1,6 +1,7 @@
 // check-pass
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 
 #![allow(ellipsis_inclusive_range_patterns)]
 
@@ -10,6 +11,11 @@ fn main() {
             if let 2...$e = 3 {}
             if let 2..=$e = 3 {}
             if let 2..$e = 3 {}
+            if let ..$e = 3 {}
+            if let ..=$e = 3 {}
+            if let $e.. = 5 {}
+            if let $e..5 = 4 {}
+            if let $e..=5 = 4 {}
         }
     }
     mac_expr!(4);
diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
index 1730adfa914..5ec143fae23 100644
--- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
+++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 // The problem in #66357 was that the call trace:
 //
 // - parse_fn_block_decl
@@ -11,4 +13,4 @@
 
 fn f() { |[](* }
 //~^ ERROR expected one of `,` or `:`, found `(`
-//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
index 00d84e2afe3..c3810999d23 100644
--- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
+++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
@@ -1,11 +1,11 @@
 error: expected one of `,` or `:`, found `(`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
+  --> $DIR/issue-66357-unexpected-unreachable.rs:14:13
    |
 LL | fn f() { |[](* }
    |             ^ expected one of `,` or `:`
 
-error: expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:14
+error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+  --> $DIR/issue-66357-unexpected-unreachable.rs:14:14
    |
 LL | fn f() { |[](* }
    |             -^ help: `)` may belong here
diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs
deleted file mode 100644
index 2f03160430a..00000000000
--- a/src/test/ui/parser/pat-tuple-4.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-fn main() {
-    const PAT: u8 = 0;
-
-    match 0 {
-        (.. PAT) => {}
-        //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
-    }
-}
-
-const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr
deleted file mode 100644
index 6c64290e144..00000000000
--- a/src/test/ui/parser/pat-tuple-4.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error: `..X` range patterns are not supported
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
-  --> $DIR/pat-tuple-4.rs:11:30
-   |
-LL | const RECOVERY_WITNESS: () = 0;
-   |                              ^ expected `()`, found integer
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs
deleted file mode 100644
index 5334ef93bb3..00000000000
--- a/src/test/ui/parser/pat-tuple-5.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    const PAT: u8 = 0;
-
-    match (0, 1) {
-        (PAT ..) => {}
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
-        //~| ERROR mismatched types
-    }
-}
diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr
deleted file mode 100644
index 8ff4f948a05..00000000000
--- a/src/test/ui/parser/pat-tuple-5.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error: `X..` range patterns are not supported
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |         (PAT ..) => {}
-   |          ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |         (PAT ..) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |     match (0, 1) {
-   |           ------ this expression has type `({integer}, {integer})`
-LL |         (PAT ..) => {}
-   |          ^^^ expected tuple, found `u8`
-   |
-   = note: expected tuple `({integer}, {integer})`
-               found type `u8`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs
index 260e1083159..a5aae2861b2 100644
--- a/src/test/ui/parser/recover-range-pats.rs
+++ b/src/test/ui/parser/recover-range-pats.rs
@@ -4,6 +4,7 @@
 // 2. Or at least we have parser recovery if they don't.
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 #![deny(ellipsis_inclusive_range_patterns)]
 
 fn main() {}
@@ -55,68 +56,64 @@ fn inclusive2_from_to() {
 }
 
 fn exclusive_from() {
-    if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported
-    if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported
-    if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let 0.. = 0 {}
+    if let X.. = 0 {}
+    if let true.. = 0 {}
     //~^ ERROR only char and numeric types
-    if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let .0.. = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive_from() {
-    if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
-    if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported
-    if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let 0..= = 0 {} //~ ERROR inclusive range with no end
+    if let X..= = 0 {} //~ ERROR inclusive range with no end
+    if let true..= = 0 {} //~ ERROR inclusive range with no end
     //~| ERROR only char and numeric types
-    if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let .0..= = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive2_from() {
-    if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let X... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let true... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
+    if let 0... = 0 {} //~ ERROR inclusive range with no end
+    if let X... = 0 {} //~ ERROR inclusive range with no end
+    if let true... = 0 {} //~ ERROR inclusive range with no end
     //~| ERROR only char and numeric types
-    if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported
+    if let .0... = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
-    //~| ERROR `...` range patterns are deprecated
     //~| ERROR mismatched types
 }
 
 fn exclusive_to() {
-    if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported
-    if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported
-    if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported
-    //~| ERROR only char and numeric types
-    if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported
+    if let ..0 = 0 {}
+    if let ..Y = 0 {}
+    if let ..true = 0 {}
+    //~^ ERROR only char and numeric types
+    if let .. .0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive_to() {
-    if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported
-    if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported
-    if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported
-    //~| ERROR only char and numeric types
-    if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported
+    if let ..=3 = 0 {}
+    if let ..=Y = 0 {}
+    if let ..=true = 0 {}
+    //~^ ERROR only char and numeric types
+    if let ..=.0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive2_to() {
-    if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported
+    if let ...3 = 0 {}
     //~^ ERROR `...` range patterns are deprecated
-    if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported
+    if let ...Y = 0 {}
     //~^ ERROR `...` range patterns are deprecated
-    if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported
+    if let ...true = 0 {}
     //~^ ERROR `...` range patterns are deprecated
     //~| ERROR only char and numeric types
-    if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported
+    if let ....3 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR `...` range patterns are deprecated
     //~| ERROR mismatched types
@@ -136,14 +133,13 @@ fn with_macro_expr_var() {
 
     macro_rules! mac {
         ($e:expr) => {
-            let ..$e; //~ ERROR `..X` range patterns are not supported
-            let ...$e; //~ ERROR `...X` range patterns are not supported
-            //~^ ERROR `...` range patterns are deprecated
-            let ..=$e; //~ ERROR `..=X` range patterns are not supported
-            let $e..; //~ ERROR `X..` range patterns are not supported
-            let $e...; //~ ERROR `X...` range patterns are not supported
+            let ..$e;
+            let ...$e;
             //~^ ERROR `...` range patterns are deprecated
-            let $e..=; //~ ERROR `X..=` range patterns are not supported
+            let ..=$e;
+            let $e..;
+            let $e...; //~ ERROR inclusive range with no end
+            let $e..=; //~ ERROR inclusive range with no end
         }
     }
 
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index 3fed64c191a..d3d3169022a 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -1,377 +1,241 @@
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:24:16
    |
 LL |     if let X.. .0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:37:16
    |
 LL |     if let X..=.0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:49:12
+  --> $DIR/recover-range-pats.rs:50:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:52:17
+  --> $DIR/recover-range-pats.rs:53:17
    |
 LL |     if let X... .0 = 0 {}
    |                 ^^ help: must have an integer part: `0.0`
 
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:58:12
-   |
-LL |     if let 0.. = 0 {}
-   |            ^^^ help: try using the maximum value for the type: `0..MAX`
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:59:12
-   |
-LL |     if let X.. = 0 {}
-   |            ^^^ help: try using the maximum value for the type: `X..MAX`
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:60:12
-   |
-LL |     if let true.. = 0 {}
-   |            ^^^^^^ help: try using the maximum value for the type: `true..MAX`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:62:12
+  --> $DIR/recover-range-pats.rs:63:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:62:12
-   |
-LL |     if let .0.. = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0.0..MAX`
-
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:68:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:69:13
    |
 LL |     if let 0..= = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:69:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:70:13
    |
 LL |     if let X..= = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `X..=MAX`
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:70:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:71:16
    |
 LL |     if let true..= = 0 {}
-   |            ^^^^^^^ help: try using the maximum value for the type: `true..=MAX`
+   |                ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:72:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:73:14
    |
 LL |     if let .0..= = 0 {}
-   |            ^^^^^ help: try using the maximum value for the type: `0.0..=MAX`
+   |              ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:78:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:79:13
    |
 LL |     if let 0... = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0...MAX`
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:80:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:80:13
    |
 LL |     if let X... = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `X...MAX`
+   |             ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:82:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:81:16
    |
 LL |     if let true... = 0 {}
-   |            ^^^^^^^ help: try using the maximum value for the type: `true...MAX`
+   |                ^^^
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:85:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:85:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:83:14
    |
 LL |     if let .0... = 0 {}
-   |            ^^^^^ help: try using the maximum value for the type: `0.0...MAX`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:92:12
-   |
-LL |     if let ..0 = 0 {}
-   |            ^^^ help: try using the minimum value for the type: `MIN..0`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:93:12
+   |              ^^^
    |
-LL |     if let ..Y = 0 {}
-   |            ^^^ help: try using the minimum value for the type: `MIN..Y`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:94:12
-   |
-LL |     if let ..true = 0 {}
-   |            ^^^^^^ help: try using the minimum value for the type: `MIN..true`
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:96:15
+  --> $DIR/recover-range-pats.rs:93:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:96:12
-   |
-LL |     if let .. .0 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN..0.0`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:102:12
-   |
-LL |     if let ..=3 = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN..=3`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:103:12
-   |
-LL |     if let ..=Y = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN..=Y`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:104:12
-   |
-LL |     if let ..=true = 0 {}
-   |            ^^^^^^^ help: try using the minimum value for the type: `MIN..=true`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:106:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:106:12
-   |
-LL |     if let ..=.0 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN..=0.0`
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:112:12
-   |
-LL |     if let ...3 = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN...3`
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:114:12
-   |
-LL |     if let ...Y = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN...Y`
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:116:12
-   |
-LL |     if let ...true = 0 {}
-   |            ^^^^^^^ help: try using the minimum value for the type: `MIN...true`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:119:15
+  --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ help: must have an integer part: `0.3`
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:119:12
-   |
-LL |     if let ....3 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN...0.3`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:139:17
-   |
-LL |             let ..$e;
-   |                 ^^ help: try using the minimum value for the type: `MIN..0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:140:17
-   |
-LL |             let ...$e;
-   |                 ^^^ help: try using the minimum value for the type: `MIN...0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:142:17
-   |
-LL |             let ..=$e;
-   |                 ^^^ help: try using the minimum value for the type: `MIN..=0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:143:19
-   |
-LL |             let $e..;
-   |                   ^^ help: try using the maximum value for the type: `0..MAX`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:144:19
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:141:19
    |
 LL |             let $e...;
-   |                   ^^^ help: try using the maximum value for the type: `0...MAX`
+   |                   ^^^
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:146:19
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:142:19
    |
 LL |             let $e..=;
-   |                   ^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                   ^^^
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
+   |
+   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:41:13
+  --> $DIR/recover-range-pats.rs:42:13
    |
 LL |     if let 0...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
 note: lint level defined here
-  --> $DIR/recover-range-pats.rs:7:9
+  --> $DIR/recover-range-pats.rs:8:9
    |
 LL | #![deny(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:42:13
+  --> $DIR/recover-range-pats.rs:43:13
    |
 LL |     if let 0...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:43:13
+  --> $DIR/recover-range-pats.rs:44:13
    |
 LL |     if let X...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:44:13
+  --> $DIR/recover-range-pats.rs:45:13
    |
 LL |     if let X...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:45:16
+  --> $DIR/recover-range-pats.rs:46:16
    |
 LL |     if let true...Y = 0 {}
    |                ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:47:13
+  --> $DIR/recover-range-pats.rs:48:13
    |
 LL |     if let X...true = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:49:14
+  --> $DIR/recover-range-pats.rs:50:14
    |
 LL |     if let .0...Y = 0 {}
    |              ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:52:13
+  --> $DIR/recover-range-pats.rs:53:13
    |
 LL |     if let X... .0 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:78:13
-   |
-LL |     if let 0... = 0 {}
-   |             ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:80:13
-   |
-LL |     if let X... = 0 {}
-   |             ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:82:16
-   |
-LL |     if let true... = 0 {}
-   |                ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:85:14
-   |
-LL |     if let .0... = 0 {}
-   |              ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:112:12
+  --> $DIR/recover-range-pats.rs:109:12
    |
 LL |     if let ...3 = 0 {}
    |            ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:114:12
+  --> $DIR/recover-range-pats.rs:111:12
    |
 LL |     if let ...Y = 0 {}
    |            ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:116:12
+  --> $DIR/recover-range-pats.rs:113:12
    |
 LL |     if let ...true = 0 {}
    |            ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:119:12
+  --> $DIR/recover-range-pats.rs:116:12
    |
 LL |     if let ....3 = 0 {}
    |            ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:129:20
+  --> $DIR/recover-range-pats.rs:126:20
    |
 LL |             let $e1...$e2;
    |                    ^^^ help: use `..=` for an inclusive range
@@ -380,7 +244,7 @@ LL |     mac2!(0, 1);
    |     ------------ in this macro invocation
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:140:17
+  --> $DIR/recover-range-pats.rs:137:17
    |
 LL |             let ...$e;
    |                 ^^^ help: use `..=` for an inclusive range
@@ -388,17 +252,8 @@ LL |             let ...$e;
 LL |     mac!(0);
    |     -------- in this macro invocation
 
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:144:19
-   |
-LL |             let $e...;
-   |                   ^^^ help: use `..=` for an inclusive range
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:19:12
+  --> $DIR/recover-range-pats.rs:20:12
    |
 LL |     if let true..Y = 0 {}
    |            ^^^^  - this is of type `u8`
@@ -406,7 +261,7 @@ LL |     if let true..Y = 0 {}
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:20:15
+  --> $DIR/recover-range-pats.rs:21:15
    |
 LL |     if let X..true = 0 {}
    |            -  ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -414,7 +269,7 @@ LL |     if let X..true = 0 {}
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^  - this is of type `u8`
@@ -422,7 +277,7 @@ LL |     if let .0..Y = 0 {}
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:24:16
    |
 LL |     if let X.. .0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -431,7 +286,7 @@ LL |     if let X.. .0 = 0 {}
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:32:12
+  --> $DIR/recover-range-pats.rs:33:12
    |
 LL |     if let true..=Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -439,7 +294,7 @@ LL |     if let true..=Y = 0 {}
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:33:16
+  --> $DIR/recover-range-pats.rs:34:16
    |
 LL |     if let X..=true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -447,7 +302,7 @@ LL |     if let X..=true = 0 {}
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^   - this is of type `u8`
@@ -455,7 +310,7 @@ LL |     if let .0..=Y = 0 {}
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:37:16
    |
 LL |     if let X..=.0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -464,7 +319,7 @@ LL |     if let X..=.0 = 0 {}
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:45:12
+  --> $DIR/recover-range-pats.rs:46:12
    |
 LL |     if let true...Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -472,7 +327,7 @@ LL |     if let true...Y = 0 {}
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:47:16
+  --> $DIR/recover-range-pats.rs:48:16
    |
 LL |     if let X...true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -480,7 +335,7 @@ LL |     if let X...true = 0 {}
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:49:12
+  --> $DIR/recover-range-pats.rs:50:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^   - this is of type `u8`
@@ -488,7 +343,7 @@ LL |     if let .0...Y = 0 {}
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:52:17
+  --> $DIR/recover-range-pats.rs:53:17
    |
 LL |     if let X... .0 = 0 {}
    |            -    ^^   - this expression has type `u8`
@@ -497,78 +352,78 @@ LL |     if let X... .0 = 0 {}
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:60:12
+  --> $DIR/recover-range-pats.rs:61:12
    |
 LL |     if let true.. = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:62:12
+  --> $DIR/recover-range-pats.rs:63:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:70:12
+  --> $DIR/recover-range-pats.rs:71:12
    |
 LL |     if let true..= = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:82:12
+  --> $DIR/recover-range-pats.rs:81:12
    |
 LL |     if let true... = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:85:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:94:14
+  --> $DIR/recover-range-pats.rs:91:14
    |
 LL |     if let ..true = 0 {}
    |              ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:96:15
+  --> $DIR/recover-range-pats.rs:93:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:104:15
+  --> $DIR/recover-range-pats.rs:101:15
    |
 LL |     if let ..=true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:106:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:116:15
+  --> $DIR/recover-range-pats.rs:113:15
    |
 LL |     if let ...true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:119:15
+  --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ expected integer, found floating-point number
 
-error: aborting due to 85 previous errors
+error: aborting due to 60 previous errors
 
-Some errors have detailed explanations: E0029, E0308.
+Some errors have detailed explanations: E0029, E0308, E0586.
 For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
index dec5809f153..96401cb71d9 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `A` in the current scope
+error[E0599]: no method named `foo` found for struct `A` in the current scope
   --> $DIR/point-at-arbitrary-self-type-method.rs:8:7
    |
 LL | struct A;
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
index e93c4da9dfc..28a7b68a682 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `A` in the current scope
+error[E0599]: no method named `foo` found for struct `A` in the current scope
   --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7
    |
 LL | trait B { fn foo(self: Box<Self>); }
diff --git a/src/test/ui/self/suggest-self-2.rs b/src/test/ui/self/suggest-self-2.rs
index d6bf5433527..1e001827e47 100644
--- a/src/test/ui/self/suggest-self-2.rs
+++ b/src/test/ui/self/suggest-self-2.rs
@@ -18,7 +18,7 @@ impl Foo {
         //~^ ERROR cannot find function `bar` in this scope
 
         self.bar();
-        //~^ ERROR no method named `bar` found for type
+        //~^ ERROR no method named `bar` found for reference
     }
 }
 
diff --git a/src/test/ui/self/suggest-self-2.stderr b/src/test/ui/self/suggest-self-2.stderr
index 452c3127515..4bd025ea076 100644
--- a/src/test/ui/self/suggest-self-2.stderr
+++ b/src/test/ui/self/suggest-self-2.stderr
@@ -28,7 +28,7 @@ error[E0425]: cannot find function `bar` in this scope
 LL |         bar();
    |         ^^^ not found in this scope
 
-error[E0599]: no method named `bar` found for type `&Foo` in the current scope
+error[E0599]: no method named `bar` found for reference `&Foo` in the current scope
   --> $DIR/suggest-self-2.rs:20:14
    |
 LL |         self.bar();
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr
index 3597cc53420..362907ecbd7 100644
--- a/src/test/ui/shadowed/shadowed-trait-methods.stderr
+++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `()` in the current scope
+error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/shadowed-trait-methods.rs:13:8
    |
 LL |     ().f()
diff --git a/src/test/ui/span/issue-7575.rs b/src/test/ui/span/issue-7575.rs
index ea0a66540b9..eddd158aef0 100644
--- a/src/test/ui/span/issue-7575.rs
+++ b/src/test/ui/span/issue-7575.rs
@@ -60,15 +60,15 @@ impl ManyImplTrait for Myisize {}
 
 fn no_param_bound(u: usize, m: Myisize) -> usize {
     u.f8(42) + u.f9(342) + m.fff(42)
-            //~^ ERROR no method named `f9` found for type `usize` in the current scope
-            //~| ERROR no method named `fff` found for type `Myisize` in the current scope
+            //~^ ERROR no method named `f9` found
+            //~| ERROR no method named `fff` found
 
 
 }
 
 fn param_bound<T: ManyImplTrait>(t: T) -> bool {
     t.is_str()
-    //~^ ERROR no method named `is_str` found for type `T` in the current scope
+    //~^ ERROR no method named `is_str` found
 }
 
 fn main() {
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index 53a6238422b..eb85be039ba 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -38,7 +38,7 @@ help: disambiguate the method call for candidate #3
 LL |     u.f8(42) + UnusedTrait::f9(u, 342) + m.fff(42)
    |                ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `fff` found for type `Myisize` in the current scope
+error[E0599]: no method named `fff` found for struct `Myisize` in the current scope
   --> $DIR/issue-7575.rs:62:30
    |
 LL | struct Myisize(isize);
@@ -57,7 +57,7 @@ note: the candidate is defined in an impl for the type `Myisize`
 LL |     fn fff(i: isize) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `is_str` found for type `T` in the current scope
+error[E0599]: no method named `is_str` found for type parameter `T` in the current scope
   --> $DIR/issue-7575.rs:70:7
    |
 LL |     t.is_str()
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
index 34a14168573..5c104449fe9 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -20,5 +20,5 @@ default impl<T> Foo for T {
 
 fn main() {
     println!("{}", MyStruct.foo_one());
-    //~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
+    //~^ ERROR no method named `foo_one` found
 }
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index bbfe4c3d59d..19809778a5e 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo_one` found for type `MyStruct` in the current scope
+error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
   --> $DIR/specialization-trait-not-implemented.rs:22:29
    |
 LL | struct MyStruct;
diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed
index dda9e931353..f292f27f0f3 100644
--- a/src/test/ui/suggestions/constrain-trait.fixed
+++ b/src/test/ui/suggestions/constrain-trait.fixed
@@ -12,13 +12,13 @@ trait GetString {
 
 trait UseString: std::fmt::Debug + GetString {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
 trait UseString2: GetString {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs
index 4ef0eff5bd7..99ccf7a7f3b 100644
--- a/src/test/ui/suggestions/constrain-trait.rs
+++ b/src/test/ui/suggestions/constrain-trait.rs
@@ -12,13 +12,13 @@ trait GetString {
 
 trait UseString: std::fmt::Debug {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
 trait UseString2 {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr
index 3cc351ac80a..f1c50e59a84 100644
--- a/src/test/ui/suggestions/constrain-trait.stderr
+++ b/src/test/ui/suggestions/constrain-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
   --> $DIR/constrain-trait.rs:15:31
    |
 LL |         println!("{:?}", self.get_a());
@@ -10,7 +10,7 @@ help: the following trait defines an item `get_a`, perhaps you need to add anoth
 LL | trait UseString: std::fmt::Debug + GetString {
    |                                  ^^^^^^^^^^^
 
-error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
   --> $DIR/constrain-trait.rs:21:31
    |
 LL |         println!("{:?}", self.get_a());
diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
index 4aec72006ee..db54d044d9e 100644
--- a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
+++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `hello` found for type `impl Foo` in the current scope
+error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope
   --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9
    |
 LL |     foo.hello();
diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr
index f2496f696d6..14c7b18ea51 100644
--- a/src/test/ui/suggestions/issue-21673.stderr
+++ b/src/test/ui/suggestions/issue-21673.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for type `&T` in the current scope
+error[E0599]: no method named `method` found for reference `&T` in the current scope
   --> $DIR/issue-21673.rs:6:7
    |
 LL |     x.method()
@@ -10,7 +10,7 @@ help: the following trait defines an item `method`, perhaps you need to restrict
 LL | fn call_method<T: Foo + std::fmt::Debug>(x: &T) {
    |                ^^^^^^^^
 
-error[E0599]: no method named `method` found for type `T` in the current scope
+error[E0599]: no method named `method` found for type parameter `T` in the current scope
   --> $DIR/issue-21673.rs:10:7
    |
 LL |     x.method()
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
index dcef2ada63b..f8b86377187 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
@@ -19,5 +19,5 @@ fn main() {
     //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
     //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
 
-    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type
+    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for struct
 }
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index daa8e1162d1..2c3c07c19e7 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -25,7 +25,7 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
    = note: required by `std::io::BufWriter`
 
-error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope
+error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope
   --> $DIR/mut-borrow-needed-by-trait.rs:22:5
    |
 LL |     writeln!(fp, "hello world").unwrap();
diff --git a/src/test/ui/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs
index d10300b48ba..289a784ba6a 100644
--- a/src/test/ui/suggestions/remove-as_str.rs
+++ b/src/test/ui/suggestions/remove-as_str.rs
@@ -1,21 +1,21 @@
 fn foo1(s: &str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo2<'a>(s: &'a str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&'a str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo3(s: &mut str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&mut str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo4(s: &&str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&&str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn main() {}
diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr
index eae9cc07508..534c497780a 100644
--- a/src/test/ui/suggestions/remove-as_str.stderr
+++ b/src/test/ui/suggestions/remove-as_str.stderr
@@ -1,22 +1,22 @@
-error[E0599]: no method named `as_str` found for type `&str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&str` in the current scope
   --> $DIR/remove-as_str.rs:2:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&'a str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&'a str` in the current scope
   --> $DIR/remove-as_str.rs:7:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&mut str` in the current scope
+error[E0599]: no method named `as_str` found for mutable reference `&mut str` in the current scope
   --> $DIR/remove-as_str.rs:12:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&&str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&&str` in the current scope
   --> $DIR/remove-as_str.rs:17:7
    |
 LL |     s.as_str();
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
index 5480adb3101..f738a1f2119 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
@@ -9,5 +9,5 @@ fn main() {
     let shared_state = RefCell::new(HasAssocMethod);
     let state = shared_state.borrow_mut();
     state.hello();
-    //~^ ERROR no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>`
+    //~^ ERROR no method named `hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
index a1c0126146e..507f822e7b8 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
+error[E0599]: no method named `hello` found for struct `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
   --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
    |
 LL |     state.hello();
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
index ef4b38de947..2a829db5383 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
@@ -7,5 +7,5 @@ impl<T> GenericAssocMethod<T> {
 fn main() {
     let x = GenericAssocMethod(33i32);
     x.default_hello();
-    //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod<i32>`
+    //~^ ERROR no method named `default_hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
index 8cfa7de08bb..dfc1887d3af 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `default_hello` found for type `GenericAssocMethod<i32>` in the current scope
+error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope
   --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7
    |
 LL | struct GenericAssocMethod<T>(T);
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index 4678410eb48..a715c565946 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `bat` found for type `Foo` in the current scope
+error[E0599]: no method named `bat` found for struct `Foo` in the current scope
   --> $DIR/suggest-methods.rs:18:7
    |
 LL | struct Foo;
@@ -7,7 +7,7 @@ LL | struct Foo;
 LL |     f.bat(1.0);
    |       ^^^ help: there is a method with a similar name: `bar`
 
-error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
+error[E0599]: no method named `is_emtpy` found for struct `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy();
diff --git a/src/test/ui/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs
index d418834432e..dd05d0f04ab 100644
--- a/src/test/ui/suggestions/suggest-variants.rs
+++ b/src/test/ui/suggestions/suggest-variants.rs
@@ -9,9 +9,9 @@ struct S {
 }
 
 fn main() {
-    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant `Squareee`
-    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant `Circl`
-    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant `Rombus`
+    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant named `Squareee`
+    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant named `Circl`
+    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant named `Rombus`
     Shape::Squareee; //~ ERROR no variant
     Shape::Circl; //~ ERROR no variant
     Shape::Rombus; //~ ERROR no variant
diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr
index b4338e20554..9227baa3e1a 100644
--- a/src/test/ui/suggestions/suggest-variants.stderr
+++ b/src/test/ui/suggestions/suggest-variants.stderr
@@ -1,4 +1,4 @@
-error: no variant `Squareee` in enum `Shape`
+error[E0599]: no variant named `Squareee` found for enum `Shape`
   --> $DIR/suggest-variants.rs:12:41
    |
 LL | enum Shape {
@@ -7,7 +7,7 @@ LL | enum Shape {
 LL |     println!("My shape is {:?}", Shape::Squareee { size: 5});
    |                                         ^^^^^^^^ help: there is a variant with a similar name: `Square`
 
-error: no variant `Circl` in enum `Shape`
+error[E0599]: no variant named `Circl` found for enum `Shape`
   --> $DIR/suggest-variants.rs:13:41
    |
 LL | enum Shape {
@@ -16,7 +16,7 @@ LL | enum Shape {
 LL |     println!("My shape is {:?}", Shape::Circl { size: 5});
    |                                         ^^^^^ help: there is a variant with a similar name: `Circle`
 
-error: no variant `Rombus` in enum `Shape`
+error[E0599]: no variant named `Rombus` found for enum `Shape`
   --> $DIR/suggest-variants.rs:14:41
    |
 LL | enum Shape {
@@ -25,7 +25,7 @@ LL | enum Shape {
 LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
    |                                         ^^^^^^ variant not found in `Shape`
 
-error[E0599]: no variant or associated item named `Squareee` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Squareee` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:15:12
    |
 LL | enum Shape {
@@ -37,7 +37,7 @@ LL |     Shape::Squareee;
    |            variant or associated item not found in `Shape`
    |            help: there is a variant with a similar name: `Square`
 
-error[E0599]: no variant or associated item named `Circl` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:16:12
    |
 LL | enum Shape {
@@ -49,7 +49,7 @@ LL |     Shape::Circl;
    |            variant or associated item not found in `Shape`
    |            help: there is a variant with a similar name: `Circle`
 
-error[E0599]: no variant or associated item named `Rombus` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:17:12
    |
 LL | enum Shape {
diff --git a/src/test/ui/traits/trait-impl-1.rs b/src/test/ui/traits/trait-impl-1.rs
index 43b82221835..d22ac72d1cc 100644
--- a/src/test/ui/traits/trait-impl-1.rs
+++ b/src/test/ui/traits/trait-impl-1.rs
@@ -12,5 +12,5 @@ impl T for i32 {}
 
 fn main() {
     let x = &42i32;
-    x.foo(); //~ERROR: no method named `foo` found for type `&i32` in the current scope
+    x.foo(); //~ERROR: no method named `foo` found
 }
diff --git a/src/test/ui/traits/trait-impl-1.stderr b/src/test/ui/traits/trait-impl-1.stderr
index 0d61c3ed00d..da0936e8eeb 100644
--- a/src/test/ui/traits/trait-impl-1.stderr
+++ b/src/test/ui/traits/trait-impl-1.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&i32` in the current scope
+error[E0599]: no method named `foo` found for reference `&i32` in the current scope
   --> $DIR/trait-impl-1.rs:15:7
    |
 LL |     x.foo();
diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs
index d58bbef38c4..8507d8ef17e 100644
--- a/src/test/ui/traits/trait-item-privacy.rs
+++ b/src/test/ui/traits/trait-item-privacy.rs
@@ -64,8 +64,8 @@ fn check_method() {
 
     // Methods, method call
     // a, b, c are resolved as trait items, their traits need to be in scope
-    S.a(); //~ ERROR no method named `a` found for type `S` in the current scope
-    S.b(); //~ ERROR no method named `b` found for type `S` in the current scope
+    S.a(); //~ ERROR no method named `a` found
+    S.b(); //~ ERROR no method named `b` found
     S.c(); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     let c = &S as &dyn C;
@@ -76,9 +76,9 @@ fn check_method() {
     // Methods, UFCS
     // a, b, c are resolved as trait items, their traits need to be in scope
     S::a(&S);
-    //~^ ERROR no function or associated item named `a` found for type `S`
+    //~^ ERROR no function or associated item named `a` found
     S::b(&S);
-    //~^ ERROR no function or associated item named `b` found for type `S`
+    //~^ ERROR no function or associated item named `b` found
     S::c(&S); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     C::a(&S); //~ ERROR method `a` is private
@@ -94,8 +94,8 @@ fn check_assoc_const() {
 
     // Associated constants
     // A, B, C are resolved as trait items, their traits need to be in scope
-    S::A; //~ ERROR no associated item named `A` found for type `S` in the current scope
-    S::B; //~ ERROR no associated item named `B` found for type `S` in the current scope
+    S::A; //~ ERROR no associated item named `A` found
+    S::B; //~ ERROR no associated item named `B` found
     S::C; // OK
     // A, B, C are resolved as inherent items, their traits don't need to be in scope
     C::A; //~ ERROR associated constant `A` is private
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
index 64a92c6b0b4..4df8845de27 100644
--- a/src/test/ui/traits/trait-item-privacy.stderr
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `a` found for type `S` in the current scope
+error[E0599]: no method named `a` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:67:7
    |
 LL | struct S;
@@ -11,7 +11,7 @@ LL |     S.a();
    = note: the following trait defines an item `a`, perhaps you need to implement it:
            candidate #1: `method::A`
 
-error[E0599]: no method named `b` found for type `S` in the current scope
+error[E0599]: no method named `b` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:68:7
    |
 LL | struct S;
@@ -39,7 +39,7 @@ error[E0624]: method `a` is private
 LL |     c.a();
    |       ^
 
-error[E0599]: no function or associated item named `a` found for type `S` in the current scope
+error[E0599]: no function or associated item named `a` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:78:8
    |
 LL | struct S;
@@ -52,7 +52,7 @@ LL |     S::a(&S);
    = note: the following trait defines an item `a`, perhaps you need to implement it:
            candidate #1: `method::A`
 
-error[E0599]: no function or associated item named `b` found for type `S` in the current scope
+error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:80:8
    |
 LL | struct S;
@@ -73,7 +73,7 @@ error[E0624]: method `a` is private
 LL |     C::a(&S);
    |     ^^^^
 
-error[E0599]: no associated item named `A` found for type `S` in the current scope
+error[E0599]: no associated item named `A` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:97:8
    |
 LL | struct S;
@@ -86,7 +86,7 @@ LL |     S::A;
    = note: the following trait defines an item `A`, perhaps you need to implement it:
            candidate #1: `assoc_const::A`
 
-error[E0599]: no associated item named `B` found for type `S` in the current scope
+error[E0599]: no associated item named `B` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:98:8
    |
 LL | struct S;
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
index 82a593ff16c..66d4db3ebaf 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.rs
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -35,7 +35,7 @@ fn main() {
     <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
     let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
     let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
-    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y`
+    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found
     <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
 
     let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
@@ -52,5 +52,5 @@ fn main() {
     let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
     let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
-    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X`
+    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found
 }
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index dbd41da6daf..60ebe8ee053 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -207,13 +207,13 @@ error[E0223]: ambiguous associated type
 LL |     let _: <u8 as Tr>::Y::NN;
    |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
 
-error[E0599]: no associated item named `NN` found for type `<u8 as Tr>::Y` in the current scope
+error[E0599]: no associated item named `NN` found for associated type `<u8 as Tr>::Y` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:38:20
    |
 LL |     <u8 as Tr>::Y::NN;
    |                    ^^ associated item not found in `<u8 as Tr>::Y`
 
-error[E0599]: no associated item named `N` found for type `<u8 as Dr>::X` in the current scope
+error[E0599]: no associated item named `N` found for associated type `<u8 as Dr>::X` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:55:20
    |
 LL |     <u8 as Dr>::X::N;
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
index 18276d5710c..2d058521e4e 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `call` found for type `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr
index 44cfc5cc5d2..29836137860 100644
--- a/src/test/ui/underscore-imports/hygiene.stderr
+++ b/src/test/ui/underscore-imports/hygiene.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `deref` found for type `&()` in the current scope
+error[E0599]: no method named `deref` found for reference `&()` in the current scope
   --> $DIR/hygiene.rs:38:11
    |
 LL |     (&()).deref();
@@ -10,7 +10,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use std::ops::Deref;
    |
 
-error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope
+error[E0599]: no method named `deref_mut` found for mutable reference `&mut ()` in the current scope
   --> $DIR/hygiene.rs:39:15
    |
 LL |     (&mut ()).deref_mut();
diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr
index 102c17f6f56..eb16fa9d566 100644
--- a/src/test/ui/underscore-imports/shadow.stderr
+++ b/src/test/ui/underscore-imports/shadow.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `deref` found for type `&()` in the current scope
+error[E0599]: no method named `deref` found for reference `&()` in the current scope
   --> $DIR/shadow.rs:19:11
    |
 LL |         x.deref();
diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs
index 60e280f53f5..4a106cc940a 100644
--- a/src/test/ui/union/union-derive-clone.rs
+++ b/src/test/ui/union/union-derive-clone.rs
@@ -34,5 +34,5 @@ struct CloneNoCopy;
 
 fn main() {
     let u = U5 { a: ManuallyDrop::new(CloneNoCopy) };
-    let w = u.clone(); //~ ERROR no method named `clone` found for type `U5<CloneNoCopy>`
+    let w = u.clone(); //~ ERROR no method named `clone` found for union `U5<CloneNoCopy>`
 }
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index 6893f9176f2..0ef5753b590 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -6,7 +6,7 @@ LL | #[derive(Clone)]
    |
    = note: required by `std::clone::AssertParamIsCopy`
 
-error[E0599]: no method named `clone` found for type `U5<CloneNoCopy>` in the current scope
+error[E0599]: no method named `clone` found for union `U5<CloneNoCopy>` in the current scope
   --> $DIR/union-derive-clone.rs:37:15
    |
 LL | union U5<T> {
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index cd46878c19b..92cda6482c0 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `std::boxed::Box<dyn Foo>` in the current scope
+error[E0599]: no method named `clone` found for struct `std::boxed::Box<dyn Foo>` in the current scope
   --> $DIR/unique-object-noncopyable.rs:24:16
    |
 LL |     let _z = y.clone();
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index 19ef2b21c26..e5c3eaccbd3 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `std::boxed::Box<R>` in the current scope
+error[E0599]: no method named `clone` found for struct `std::boxed::Box<R>` in the current scope
   --> $DIR/unique-pinned-nocopy.rs:12:16
    |
 LL |     let _j = i.clone();
diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr
index b72d45ebdbf..e057a7842b2 100644
--- a/src/test/ui/unspecified-self-in-trait-ref.stderr
+++ b/src/test/ui/unspecified-self-in-trait-ref.stderr
@@ -1,22 +1,22 @@
-error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:10:18
    |
 LL |     let a = Foo::lol();
    |                  ^^^ function or associated item not found in `dyn Foo<_>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:12:23
    |
 LL |     let b = Foo::<_>::lol();
    |                       ^^^ function or associated item not found in `dyn Foo<_>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Bar<_, _>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<_, _>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:14:18
    |
 LL |     let c = Bar::lol();
    |                  ^^^ function or associated item not found in `dyn Bar<_, _>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Bar<usize, _>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<usize, _>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:16:30
    |
 LL |     let d = Bar::<usize, _>::lol();
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject e8642c7a2900bed28003a98d4db8b62290ac802
+Subproject 43ac9416d935942d6c7d2b2e0c876c551652c4e
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index da1e3760e01..0642823404a 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,6 +1,8 @@
 #![crate_name = "compiletest"]
-#![feature(test)]
 #![deny(warnings)]
+// The `test` crate is the only unstable feature
+// allowed here, just to share similar code.
+#![feature(test)]
 
 extern crate test;