about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--library/core/src/convert/mod.rs1
-rw-r--r--library/core/src/future/future.rs1
-rw-r--r--library/core/src/future/mod.rs2
-rw-r--r--library/core/src/iter/traits/collect.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs1
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/ops/range.rs7
-rw-r--r--library/core/src/ops/try.rs3
-rw-r--r--library/core/src/option.rs2
-rw-r--r--library/core/src/pin.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs148
-rw-r--r--library/core/src/ptr/mut_ptr.rs287
-rw-r--r--library/core/src/ptr/non_null.rs241
-rw-r--r--library/core/src/result.rs2
-rw-r--r--library/core/src/task/poll.rs2
-rw-r--r--library/std/src/alloc.rs9
-rw-r--r--library/std/src/ascii.rs23
-rw-r--r--library/std/src/env.rs41
-rw-r--r--library/std/src/error.rs28
-rw-r--r--library/std/src/panic.rs17
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/librustc_ast/lib.rs2
-rw-r--r--src/librustc_ast_lowering/expr.rs167
-rw-r--r--src/librustc_ast_lowering/item.rs2
-rw-r--r--src/librustc_ast_lowering/lib.rs113
-rw-r--r--src/librustc_ast_lowering/pat.rs2
-rw-r--r--src/librustc_ast_lowering/path.rs2
-rw-r--r--src/librustc_ast_passes/ast_validation.rs2
-rw-r--r--src/librustc_ast_passes/feature_gate.rs5
-rw-r--r--src/librustc_ast_passes/node_count.rs2
-rw-r--r--src/librustc_ast_passes/show_span.rs2
-rw-r--r--src/librustc_ast_pretty/pprust.rs20
-rw-r--r--src/librustc_ast_pretty/pprust/tests.rs2
-rw-r--r--src/librustc_attr/builtin.rs2
-rw-r--r--src/librustc_builtin_macros/Cargo.toml2
-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.rs2
-rw-r--r--src/librustc_builtin_macros/cfg_accessible.rs2
-rw-r--r--src/librustc_builtin_macros/cmdline_attrs.rs2
-rw-r--r--src/librustc_builtin_macros/concat.rs2
-rw-r--r--src/librustc_builtin_macros/concat_idents.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/bounds.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/clone.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/cmp/eq.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/cmp/ord.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/cmp/partial_eq.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/cmp/partial_ord.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/debug.rs3
-rw-r--r--src/librustc_builtin_macros/deriving/decodable.rs3
-rw-r--r--src/librustc_builtin_macros/deriving/default.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/encodable.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/generic/mod.rs4
-rw-r--r--src/librustc_builtin_macros/deriving/generic/ty.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/hash.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/mod.rs3
-rw-r--r--src/librustc_builtin_macros/env.rs2
-rw-r--r--src/librustc_builtin_macros/format.rs2
-rw-r--r--src/librustc_builtin_macros/global_allocator.rs4
-rw-r--r--src/librustc_builtin_macros/global_asm.rs2
-rw-r--r--src/librustc_builtin_macros/llvm_asm.rs3
-rw-r--r--src/librustc_builtin_macros/proc_macro_harness.rs2
-rw-r--r--src/librustc_builtin_macros/source_util.rs2
-rw-r--r--src/librustc_builtin_macros/standard_library_imports.rs2
-rw-r--r--src/librustc_builtin_macros/test.rs4
-rw-r--r--src/librustc_builtin_macros/test_harness.rs4
-rw-r--r--src/librustc_builtin_macros/util.rs2
-rw-r--r--src/librustc_codegen_llvm/Cargo.toml2
-rw-r--r--src/librustc_codegen_llvm/asm.rs6
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs2
-rw-r--r--src/librustc_codegen_llvm/back/write.rs2
-rw-r--r--src/librustc_codegen_llvm/builder.rs6
-rw-r--r--src/librustc_codegen_llvm/callee.rs2
-rw-r--r--src/librustc_codegen_llvm/common.rs4
-rw-r--r--src/librustc_codegen_llvm/consts.rs2
-rw-r--r--src/librustc_codegen_llvm/coverageinfo/mapgen.rs2
-rw-r--r--src/librustc_codegen_llvm/coverageinfo/mod.rs2
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs4
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs2
-rw-r--r--src/librustc_codegen_llvm/declare.rs2
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs5
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs6
-rw-r--r--src/librustc_codegen_llvm/metadata.rs2
-rw-r--r--src/librustc_codegen_llvm/mono_item.rs2
-rw-r--r--src/librustc_codegen_llvm/type_.rs2
-rw-r--r--src/librustc_codegen_llvm/type_of.rs2
-rw-r--r--src/librustc_codegen_ssa/Cargo.toml2
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs2
-rw-r--r--src/librustc_codegen_ssa/lib.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/asm.rs2
-rw-r--r--src/librustc_data_structures/Cargo.toml4
-rw-r--r--src/librustc_data_structures/lib.rs2
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_driver/pretty.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0754.md20
-rw-r--r--src/librustc_errors/diagnostic.rs15
-rw-r--r--src/librustc_errors/diagnostic_builder.rs14
-rw-r--r--src/librustc_expand/base.rs2
-rw-r--r--src/librustc_expand/build.rs2
-rw-r--r--src/librustc_expand/config.rs2
-rw-r--r--src/librustc_expand/expand.rs4
-rw-r--r--src/librustc_expand/mbe/macro_check.rs2
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs2
-rw-r--r--src/librustc_expand/mbe/quoted.rs2
-rw-r--r--src/librustc_expand/mbe/transcribe.rs2
-rw-r--r--src/librustc_expand/module.rs3
-rw-r--r--src/librustc_expand/mut_visit/tests.rs2
-rw-r--r--src/librustc_expand/parse/tests.rs2
-rw-r--r--src/librustc_expand/placeholders.rs2
-rw-r--r--src/librustc_expand/proc_macro.rs2
-rw-r--r--src/librustc_expand/proc_macro_server.rs2
-rw-r--r--src/librustc_expand/tests.rs2
-rw-r--r--src/librustc_hir/arena.rs4
-rw-r--r--src/librustc_hir/def.rs4
-rw-r--r--src/librustc_hir/hir.rs120
-rw-r--r--src/librustc_hir/intravisit.rs7
-rw-r--r--src/librustc_hir/lang_items.rs38
-rw-r--r--src/librustc_hir/target.rs2
-rw-r--r--src/librustc_hir/weak_lang_items.rs2
-rw-r--r--src/librustc_hir_pretty/lib.rs12
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs2
-rw-r--r--src/librustc_incremental/assert_module_sources.rs2
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs2
-rw-r--r--src/librustc_infer/infer/combine.rs2
-rw-r--r--src/librustc_interface/interface.rs2
-rw-r--r--src/librustc_interface/passes.rs2
-rw-r--r--src/librustc_interface/queries.rs2
-rw-r--r--src/librustc_interface/util.rs3
-rw-r--r--src/librustc_lint/builtin.rs8
-rw-r--r--src/librustc_lint/context.rs4
-rw-r--r--src/librustc_lint/early.rs2
-rw-r--r--src/librustc_lint/internal.rs2
-rw-r--r--src/librustc_lint/late.rs2
-rw-r--r--src/librustc_lint/levels.rs2
-rw-r--r--src/librustc_lint/lib.rs2
-rw-r--r--src/librustc_lint/non_ascii_idents.rs2
-rw-r--r--src/librustc_lint/nonstandard_style.rs2
-rw-r--r--src/librustc_lint/passes.rs2
-rw-r--r--src/librustc_lint/redundant_semicolon.rs2
-rw-r--r--src/librustc_lint/types.rs10
-rw-r--r--src/librustc_lint/unused.rs6
-rw-r--r--src/librustc_metadata/creader.rs2
-rw-r--r--src/librustc_metadata/locator.rs14
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs2
-rw-r--r--src/librustc_metadata/rmeta/decoder/cstore_impl.rs2
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs2
-rw-r--r--src/librustc_metadata/rmeta/mod.rs2
-rw-r--r--src/librustc_middle/arena.rs4
-rw-r--r--src/librustc_middle/hir/map/blocks.rs2
-rw-r--r--src/librustc_middle/hir/map/mod.rs2
-rw-r--r--src/librustc_middle/ich/hcx.rs2
-rw-r--r--src/librustc_middle/ich/impls_syntax.rs2
-rw-r--r--src/librustc_middle/middle/cstore.rs2
-rw-r--r--src/librustc_middle/middle/limits.rs2
-rw-r--r--src/librustc_middle/middle/stability.rs2
-rw-r--r--src/librustc_middle/mir/interpret/allocation.rs2
-rw-r--r--src/librustc_middle/mir/interpret/mod.rs2
-rw-r--r--src/librustc_middle/mir/mod.rs2
-rw-r--r--src/librustc_middle/mir/terminator/mod.rs4
-rw-r--r--src/librustc_middle/ty/cast.rs2
-rw-r--r--src/librustc_middle/ty/context.rs4
-rw-r--r--src/librustc_middle/ty/error.rs2
-rw-r--r--src/librustc_middle/ty/fast_reject.rs2
-rw-r--r--src/librustc_middle/ty/layout.rs2
-rw-r--r--src/librustc_middle/ty/mod.rs2
-rw-r--r--src/librustc_middle/ty/print/pretty.rs2
-rw-r--r--src/librustc_middle/ty/query/mod.rs2
-rw-r--r--src/librustc_middle/ty/query/on_disk_cache.rs4
-rw-r--r--src/librustc_middle/ty/structural_impls.rs8
-rw-r--r--src/librustc_middle/ty/sty.rs2
-rw-r--r--src/librustc_middle/ty/util.rs2
-rw-r--r--src/librustc_mir/const_eval/machine.rs2
-rw-r--r--src/librustc_mir/dataflow/framework/engine.rs2
-rw-r--r--src/librustc_mir/dataflow/mod.rs2
-rw-r--r--src/librustc_mir/interpret/cast.rs2
-rw-r--r--src/librustc_mir/interpret/intern.rs2
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs42
-rw-r--r--src/librustc_mir/interpret/machine.rs10
-rw-r--r--src/librustc_mir/interpret/memory.rs25
-rw-r--r--src/librustc_mir/interpret/operator.rs2
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs2
-rw-r--r--src/librustc_mir/transform/promote_consts.rs2
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs2
-rw-r--r--src/librustc_mir/transform/simplify_try.rs259
-rw-r--r--src/librustc_mir_build/build/expr/into.rs2
-rw-r--r--src/librustc_mir_build/thir/constant.rs2
-rw-r--r--src/librustc_mir_build/thir/cx/mod.rs2
-rw-r--r--src/librustc_mir_build/thir/mod.rs2
-rw-r--r--src/librustc_mir_build/thir/pattern/check_match.rs2
-rw-r--r--src/librustc_mir_build/thir/pattern/mod.rs2
-rw-r--r--src/librustc_parse/lib.rs2
-rw-r--r--src/librustc_parse/parser/attr.rs2
-rw-r--r--src/librustc_parse/parser/diagnostics.rs8
-rw-r--r--src/librustc_parse/parser/expr.rs6
-rw-r--r--src/librustc_parse/parser/generics.rs4
-rw-r--r--src/librustc_parse/parser/item.rs14
-rw-r--r--src/librustc_parse/parser/mod.rs8
-rw-r--r--src/librustc_parse/parser/pat.rs4
-rw-r--r--src/librustc_parse/parser/path.rs8
-rw-r--r--src/librustc_parse/parser/stmt.rs6
-rw-r--r--src/librustc_parse/parser/ty.rs6
-rw-r--r--src/librustc_parse/validate_attr.rs2
-rw-r--r--src/librustc_passes/check_attr.rs2
-rw-r--r--src/librustc_passes/dead.rs2
-rw-r--r--src/librustc_passes/diagnostic_items.rs2
-rw-r--r--src/librustc_passes/hir_stats.rs2
-rw-r--r--src/librustc_passes/intrinsicck.rs2
-rw-r--r--src/librustc_passes/lang_items.rs10
-rw-r--r--src/librustc_passes/layout_test.rs2
-rw-r--r--src/librustc_passes/lib_features.rs2
-rw-r--r--src/librustc_passes/liveness.rs8
-rw-r--r--src/librustc_passes/stability.rs2
-rw-r--r--src/librustc_plugin_impl/load.rs2
-rw-r--r--src/librustc_privacy/lib.rs6
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs4
-rw-r--r--src/librustc_resolve/check_unused.rs2
-rw-r--r--src/librustc_resolve/def_collector.rs2
-rw-r--r--src/librustc_resolve/diagnostics.rs2
-rw-r--r--src/librustc_resolve/imports.rs2
-rw-r--r--src/librustc_resolve/late.rs2
-rw-r--r--src/librustc_resolve/late/diagnostics.rs2
-rw-r--r--src/librustc_resolve/late/lifetimes.rs28
-rw-r--r--src/librustc_resolve/lib.rs37
-rw-r--r--src/librustc_resolve/macros.rs2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs28
-rw-r--r--src/librustc_save_analysis/lib.rs41
-rw-r--r--src/librustc_save_analysis/sig.rs5
-rw-r--r--src/librustc_session/output.rs2
-rw-r--r--src/librustc_session/session.rs2
-rw-r--r--src/librustc_span/symbol.rs2
-rw-r--r--src/librustc_symbol_mangling/v0.rs2
-rw-r--r--src/librustc_trait_selection/traits/on_unimplemented.rs2
-rw-r--r--src/librustc_traits/chalk/lowering.rs2
-rw-r--r--src/librustc_traits/chalk/mod.rs2
-rw-r--r--src/librustc_typeck/astconv.rs48
-rw-r--r--src/librustc_typeck/check/cast.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs3
-rw-r--r--src/librustc_typeck/check/expr.rs20
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs85
-rw-r--r--src/librustc_typeck/check/pat.rs10
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs2
-rw-r--r--src/librustc_typeck/collect.rs32
-rw-r--r--src/librustdoc/clean/cfg.rs2
-rw-r--r--src/librustdoc/clean/cfg/tests.rs2
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs22
-rw-r--r--src/librustdoc/clean/types.rs4
-rw-r--r--src/librustdoc/clean/utils.rs1
-rw-r--r--src/librustdoc/doctree.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs30
-rw-r--r--src/librustdoc/test.rs2
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/test/mir-opt/simplify-arm.rs2
-rw-r--r--src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff20
-rw-r--r--src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff38
-rw-r--r--src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff40
-rw-r--r--src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff47
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff112
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff96
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit17
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit17
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs2
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-tool-test.rs2
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs2
-rw-r--r--src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs11
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs2
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr14
-rw-r--r--src/test/ui/consts/ptr_comparisons.rs78
-rw-r--r--src/test/ui/consts/ptr_comparisons.stderr47
-rw-r--r--src/test/ui/consts/ptr_is_null.rs16
-rw-r--r--src/test/ui/hygiene/hir-res-hygiene.rs18
-rw-r--r--src/test/ui/range/range-1.stderr6
-rw-r--r--src/test/ui/suggestions/chain-method-call-mutation-in-place.rs4
-rw-r--r--src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr20
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/default_trait_access.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/match_on_vec_items.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmuting_null.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/try_err.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/higher.rs98
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/hir_utils.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/inspector.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/paths.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/sugg.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs2
-rw-r--r--src/tools/clippy/tests/ui/author/for_loop.stdout16
309 files changed, 2239 insertions, 1293 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c1fa3bef07c..5c767817ae5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4345,9 +4345,9 @@ checksum = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
 
 [[package]]
 name = "stacker"
-version = "0.1.9"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72dd941b456e1c006d6b9f27c526d5b69281288aeea8cba82c19d3843d8ccdd2"
+checksum = "a92bc346006ae78c539d6ab2cf1a1532bc657b8339c464877a990ec82073c66f"
 dependencies = [
  "cc",
  "cfg-if",
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 03b798d57db..fcd07befae5 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -385,6 +385,7 @@ pub trait Into<T>: Sized {
 ))]
 pub trait From<T>: Sized {
     /// Performs the conversion.
+    #[cfg_attr(not(bootstrap), lang = "from")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn from(_: T) -> Self;
 }
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index 733ebdc0e97..8169c146137 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -96,6 +96,7 @@ pub trait Future {
     /// [`Context`]: ../task/struct.Context.html
     /// [`Waker`]: ../task/struct.Waker.html
     /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
+    #[cfg_attr(not(bootstrap), lang = "poll")]
     #[stable(feature = "futures_api", since = "1.36.0")]
     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
 }
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 6d1ad9db744..d44ef857c13 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -53,6 +53,7 @@ unsafe impl Sync for ResumeTy {}
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
 // This is `const` to avoid extra errors after we recover from `const async fn`
+#[cfg_attr(not(bootstrap), lang = "from_generator")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[inline]
@@ -85,6 +86,7 @@ where
     GenFuture(gen)
 }
 
+#[cfg_attr(not(bootstrap), lang = "get_context")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[inline]
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 9d20022b6ed..84c7787a18f 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -235,6 +235,7 @@ pub trait IntoIterator {
     /// assert_eq!(Some(3), iter.next());
     /// assert_eq!(None, iter.next());
     /// ```
+    #[cfg_attr(not(bootstrap), lang = "into_iter")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn into_iter(self) -> Self::IntoIter;
 }
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index f89b616c4e2..81d8f27ec19 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -129,6 +129,7 @@ pub trait Iterator {
     /// assert_eq!(None, iter.next());
     /// assert_eq!(None, iter.next());
     /// ```
+    #[cfg_attr(not(bootstrap), lang = "next")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn next(&mut self) -> Option<Self::Item>;
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 763457d485d..3838fcf74cc 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -114,6 +114,7 @@
 #![feature(optin_builtin_traits)]
 #![feature(or_patterns)]
 #![feature(prelude_import)]
+#![feature(ptr_as_uninit)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
 #![feature(simd_ffi)]
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 179038d1977..e9ab82b5398 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -38,6 +38,7 @@ use crate::hash::Hash;
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[cfg_attr(not(bootstrap), lang = "RangeFull")]
 #[doc(alias = "..")]
 #[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -70,6 +71,7 @@ impl fmt::Debug for RangeFull {
 /// assert_eq!(arr[1.. 3], [  1,2    ]);  // Range
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
+#[cfg_attr(not(bootstrap), lang = "Range")]
 #[doc(alias = "..")]
 #[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -178,6 +180,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
 /// ```
 ///
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
+#[cfg_attr(not(bootstrap), lang = "RangeFrom")]
 #[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -260,6 +263,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[cfg_attr(not(bootstrap), lang = "RangeTo")]
 #[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -328,6 +332,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// assert_eq!(arr[1.. 3], [  1,2    ]);
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);  // RangeInclusive
 /// ```
+#[cfg_attr(not(bootstrap), lang = "RangeInclusive")]
 #[doc(alias = "..=")]
 #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
@@ -359,6 +364,7 @@ impl<Idx> RangeInclusive<Idx> {
     ///
     /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
     /// ```
+    #[cfg_attr(not(bootstrap), lang = "range_inclusive_new")]
     #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
     #[inline]
     #[rustc_promotable]
@@ -555,6 +561,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[cfg_attr(not(bootstrap), lang = "RangeToInclusive")]
 #[doc(alias = "..=")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "inclusive_range", since = "1.26.0")]
diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs
index 9bc35ae1f5c..e6b05cc641e 100644
--- a/library/core/src/ops/try.rs
+++ b/library/core/src/ops/try.rs
@@ -43,16 +43,19 @@ pub trait Try {
     /// in the return type of the enclosing scope (which must itself implement
     /// `Try`). Specifically, the value `X::from_error(From::from(e))`
     /// is returned, where `X` is the return type of the enclosing function.
+    #[cfg_attr(not(bootstrap), lang = "into_result")]
     #[unstable(feature = "try_trait", issue = "42327")]
     fn into_result(self) -> Result<Self::Ok, Self::Error>;
 
     /// Wrap an error value to construct the composite result. For example,
     /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
+    #[cfg_attr(not(bootstrap), lang = "from_error")]
     #[unstable(feature = "try_trait", issue = "42327")]
     fn from_error(v: Self::Error) -> Self;
 
     /// Wrap an OK value to construct the composite result. For example,
     /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
+    #[cfg_attr(not(bootstrap), lang = "from_ok")]
     #[unstable(feature = "try_trait", issue = "42327")]
     fn from_ok(v: Self::Ok) -> Self;
 }
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 6d078fb0a54..b6aa2c66971 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -144,9 +144,11 @@ use crate::{
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Option<T> {
     /// No value
+    #[cfg_attr(not(bootstrap), lang = "None")]
     #[stable(feature = "rust1", since = "1.0.0")]
     None,
     /// Some value `T`
+    #[cfg_attr(not(bootstrap), lang = "Some")]
     #[stable(feature = "rust1", since = "1.0.0")]
     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
 }
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 960cccc0fb2..b63219a4403 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -569,6 +569,7 @@ impl<P: Deref> Pin<P> {
     ///  ```
     ///
     /// [`mem::swap`]: ../../std/mem/fn.swap.html
+    #[cfg_attr(not(bootstrap), lang = "new_unchecked")]
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
     pub unsafe fn new_unchecked(pointer: P) -> Pin<P> {
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index ac20897d258..7d7306574a6 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -2,7 +2,7 @@ use super::*;
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics;
 use crate::mem;
-use crate::slice::SliceIndex;
+use crate::slice::{self, SliceIndex};
 
 #[lang = "const_ptr"]
 impl<T: ?Sized> *const T {
@@ -13,6 +13,15 @@ impl<T: ?Sized> *const T {
     /// Therefore, two pointers that are null may still not compare equal to
     /// each other.
     ///
+    /// ## Behavior during const evaluation
+    ///
+    /// When this function is used during const evaluation, it may return `false` for pointers
+    /// that turn out to be null at runtime. Specifically, when a pointer to some memory
+    /// is offset beyond its bounds in such a way that the resulting pointer is null,
+    /// the function will still return `false`. There is no way for CTFE to know
+    /// the absolute position of that memory, so we cannot tell if the pointer is
+    /// null or not.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -23,11 +32,12 @@ impl<T: ?Sized> *const T {
     /// assert!(!ptr.is_null());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
     #[inline]
-    pub fn is_null(self) -> bool {
+    pub const fn is_null(self) -> bool {
         // Compare via a cast to a thin pointer, so fat pointers are only
         // considering their "data" part for null-ness.
-        (self as *const u8) == null()
+        (self as *const u8).guaranteed_eq(null())
     }
 
     /// Casts to a pointer of another type.
@@ -38,32 +48,33 @@ impl<T: ?Sized> *const T {
         self as _
     }
 
-    /// Returns `None` if the pointer is null, or else returns a reference to
-    /// the value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
+    /// must be used instead.
     ///
-    /// # Safety
+    /// [`as_uninit_ref`]: #method.as_uninit_ref
     ///
-    /// While this method and its mutable counterpart are useful for
-    /// null-safety, it is important to note that this is still an unsafe
-    /// operation because the returned value could be pointing to invalid
-    /// memory.
+    /// # Safety
     ///
     /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
     /// all of the following is true:
-    /// - it is properly aligned
-    /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferenceable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
-    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
-    /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
-    ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -101,6 +112,56 @@ impl<T: ?Sized> *const T {
         if self.is_null() { None } else { unsafe { Some(&*self) } }
     }
 
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// [`as_ref`]: #method.as_ref
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_as_uninit)]
+    ///
+    /// let ptr: *const u8 = &10u8 as *const u8;
+    ///
+    /// unsafe {
+    ///     if let Some(val_back) = ptr.as_uninit_ref() {
+    ///         println!("We got back the value: {}!", val_back.assume_init());
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
+    where
+        T: Sized,
+    {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
+    }
+
     /// Calculates the offset from a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -915,6 +976,55 @@ impl<T> *const [T] {
         // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
         unsafe { index.get_unchecked(self) }
     }
+
+    /// Returns `None` if the pointer is null, or else returns a shared slice to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// [`as_ref`]: #method.as_ref
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
+    ///   and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
+        if self.is_null() {
+            None
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
+            Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit<T>, self.len()) })
+        }
+    }
 }
 
 // Equality for pointers
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index df00139118a..3daeec36041 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1,7 +1,7 @@
 use super::*;
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics;
-use crate::slice::SliceIndex;
+use crate::slice::{self, SliceIndex};
 
 #[lang = "mut_ptr"]
 impl<T: ?Sized> *mut T {
@@ -12,6 +12,15 @@ impl<T: ?Sized> *mut T {
     /// Therefore, two pointers that are null may still not compare equal to
     /// each other.
     ///
+    /// ## Behavior during const evaluation
+    ///
+    /// When this function is used during const evaluation, it may return `false` for pointers
+    /// that turn out to be null at runtime. Specifically, when a pointer to some memory
+    /// is offset beyond its bounds in such a way that the resulting pointer is null,
+    /// the function will still return `false`. There is no way for CTFE to know
+    /// the absolute position of that memory, so we cannot tell if the pointer is
+    /// null or not.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -22,11 +31,12 @@ impl<T: ?Sized> *mut T {
     /// assert!(!ptr.is_null());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
     #[inline]
-    pub fn is_null(self) -> bool {
+    pub const fn is_null(self) -> bool {
         // Compare via a cast to a thin pointer, so fat pointers are only
         // considering their "data" part for null-ness.
-        (self as *mut u8) == null_mut()
+        (self as *mut u8).guaranteed_eq(null_mut())
     }
 
     /// Casts to a pointer of another type.
@@ -37,32 +47,36 @@ impl<T: ?Sized> *mut T {
         self as _
     }
 
-    /// Returns `None` if the pointer is null, or else returns a reference to
-    /// the value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
+    /// must be used instead.
     ///
-    /// # Safety
+    /// For the mutable counterpart see [`as_mut`].
     ///
-    /// While this method and its mutable counterpart are useful for
-    /// null-safety, it is important to note that this is still an unsafe
-    /// operation because the returned value could be pointing to invalid
-    /// memory.
+    /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+    /// [`as_mut`]: #method.as_mut
+    ///
+    /// # Safety
     ///
     /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
     /// all of the following is true:
-    /// - it is properly aligned
-    /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferencable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
-    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
-    /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
-    ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -100,6 +114,59 @@ impl<T: ?Sized> *mut T {
         if self.is_null() { None } else { unsafe { Some(&*self) } }
     }
 
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_as_uninit)]
+    ///
+    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+    ///
+    /// unsafe {
+    ///     if let Some(val_back) = ptr.as_uninit_ref() {
+    ///         println!("We got back the value: {}!", val_back.assume_init());
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
+    where
+        T: Sized,
+    {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
+    }
+
     /// Calculates the offset from a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -225,33 +292,36 @@ impl<T: ?Sized> *mut T {
         unsafe { intrinsics::arith_offset(self, count) as *mut T }
     }
 
-    /// Returns `None` if the pointer is null, or else returns a mutable
-    /// reference to the value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a unique reference to
+    /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`]
+    /// must be used instead.
     ///
-    /// # Safety
+    /// For the shared counterpart see [`as_ref`].
+    ///
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    /// [`as_ref`]: #method.as_ref-1
     ///
-    /// As with [`as_ref`], this is unsafe because it cannot verify the validity
-    /// of the returned pointer, nor can it ensure that the lifetime `'a`
-    /// returned is indeed a valid lifetime for the contained data.
+    /// # Safety
     ///
     /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
     /// all of the following is true:
-    /// - it is properly aligned
-    /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferenceable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
-    /// it is the only safe approach is to ensure that they are indeed initialized.)
-    ///
-    /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
-    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
-    /// the memory this pointer points to must not get accessed (read or written)
-    /// through any other pointer.
+    /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// [here]: crate::ptr#safety
-    /// [`as_ref`]: #method.as_ref
+    /// [the module documentation]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -262,6 +332,7 @@ impl<T: ?Sized> *mut T {
     /// let ptr: *mut u32 = s.as_mut_ptr();
     /// let first_value = unsafe { ptr.as_mut().unwrap() };
     /// *first_value = 4;
+    /// # assert_eq!(s, [4, 2, 3]);
     /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
     /// ```
     ///
@@ -276,6 +347,7 @@ impl<T: ?Sized> *mut T {
     /// let ptr: *mut u32 = s.as_mut_ptr();
     /// let first_value = unsafe { &mut *ptr };
     /// *first_value = 4;
+    /// # assert_eq!(s, [4, 2, 3]);
     /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
@@ -286,6 +358,43 @@ impl<T: ?Sized> *mut T {
         if self.is_null() { None } else { unsafe { Some(&mut *self) } }
     }
 
+    /// Returns `None` if the pointer is null, or else returns a unique reference to
+    /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_ref`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
+    where
+        T: Sized,
+    {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        if self.is_null() { None } else { Some(unsafe { &mut *(self as *mut MaybeUninit<T>) }) }
+    }
+
     /// Returns whether two pointers are guaranteed to be equal.
     ///
     /// At runtime this function behaves like `self == other`.
@@ -1121,6 +1230,110 @@ impl<T> *mut [T] {
         // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
         unsafe { index.get_unchecked_mut(self) }
     }
+
+    /// Returns `None` if the pointer is null, or else returns a shared slice to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_slice_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
+    ///   and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
+        if self.is_null() {
+            None
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
+            Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit<T>, self.len()) })
+        }
+    }
+
+    /// Returns `None` if the pointer is null, or else returns a unique slice to
+    /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_slice`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_slice`]: #method.as_uninit_slice-1
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
+    ///   many bytes, and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts_mut`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
+        if self.is_null() {
+            None
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
+            Some(unsafe { slice::from_raw_parts_mut(self as *mut MaybeUninit<T>, self.len()) })
+        }
+    }
 }
 
 // Equality for pointers
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d876ab23653..294a3173d0c 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -3,10 +3,10 @@ use crate::convert::From;
 use crate::fmt;
 use crate::hash;
 use crate::marker::Unsize;
-use crate::mem;
+use crate::mem::{self, MaybeUninit};
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
 use crate::ptr::Unique;
-use crate::slice::SliceIndex;
+use crate::slice::{self, SliceIndex};
 
 /// `*mut T` but non-zero and covariant.
 ///
@@ -76,6 +76,70 @@ impl<T: Sized> NonNull<T> {
             NonNull::new_unchecked(ptr)
         }
     }
+
+    /// Returns a shared references to the value. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_ref(&self) -> &MaybeUninit<T> {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        unsafe { &*self.cast().as_ptr() }
+    }
+
+    /// Returns a unique references to the value. In contrast to [`as_mut`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_ref`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_ref`]: #method.as_uninit_ref
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_mut(&mut self) -> &mut MaybeUninit<T> {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        unsafe { &mut *self.cast().as_ptr() }
+    }
 }
 
 impl<T: ?Sized> NonNull<T> {
@@ -112,29 +176,34 @@ impl<T: ?Sized> NonNull<T> {
         self.pointer as *mut T
     }
 
-    /// Dereferences the content.
+    /// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`]
+    /// must be used instead.
+    ///
+    /// For the mutable counterpart see [`as_mut`].
     ///
-    /// The resulting lifetime is bound to self so this behaves "as if"
-    /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+    /// [`as_uninit_ref`]: #method.as_uninit_ref
+    /// [`as_mut`]: #method.as_mut
     ///
     /// # Safety
     ///
     /// When calling this method, you have to ensure that all of the following is true:
-    /// - `self` is properly aligned
-    /// - `self` must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferencable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// Additionally, the lifetime of `self` does not necessarily reflect the actual
-    /// lifetime of the data. *You* must enforce Rust's aliasing rules. In particular,
-    /// for the duration of this lifetime, the memory the pointer points to must not
-    /// get mutated (except inside `UnsafeCell`).
-    ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub unsafe fn as_ref(&self) -> &T {
@@ -143,29 +212,34 @@ impl<T: ?Sized> NonNull<T> {
         unsafe { &*self.as_ptr() }
     }
 
-    /// Mutably dereferences the content.
+    /// Returns a unique reference to the value. If the value may be uninitialized, [`as_uninit_mut`]
+    /// must be used instead.
+    ///
+    /// For the shared counterpart see [`as_ref`].
     ///
-    /// The resulting lifetime is bound to self so this behaves "as if"
-    /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    /// [`as_ref`]: #method.as_ref
     ///
     /// # Safety
     ///
     /// When calling this method, you have to ensure that all of the following is true:
-    /// - `self` is properly aligned
-    /// - `self` must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferenceable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
-    /// it is the only safe approach is to ensure that they are indeed initialized.)
-    ///
-    /// Additionally, the lifetime of `self` does not necessarily reflect the actual
-    /// lifetime of the data. *You* must enforce Rust's aliasing rules. In particular,
-    /// for the duration of this lifetime, the memory this pointer points to must not
-    /// get accessed (read or written) through any other pointer.
+    /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub unsafe fn as_mut(&mut self) -> &mut T {
@@ -278,6 +352,115 @@ impl<T> NonNull<[T]> {
         self.as_non_null_ptr().as_ptr()
     }
 
+    /// Returns a shared reference to a slice of possibly uninitialized values. In contrast to
+    /// [`as_ref`], this does not require that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_slice_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref
+    /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
+    ///   and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit<T>] {
+        // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
+        unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
+    }
+
+    /// Returns a unique reference to a slice of possibly uninitialized values. In contrast to
+    /// [`as_mut`], this does not require that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_slice`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_slice`]: #method.as_uninit_slice
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
+    ///   many bytes, and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts_mut`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(allocator_api, ptr_as_uninit)]
+    ///
+    /// use std::alloc::{AllocRef, Layout, Global};
+    /// use std::mem::MaybeUninit;
+    /// use std::ptr::NonNull;
+    ///
+    /// let memory: NonNull<[u8]> = Global.alloc(Layout::new::<[u8; 32]>())?;
+    /// // This is safe as `memory` is valid for reads and writes for `memory.len()` many bytes.
+    /// // Note that calling `memory.as_mut()` is not allowed here as the content may be uninitialized.
+    /// # #[allow(unused_variables)]
+    /// let slice: &mut [MaybeUninit<u8>] = unsafe { memory.as_uninit_slice_mut() };
+    /// # Ok::<_, std::alloc::AllocErr>(())
+    /// ```
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice_mut(&self) -> &mut [MaybeUninit<T>] {
+        // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
+        unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
+    }
+
     /// Returns a raw pointer to an element or subslice, without doing bounds
     /// checking.
     ///
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index e68dbf5215f..5eddcb2172a 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -246,10 +246,12 @@ use crate::{convert, fmt};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Result<T, E> {
     /// Contains the success value
+    #[cfg_attr(not(bootstrap), lang = "Ok")]
     #[stable(feature = "rust1", since = "1.0.0")]
     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
 
     /// Contains the error value
+    #[cfg_attr(not(bootstrap), lang = "Err")]
     #[stable(feature = "rust1", since = "1.0.0")]
     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
 }
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index b3a4bd20b8f..fea396d20ff 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -10,6 +10,7 @@ use crate::result::Result;
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub enum Poll<T> {
     /// Represents that a value is immediately ready.
+    #[cfg_attr(not(bootstrap), lang = "Ready")]
     #[stable(feature = "futures_api", since = "1.36.0")]
     Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),
 
@@ -18,6 +19,7 @@ pub enum Poll<T> {
     /// When a function returns `Pending`, the function *must* also
     /// ensure that the current task is scheduled to be awoken when
     /// progress can be made.
+    #[cfg_attr(not(bootstrap), lang = "Pending")]
     #[stable(feature = "futures_api", since = "1.36.0")]
     Pending,
 }
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 54272165fb1..74427199346 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -7,8 +7,6 @@
 //! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by
 //! default.
 //!
-//! [`System`]: struct.System.html
-//!
 //! # The `#[global_allocator]` attribute
 //!
 //! This attribute allows configuring the choice of global allocator.
@@ -43,8 +41,6 @@
 //! The attribute is used on a `static` item whose type implements the
 //! [`GlobalAlloc`] trait. This type can be provided by an external library:
 //!
-//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
-//!
 //! ```rust,ignore (demonstrates crates.io usage)
 //! extern crate jemallocator;
 //!
@@ -277,9 +273,6 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 /// about the allocation that failed.
 ///
 /// The allocation error hook is a global resource.
-///
-/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html
-/// [`take_alloc_error_hook`]: fn.take_alloc_error_hook.html
 #[unstable(feature = "alloc_error_hook", issue = "51245")]
 pub fn set_alloc_error_hook(hook: fn(Layout)) {
     HOOK.store(hook as *mut (), Ordering::SeqCst);
@@ -290,8 +283,6 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) {
 /// *See also the function [`set_alloc_error_hook`].*
 ///
 /// If no custom hook is registered, the default hook will be returned.
-///
-/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html
 #[unstable(feature = "alloc_error_hook", issue = "51245")]
 pub fn take_alloc_error_hook() -> fn(Layout) {
     let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
diff --git a/library/std/src/ascii.rs b/library/std/src/ascii.rs
index 5cd2a25b117..c9106136d34 100644
--- a/library/std/src/ascii.rs
+++ b/library/std/src/ascii.rs
@@ -10,9 +10,6 @@
 //!
 //! The [`escape_default`] function provides an iterator over the bytes of an
 //! escaped version of the character given.
-//!
-//! [`AsciiExt`]: trait.AsciiExt.html
-//! [`escape_default`]: fn.escape_default.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -52,7 +49,7 @@ pub trait AsciiExt {
     ///
     /// # Note
     ///
-    /// This method will be deprecated in favor of the identically-named
+    /// This method is deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn is_ascii(&self) -> bool;
@@ -69,10 +66,10 @@ pub trait AsciiExt {
     ///
     /// # Note
     ///
-    /// This method will be deprecated in favor of the identically-named
+    /// This method is deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
-    /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
+    /// [`make_ascii_uppercase`]: AsciiExt::make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
@@ -90,10 +87,10 @@ pub trait AsciiExt {
     ///
     /// # Note
     ///
-    /// This method will be deprecated in favor of the identically-named
+    /// This method is deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
-    /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
+    /// [`make_ascii_lowercase`]: AsciiExt::make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
@@ -106,7 +103,7 @@ pub trait AsciiExt {
     ///
     /// # Note
     ///
-    /// This method will be deprecated in favor of the identically-named
+    /// This method is deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
@@ -121,10 +118,10 @@ pub trait AsciiExt {
     ///
     /// # Note
     ///
-    /// This method will be deprecated in favor of the identically-named
+    /// This method is deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
-    /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase
+    /// [`to_ascii_uppercase`]: AsciiExt::to_ascii_uppercase
     #[stable(feature = "ascii", since = "1.9.0")]
     fn make_ascii_uppercase(&mut self);
 
@@ -138,10 +135,10 @@ pub trait AsciiExt {
     ///
     /// # Note
     ///
-    /// This method will be deprecated in favor of the identically-named
+    /// This method is deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
-    /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
+    /// [`to_ascii_lowercase`]: AsciiExt::to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
     fn make_ascii_lowercase(&mut self);
 }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 6489e0709cb..387c588f4a0 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -7,9 +7,6 @@
 //! There are several functions and structs in this module that have a
 //! counterpart ending in `os`. Those ending in `os` will return an [`OsString`]
 //! and those without will return a [`String`].
-//!
-//! [`OsString`]: ../../std/ffi/struct.OsString.html
-//! [`String`]: ../string/struct.String.html
 
 #![stable(feature = "env", since = "1.0.0")]
 
@@ -31,9 +28,6 @@ use crate::sys::os as os_imp;
 /// * Current directory does not exist.
 /// * There are insufficient permissions to access the current directory.
 ///
-/// [`PathBuf`]: ../../std/path/struct.PathBuf.html
-/// [`Err`]: ../../std/result/enum.Result.html#method.err
-///
 /// # Examples
 ///
 /// ```
@@ -54,8 +48,6 @@ pub fn current_dir() -> io::Result<PathBuf> {
 ///
 /// Returns an [`Err`] if the operation fails.
 ///
-/// [`Err`]: ../../std/result/enum.Result.html#method.err
-///
 /// # Examples
 ///
 /// ```
@@ -76,7 +68,7 @@ pub fn set_current_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// This structure is created by the [`std::env::vars`] function. See its
 /// documentation for more.
 ///
-/// [`std::env::vars`]: fn.vars.html
+/// [`std::env::vars`]: vars
 #[stable(feature = "env", since = "1.0.0")]
 pub struct Vars {
     inner: VarsOs,
@@ -87,7 +79,7 @@ pub struct Vars {
 /// This structure is created by the [`std::env::vars_os`] function. See
 /// its documentation for more.
 ///
-/// [`std::env::vars_os`]: fn.vars_os.html
+/// [`std::env::vars_os`]: vars_os
 #[stable(feature = "env", since = "1.0.0")]
 pub struct VarsOs {
     inner: os_imp::Env,
@@ -106,7 +98,7 @@ pub struct VarsOs {
 /// environment is not valid unicode. If this is not desired, consider using the
 /// [`env::vars_os`] function.
 ///
-/// [`env::vars_os`]: fn.vars_os.html
+/// [`env::vars_os`]: vars_os
 ///
 /// # Examples
 ///
@@ -222,8 +214,6 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 /// Fetches the environment variable `key` from the current process, returning
 /// [`None`] if the variable isn't set.
 ///
-/// [`None`]: ../option/enum.Option.html#variant.None
-///
 /// # Panics
 ///
 /// This function may panic if `key` is empty, contains an ASCII equals sign
@@ -254,7 +244,7 @@ fn _var_os(key: &OsStr) -> Option<OsString> {
 /// The error type for operations interacting with environment variables.
 /// Possibly returned from the [`env::var`] function.
 ///
-/// [`env::var`]: fn.var.html
+/// [`env::var`]: var
 #[derive(Debug, PartialEq, Eq, Clone)]
 #[stable(feature = "env", since = "1.0.0")]
 pub enum VarError {
@@ -382,8 +372,7 @@ fn _remove_var(k: &OsStr) {
 /// This structure is created by the [`std::env::split_paths`] function. See its
 /// documentation for more.
 ///
-/// [`PathBuf`]: ../../std/path/struct.PathBuf.html
-/// [`std::env::split_paths`]: fn.split_paths.html
+/// [`std::env::split_paths`]: split_paths
 #[stable(feature = "env", since = "1.0.0")]
 pub struct SplitPaths<'a> {
     inner: os_imp::SplitPaths<'a>,
@@ -410,8 +399,6 @@ pub struct SplitPaths<'a> {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
-///
-/// [`PathBuf`]: ../../std/path/struct.PathBuf.html
 #[stable(feature = "env", since = "1.0.0")]
 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
     SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
@@ -438,7 +425,7 @@ impl fmt::Debug for SplitPaths<'_> {
 /// The error type for operations on the `PATH` variable. Possibly returned from
 /// the [`env::join_paths`] function.
 ///
-/// [`env::join_paths`]: fn.join_paths.html
+/// [`env::join_paths`]: join_paths
 #[derive(Debug)]
 #[stable(feature = "env", since = "1.0.0")]
 pub struct JoinPathsError {
@@ -450,14 +437,10 @@ pub struct JoinPathsError {
 ///
 /// # Errors
 ///
-/// Returns an [`Err`][err] (containing an error message) if one of the input
+/// Returns an [`Err`] (containing an error message) if one of the input
 /// [`Path`]s contains an invalid character for constructing the `PATH`
 /// variable (a double quote on Windows or a colon on Unix).
 ///
-/// [`Path`]: ../../std/path/struct.Path.html
-/// [`OsString`]: ../../std/ffi/struct.OsString.html
-/// [err]: ../../std/result/enum.Result.html#variant.Err
-///
 /// # Examples
 ///
 /// Joining paths on a Unix-like platform:
@@ -508,7 +491,7 @@ pub struct JoinPathsError {
 /// }
 /// ```
 ///
-/// [`env::split_paths`]: fn.split_paths.html
+/// [`env::split_paths`]: split_paths
 #[stable(feature = "env", since = "1.0.0")]
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 where
@@ -688,8 +671,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 /// set to arbitrary text, and may not even exist. This means this property
 /// should not be relied upon for security purposes.
 ///
-/// [`String`]: ../string/struct.String.html
-/// [`std::env::args`]: ./fn.args.html
+/// [`std::env::args`]: args
 #[stable(feature = "env", since = "1.0.0")]
 pub struct Args {
     inner: ArgsOs,
@@ -705,8 +687,7 @@ pub struct Args {
 /// set to arbitrary text, and may not even exist. This means this property
 /// should not be relied upon for security purposes.
 ///
-/// [`OsString`]: ../ffi/struct.OsString.html
-/// [`std::env::args_os`]: ./fn.args_os.html
+/// [`std::env::args_os`]: args_os
 #[stable(feature = "env", since = "1.0.0")]
 pub struct ArgsOs {
     inner: sys::args::Args,
@@ -744,8 +725,6 @@ pub struct ArgsOs {
 ///     println!("{}", argument);
 /// }
 /// ```
-///
-/// [`args_os`]: ./fn.args_os.html
 #[stable(feature = "env", since = "1.0.0")]
 pub fn args() -> Args {
     Args { inner: args_os() }
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 3b4cb859dd4..1b7681bd4bb 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -40,10 +40,8 @@ use crate::string;
 /// provide its own errors while also revealing some of the implementation for
 /// debugging via [`source`] chains.
 ///
-/// [`Result<T, E>`]: ../result/enum.Result.html
-/// [`Display`]: ../fmt/trait.Display.html
-/// [`Debug`]: ../fmt/trait.Debug.html
-/// [`source`]: trait.Error.html#method.source
+/// [`Result<T, E>`]: Result
+/// [`source`]: Error::source
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
@@ -164,8 +162,6 @@ mod private {
 impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     /// Converts a type of [`Error`] into a box of dyn [`Error`].
     ///
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -199,8 +195,6 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
     /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
     /// dyn [`Error`] + [`Send`] + [`Sync`].
     ///
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -238,8 +232,6 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
 impl From<String> for Box<dyn Error + Send + Sync> {
     /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -283,8 +275,6 @@ impl From<String> for Box<dyn Error + Send + Sync> {
 impl From<String> for Box<dyn Error> {
     /// Converts a [`String`] into a box of dyn [`Error`].
     ///
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -306,8 +296,6 @@ impl From<String> for Box<dyn Error> {
 impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
     /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -329,8 +317,6 @@ impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
 impl From<&str> for Box<dyn Error> {
     /// Converts a [`str`] into a box of dyn [`Error`].
     ///
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -350,9 +336,6 @@ impl From<&str> for Box<dyn Error> {
 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
     /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
-    /// [`Cow`]: ../borrow/enum.Cow.html
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -374,9 +357,6 @@ impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
     /// Converts a [`Cow`] into a box of dyn [`Error`].
     ///
-    /// [`Cow`]: ../borrow/enum.Cow.html
-    /// [`Error`]: ../error/trait.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -703,7 +683,7 @@ impl dyn Error {
     /// assert!(iter.next().is_none());
     /// ```
     ///
-    /// [`source`]: trait.Error.html#method.source
+    /// [`source`]: Error::source
     #[unstable(feature = "error_iter", issue = "58520")]
     #[inline]
     pub fn chain(&self) -> Chain<'_> {
@@ -715,8 +695,6 @@ impl dyn Error {
 ///
 /// If you want to omit the initial error and only process
 /// its sources, use `skip(1)`.
-///
-/// [`Error`]: trait.Error.html
 #[unstable(feature = "error_iter", issue = "58520")]
 #[derive(Clone, Debug)]
 pub struct Chain<'a> {
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 6ad5519d34a..8fcb24033b1 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -30,10 +30,6 @@ pub use core::panic::{Location, PanicInfo};
 /// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`]
 /// boundary with no fear of unwind safety.
 ///
-/// [`Send`]: ../marker/trait.Send.html
-/// [`Sync`]: ../marker/trait.Sync.html
-/// [`catch_unwind`]: ./fn.catch_unwind.html
-///
 /// ## What is unwind safety?
 ///
 /// In Rust a function can "return" early if it either panics or calls a
@@ -99,8 +95,6 @@ pub use core::panic::{Location, PanicInfo};
 /// above, the lack of `unsafe` means it is mostly an advisory. The
 /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be
 /// implemented for any closed over variables passed to `catch_unwind`.
-///
-/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented(
     message = "the type `{Self}` may not be safely transferred across an unwind boundary",
@@ -116,9 +110,6 @@ pub auto trait UnwindSafe {}
 ///
 /// This is a "helper marker trait" used to provide impl blocks for the
 /// [`UnwindSafe`] trait, for more information see that documentation.
-///
-/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html
-/// [`UnwindSafe`]: ./trait.UnwindSafe.html
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented(
     message = "the type `{Self}` may contain interior mutability and a reference may not be safely \
@@ -138,7 +129,6 @@ pub auto trait RefUnwindSafe {}
 /// account. This wrapper struct is useful for a quick and lightweight
 /// annotation that a variable is indeed unwind safe.
 ///
-/// [`catch_unwind`]: ./fn.catch_unwind.html
 /// # Examples
 ///
 /// One way to use `AssertUnwindSafe` is to assert that the entire closure
@@ -352,8 +342,6 @@ impl<F: Future> Future for AssertUnwindSafe<F> {
 /// can fail on a regular basis. Additionally, this function is not guaranteed
 /// to catch all panics, see the "Notes" section below.
 ///
-/// [`Result`]: ../result/enum.Result.html
-///
 /// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure
 /// that all captured variables are safe to cross this boundary. The purpose of
 /// this bound is to encode the concept of [exception safety][rfc] in the type
@@ -362,9 +350,6 @@ impl<F: Future> Future for AssertUnwindSafe<F> {
 /// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly
 /// assert that the usage here is indeed unwind safe.
 ///
-/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
-/// [`UnwindSafe`]: ./trait.UnwindSafe.html
-///
 /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
 ///
 /// # Notes
@@ -399,8 +384,6 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 /// This is designed to be used in conjunction with [`catch_unwind`] to, for
 /// example, carry a panic across a layer of C code.
 ///
-/// [`catch_unwind`]: ./fn.catch_unwind.html
-///
 /// # Notes
 ///
 /// Note that panics in Rust are not always implemented via unwinding, but they
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 61261e82147..21874853839 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -204,7 +204,7 @@ target | std | host | notes
 `thumbv4t-none-eabi` | * |  | ARMv4T T32
 `x86_64-apple-ios-macabi` | ✓[^apple] |  | Apple Catalyst
 `x86_64-apple-tvos` | *[^apple] | | x86 64-bit tvOS
-`x86_64-linux-kernel` | ? |  | Linux kernel modules
+`x86_64-linux-kernel` | * |  | Linux kernel modules
 `x86_64-pc-solaris` | ? |  |
 `x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support
 `x86_64-unknown-cloudabi` | ✓ |  | 64-bit CloudABI
diff --git a/src/librustc_ast/lib.rs b/src/librustc_ast/lib.rs
index fb5ce311826..b556c1a446b 100644
--- a/src/librustc_ast/lib.rs
+++ b/src/librustc_ast/lib.rs
@@ -51,6 +51,8 @@ pub mod token;
 pub mod tokenstream;
 pub mod visit;
 
+pub use self::ast::*;
+
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index f9e54903a66..df452825bba 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -1,8 +1,8 @@
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
 
-use rustc_ast::ast::*;
 use rustc_ast::attr;
 use rustc_ast::ptr::P as AstP;
+use rustc_ast::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::thin_vec::ThinVec;
@@ -449,7 +449,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             // `::std::ops::Try::from_ok($tail_expr)`
             block.expr = Some(this.wrap_in_try_constructor(
-                sym::from_ok,
+                hir::LangItem::TryFromOk,
                 try_span,
                 tail_expr,
                 ok_wrapped_span,
@@ -461,14 +461,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn wrap_in_try_constructor(
         &mut self,
-        method: Symbol,
+        lang_item: hir::LangItem,
         method_span: Span,
         expr: &'hir hir::Expr<'hir>,
         overall_span: Span,
     ) -> &'hir hir::Expr<'hir> {
-        let path = &[sym::ops, sym::Try, method];
         let constructor =
-            self.arena.alloc(self.expr_std_path(method_span, path, None, ThinVec::new()));
+            self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new()));
         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
     }
 
@@ -558,12 +557,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `future::from_generator`:
         let unstable_span =
             self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
-        let gen_future = self.expr_std_path(
-            unstable_span,
-            &[sym::future, sym::from_generator],
-            None,
-            ThinVec::new(),
-        );
+        let gen_future =
+            self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new());
 
         // `future::from_generator(generator)`:
         hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
@@ -630,23 +625,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // Use of `await` outside of an async context, we cannot use `task_context` here.
                 self.expr_err(span)
             };
-            let pin_ty_id = self.next_id();
-            let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
-                pin_ty_id,
+            let new_unchecked = self.expr_call_lang_item_fn_mut(
                 span,
-                &[sym::pin, sym::Pin],
-                "new_unchecked",
+                hir::LangItem::PinNewUnchecked,
                 arena_vec![self; ref_mut_pinned],
             );
-            let new_unchecked = self.expr(span, new_unchecked_expr_kind, ThinVec::new());
-            let get_context = self.expr_call_std_path_mut(
+            let get_context = self.expr_call_lang_item_fn_mut(
                 gen_future_span,
-                &[sym::future, sym::get_context],
+                hir::LangItem::GetContext,
                 arena_vec![self; task_context],
             );
-            let call = self.expr_call_std_path(
+            let call = self.expr_call_lang_item_fn(
                 span,
-                &[sym::future, sym::Future, sym::poll],
+                hir::LangItem::FuturePoll,
                 arena_vec![self; new_unchecked, get_context],
             );
             self.arena.alloc(self.expr_unsafe(call))
@@ -659,11 +650,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let x_ident = Ident::with_dummy_span(sym::result);
             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
             let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
-            let ready_pat = self.pat_std_enum(
-                span,
-                &[sym::task, sym::Poll, sym::Ready],
-                arena_vec![self; x_pat],
-            );
+            let ready_field = self.single_pat_field(span, x_pat);
+            let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
             let break_x = self.with_loop_scope(loop_node_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
@@ -674,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         // `::std::task::Poll::Pending => {}`
         let pending_arm = {
-            let pending_pat = self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], &[]);
+            let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);
             let empty_block = self.expr_block_empty(span);
             self.arm(pending_pat, empty_block)
         };
@@ -842,16 +830,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
     fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
-        let id = self.next_id();
         let e1 = self.lower_expr_mut(e1);
         let e2 = self.lower_expr_mut(e2);
-        self.expr_call_std_assoc_fn(
-            id,
-            span,
-            &[sym::ops, sym::RangeInclusive],
-            "new",
-            arena_vec![self; e1, e2],
-        )
+        let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
+        let fn_expr =
+            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
+        hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
     }
 
     fn lower_expr_range(
@@ -861,14 +845,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         e2: Option<&Expr>,
         lims: RangeLimits,
     ) -> hir::ExprKind<'hir> {
-        use rustc_ast::ast::RangeLimits::*;
-
-        let path = match (e1, e2, lims) {
-            (None, None, HalfOpen) => sym::RangeFull,
-            (Some(..), None, HalfOpen) => sym::RangeFrom,
-            (None, Some(..), HalfOpen) => sym::RangeTo,
-            (Some(..), Some(..), HalfOpen) => sym::Range,
-            (None, Some(..), Closed) => sym::RangeToInclusive,
+        use rustc_ast::RangeLimits::*;
+
+        let lang_item = match (e1, e2, lims) {
+            (None, None, HalfOpen) => hir::LangItem::RangeFull,
+            (Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
+            (None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
+            (Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
+            (None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
             (Some(..), Some(..), Closed) => unreachable!(),
             (_, None, Closed) => {
                 self.diagnostic().span_fatal(span, "inclusive range with no end").raise()
@@ -883,16 +867,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }),
         );
 
-        let is_unit = fields.is_empty();
-        let struct_path = [sym::ops, path];
-        let struct_path = self.std_path(span, &struct_path, None, is_unit);
-        let struct_path = hir::QPath::Resolved(None, struct_path);
-
-        if is_unit {
-            hir::ExprKind::Path(struct_path)
-        } else {
-            hir::ExprKind::Struct(self.arena.alloc(struct_path), fields, None)
-        }
+        hir::ExprKind::Struct(self.arena.alloc(hir::QPath::LangItem(lang_item, span)), fields, None)
     }
 
     fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
@@ -1412,9 +1387,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let match_expr = {
             let iter = self.expr_ident(desugared_span, iter, iter_pat_nid);
             let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
-            let next_path = &[sym::iter, sym::Iterator, sym::next];
-            let next_expr =
-                self.expr_call_std_path(desugared_span, next_path, arena_vec![self; ref_mut_iter]);
+            let next_expr = self.expr_call_lang_item_fn(
+                desugared_span,
+                hir::LangItem::IteratorNext,
+                arena_vec![self; ref_mut_iter],
+            );
             let arms = arena_vec![self; pat_arm, break_arm];
 
             self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
@@ -1472,8 +1449,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
         let into_iter_expr = {
-            let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
-            self.expr_call_std_path(into_iter_span, into_iter_path, arena_vec![self; head])
+            self.expr_call_lang_item_fn(
+                into_iter_span,
+                hir::LangItem::IntoIterIntoIter,
+                arena_vec![self; head],
+            )
         };
 
         let match_expr = self.arena.alloc(self.expr_match(
@@ -1521,8 +1501,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
             // expand <expr>
             let sub_expr = self.lower_expr_mut(sub_expr);
 
-            let path = &[sym::ops, sym::Try, sym::into_result];
-            self.expr_call_std_path(unstable_span, path, arena_vec![self; sub_expr])
+            self.expr_call_lang_item_fn(
+                unstable_span,
+                hir::LangItem::TryIntoResult,
+                arena_vec![self; sub_expr],
+            )
         };
 
         // `#[allow(unreachable_code)]`
@@ -1558,12 +1541,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let err_ident = Ident::with_dummy_span(sym::err);
             let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
             let from_expr = {
-                let from_path = &[sym::convert, sym::From, sym::from];
                 let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
-                self.expr_call_std_path(try_span, from_path, arena_vec![self; err_expr])
+                self.expr_call_lang_item_fn(
+                    try_span,
+                    hir::LangItem::FromFrom,
+                    arena_vec![self; err_expr],
+                )
             };
-            let from_err_expr =
-                self.wrap_in_try_constructor(sym::from_error, unstable_span, from_expr, try_span);
+            let from_err_expr = self.wrap_in_try_constructor(
+                hir::LangItem::TryFromError,
+                unstable_span,
+                from_expr,
+                try_span,
+            );
             let thin_attrs = ThinVec::from(attrs);
             let catch_scope = self.catch_scopes.last().copied();
             let ret_expr = if let Some(catch_node) = catch_scope {
@@ -1674,63 +1664,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.arena.alloc(self.expr_call_mut(span, e, args))
     }
 
-    // Note: associated functions must use `expr_call_std_path`.
-    fn expr_call_std_path_mut(
+    fn expr_call_lang_item_fn_mut(
         &mut self,
         span: Span,
-        path_components: &[Symbol],
+        lang_item: hir::LangItem,
         args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
-        let path =
-            self.arena.alloc(self.expr_std_path(span, path_components, None, ThinVec::new()));
+        let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new()));
         self.expr_call_mut(span, path, args)
     }
 
-    fn expr_call_std_path(
+    fn expr_call_lang_item_fn(
         &mut self,
         span: Span,
-        path_components: &[Symbol],
+        lang_item: hir::LangItem,
         args: &'hir [hir::Expr<'hir>],
     ) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr_call_std_path_mut(span, path_components, args))
-    }
-
-    // Create an expression calling an associated function of an std type.
-    //
-    // Associated functions cannot be resolved through the normal `std_path` function,
-    // as they are resolved differently and so cannot use `expr_call_std_path`.
-    //
-    // This function accepts the path component (`ty_path_components`) separately from
-    // the name of the associated function (`assoc_fn_name`) in order to facilitate
-    // separate resolution of the type and creation of a path referring to its associated
-    // function.
-    fn expr_call_std_assoc_fn(
-        &mut self,
-        ty_path_id: hir::HirId,
-        span: Span,
-        ty_path_components: &[Symbol],
-        assoc_fn_name: &str,
-        args: &'hir [hir::Expr<'hir>],
-    ) -> hir::ExprKind<'hir> {
-        let ty_path = self.std_path(span, ty_path_components, None, false);
-        let ty =
-            self.arena.alloc(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path)));
-        let fn_seg = self.arena.alloc(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name)));
-        let fn_path = hir::QPath::TypeRelative(ty, fn_seg);
-        let fn_expr =
-            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
-        hir::ExprKind::Call(fn_expr, args)
+        self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args))
     }
 
-    fn expr_std_path(
+    fn expr_lang_item_path(
         &mut self,
         span: Span,
-        components: &[Symbol],
-        params: Option<&'hir hir::GenericArgs<'hir>>,
+        lang_item: hir::LangItem,
         attrs: AttrVec,
     ) -> hir::Expr<'hir> {
-        let path = self.std_path(span, components, params, true);
-        self.expr(span, hir::ExprKind::Path(hir::QPath::Resolved(None, path)), attrs)
+        self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, span)), attrs)
     }
 
     pub(super) fn expr_ident(
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 699f5c9778a..473fb7ccc70 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -2,10 +2,10 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
 use super::{ImplTraitContext, ImplTraitPosition};
 use crate::Arena;
 
-use rustc_ast::ast::*;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
+use rustc_ast::*;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 7cfde3fc6d2..31eedeaed0a 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -35,13 +35,12 @@
 #![feature(or_patterns)]
 #![recursion_limit = "256"]
 
-use rustc_ast::ast;
-use rustc_ast::ast::*;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast::walk_list;
+use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
@@ -85,8 +84,6 @@ const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 rustc_hir::arena_types!(rustc_arena::declare_arena, [], 'tcx);
 
 struct LoweringContext<'a, 'hir: 'a> {
-    crate_root: Option<Symbol>,
-
     /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
     sess: &'a Session,
 
@@ -189,16 +186,6 @@ pub trait ResolverAstLowering {
     /// This should only return `None` during testing.
     fn definitions(&mut self) -> &mut Definitions;
 
-    /// Given suffix `["b", "c", "d"]`, creates an AST path for `[::crate_root]::b::c::d` and
-    /// resolves it based on `is_value`.
-    fn resolve_str_path(
-        &mut self,
-        span: Span,
-        crate_root: Option<Symbol>,
-        components: &[Symbol],
-        ns: Namespace,
-    ) -> (ast::Path, Res<NodeId>);
-
     fn lint_buffer(&mut self) -> &mut LintBuffer;
 
     fn next_node_id(&mut self) -> NodeId;
@@ -305,7 +292,6 @@ pub fn lower_crate<'a, 'hir>(
     let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
 
     LoweringContext {
-        crate_root: sess.parse_sess.injected_crate_name.get().copied(),
         sess,
         resolver,
         nt_to_tokenstream,
@@ -2064,23 +2050,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
 
         // "<Output = T>"
-        let future_params = self.arena.alloc(hir::GenericArgs {
+        let future_args = self.arena.alloc(hir::GenericArgs {
             args: &[],
             bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
             parenthesized: false,
         });
 
-        // ::std::future::Future<future_params>
-        let future_path =
-            self.std_path(span, &[sym::future, sym::Future], Some(future_params), false);
-
-        hir::GenericBound::Trait(
-            hir::PolyTraitRef {
-                trait_ref: hir::TraitRef { path: future_path, hir_ref_id: self.next_id() },
-                bound_generic_params: &[],
-                span,
-            },
-            hir::TraitBoundModifier::None,
+        hir::GenericBound::LangItemTrait(
+            // ::std::future::Future<future_params>
+            hir::LangItem::FutureTraitLangItem,
+            span,
+            self.next_id(),
+            future_args,
         )
     }
 
@@ -2480,35 +2461,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
-        self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], arena_vec![self; pat])
+        let field = self.single_pat_field(span, pat);
+        self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field)
     }
 
     fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
-        self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], arena_vec![self; pat])
+        let field = self.single_pat_field(span, pat);
+        self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field)
     }
 
     fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
-        self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], arena_vec![self; pat])
+        let field = self.single_pat_field(span, pat);
+        self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field)
     }
 
     fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
-        self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], &[])
+        self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[])
     }
 
-    fn pat_std_enum(
+    fn single_pat_field(
         &mut self,
         span: Span,
-        components: &[Symbol],
-        subpats: &'hir [&'hir hir::Pat<'hir>],
-    ) -> &'hir hir::Pat<'hir> {
-        let path = self.std_path(span, components, None, true);
-        let qpath = hir::QPath::Resolved(None, path);
-        let pt = if subpats.is_empty() {
-            hir::PatKind::Path(qpath)
-        } else {
-            hir::PatKind::TupleStruct(qpath, subpats, None)
+        pat: &'hir hir::Pat<'hir>,
+    ) -> &'hir [hir::FieldPat<'hir>] {
+        let field = hir::FieldPat {
+            hir_id: self.next_id(),
+            ident: Ident::new(sym::integer(0), span),
+            is_shorthand: false,
+            pat,
+            span,
         };
-        self.pat(span, pt)
+        arena_vec![self; field]
+    }
+
+    fn pat_lang_item_variant(
+        &mut self,
+        span: Span,
+        lang_item: hir::LangItem,
+        fields: &'hir [hir::FieldPat<'hir>],
+    ) -> &'hir hir::Pat<'hir> {
+        let qpath = hir::QPath::LangItem(lang_item, span);
+        self.pat(span, hir::PatKind::Struct(qpath, fields, false))
     }
 
     fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
@@ -2541,42 +2534,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.arena.alloc(hir::Pat { hir_id: self.next_id(), kind, span })
     }
 
-    /// Given a suffix `["b", "c", "d"]`, returns path `::std::b::c::d` when
-    /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
-    /// The path is also resolved according to `is_value`.
-    fn std_path(
-        &mut self,
-        span: Span,
-        components: &[Symbol],
-        params: Option<&'hir hir::GenericArgs<'hir>>,
-        is_value: bool,
-    ) -> &'hir hir::Path<'hir> {
-        let ns = if is_value { Namespace::ValueNS } else { Namespace::TypeNS };
-        let (path, res) = self.resolver.resolve_str_path(span, self.crate_root, components, ns);
-
-        let mut segments: Vec<_> = path
-            .segments
-            .iter()
-            .map(|segment| {
-                let res = self.expect_full_res(segment.id);
-                hir::PathSegment {
-                    ident: segment.ident,
-                    hir_id: Some(self.lower_node_id(segment.id)),
-                    res: Some(self.lower_res(res)),
-                    infer_args: true,
-                    args: None,
-                }
-            })
-            .collect();
-        segments.last_mut().unwrap().args = params;
-
-        self.arena.alloc(hir::Path {
-            span,
-            res: res.map_id(|_| panic!("unexpected `NodeId`")),
-            segments: self.arena.alloc_from_iter(segments),
-        })
-    }
-
     fn ty_path(
         &mut self,
         mut hir_id: hir::HirId,
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index 171856e7e63..cb7b7c0eb61 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -1,7 +1,7 @@
 use super::{ImplTraitContext, LoweringContext, ParamMode};
 
-use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
+use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs
index 2541d6824fe..cf68dfb9ae1 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_ast::ast::{self, *};
+use rustc_ast::{self as ast, *};
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 3c2a063cf24..a01dd8c939c 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -7,10 +7,10 @@
 // or type checking or some other kind of complex analysis.
 
 use itertools::{Either, Itertools};
-use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::walk_list;
+use rustc_ast::*;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index ce39ceff8f3..b15792dfd4c 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -1,6 +1,7 @@
-use rustc_ast::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use rustc_ast::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
+use rustc_ast as ast;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
+use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
+use rustc_ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
 use rustc_errors::struct_span_err;
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 use rustc_feature::{Features, GateIssue};
diff --git a/src/librustc_ast_passes/node_count.rs b/src/librustc_ast_passes/node_count.rs
index 34db59b1b45..706dca2b7f4 100644
--- a/src/librustc_ast_passes/node_count.rs
+++ b/src/librustc_ast_passes/node_count.rs
@@ -1,7 +1,7 @@
 // Simply gives a rough count of the number of nodes in an AST.
 
-use rustc_ast::ast::*;
 use rustc_ast::visit::*;
+use rustc_ast::*;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
diff --git a/src/librustc_ast_passes/show_span.rs b/src/librustc_ast_passes/show_span.rs
index 2366426d4dc..053aba86222 100644
--- a/src/librustc_ast_passes/show_span.rs
+++ b/src/librustc_ast_passes/show_span.rs
@@ -5,7 +5,7 @@
 
 use std::str::FromStr;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::visit;
 use rustc_ast::visit::Visitor;
 
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 9d9ca78de55..cb48deb5886 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1,11 +1,6 @@
 use crate::pp::Breaks::{Consistent, Inconsistent};
 use crate::pp::{self, Breaks};
 
-use rustc_ast::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
-use rustc_ast::ast::{Attribute, GenericArg, MacArgs};
-use rustc_ast::ast::{GenericBound, SelfKind, TraitBoundModifier};
-use rustc_ast::ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_ast::attr;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, CommentKind, DelimToken, Nonterminal, Token, TokenKind};
@@ -13,6 +8,11 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::util::classify;
 use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
+use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
+use rustc_ast::{GenericArg, MacArgs};
+use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
+use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
@@ -902,7 +902,7 @@ impl<'a> State<'a> {
         }
     }
 
-    crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[Attribute]) {
+    crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) {
         self.print_inner_attributes(attrs);
         for item in &nmod.items {
             self.print_foreign_item(item);
@@ -1666,7 +1666,7 @@ impl<'a> State<'a> {
         }
     }
 
-    fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>], attrs: &[Attribute]) {
+    fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>], attrs: &[ast::Attribute]) {
         self.ibox(INDENT_UNIT);
         self.s.word("[");
         self.print_inner_attributes_inline(attrs);
@@ -1679,7 +1679,7 @@ impl<'a> State<'a> {
         &mut self,
         element: &ast::Expr,
         count: &ast::AnonConst,
-        attrs: &[Attribute],
+        attrs: &[ast::Attribute],
     ) {
         self.ibox(INDENT_UNIT);
         self.s.word("[");
@@ -1696,7 +1696,7 @@ impl<'a> State<'a> {
         path: &ast::Path,
         fields: &[ast::Field],
         wth: &Option<P<ast::Expr>>,
-        attrs: &[Attribute],
+        attrs: &[ast::Attribute],
     ) {
         self.print_path(path, true, 0);
         self.s.word("{");
@@ -1736,7 +1736,7 @@ impl<'a> State<'a> {
         self.s.word("}");
     }
 
-    fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>], attrs: &[Attribute]) {
+    fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>], attrs: &[ast::Attribute]) {
         self.popen();
         self.print_inner_attributes_inline(attrs);
         self.commasep_exprs(Inconsistent, &exprs[..]);
diff --git a/src/librustc_ast_pretty/pprust/tests.rs b/src/librustc_ast_pretty/pprust/tests.rs
index fdbd073255e..fdbf3feb900 100644
--- a/src/librustc_ast_pretty/pprust/tests.rs
+++ b/src/librustc_ast_pretty/pprust/tests.rs
@@ -1,6 +1,6 @@
 use super::*;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_span::source_map::respan;
 use rustc_span::symbol::Ident;
 use rustc_span::with_default_session_globals;
diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs
index 3ddabcc17f8..b8929fe0889 100644
--- a/src/librustc_attr/builtin.rs
+++ b/src/librustc_attr/builtin.rs
@@ -1,6 +1,6 @@
 //! Parsing and validation of builtin attributes
 
-use rustc_ast::ast::{self, Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem};
+use rustc_ast::{self as ast, Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml
index c612781153e..dee6fed317e 100644
--- a/src/librustc_builtin_macros/Cargo.toml
+++ b/src/librustc_builtin_macros/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_parse_format = { path = "../librustc_parse_format" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index 52f86aa7e06..5dafd6b77ab 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs
index 166cd628350..25181715540 100644
--- a/src/librustc_builtin_macros/assert.rs
+++ b/src/librustc_builtin_macros/assert.rs
@@ -1,9 +1,9 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
 
-use rustc_ast::ast::{self, *};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
+use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 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 0247ca32991..4c00162b556 100644
--- a/src/librustc_builtin_macros/cfg.rs
+++ b/src/librustc_builtin_macros/cfg.rs
@@ -2,7 +2,7 @@
 //! a literal `true` or `false` based on whether the given cfg matches the
 //! current compilation environment.
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_attr as attr;
diff --git a/src/librustc_builtin_macros/cfg_accessible.rs b/src/librustc_builtin_macros/cfg_accessible.rs
index 7a91dde5a9d..75f4b077640 100644
--- a/src/librustc_builtin_macros/cfg_accessible.rs
+++ b/src/librustc_builtin_macros/cfg_accessible.rs
@@ -1,6 +1,6 @@
 //! Implementation of the `#[cfg_accessible(path)]` attribute macro.
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_feature::AttributeTemplate;
 use rustc_parse::validate_attr;
diff --git a/src/librustc_builtin_macros/cmdline_attrs.rs b/src/librustc_builtin_macros/cmdline_attrs.rs
index 093815dbbcd..34e2accc615 100644
--- a/src/librustc_builtin_macros/cmdline_attrs.rs
+++ b/src/librustc_builtin_macros/cmdline_attrs.rs
@@ -1,8 +1,8 @@
 //! Attributes injected into the crate root from command line using `-Z crate-attr`.
 
-use rustc_ast::ast::{self, AttrItem, AttrStyle};
 use rustc_ast::attr::mk_attr;
 use rustc_ast::token;
+use rustc_ast::{self as ast, AttrItem, AttrStyle};
 use rustc_session::parse::ParseSess;
 use rustc_span::FileName;
 
diff --git a/src/librustc_builtin_macros/concat.rs b/src/librustc_builtin_macros/concat.rs
index 4980ba0d9d3..e5077d93674 100644
--- a/src/librustc_builtin_macros/concat.rs
+++ b/src/librustc_builtin_macros/concat.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_expand::base::{self, DummyResult};
 use rustc_span::symbol::Symbol;
diff --git a/src/librustc_builtin_macros/concat_idents.rs b/src/librustc_builtin_macros/concat_idents.rs
index fdf05ac3880..8223cdda072 100644
--- a/src/librustc_builtin_macros/concat_idents.rs
+++ b/src/librustc_builtin_macros/concat_idents.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
diff --git a/src/librustc_builtin_macros/deriving/bounds.rs b/src/librustc_builtin_macros/deriving/bounds.rs
index cef0da60a61..12ef166b8b0 100644
--- a/src/librustc_builtin_macros/deriving/bounds.rs
+++ b/src/librustc_builtin_macros/deriving/bounds.rs
@@ -2,7 +2,7 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use rustc_ast::ast::MetaItem;
+use rustc_ast::MetaItem;
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::Span;
 
diff --git a/src/librustc_builtin_macros/deriving/clone.rs b/src/librustc_builtin_macros/deriving/clone.rs
index b307ee26c91..957c8035399 100644
--- a/src/librustc_builtin_macros/deriving/clone.rs
+++ b/src/librustc_builtin_macros/deriving/clone.rs
@@ -2,8 +2,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use rustc_ast::ast::{self, Expr, GenericArg, Generics, ItemKind, MetaItem, VariantData};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Expr, GenericArg, Generics, ItemKind, MetaItem, VariantData};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/cmp/eq.rs b/src/librustc_builtin_macros/deriving/cmp/eq.rs
index d1b799cd6a1..79f35ad5819 100644
--- a/src/librustc_builtin_macros/deriving/cmp/eq.rs
+++ b/src/librustc_builtin_macros/deriving/cmp/eq.rs
@@ -2,8 +2,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use rustc_ast::ast::{self, Expr, GenericArg, MetaItem};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Expr, GenericArg, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/cmp/ord.rs b/src/librustc_builtin_macros/deriving/cmp/ord.rs
index 3bf3860d323..c1473e24093 100644
--- a/src/librustc_builtin_macros/deriving/cmp/ord.rs
+++ b/src/librustc_builtin_macros/deriving/cmp/ord.rs
@@ -2,8 +2,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use rustc_ast::ast::{self, Expr, MetaItem};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Expr, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs
index d8edd641acd..8e9f15743cc 100644
--- a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs
+++ b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs
@@ -2,8 +2,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::{path_local, path_std};
 
-use rustc_ast::ast::{BinOpKind, Expr, MetaItem};
 use rustc_ast::ptr::P;
+use rustc_ast::{BinOpKind, Expr, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs
index 39a747c8568..21174ca4c8b 100644
--- a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs
+++ b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs
@@ -4,8 +4,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::{path_local, path_std, pathvec_std};
 
-use rustc_ast::ast::{self, BinOpKind, Expr, MetaItem};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, BinOpKind, Expr, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/debug.rs b/src/librustc_builtin_macros/deriving/debug.rs
index 76e21bc43c5..120e859f2b1 100644
--- a/src/librustc_builtin_macros/deriving/debug.rs
+++ b/src/librustc_builtin_macros/deriving/debug.rs
@@ -2,9 +2,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
-use rustc_ast::ast;
-use rustc_ast::ast::{Expr, MetaItem};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Expr, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
diff --git a/src/librustc_builtin_macros/deriving/decodable.rs b/src/librustc_builtin_macros/deriving/decodable.rs
index ce8c2dfe4d5..df69f6c90d8 100644
--- a/src/librustc_builtin_macros/deriving/decodable.rs
+++ b/src/librustc_builtin_macros/deriving/decodable.rs
@@ -4,9 +4,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::pathvec_std;
 
-use rustc_ast::ast;
-use rustc_ast::ast::{Expr, MetaItem, Mutability};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Expr, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs
index 2611855a3a1..980be3a0050 100644
--- a/src/librustc_builtin_macros/deriving/default.rs
+++ b/src/librustc_builtin_macros/deriving/default.rs
@@ -1,8 +1,8 @@
 use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 
-use rustc_ast::ast::{Expr, MetaItem};
 use rustc_ast::ptr::P;
+use rustc_ast::{Expr, MetaItem};
 use rustc_errors::struct_span_err;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::{kw, sym};
diff --git a/src/librustc_builtin_macros/deriving/encodable.rs b/src/librustc_builtin_macros/deriving/encodable.rs
index 7a880357a59..62aa1cbfbf2 100644
--- a/src/librustc_builtin_macros/deriving/encodable.rs
+++ b/src/librustc_builtin_macros/deriving/encodable.rs
@@ -89,8 +89,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::pathvec_std;
 
-use rustc_ast::ast::{Expr, ExprKind, MetaItem, Mutability};
 use rustc_ast::ptr::P;
+use rustc_ast::{Expr, ExprKind, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs
index 908aabe9024..accb0b3c949 100644
--- a/src/librustc_builtin_macros/deriving/generic/mod.rs
+++ b/src/librustc_builtin_macros/deriving/generic/mod.rs
@@ -181,9 +181,9 @@ use std::cell::RefCell;
 use std::iter;
 use std::vec;
 
-use rustc_ast::ast::{self, BinOpKind, EnumDef, Expr, Generics, PatKind};
-use rustc_ast::ast::{GenericArg, GenericParamKind, VariantData};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, BinOpKind, EnumDef, Expr, Generics, PatKind};
+use rustc_ast::{GenericArg, GenericParamKind, VariantData};
 use rustc_attr as attr;
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_expand::base::{Annotatable, ExtCtxt};
diff --git a/src/librustc_builtin_macros/deriving/generic/ty.rs b/src/librustc_builtin_macros/deriving/generic/ty.rs
index 51314dbcffc..6b7d0e1f204 100644
--- a/src/librustc_builtin_macros/deriving/generic/ty.rs
+++ b/src/librustc_builtin_macros/deriving/generic/ty.rs
@@ -4,8 +4,8 @@
 pub use PtrTy::*;
 pub use Ty::*;
 
-use rustc_ast::ast::{self, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
 use rustc_expand::base::ExtCtxt;
 use rustc_span::source_map::{respan, DUMMY_SP};
 use rustc_span::symbol::{kw, Ident, Symbol};
diff --git a/src/librustc_builtin_macros/deriving/hash.rs b/src/librustc_builtin_macros/deriving/hash.rs
index d7195188085..868f863b990 100644
--- a/src/librustc_builtin_macros/deriving/hash.rs
+++ b/src/librustc_builtin_macros/deriving/hash.rs
@@ -2,8 +2,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::{self, path_std, pathvec_std};
 
-use rustc_ast::ast::{Expr, MetaItem, Mutability};
 use rustc_ast::ptr::P;
+use rustc_ast::{Expr, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs
index 33c0edde98f..7e3fd131d44 100644
--- a/src/librustc_builtin_macros/deriving/mod.rs
+++ b/src/librustc_builtin_macros/deriving/mod.rs
@@ -1,7 +1,8 @@
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
-use rustc_ast::ast::{self, ItemKind, MetaItem};
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
+use rustc_ast::{ItemKind, MetaItem};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/env.rs b/src/librustc_builtin_macros/env.rs
index b6f733ee93d..6de12acfb94 100644
--- a/src/librustc_builtin_macros/env.rs
+++ b/src/librustc_builtin_macros/env.rs
@@ -3,8 +3,8 @@
 // interface.
 //
 
-use rustc_ast::ast::{self, GenericArg};
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{self as ast, GenericArg};
 use rustc_expand::base::{self, *};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs
index 78cead02b7b..373277f525d 100644
--- a/src/librustc_builtin_macros/format.rs
+++ b/src/librustc_builtin_macros/format.rs
@@ -1,7 +1,7 @@
 use ArgumentType::*;
 use Position::*;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs
index ccff8aa90a8..c37adb7baa0 100644
--- a/src/librustc_builtin_macros/global_allocator.rs
+++ b/src/librustc_builtin_macros/global_allocator.rs
@@ -1,11 +1,11 @@
 use crate::util::check_builtin_macro_attribute;
 
-use rustc_ast::ast::{self, Attribute, Expr, FnHeader, FnSig, Generics, Param};
-use rustc_ast::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_ast::expand::allocator::{
     AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
 };
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param};
+use rustc_ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs
index 2729239f62b..2465f33622e 100644
--- a/src/librustc_builtin_macros/global_asm.rs
+++ b/src/librustc_builtin_macros/global_asm.rs
@@ -8,7 +8,7 @@
 //! LLVM's `module asm "some assembly here"`. All of LLVM's caveats
 //! therefore apply.
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
diff --git a/src/librustc_builtin_macros/llvm_asm.rs b/src/librustc_builtin_macros/llvm_asm.rs
index 77fd71d58ef..db73fdbe24f 100644
--- a/src/librustc_builtin_macros/llvm_asm.rs
+++ b/src/librustc_builtin_macros/llvm_asm.rs
@@ -2,10 +2,11 @@
 //
 use State::*;
 
-use rustc_ast::ast::{self, LlvmAsmDialect};
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{self, TokenStream};
+use rustc_ast::LlvmAsmDialect;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, PResult};
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs
index 4f2f066e652..0c6769906f3 100644
--- a/src/librustc_builtin_macros/proc_macro_harness.rs
+++ b/src/librustc_builtin_macros/proc_macro_harness.rs
@@ -1,9 +1,9 @@
 use std::mem;
 
-use rustc_ast::ast::{self, NodeId};
 use rustc_ast::attr;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
+use rustc_ast::{self as ast, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::{ExtCtxt, ResolverExpand};
 use rustc_expand::expand::{AstFragment, ExpansionConfig};
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index e46cf67e64d..70753208af3 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
diff --git a/src/librustc_builtin_macros/standard_library_imports.rs b/src/librustc_builtin_macros/standard_library_imports.rs
index 52759fede75..e801b5c7b0c 100644
--- a/src/librustc_builtin_macros/standard_library_imports.rs
+++ b/src/librustc_builtin_macros/standard_library_imports.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_expand::base::{ExtCtxt, ResolverExpand};
 use rustc_expand::expand::ExpansionConfig;
diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs
index 16a95288ee8..8e56e80bba2 100644
--- a/src/librustc_builtin_macros/test.rs
+++ b/src/librustc_builtin_macros/test.rs
@@ -2,7 +2,7 @@
 /// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
 use crate::util::check_builtin_macro_attribute;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::*;
@@ -299,7 +299,7 @@ pub fn expand_test_or_bench(
     // extern crate test
     let test_extern = cx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None));
 
-    log::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
+    tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
     vec![
         // Access to libtest under a hygienic name
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index b21a7c1e4d5..277cd8389e3 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -1,7 +1,6 @@
 // Code that generates a test runner to run all the tests in a crate
 
-use log::debug;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::entry::EntryPointType;
 use rustc_ast::mut_visit::{ExpectOne, *};
@@ -16,6 +15,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::PanicStrategy;
 use smallvec::{smallvec, SmallVec};
+use tracing::debug;
 
 use std::{iter, mem};
 
diff --git a/src/librustc_builtin_macros/util.rs b/src/librustc_builtin_macros/util.rs
index 3ee6cd73964..01ea80c4c8a 100644
--- a/src/librustc_builtin_macros/util.rs
+++ b/src/librustc_builtin_macros/util.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast::MetaItem;
+use rustc_ast::MetaItem;
 use rustc_expand::base::ExtCtxt;
 use rustc_feature::AttributeTemplate;
 use rustc_parse::validate_attr;
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index ec4dfabdcc2..2e4b9f22f81 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -15,7 +15,7 @@ bitflags = "1.0"
 flate2 = "1.0"
 libc = "0.2"
 measureme = "0.7.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc-demangle = "0.1"
 rustc_attr = { path = "../librustc_attr" }
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index fb2e1c43524..a6062de6bf8 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -5,8 +5,8 @@ use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 
-use rustc_ast::ast::LlvmAsmDialect;
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_ast::LlvmAsmDialect;
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_codegen_ssa::mir::operand::OperandValue;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
@@ -19,7 +19,7 @@ use rustc_target::abi::*;
 use rustc_target::asm::*;
 
 use libc::{c_char, c_uint};
-use log::debug;
+use tracing::debug;
 
 impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn codegen_llvm_inline_asm(
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 6b02b5e8120..7c710a1cb3d 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -4,7 +4,6 @@ use crate::back::write::{
 use crate::llvm::archive_ro::ArchiveRO;
 use crate::llvm::{self, False, True};
 use crate::{LlvmCodegenBackend, ModuleLlvm};
-use log::{debug, info};
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
 use rustc_codegen_ssa::back::symbol_export;
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
@@ -18,6 +17,7 @@ use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::exported_symbols::SymbolExportLevel;
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, CrateType, Lto};
+use tracing::{debug, info};
 
 use std::ffi::{CStr, CString};
 use std::fs::File;
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 1a5794d1133..6f386c1287c 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -11,7 +11,6 @@ use crate::llvm_util;
 use crate::type_::Type;
 use crate::LlvmCodegenBackend;
 use crate::ModuleLlvm;
-use log::debug;
 use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
@@ -26,6 +25,7 @@ use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::InnerSpan;
 use rustc_target::spec::{CodeModel, RelocModel};
+use tracing::debug;
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
 use std::ffi::CString;
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index a0f4311b33a..4737c73d57f 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -6,7 +6,6 @@ use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use libc::{c_char, c_uint};
-use log::debug;
 use rustc_codegen_ssa::base::to_immediate;
 use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, TypeKind};
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
@@ -26,6 +25,7 @@ use std::ffi::CStr;
 use std::iter::TrustedLen;
 use std::ops::{Deref, Range};
 use std::ptr;
+use tracing::debug;
 
 // All Builders must have an llfn associated with them
 #[must_use]
@@ -303,8 +303,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         lhs: Self::Value,
         rhs: Self::Value,
     ) -> (Self::Value, Self::Value) {
-        use rustc_ast::ast::IntTy::*;
-        use rustc_ast::ast::UintTy::*;
+        use rustc_ast::IntTy::*;
+        use rustc_ast::UintTy::*;
         use rustc_middle::ty::{Int, Uint};
 
         let new_kind = match ty.kind {
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index afdc8dc6187..4afd906fce7 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -9,8 +9,8 @@ use crate::attributes;
 use crate::context::CodegenCx;
 use crate::llvm;
 use crate::value::Value;
-use log::debug;
 use rustc_codegen_ssa::traits::*;
+use tracing::debug;
 
 use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
 use rustc_middle::ty::{self, Instance, TypeFoldable};
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 2a50d4a46d2..0b1cf03fa7e 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -9,7 +9,7 @@ use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
@@ -19,7 +19,7 @@ use rustc_span::symbol::Symbol;
 use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size};
 
 use libc::{c_char, c_uint};
-use log::debug;
+use tracing::debug;
 
 /*
 * A note on nomenclature of linking: "extern", "foreign", and "upcall".
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 0c749657001..86a5ec59254 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -6,7 +6,6 @@ use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use libc::c_uint;
-use log::debug;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -21,6 +20,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
+use tracing::debug;
 
 use std::ffi::CStr;
 
diff --git a/src/librustc_codegen_llvm/coverageinfo/mapgen.rs b/src/librustc_codegen_llvm/coverageinfo/mapgen.rs
index b50b3b6d975..a39234c0b7f 100644
--- a/src/librustc_codegen_llvm/coverageinfo/mapgen.rs
+++ b/src/librustc_codegen_llvm/coverageinfo/mapgen.rs
@@ -3,11 +3,11 @@ use crate::coverageinfo;
 use crate::llvm;
 
 use llvm::coverageinfo::CounterMappingRegion;
-use log::debug;
 use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression, Region};
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_llvm::RustString;
+use tracing::debug;
 
 use std::ffi::CString;
 
diff --git a/src/librustc_codegen_llvm/coverageinfo/mod.rs b/src/librustc_codegen_llvm/coverageinfo/mod.rs
index da567293d7b..54570920219 100644
--- a/src/librustc_codegen_llvm/coverageinfo/mod.rs
+++ b/src/librustc_codegen_llvm/coverageinfo/mod.rs
@@ -5,7 +5,6 @@ use crate::common::CodegenCx;
 
 use libc::c_uint;
 use llvm::coverageinfo::CounterMappingRegion;
-use log::debug;
 use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage, Region};
 use rustc_codegen_ssa::traits::{
     BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods,
@@ -13,6 +12,7 @@ use rustc_codegen_ssa::traits::{
 use rustc_data_structures::fx::FxHashMap;
 use rustc_llvm::RustString;
 use rustc_middle::ty::Instance;
+use tracing::debug;
 
 use std::cell::RefCell;
 use std::ffi::CString;
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 9d6b15ec4af..9d92d53775c 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -18,8 +18,7 @@ use crate::llvm::debuginfo::{
 };
 use crate::value::Value;
 
-use log::debug;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -43,6 +42,7 @@ use rustc_span::{self, SourceFile, SourceFileHash, Span};
 use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding};
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
+use tracing::debug;
 
 use libc::{c_longlong, c_uint};
 use std::collections::hash_map::Entry;
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index a01b8553721..b414426af8c 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -33,9 +33,9 @@ use rustc_span::{self, BytePos, Span};
 use rustc_target::abi::{LayoutOf, Primitive, Size};
 
 use libc::c_uint;
-use log::debug;
 use smallvec::SmallVec;
 use std::cell::RefCell;
+use tracing::debug;
 
 mod create_scope_map;
 pub mod gdb;
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index 26ab46bde38..ec42bd4a039 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -18,9 +18,9 @@ use crate::llvm;
 use crate::llvm::AttributePlace::Function;
 use crate::type_::Type;
 use crate::value::Value;
-use log::debug;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::ty::Ty;
+use tracing::debug;
 
 /// Declare a function.
 ///
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 14aec1ff5e1..f1977946ee9 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -7,9 +7,7 @@ use crate::type_of::LayoutLlvmExt;
 use crate::va_arg::emit_va_arg;
 use crate::value::Value;
 
-use log::debug;
-
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
 use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -28,6 +26,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, symbol::kw, Span, Symbol};
 use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive};
 use rustc_target::spec::PanicStrategy;
+use tracing::debug;
 
 use std::cmp::Ordering;
 use std::iter;
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 63b0aa64bd3..32822eba930 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -389,10 +389,10 @@ pub enum AsmDialect {
 }
 
 impl AsmDialect {
-    pub fn from_generic(asm: rustc_ast::ast::LlvmAsmDialect) -> Self {
+    pub fn from_generic(asm: rustc_ast::LlvmAsmDialect) -> Self {
         match asm {
-            rustc_ast::ast::LlvmAsmDialect::Att => AsmDialect::Att,
-            rustc_ast::ast::LlvmAsmDialect::Intel => AsmDialect::Intel,
+            rustc_ast::LlvmAsmDialect::Att => AsmDialect::Att,
+            rustc_ast::LlvmAsmDialect::Intel => AsmDialect::Intel,
         }
     }
 }
diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs
index 6d0612ca075..9036428c04b 100644
--- a/src/librustc_codegen_llvm/metadata.rs
+++ b/src/librustc_codegen_llvm/metadata.rs
@@ -4,10 +4,10 @@ use crate::llvm::{mk_section_iter, False, ObjectFile};
 use rustc_middle::middle::cstore::MetadataLoader;
 use rustc_target::spec::Target;
 
-use log::debug;
 use rustc_codegen_ssa::METADATA_FILENAME;
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_data_structures::rustc_erase_owner;
+use tracing::debug;
 
 use rustc_fs_util::path_to_c_string;
 use std::path::Path;
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index 0936deb7bb5..992e83d08fc 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -4,7 +4,6 @@ use crate::base;
 use crate::context::CodegenCx;
 use crate::llvm;
 use crate::type_of::LayoutLlvmExt;
-use log::debug;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 pub use rustc_middle::mir::mono::MonoItem;
@@ -12,6 +11,7 @@ use rustc_middle::mir::mono::{Linkage, Visibility};
 use rustc_middle::ty::layout::FnAbiExt;
 use rustc_middle::ty::{self, Instance, TypeFoldable};
 use rustc_target::abi::LayoutOf;
+use tracing::debug;
 
 impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn predefine_static(
diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index 05e364884f6..3b53b4fe77b 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -7,7 +7,7 @@ use crate::llvm;
 use crate::llvm::{Bool, False, True};
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_codegen_ssa::common::TypeKind;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::small_c_str::SmallCStr;
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index 1d0adc5783f..40870c66475 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -1,7 +1,6 @@
 use crate::abi::FnAbi;
 use crate::common::*;
 use crate::type_::Type;
-use log::debug;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
@@ -10,6 +9,7 @@ use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAndLayoutMethods, Variants};
+use tracing::debug;
 
 use std::fmt::Write;
 
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index ff9dac372ab..5707d3cd0ed 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -14,7 +14,7 @@ bitflags = "1.2.1"
 cc = "1.0.1"
 num_cpus = "1.0"
 memmap = "0.7"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 libc = "0.2.50"
 jobserver = "0.1.11"
 tempfile = "3.1"
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 5100ef8ad4f..0ddf8bd316f 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -266,7 +266,7 @@ impl<'a> GccLinker<'a> {
                 if let Some(implib_name) = implib_name {
                     let implib = out_filename.parent().map(|dir| dir.join(&implib_name));
                     if let Some(implib) = implib {
-                        self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
+                        self.linker_arg(&format!("--out-implib={}", (*implib).to_str().unwrap()));
                     }
                 }
             }
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 6bfbda0f1d7..73e33369175 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -19,7 +19,7 @@
 #[macro_use]
 extern crate rustc_macros;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index e8270b4fa0a..371e1274d8d 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -9,7 +9,7 @@ use crate::meth;
 use crate::traits::*;
 use crate::MemFlags;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_hir::lang_items;
 use rustc_index::vec::Idx;
 use rustc_middle::mir;
diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs
index b6b57744f95..69931935c49 100644
--- a/src/librustc_codegen_ssa/traits/asm.rs
+++ b/src/librustc_codegen_ssa/traits/asm.rs
@@ -1,7 +1,7 @@
 use super::BackendTypes;
 use crate::mir::operand::OperandRef;
 use crate::mir::place::PlaceRef;
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{GlobalAsm, LlvmInlineAsmInner};
 use rustc_middle::ty::Instance;
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 1926dbf06e7..988bb733f9f 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 [dependencies]
 ena = "0.14"
 indexmap = "1.5.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 lazy_static = "1"
 once_cell = { version = "1", features = ["parking_lot"] }
@@ -30,7 +30,7 @@ rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
 measureme = "0.7.1"
 libc = "0.2"
-stacker = "0.1.9"
+stacker = "0.1.11"
 tempfile = "3.0.5"
 
 [dependencies.parking_lot]
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 017511cc50d..1937f615e70 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -26,7 +26,7 @@
 #![allow(rustc::default_hash_types)]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate cfg_if;
 #[macro_use]
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index cd94ccc7ad7..09f5b22cc63 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -15,7 +15,7 @@ extern crate lazy_static;
 
 pub extern crate rustc_plugin_impl as plugin;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_codegen_ssa::{traits::CodegenBackend, CodegenResults};
 use rustc_data_structures::profiling::print_time_passes_entry;
 use rustc_data_structures::sync::SeqCst;
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 2864e46cadc..b0fbf1e03f5 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -1,6 +1,6 @@
 //! The various pretty-printing routines.
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
diff --git a/src/librustc_error_codes/error_codes/E0754.md b/src/librustc_error_codes/error_codes/E0754.md
index abdc01ed21a..57620bcd65c 100644
--- a/src/librustc_error_codes/error_codes/E0754.md
+++ b/src/librustc_error_codes/error_codes/E0754.md
@@ -1,31 +1,25 @@
 An non-ascii identifier was used in an invalid context.
 
-Erroneous code example:
+Erroneous code examples:
 
 ```compile_fail,E0754
 # #![feature(non_ascii_idents)]
 
-mod řųśť;
-// ^ error!
-fn main() {}
-```
-
-```compile_fail,E0754
-# #![feature(non_ascii_idents)]
+mod řųśť; // error!
 
 #[no_mangle]
-fn řųśť() {}
-// ^ error!
+fn řųśť() {} // error!
+
 fn main() {}
 ```
 
-Non-ascii can be used as module names if it is inline
-or a #\[path\] attribute is specified. For example:
+Non-ascii can be used as module names if it is inlined or if a `#[path]`
+attribute is specified. For example:
 
 ```
 # #![feature(non_ascii_idents)]
 
-mod řųśť {
+mod řųśť { // ok!
     const IS_GREAT: bool = true;
 }
 
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index cd4b5d56f36..870f7b81e21 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -127,14 +127,15 @@ impl Diagnostic {
     }
 
     /// Adds a span/label to be included in the resulting snippet.
-    /// This label will be shown together with the original span/label used when creating the
-    /// diagnostic, *not* a span added by one of the `span_*` methods.
     ///
-    /// This is pushed onto the `MultiSpan` that was created when the
-    /// diagnostic was first built. If you don't call this function at
-    /// all, and you just supplied a `Span` to create the diagnostic,
-    /// then the snippet will just include that `Span`, which is
-    /// called the primary span.
+    /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic
+    /// was first built. That means it will be shown together with the original
+    /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods.
+    ///
+    /// This span is *not* considered a ["primary span"][`MultiSpan`]; only
+    /// the `Span` supplied when creating the diagnostic is primary.
+    ///
+    /// [`MultiSpan`]: ../rustc_span/struct.MultiSpan.html
     pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
         self.span.push_span_label(span, label.into());
         self
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index dc52e29fa9b..d1ff6f721c4 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -184,11 +184,15 @@ impl<'a> DiagnosticBuilder<'a> {
     }
 
     /// Adds a span/label to be included in the resulting snippet.
-    /// This is pushed onto the `MultiSpan` that was created when the
-    /// diagnostic was first built. If you don't call this function at
-    /// all, and you just supplied a `Span` to create the diagnostic,
-    /// then the snippet will just include that `Span`, which is
-    /// called the primary span.
+    ///
+    /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic
+    /// was first built. That means it will be shown together with the original
+    /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods.
+    ///
+    /// This span is *not* considered a ["primary span"][`MultiSpan`]; only
+    /// the `Span` supplied when creating the diagnostic is primary.
+    ///
+    /// [`MultiSpan`]: ../rustc_span/struct.MultiSpan.html
     pub fn span_label(&mut self, span: Span, label: impl Into<String>) -> &mut Self {
         self.0.diagnostic.span_label(span, label);
         self
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 5a36df8299c..0a5e1f76d10 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -1,12 +1,12 @@
 use crate::expand::{self, AstFragment, Invocation};
 use crate::module::DirectoryOwnership;
 
-use rustc_ast::ast::{self, Attribute, NodeId, PatKind};
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{self, TokenStream};
 use rustc_ast::visit::{AssocCtxt, Visitor};
+use rustc_ast::{self as ast, Attribute, NodeId, PatKind};
 use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs
index 81ff4b31578..7f4737a38ab 100644
--- a/src/librustc_expand/build.rs
+++ b/src/librustc_expand/build.rs
@@ -1,8 +1,8 @@
 use crate::base::ExtCtxt;
 
-use rustc_ast::ast::{self, AttrVec, BlockCheckMode, Expr, PatKind, UnOp};
 use rustc_ast::attr;
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, PatKind, UnOp};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 
diff --git a/src/librustc_expand/config.rs b/src/librustc_expand/config.rs
index f6ddcd35068..afd1e606402 100644
--- a/src/librustc_expand/config.rs
+++ b/src/librustc_expand/config.rs
@@ -1,9 +1,9 @@
 //! Conditional compilation stripping.
 
-use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem};
 use rustc_ast::attr::HasAttrs;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, AttrItem, Attribute, MetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::map_in_place::MapInPlace;
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index 8da56dc67e5..7a21caf255a 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -7,13 +7,13 @@ use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwne
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
-use rustc_ast::ast::{self, AttrItem, Block, LitKind, NodeId, PatKind, Path};
-use rustc_ast::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::{self as ast, AttrItem, Block, LitKind, NodeId, PatKind, Path};
+use rustc_ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
 use rustc_data_structures::map_in_place::MapInPlace;
diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs
index ca3e68fa670..6b419dae3f6 100644
--- a/src/librustc_expand/mbe/macro_check.rs
+++ b/src/librustc_expand/mbe/macro_check.rs
@@ -106,8 +106,8 @@
 //! bound.
 use crate::mbe::{KleeneToken, TokenTree};
 
-use rustc_ast::ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast::token::{DelimToken, Token, TokenKind};
+use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
 use rustc_session::parse::ParseSess;
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 808d77842cb..48a622d13ef 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -8,7 +8,7 @@ use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success};
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
 use crate::mbe::transcribe::transcribe;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::token::{self, NonterminalKind, NtTT, Token, TokenKind::*};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast_pretty::pprust;
diff --git a/src/librustc_expand/mbe/quoted.rs b/src/librustc_expand/mbe/quoted.rs
index 774cc84afde..01b11bb979d 100644
--- a/src/librustc_expand/mbe/quoted.rs
+++ b/src/librustc_expand/mbe/quoted.rs
@@ -1,9 +1,9 @@
 use crate::mbe::macro_parser;
 use crate::mbe::{Delimited, KleeneOp, KleeneToken, SequenceRepetition, TokenTree};
 
-use rustc_ast::ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream;
+use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, Ident};
diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs
index e2d3d5c4d64..b908a12c1fc 100644
--- a/src/librustc_expand/mbe/transcribe.rs
+++ b/src/librustc_expand/mbe/transcribe.rs
@@ -2,10 +2,10 @@ use crate::base::ExtCtxt;
 use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
-use rustc_ast::ast::MacCall;
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{self, NtTT, Token};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
+use rustc_ast::MacCall;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{pluralize, PResult};
diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs
index 12fe49ed585..1e123a2e145 100644
--- a/src/librustc_expand/module.rs
+++ b/src/librustc_expand/module.rs
@@ -1,5 +1,4 @@
-use rustc_ast::ast::{Attribute, Mod};
-use rustc_ast::token;
+use rustc_ast::{token, Attribute, Mod};
 use rustc_errors::{struct_span_err, PResult};
 use rustc_parse::new_parser_from_file;
 use rustc_session::parse::ParseSess;
diff --git a/src/librustc_expand/mut_visit/tests.rs b/src/librustc_expand/mut_visit/tests.rs
index 0608ccfffb8..38ff594b6e9 100644
--- a/src/librustc_expand/mut_visit/tests.rs
+++ b/src/librustc_expand/mut_visit/tests.rs
@@ -1,6 +1,6 @@
 use crate::tests::{matches_codepattern, string_to_crate};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast_pretty::pprust;
 use rustc_span::symbol::Ident;
diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs
index 5c9116b2f13..643305f153c 100644
--- a/src/librustc_expand/parse/tests.rs
+++ b/src/librustc_expand/parse/tests.rs
@@ -1,10 +1,10 @@
 use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
 
-use rustc_ast::ast::{self, PatKind};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::visit;
+use rustc_ast::{self as ast, PatKind};
 use rustc_ast_pretty::pprust::item_to_string;
 use rustc_errors::PResult;
 use rustc_parse::new_parser_from_source_str;
diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs
index b4ffd714fef..0788823b0e7 100644
--- a/src/librustc_expand/placeholders.rs
+++ b/src/librustc_expand/placeholders.rs
@@ -1,7 +1,7 @@
 use crate::base::ExtCtxt;
 use crate::expand::{AstFragment, AstFragmentKind};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_span::source_map::{dummy_spanned, DUMMY_SP};
diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs
index 85fbf3bc0d0..4e865c20d6f 100644
--- a/src/librustc_expand/proc_macro.rs
+++ b/src/librustc_expand/proc_macro.rs
@@ -1,9 +1,9 @@
 use crate::base::{self, *};
 use crate::proc_macro_server;
 
-use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
 use rustc_ast::token;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::{self as ast, *};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, ErrorReported};
 use rustc_parse::nt_to_tokenstream;
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index 83a650443bc..33e35cd0404 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -1,6 +1,6 @@
 use crate::base::ExtCtxt;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 use rustc_ast_pretty::pprust;
diff --git a/src/librustc_expand/tests.rs b/src/librustc_expand/tests.rs
index b562a690f83..6993ce58fa6 100644
--- a/src/librustc_expand/tests.rs
+++ b/src/librustc_expand/tests.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
 use rustc_session::parse::ParseSess;
diff --git a/src/librustc_hir/arena.rs b/src/librustc_hir/arena.rs
index 6ba39666607..85ab7906d25 100644
--- a/src/librustc_hir/arena.rs
+++ b/src/librustc_hir/arena.rs
@@ -15,8 +15,8 @@ macro_rules! arena_types {
             [few] hir_krate: rustc_hir::Crate<$tcx>,
             [] arm: rustc_hir::Arm<$tcx>,
             [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
-            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
-            [] attribute: rustc_ast::ast::Attribute,
+            [] asm_template: rustc_ast::InlineAsmTemplatePiece,
+            [] attribute: rustc_ast::Attribute,
             [] block: rustc_hir::Block<$tcx>,
             [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
             [few] global_asm: rustc_hir::GlobalAsm,
diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs
index c4877be3f64..fb7fced27c2 100644
--- a/src/librustc_hir/def.rs
+++ b/src/librustc_hir/def.rs
@@ -1,8 +1,8 @@
 use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use crate::hir;
 
-use rustc_ast::ast;
-use rustc_ast::ast::NodeId;
+use rustc_ast as ast;
+use rustc_ast::NodeId;
 use rustc_macros::HashStable_Generic;
 use rustc_span::hygiene::MacroKind;
 
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 928235adac3..cf356763130 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1,19 +1,19 @@
 use crate::def::{DefKind, Namespace, Res};
 use crate::def_id::DefId;
 crate use crate::hir_id::HirId;
-use crate::itemlikevisit;
+use crate::{itemlikevisit, LangItem};
 
-use rustc_ast::ast::{self, CrateSugar, LlvmAsmDialect};
-use rustc_ast::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
-pub use rustc_ast::ast::{BorrowKind, ImplPolarity, IsAuto};
-pub use rustc_ast::ast::{CaptureBy, Movability, Mutability};
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::util::parser::ExprPrecedence;
+use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect};
+use rustc_ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
+pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
+pub use rustc_ast::{CaptureBy, Movability, Mutability};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_macros::HashStable_Generic;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::source_map::{SourceMap, Spanned};
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::asm::InlineAsmRegOrRegClass;
@@ -363,6 +363,8 @@ pub enum TraitBoundModifier {
 #[derive(Debug, HashStable_Generic)]
 pub enum GenericBound<'hir> {
     Trait(PolyTraitRef<'hir>, TraitBoundModifier),
+    // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
+    LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
     Outlives(Lifetime),
 }
 
@@ -377,6 +379,7 @@ impl GenericBound<'_> {
     pub fn span(&self) -> Span {
         match self {
             &GenericBound::Trait(ref t, ..) => t.span,
+            &GenericBound::LangItemTrait(_, span, ..) => span,
             &GenericBound::Outlives(ref l) => l.span,
         }
     }
@@ -1419,10 +1422,10 @@ impl Expr<'_> {
         self.is_place_expr(|_| true)
     }
 
-    // Whether this is a place expression.
-    // `allow_projections_from` should return `true` if indexing a field or
-    // index expression based on the given expression should be considered a
-    // place expression.
+    /// Whether this is a place expression.
+    ///
+    /// `allow_projections_from` should return `true` if indexing a field or index expression based
+    /// on the given expression should be considered a place expression.
     pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
         match self.kind {
             ExprKind::Path(QPath::Resolved(_, ref path)) => match path.res {
@@ -1441,6 +1444,9 @@ impl Expr<'_> {
                 allow_projections_from(base) || base.is_place_expr(allow_projections_from)
             }
 
+            // Lang item paths cannot currently be local variables or statics.
+            ExprKind::Path(QPath::LangItem(..)) => false,
+
             // Partially qualified paths in expressions can only legally
             // refer to associated items which are always rvalues.
             ExprKind::Path(QPath::TypeRelative(..))
@@ -1489,58 +1495,28 @@ impl Expr<'_> {
 
 /// Checks if the specified expression is a built-in range literal.
 /// (See: `LoweringContext::lower_expr()`).
-///
-/// FIXME(#60607): This function is a hack. If and when we have `QPath::Lang(...)`,
-/// we can use that instead as simpler, more reliable mechanism, as opposed to using `SourceMap`.
-pub fn is_range_literal(sm: &SourceMap, expr: &Expr<'_>) -> bool {
-    // Returns whether the given path represents a (desugared) range,
-    // either in std or core, i.e. has either a `::std::ops::Range` or
-    // `::core::ops::Range` prefix.
-    fn is_range_path(path: &Path<'_>) -> bool {
-        let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
-        let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
-
-        // "{{root}}" is the equivalent of `::` prefix in `Path`.
-        if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
-            (*std_core == "std" || *std_core == "core") && range.starts_with("Range")
-        } else {
-            false
-        }
-    };
-
-    // Check whether a span corresponding to a range expression is a
-    // range literal, rather than an explicit struct or `new()` call.
-    fn is_lit(sm: &SourceMap, span: &Span) -> bool {
-        sm.span_to_snippet(*span).map(|range_src| range_src.contains("..")).unwrap_or(false)
-    };
-
+pub fn is_range_literal(expr: &Expr<'_>) -> bool {
     match expr.kind {
         // All built-in range literals but `..=` and `..` desugar to `Struct`s.
-        ExprKind::Struct(ref qpath, _, _) => {
-            if let QPath::Resolved(None, ref path) = **qpath {
-                return is_range_path(&path) && is_lit(sm, &expr.span);
-            }
-        }
-
-        // `..` desugars to its struct path.
-        ExprKind::Path(QPath::Resolved(None, ref path)) => {
-            return is_range_path(&path) && is_lit(sm, &expr.span);
-        }
+        ExprKind::Struct(ref qpath, _, _) => matches!(
+            **qpath,
+            QPath::LangItem(
+                LangItem::Range
+                | LangItem::RangeTo
+                | LangItem::RangeFrom
+                | LangItem::RangeFull
+                | LangItem::RangeToInclusive,
+                _,
+            )
+        ),
 
         // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
         ExprKind::Call(ref func, _) => {
-            if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
-                if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
-                    let new_call = segment.ident.name == sym::new;
-                    return is_range_path(&path) && is_lit(sm, &expr.span) && new_call;
-                }
-            }
+            matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _)))
         }
 
-        _ => {}
+        _ => false,
     }
-
-    false
 }
 
 #[derive(Debug, HashStable_Generic)]
@@ -1677,6 +1653,40 @@ pub enum QPath<'hir> {
     /// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
     /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
     TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
+
+    /// Reference to a `#[lang = "foo"]` item.
+    LangItem(LangItem, Span),
+}
+
+impl<'hir> QPath<'hir> {
+    /// Returns the span of this `QPath`.
+    pub fn span(&self) -> Span {
+        match *self {
+            QPath::Resolved(_, path) => path.span,
+            QPath::TypeRelative(_, ps) => ps.ident.span,
+            QPath::LangItem(_, span) => span,
+        }
+    }
+
+    /// Returns the span of the qself of this `QPath`. For example, `()` in
+    /// `<() as Trait>::method`.
+    pub fn qself_span(&self) -> Span {
+        match *self {
+            QPath::Resolved(_, path) => path.span,
+            QPath::TypeRelative(qself, _) => qself.span,
+            QPath::LangItem(_, span) => span,
+        }
+    }
+
+    /// Returns the span of the last segment of this `QPath`. For example, `method` in
+    /// `<() as Trait>::method`.
+    pub fn last_segment_span(&self) -> Span {
+        match *self {
+            QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
+            QPath::TypeRelative(_, segment) => segment.ident.span,
+            QPath::LangItem(_, span) => span,
+        }
+    }
 }
 
 /// Hints at the original code for a let statement.
diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs
index 23d642731da..76cf6bd4776 100644
--- a/src/librustc_hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -34,8 +34,8 @@
 use crate::hir::*;
 use crate::hir_id::CRATE_HIR_ID;
 use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
-use rustc_ast::ast::{Attribute, Label};
 use rustc_ast::walk_list;
+use rustc_ast::{Attribute, Label};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
 
@@ -724,6 +724,7 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(
             visitor.visit_ty(qself);
             visitor.visit_path_segment(span, segment);
         }
+        QPath::LangItem(..) => {}
     }
 }
 
@@ -838,6 +839,10 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
         GenericBound::Trait(ref typ, modifier) => {
             visitor.visit_poly_trait_ref(typ, modifier);
         }
+        GenericBound::LangItemTrait(_, span, hir_id, args) => {
+            visitor.visit_id(hir_id);
+            visitor.visit_generic_args(span, args);
+        }
         GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
     }
 }
diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs
index b09657bd9b4..c00d861350d 100644
--- a/src/librustc_hir/lang_items.rs
+++ b/src/librustc_hir/lang_items.rs
@@ -10,9 +10,9 @@
 pub use self::LangItem::*;
 
 use crate::def_id::DefId;
-use crate::Target;
+use crate::{MethodKind, Target};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable_Generic;
@@ -307,4 +307,38 @@ language_item_table! {
     CountCodeRegionFnLangItem,         sym::count_code_region,         count_code_region_fn,         Target::Fn;
     CoverageCounterAddFnLangItem,      sym::coverage_counter_add,      coverage_counter_add_fn,      Target::Fn;
     CoverageCounterSubtractFnLangItem, sym::coverage_counter_subtract, coverage_counter_subtract_fn, Target::Fn;
+
+    // Language items from AST lowering
+    TryFromError,                  sym::from_error,         from_error_fn,           Target::Method(MethodKind::Trait { body: false });
+    TryFromOk,                     sym::from_ok,            from_ok_fn,              Target::Method(MethodKind::Trait { body: false });
+    TryIntoResult,                 sym::into_result,        into_result_fn,          Target::Method(MethodKind::Trait { body: false });
+
+    PollReady,                     sym::Ready,              poll_ready_variant,      Target::Variant;
+    PollPending,                   sym::Pending,            poll_pending_variant,    Target::Variant;
+
+    FromGenerator,                 sym::from_generator,     from_generator_fn,       Target::Fn;
+    GetContext,                    sym::get_context,        get_context_fn,          Target::Fn;
+
+    FuturePoll,                    sym::poll,               future_poll_fn,          Target::Method(MethodKind::Trait { body: false });
+
+    FromFrom,                      sym::from,               from_fn,                 Target::Method(MethodKind::Trait { body: false });
+
+    OptionSome,                    sym::Some,               option_some_variant,     Target::Variant;
+    OptionNone,                    sym::None,               option_none_variant,     Target::Variant;
+
+    ResultOk,                      sym::Ok,                 result_ok_variant,       Target::Variant;
+    ResultErr,                     sym::Err,                result_err_variant,      Target::Variant;
+
+    IntoIterIntoIter,              sym::into_iter,          into_iter_fn,            Target::Method(MethodKind::Trait { body: false });
+    IteratorNext,                  sym::next,               next_fn,                 Target::Method(MethodKind::Trait { body: false});
+
+    PinNewUnchecked,               sym::new_unchecked,      new_unchecked_fn,        Target::Method(MethodKind::Inherent);
+
+    RangeFrom,                     sym::RangeFrom,           range_from_struct,          Target::Struct;
+    RangeFull,                     sym::RangeFull,           range_full_struct,          Target::Struct;
+    RangeInclusiveStruct,          sym::RangeInclusive,      range_inclusive_struct,     Target::Struct;
+    RangeInclusiveNew,             sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
+    Range,                         sym::Range,               range_struct,               Target::Struct;
+    RangeToInclusive,              sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct;
+    RangeTo,                       sym::RangeTo,             range_to_struct,            Target::Struct;
 }
diff --git a/src/librustc_hir/target.rs b/src/librustc_hir/target.rs
index 3a4485a1b17..1efc8bc3124 100644
--- a/src/librustc_hir/target.rs
+++ b/src/librustc_hir/target.rs
@@ -29,6 +29,7 @@ pub enum Target {
     TyAlias,
     OpaqueTy,
     Enum,
+    Variant,
     Struct,
     Union,
     Trait,
@@ -62,6 +63,7 @@ impl Display for Target {
                 Target::TyAlias => "type alias",
                 Target::OpaqueTy => "opaque type",
                 Target::Enum => "enum",
+                Target::Variant => "enum variant",
                 Target::Struct => "struct",
                 Target::Union => "union",
                 Target::Trait => "trait",
diff --git a/src/librustc_hir/weak_lang_items.rs b/src/librustc_hir/weak_lang_items.rs
index fd64361cb35..76b95c696f7 100644
--- a/src/librustc_hir/weak_lang_items.rs
+++ b/src/librustc_hir/weak_lang_items.rs
@@ -3,7 +3,7 @@
 use crate::def_id::DefId;
 use crate::{lang_items, LangItem, LanguageItems};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::symbol::{sym, Symbol};
 
diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs
index 2298a80ae4f..f6e4b1fb418 100644
--- a/src/librustc_hir_pretty/lib.rs
+++ b/src/librustc_hir_pretty/lib.rs
@@ -1,7 +1,7 @@
 #![feature(or_patterns)]
 #![recursion_limit = "256"]
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
 use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
 use rustc_ast_pretty::pp::{self, Breaks};
@@ -1729,6 +1729,11 @@ impl<'a> State<'a> {
                     colons_before_params,
                 )
             }
+            hir::QPath::LangItem(lang_item, span) => {
+                self.s.word("#[lang = \"");
+                self.print_ident(Ident::new(lang_item.name(), span));
+                self.s.word("\"]");
+            }
         }
     }
 
@@ -2142,6 +2147,11 @@ impl<'a> State<'a> {
                     }
                     self.print_poly_trait_ref(tref);
                 }
+                GenericBound::LangItemTrait(lang_item, span, ..) => {
+                    self.s.word("#[lang = \"");
+                    self.print_ident(Ident::new(lang_item.name(), *span));
+                    self.s.word("\"]");
+                }
                 GenericBound::Outlives(lt) => {
                     self.print_lifetime(lt);
                 }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index df602d8bd1b..e17396422f1 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -33,7 +33,7 @@
 //! fn baz() { foo(); }
 //! ```
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
 use rustc_graphviz as dot;
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index ed04a947485..80448c01a26 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -21,7 +21,7 @@
 //! allows for doing a more fine-grained check to see if pre- or post-lto data
 //! was re-used.
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::mir::mono::CodegenUnitNameBuilder;
 use rustc_middle::ty::TyCtxt;
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 0f254aee8e3..f0a10885550 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -13,7 +13,7 @@
 //! Errors are reported if we are in the suitable configuration but
 //! the required condition is not met.
 
-use rustc_ast::ast::{self, Attribute, NestedMetaItem};
+use rustc_ast::{self as ast, Attribute, NestedMetaItem};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs
index 133c4bf2db5..3a54a647530 100644
--- a/src/librustc_infer/infer/combine.rs
+++ b/src/librustc_infer/infer/combine.rs
@@ -34,7 +34,7 @@ use super::{InferCtxt, MiscVariable, TypeTrace};
 
 use crate::traits::{Obligation, PredicateObligations};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_hir::def_id::DefId;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::TypeError;
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index 122d6e3543c..4d84462c42b 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -1,8 +1,8 @@
 pub use crate::passes::BoxedResolver;
 use crate::util;
 
-use rustc_ast::ast::{self, MetaItemKind};
 use rustc_ast::token;
+use rustc_ast::{self as ast, MetaItemKind};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index daa7444fb9e..007dbfb9fdd 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -4,7 +4,7 @@ use crate::util;
 
 use once_cell::sync::Lazy;
 use rustc_ast::mut_visit::MutVisitor;
-use rustc_ast::{self, ast, visit};
+use rustc_ast::{self as ast, visit};
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 2f32737cca0..8b82217a91a 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -1,7 +1,7 @@
 use crate::interface::{Compiler, Result};
 use crate::passes::{self, BoxedResolver, QueryContext};
 
-use rustc_ast::{self, ast};
+use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
 use rustc_errors::ErrorReported;
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 36eaad16079..8816ba198cf 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -1,8 +1,7 @@
-use rustc_ast::ast::{AttrVec, BlockCheckMode};
 use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
 use rustc_ast::ptr::P;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
-use rustc_ast::{self, ast};
+use rustc_ast::{self as ast, AttrVec, BlockCheckMode};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 3859d0f163a..36eb272cdfc 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -23,10 +23,10 @@
 use crate::{
     types::CItemKind, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
 };
-use rustc_ast::ast::{self, Expr};
 use rustc_ast::attr::{self, HasAttrs};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
+use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust::{self, expr_to_string};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
@@ -1057,7 +1057,7 @@ impl TypeAliasBounds {
                     _ => false,
                 }
             }
-            hir::QPath::Resolved(..) => false,
+            hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false,
         }
     }
 
@@ -1287,7 +1287,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
             return;
         }
 
-        use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot};
+        use self::ast::{PatKind, RangeSyntax::DotDotDot};
 
         /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
         /// corresponding to the ellipsis.
@@ -1860,7 +1860,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
         /// Test if this constant is all-0.
         fn is_zero(expr: &hir::Expr<'_>) -> bool {
             use hir::ExprKind::*;
-            use rustc_ast::ast::LitKind::*;
+            use rustc_ast::LitKind::*;
             match &expr.kind {
                 Lit(lit) => {
                     if let Int(i, _) = lit.node {
diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs
index 31d30a264a5..a6784ffffcd 100644
--- a/src/librustc_lint/context.rs
+++ b/src/librustc_lint/context.rs
@@ -18,7 +18,7 @@ use self::TargetLint::*;
 
 use crate::levels::LintLevelsBuilder;
 use crate::passes::{EarlyLintPassObject, LateLintPassObject};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
@@ -703,7 +703,7 @@ impl<'tcx> LateContext<'tcx> {
     pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
         match *qpath {
             hir::QPath::Resolved(_, ref path) => path.res,
-            hir::QPath::TypeRelative(..) => self
+            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
                 .maybe_typeck_results()
                 .and_then(|typeck_results| typeck_results.type_dependent_def(id))
                 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index 017d4e31e4a..998676d44d2 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -16,7 +16,7 @@
 
 use crate::context::{EarlyContext, LintContext, LintStore};
 use crate::passes::{EarlyLintPass, EarlyLintPassObject};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::visit as ast_visit;
 use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs
index 30fae324392..100e555f299 100644
--- a/src/librustc_lint/internal.rs
+++ b/src/librustc_lint/internal.rs
@@ -2,7 +2,7 @@
 //! Clippy.
 
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_ast::ast::{Item, ItemKind};
+use rustc_ast::{Item, ItemKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs
index 6c497d02285..a6c04fb0b4c 100644
--- a/src/librustc_lint/late.rs
+++ b/src/librustc_lint/late.rs
@@ -15,7 +15,7 @@
 //! for all lint attributes.
 
 use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::walk_list;
 use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
 use rustc_hir as hir;
diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs
index 145a07d8dc8..48254dcee82 100644
--- a/src/librustc_lint/levels.rs
+++ b/src/librustc_lint/levels.rs
@@ -1,6 +1,6 @@
 use crate::context::{CheckLintNameResult, LintStore};
 use crate::late::unerased_lint_store;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::unwrap_or;
 use rustc_ast_pretty::pprust;
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 1f17c7dcba4..0a14b16e274 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -55,7 +55,7 @@ mod redundant_semicolon;
 mod types;
 mod unused;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::query::Providers;
diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs
index ab1658b2229..2f0b2a8d680 100644
--- a/src/librustc_lint/non_ascii_idents.rs
+++ b/src/librustc_lint/non_ascii_idents.rs
@@ -1,5 +1,5 @@
 use crate::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::symbol::Symbol;
 
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 5ca6f461048..f23e8c5e208 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -1,5 +1,5 @@
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs
index 75e50f74a81..159286c13a4 100644
--- a/src/librustc_lint/passes.rs
+++ b/src/librustc_lint/passes.rs
@@ -1,6 +1,6 @@
 use crate::context::{EarlyContext, LateContext};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::sync;
 use rustc_hir as hir;
 use rustc_session::lint::builtin::HardwiredLints;
diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs
index 0f807cd497e..d4aa4968f25 100644
--- a/src/librustc_lint/redundant_semicolon.rs
+++ b/src/librustc_lint/redundant_semicolon.rs
@@ -1,5 +1,5 @@
 use crate::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_ast::ast::{Block, StmtKind};
+use rustc_ast::{Block, StmtKind};
 use rustc_errors::Applicability;
 use rustc_span::Span;
 
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 5891abcfd9c..4ca5f23ebfe 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1,7 +1,7 @@
 #![allow(non_snake_case)]
 
 use crate::{LateContext, LateLintPass, LintContext};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -195,8 +195,8 @@ fn report_bin_hex_error(
 //
 // No suggestion for: `isize`, `usize`.
 fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static str> {
-    use rustc_ast::ast::IntTy::*;
-    use rustc_ast::ast::UintTy::*;
+    use rustc_ast::IntTy::*;
+    use rustc_ast::UintTy::*;
     macro_rules! find_fit {
         ($ty:expr, $val:expr, $negative:expr,
          $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
@@ -258,7 +258,7 @@ fn lint_int_literal<'tcx>(
         let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
         if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
             if let hir::ExprKind::Struct(..) = par_e.kind {
-                if is_range_literal(cx.sess().source_map(), par_e)
+                if is_range_literal(par_e)
                     && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
                 {
                     // The overflowing literal lint was overridden.
@@ -317,7 +317,7 @@ fn lint_uint_literal<'tcx>(
                         return;
                     }
                 }
-                hir::ExprKind::Struct(..) if is_range_literal(cx.sess().source_map(), par_e) => {
+                hir::ExprKind::Struct(..) if is_range_literal(par_e) => {
                     let t = t.name_str();
                     if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
                         // The overflowing literal lint was overridden.
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 95e51b47be3..c793e81ebe3 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -1,8 +1,8 @@
 use crate::Lint;
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_ast::ast;
-use rustc_ast::ast::{ExprKind, StmtKind};
+use rustc_ast as ast;
 use rustc_ast::util::parser;
+use rustc_ast::{ExprKind, StmtKind};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, Applicability};
@@ -526,7 +526,7 @@ trait UnusedDelimLint {
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
-        use rustc_ast::ast::ExprKind::*;
+        use rustc_ast::ExprKind::*;
         let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
             // Do not lint `unused_braces` in `if let` expressions.
             If(ref cond, ref block, ..)
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 9827b222331..f8446d83d2b 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -5,7 +5,7 @@ use crate::locator::{CrateError, CrateLocator, CratePaths};
 use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
 
 use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_ast::{ast, visit};
+use rustc_ast::{self as ast, *};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index bdd20a4bf6f..8fa14a44f52 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -685,13 +685,19 @@ impl<'a> CrateLocator<'a> {
                     && file.ends_with(&self.target.options.dll_suffix)
             {
                 // Make sure there's at most one rlib and at most one dylib.
-                let loc = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
+                // Note to take care and match against the non-canonicalized name:
+                // some systems save build artifacts into content-addressed stores
+                // that do not preserve extensions, and then link to them using
+                // e.g. symbolic links. If we canonicalize too early, we resolve
+                // the symlink, the file type is lost and we might treat rlibs and
+                // rmetas as dylibs.
+                let loc_canon = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
-                    rlibs.insert(loc, PathKind::ExternFlag);
+                    rlibs.insert(loc_canon, PathKind::ExternFlag);
                 } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
-                    rmetas.insert(loc, PathKind::ExternFlag);
+                    rmetas.insert(loc_canon, PathKind::ExternFlag);
                 } else {
-                    dylibs.insert(loc, PathKind::ExternFlag);
+                    dylibs.insert(loc_canon, PathKind::ExternFlag);
                 }
             } else {
                 self.rejected_via_filename
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 1e4556f5fc8..10f5b671748 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -4,7 +4,7 @@ use crate::creader::CrateMetadataRef;
 use crate::rmeta::table::{FixedSizeEncoding, Table};
 use crate::rmeta::*;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index 10b89cdd15a..74d29b3df01 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -4,7 +4,7 @@ use crate::link_args;
 use crate::native_libs;
 use crate::rmeta::{self, encoder};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 0343fbeb0fa..cb3bf10926b 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -1,7 +1,7 @@
 use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
 use crate::rmeta::*;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::stable_hasher::StableHasher;
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index b15c20e515f..ac1ac360701 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -1,7 +1,7 @@
 use decoder::Metadata;
 use table::{Table, TableBuilder};
 
-use rustc_ast::ast::{self, MacroDef};
+use rustc_ast::{self as ast, MacroDef};
 use rustc_attr as attr;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs
index 99889c74da0..f6570cc95d2 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -81,7 +81,7 @@ macro_rules! arena_types {
             [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
             [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
             [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
-            [] attribute: rustc_ast::ast::Attribute,
+            [] attribute: rustc_ast::Attribute,
             [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
             [] hir_id_set: rustc_hir::HirIdSet,
 
@@ -98,7 +98,7 @@ macro_rules! arena_types {
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
             // (during lowering) and the `librustc_middle` arena (for decoding MIR)
-            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+            [decode] asm_template: rustc_ast::InlineAsmTemplatePiece,
 
             // This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
             [decode] span: rustc_span::Span,
diff --git a/src/librustc_middle/hir/map/blocks.rs b/src/librustc_middle/hir/map/blocks.rs
index a2e4372f017..6f572a4875f 100644
--- a/src/librustc_middle/hir/map/blocks.rs
+++ b/src/librustc_middle/hir/map/blocks.rs
@@ -12,7 +12,7 @@
 //! for the `Code` associated with a particular NodeId.
 
 use crate::hir::map::Map;
-use rustc_ast::ast::Attribute;
+use rustc_ast::Attribute;
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Expr, FnDecl, Node};
diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs
index 0794caca1ba..a6cc7cbc920 100644
--- a/src/librustc_middle/hir/map/mod.rs
+++ b/src/librustc_middle/hir/map/mod.rs
@@ -3,7 +3,7 @@ use self::collector::NodeCollector;
 use crate::hir::{Owner, OwnerNodes};
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
-use rustc_ast::ast::{self};
+use rustc_ast as ast;
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
diff --git a/src/librustc_middle/ich/hcx.rs b/src/librustc_middle/ich/hcx.rs
index 19a7d2ec221..084fe4cfa16 100644
--- a/src/librustc_middle/ich/hcx.rs
+++ b/src/librustc_middle/ich/hcx.rs
@@ -2,7 +2,7 @@ use crate::ich;
 use crate::middle::cstore::CrateStore;
 use crate::ty::{fast_reject, TyCtxt};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_middle/ich/impls_syntax.rs b/src/librustc_middle/ich/impls_syntax.rs
index 300aac19e51..e3d4655831b 100644
--- a/src/librustc_middle/ich/impls_syntax.rs
+++ b/src/librustc_middle/ich/impls_syntax.rs
@@ -3,7 +3,7 @@
 
 use crate::ich::StableHashingContext;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_span::SourceFile;
 
diff --git a/src/librustc_middle/middle/cstore.rs b/src/librustc_middle/middle/cstore.rs
index 6a8f6c3e202..6759ad61d3a 100644
--- a/src/librustc_middle/middle/cstore.rs
+++ b/src/librustc_middle/middle/cstore.rs
@@ -4,7 +4,7 @@
 
 use crate::ty::TyCtxt;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, MetadataRef};
diff --git a/src/librustc_middle/middle/limits.rs b/src/librustc_middle/middle/limits.rs
index e9820539484..def9e5ebb52 100644
--- a/src/librustc_middle/middle/limits.rs
+++ b/src/librustc_middle/middle/limits.rs
@@ -6,7 +6,7 @@
 //! just peeks and looks for that attribute.
 
 use crate::bug;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::sync::OnceCell;
 use rustc_session::{Limit, Session};
 use rustc_span::symbol::{sym, Symbol};
diff --git a/src/librustc_middle/middle/stability.rs b/src/librustc_middle/middle/stability.rs
index b913d7dd4ad..b32eebbb11e 100644
--- a/src/librustc_middle/middle/stability.rs
+++ b/src/librustc_middle/middle/stability.rs
@@ -4,7 +4,7 @@
 pub use self::StabilityLevel::*;
 
 use crate::ty::{self, TyCtxt};
-use rustc_ast::ast::CRATE_NODE_ID;
+use rustc_ast::CRATE_NODE_ID;
 use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{Applicability, DiagnosticBuilder};
diff --git a/src/librustc_middle/mir/interpret/allocation.rs b/src/librustc_middle/mir/interpret/allocation.rs
index bee8d13c762..505939d56ed 100644
--- a/src/librustc_middle/mir/interpret/allocation.rs
+++ b/src/librustc_middle/mir/interpret/allocation.rs
@@ -5,7 +5,7 @@ use std::convert::TryFrom;
 use std::iter;
 use std::ops::{Deref, DerefMut, Range};
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
diff --git a/src/librustc_middle/mir/interpret/mod.rs b/src/librustc_middle/mir/interpret/mod.rs
index e607da29ce4..fb7269f648f 100644
--- a/src/librustc_middle/mir/interpret/mod.rs
+++ b/src/librustc_middle/mir/interpret/mod.rs
@@ -102,7 +102,7 @@ use std::num::NonZeroU32;
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
-use rustc_ast::ast::LitKind;
+use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock};
 use rustc_data_structures::tiny_list::TinyList;
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 6a2b1d11584..1faed87f8ff 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -19,7 +19,7 @@ use rustc_hir::{self, GeneratorKind};
 use rustc_target::abi::VariantIdx;
 
 use polonius_engine::Atom;
-pub use rustc_ast::ast::Mutability;
+pub use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::{dominators, Dominators};
 use rustc_data_structures::graph::{self, GraphSuccessors};
diff --git a/src/librustc_middle/mir/terminator/mod.rs b/src/librustc_middle/mir/terminator/mod.rs
index 0ab78381224..e8fe3a97a10 100644
--- a/src/librustc_middle/mir/terminator/mod.rs
+++ b/src/librustc_middle/mir/terminator/mod.rs
@@ -1,12 +1,12 @@
 use crate::mir::interpret::Scalar;
 use crate::ty::{self, Ty, TyCtxt};
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 
 use super::{
     AssertMessage, BasicBlock, InlineAsmOperand, Operand, Place, SourceInfo, Successors,
     SuccessorsMut,
 };
-pub use rustc_ast::ast::Mutability;
+pub use rustc_ast::Mutability;
 use rustc_macros::HashStable;
 use rustc_span::Span;
 use std::borrow::Cow;
diff --git a/src/librustc_middle/ty/cast.rs b/src/librustc_middle/ty/cast.rs
index 3a3caa55f60..79a3008c364 100644
--- a/src/librustc_middle/ty/cast.rs
+++ b/src/librustc_middle/ty/cast.rs
@@ -3,7 +3,7 @@
 
 use crate::ty::{self, Ty};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_macros::HashStable;
 
 /// Types that are represented as ints.
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index d7eeaafbf46..e6b05fe4094 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -24,7 +24,7 @@ use crate::ty::{
     ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
     TyVid, TypeAndMut,
 };
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -452,7 +452,7 @@ impl<'tcx> TypeckResults<'tcx> {
     pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
         match *qpath {
             hir::QPath::Resolved(_, ref path) => path.res,
-            hir::QPath::TypeRelative(..) => self
+            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
                 .type_dependent_def(id)
                 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
         }
diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs
index 438da832226..1963881626e 100644
--- a/src/librustc_middle/ty/error.rs
+++ b/src/librustc_middle/ty/error.rs
@@ -1,7 +1,7 @@
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::diagnostics::suggest_constraining_type_param;
 use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, DiagnosticBuilder};
 use rustc_hir as hir;
diff --git a/src/librustc_middle/ty/fast_reject.rs b/src/librustc_middle/ty/fast_reject.rs
index 7456020ee9b..1bee2d60f75 100644
--- a/src/librustc_middle/ty/fast_reject.rs
+++ b/src/librustc_middle/ty/fast_reject.rs
@@ -1,6 +1,6 @@
 use crate::ich::StableHashingContext;
 use crate::ty::{self, Ty, TyCtxt};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use std::fmt::Debug;
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 16e65d2cca4..928cba324d5 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -4,7 +4,7 @@ use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
 use crate::ty::subst::Subst;
 use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
 
-use rustc_ast::ast::{self, IntTy, UintTy};
+use rustc_ast::{self as ast, IntTy, UintTy};
 use rustc_attr as attr;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 3c79fe12255..02fd18ef968 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -17,7 +17,7 @@ use crate::traits::{self, Reveal};
 use crate::ty;
 use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
 use crate::ty::util::{Discr, IntTypeExt};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index fc444d4cc5b..999a1d52a26 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -5,7 +5,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{self, ConstInt, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr::{SignedInt, UnsignedInt};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Namespace};
diff --git a/src/librustc_middle/ty/query/mod.rs b/src/librustc_middle/ty/query/mod.rs
index 4d820f75c56..f220c4fb072 100644
--- a/src/librustc_middle/ty/query/mod.rs
+++ b/src/librustc_middle/ty/query/mod.rs
@@ -50,7 +50,7 @@ use rustc_session::utils::NativeLibKind;
 use rustc_session::CrateDisambiguator;
 use rustc_target::spec::PanicStrategy;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs
index 007b46b1176..dcfb8d31430 100644
--- a/src/librustc_middle/ty/query/on_disk_cache.rs
+++ b/src/librustc_middle/ty/query/on_disk_cache.rs
@@ -766,9 +766,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>
     }
 }
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
-    for &'tcx [rustc_ast::ast::InlineAsmTemplatePiece]
-{
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsmTemplatePiece] {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         RefDecodable::decode(d)
     }
diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs
index dfa9e38a466..ffa5df6ef2d 100644
--- a/src/librustc_middle/ty/structural_impls.rs
+++ b/src/librustc_middle/ty/structural_impls.rs
@@ -274,10 +274,10 @@ CloneTypeFoldableAndLiftImpls! {
     u64,
     String,
     crate::middle::region::Scope,
-    ::rustc_ast::ast::FloatTy,
-    ::rustc_ast::ast::InlineAsmOptions,
-    ::rustc_ast::ast::InlineAsmTemplatePiece,
-    ::rustc_ast::ast::NodeId,
+    ::rustc_ast::FloatTy,
+    ::rustc_ast::InlineAsmOptions,
+    ::rustc_ast::InlineAsmTemplatePiece,
+    ::rustc_ast::NodeId,
     ::rustc_span::symbol::Symbol,
     ::rustc_hir::def::Res,
     ::rustc_hir::def_id::DefId,
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 82160681ee8..176bad6277f 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -12,7 +12,7 @@ use crate::ty::{
 };
 use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
 use polonius_engine::Atom;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::captures::Captures;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs
index 5c5fe9dbd7a..63d4dcca080 100644
--- a/src/librustc_middle/ty/util.rs
+++ b/src/librustc_middle/ty/util.rs
@@ -10,7 +10,7 @@ use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use crate::ty::TyKind::*;
 use crate::ty::{self, DefIdTree, GenericParamDefKind, List, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::Float as _;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr::{self as attr, SignedInt, UnsignedInt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index 2d0e68d5894..b0357c508a3 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -7,7 +7,7 @@ use std::hash::Hash;
 
 use rustc_data_structures::fx::FxHashMap;
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::AssertMessage;
 use rustc_session::Limit;
diff --git a/src/librustc_mir/dataflow/framework/engine.rs b/src/librustc_mir/dataflow/framework/engine.rs
index 89e2d7088f7..b703852b1de 100644
--- a/src/librustc_mir/dataflow/framework/engine.rs
+++ b/src/librustc_mir/dataflow/framework/engine.rs
@@ -4,7 +4,7 @@ use std::ffi::OsString;
 use std::fs;
 use std::path::PathBuf;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::work_queue::WorkQueue;
 use rustc_graphviz as dot;
 use rustc_hir::def_id::DefId;
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index fdec5729a54..a0c24636059 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast::{self, MetaItem};
+use rustc_ast::{self as ast, MetaItem};
 use rustc_middle::ty;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 78f149f6451..501a5bcddb3 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -2,7 +2,7 @@ use std::convert::TryFrom;
 
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::{Float, FloatConvert};
-use rustc_ast::ast::FloatTy;
+use rustc_ast::FloatTy;
 use rustc_attr as attr;
 use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
 use rustc_middle::mir::CastKind;
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 6c8ee72bc66..9959c38e5c7 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -9,7 +9,7 @@ use rustc_hir as hir;
 use rustc_middle::mir::interpret::InterpResult;
 use rustc_middle::ty::{self, query::TyCtxtAt, Ty};
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 
 use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
 
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index b45045716d1..2c0a42a9bf3 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -329,9 +329,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(offset_ptr, dest)?;
             }
             sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
-                // FIXME: return `true` for at least some comparisons where we can reliably
-                // determine the result of runtime (in)equality tests at compile-time.
-                self.write_scalar(Scalar::from_bool(false), dest)?;
+                let a = self.read_immediate(args[0])?.to_scalar()?;
+                let b = self.read_immediate(args[1])?.to_scalar()?;
+                let cmp = if intrinsic_name == sym::ptr_guaranteed_eq {
+                    self.guaranteed_eq(a, b)
+                } else {
+                    self.guaranteed_ne(a, b)
+                };
+                self.write_scalar(Scalar::from_bool(cmp), dest)?;
             }
             sym::ptr_offset_from => {
                 let a = self.read_immediate(args[0])?.to_scalar()?;
@@ -448,6 +453,37 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(true)
     }
 
+    fn guaranteed_eq(&mut self, a: Scalar<M::PointerTag>, b: Scalar<M::PointerTag>) -> bool {
+        match (a, b) {
+            // Comparisons between integers are always known.
+            (Scalar::Raw { .. }, Scalar::Raw { .. }) => a == b,
+            // Equality with integers can never be known for sure.
+            (Scalar::Raw { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Raw { .. }) => false,
+            // FIXME: return `true` for when both sides are the same pointer, *except* that
+            // some things (like functions and vtables) do not have stable addresses
+            // so we need to be careful around them.
+            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
+        }
+    }
+
+    fn guaranteed_ne(&mut self, a: Scalar<M::PointerTag>, b: Scalar<M::PointerTag>) -> bool {
+        match (a, b) {
+            // Comparisons between integers are always known.
+            (Scalar::Raw { .. }, Scalar::Raw { .. }) => a != b,
+            // Comparisons of abstract pointers with null pointers are known if the pointer
+            // is in bounds, because if they are in bounds, the pointer can't be null.
+            (Scalar::Raw { data: 0, .. }, Scalar::Ptr(ptr))
+            | (Scalar::Ptr(ptr), Scalar::Raw { data: 0, .. }) => !self.memory.ptr_may_be_null(ptr),
+            // Inequality with integers other than null can never be known for sure.
+            (Scalar::Raw { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Raw { .. }) => false,
+            // FIXME: return `true` for at least some comparisons where we can reliably
+            // determine the result of runtime inequality tests at compile-time.
+            // Examples include comparison of addresses in static items, for these we can
+            // give reliable results.
+            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
+        }
+    }
+
     pub fn exact_div(
         &mut self,
         a: ImmTy<'tcx, M::PointerTag>,
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 5cab4ba37e3..3718da1723b 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -122,6 +122,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Whether memory accesses should be alignment-checked.
     fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool;
 
+    /// Whether, when checking alignment, we should `force_int` and thus support
+    /// custom alignment logic based on whatever the integer address happens to be.
+    fn force_int_for_alignment_check(memory_extra: &Self::MemoryExtra) -> bool;
+
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
@@ -376,6 +380,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     }
 
     #[inline(always)]
+    fn force_int_for_alignment_check(_memory_extra: &Self::MemoryExtra) -> bool {
+        // We do not support `force_int`.
+        false
+    }
+
+    #[inline(always)]
     fn enforce_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
         false // for now, we don't enforce validity
     }
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 49d97ff7cec..d4be2ce0568 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -8,11 +8,11 @@
 
 use std::borrow::Cow;
 use std::collections::VecDeque;
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
 use std::fmt;
 use std::ptr;
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_middle::ty::{Instance, ParamEnv, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
@@ -380,7 +380,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             // if this is already a `Pointer` we want to do the bounds checks!
             sptr
         } else {
-            // A "real" access, we must get a pointer.
+            // A "real" access, we must get a pointer to be able to check the bounds.
             Scalar::from(self.force_ptr(sptr)?)
         };
         Ok(match normalized.to_bits_or_ptr(self.pointer_size(), self) {
@@ -411,15 +411,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
-                    if alloc_align.bytes() < align.bytes() {
-                        // The allocation itself is not aligned enough.
-                        // FIXME: Alignment check is too strict, depending on the base address that
-                        // got picked we might be aligned even if this check fails.
-                        // We instead have to fall back to converting to an integer and checking
-                        // the "real" alignment.
-                        throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
+                    if M::force_int_for_alignment_check(&self.extra) {
+                        let bits = self
+                            .force_bits(ptr.into(), self.pointer_size())
+                            .expect("ptr-to-int cast for align check should never fail");
+                        check_offset_align(bits.try_into().unwrap(), align)?;
+                    } else {
+                        // Check allocation alignment and offset alignment.
+                        if alloc_align.bytes() < align.bytes() {
+                            throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
+                        }
+                        check_offset_align(ptr.offset.bytes(), align)?;
                     }
-                    check_offset_align(ptr.offset.bytes(), align)?;
                 }
 
                 // We can still be zero-sized in this branch, in which case we have to
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index 60712293534..30c40b8fde9 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -1,7 +1,7 @@
 use std::convert::TryFrom;
 
 use rustc_apfloat::Float;
-use rustc_ast::ast::FloatTy;
+use rustc_ast::FloatTy;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::{self, layout::TyAndLayout, Ty};
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index d2a5616b8ed..6aabc1941a6 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -228,7 +228,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
             let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
             match base_ty.kind {
                 ty::RawPtr(..) => self.require_unsafe(
-                    UnsafetyViolationKind::General,
+                    UnsafetyViolationKind::GeneralAndConstFn,
                     UnsafetyViolationDetails::DerefOfRawPointer,
                 ),
                 ty::Adt(adt, _) => {
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 7e8a94f181f..be23fe7247e 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -3,7 +3,7 @@
 
 use std::cell::Cell;
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::HirId;
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 94637bae44a..b2dda1caa54 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -12,7 +12,7 @@
 //! initialization and can otherwise silence errors, if
 //! move analysis runs after promotion on broken MIR.
 
-use rustc_ast::ast::LitKind;
+use rustc_ast::LitKind;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::traversal::ReversePostorder;
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 729e22a94dc..00d269a4af8 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index 84082edd193..06829cc2f14 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -14,7 +14,7 @@ use itertools::Itertools as _;
 use rustc_index::{bit_set::BitSet, vec::IndexVec};
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::{List, Ty, TyCtxt};
+use rustc_middle::ty::{self, List, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 use std::iter::{Enumerate, Peekable};
 use std::slice::Iter;
@@ -527,21 +527,76 @@ fn match_variant_field_place<'tcx>(place: Place<'tcx>) -> Option<(Local, VarFiel
 pub struct SimplifyBranchSame;
 
 impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
-    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
-        let mut did_remove_blocks = false;
-        let bbs = body.basic_blocks_mut();
-        for bb_idx in bbs.indices() {
-            let targets = match &bbs[bb_idx].terminator().kind {
-                TerminatorKind::SwitchInt { targets, .. } => targets,
-                _ => continue,
-            };
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        trace!("Running SimplifyBranchSame on {:?}", source);
+        let finder = SimplifyBranchSameOptimizationFinder { body, tcx };
+        let opts = finder.find();
+
+        let did_remove_blocks = opts.len() > 0;
+        for opt in opts.iter() {
+            trace!("SUCCESS: Applying optimization {:?}", opt);
+            // Replace `SwitchInt(..) -> [bb_first, ..];` with a `goto -> bb_first;`.
+            body.basic_blocks_mut()[opt.bb_to_opt_terminator].terminator_mut().kind =
+                TerminatorKind::Goto { target: opt.bb_to_goto };
+        }
+
+        if did_remove_blocks {
+            // We have dead blocks now, so remove those.
+            simplify::remove_dead_blocks(body);
+        }
+    }
+}
+
+#[derive(Debug)]
+struct SimplifyBranchSameOptimization {
+    /// All basic blocks are equal so go to this one
+    bb_to_goto: BasicBlock,
+    /// Basic block where the terminator can be simplified to a goto
+    bb_to_opt_terminator: BasicBlock,
+}
+
+struct SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
+    body: &'a Body<'tcx>,
+    tcx: TyCtxt<'tcx>,
+}
 
-            let mut iter_bbs_reachable = targets
-                .iter()
-                .map(|idx| (*idx, &bbs[*idx]))
-                .filter(|(_, bb)| {
-                    // Reaching `unreachable` is UB so assume it doesn't happen.
-                    bb.terminator().kind != TerminatorKind::Unreachable
+impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
+    fn find(&self) -> Vec<SimplifyBranchSameOptimization> {
+        self.body
+            .basic_blocks()
+            .iter_enumerated()
+            .filter_map(|(bb_idx, bb)| {
+                let (discr_switched_on, targets) = match &bb.terminator().kind {
+                    TerminatorKind::SwitchInt { targets, discr, .. } => (discr, targets),
+                    _ => return None,
+                };
+
+                // find the adt that has its discriminant read
+                // assuming this must be the last statement of the block
+                let adt_matched_on = match &bb.statements.last()?.kind {
+                    StatementKind::Assign(box (place, rhs))
+                        if Some(*place) == discr_switched_on.place() =>
+                    {
+                        match rhs {
+                            Rvalue::Discriminant(adt_place) if adt_place.ty(self.body, self.tcx).ty.is_enum() => adt_place,
+                            _ => {
+                                trace!("NO: expected a discriminant read of an enum instead of: {:?}", rhs);
+                                return None;
+                            }
+                        }
+                    }
+                    other => {
+                        trace!("NO: expected an assignment of a discriminant read to a place. Found: {:?}", other);
+                        return None
+                    },
+                };
+
+                let mut iter_bbs_reachable = targets
+                    .iter()
+                    .map(|idx| (*idx, &self.body.basic_blocks()[*idx]))
+                    .filter(|(_, bb)| {
+                        // Reaching `unreachable` is UB so assume it doesn't happen.
+                        bb.terminator().kind != TerminatorKind::Unreachable
                     // But `asm!(...)` could abort the program,
                     // so we cannot assume that the `unreachable` terminator itself is reachable.
                     // FIXME(Centril): use a normalization pass instead of a check.
@@ -549,30 +604,162 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
                         StatementKind::LlvmInlineAsm(..) => true,
                         _ => false,
                     })
-                })
-                .peekable();
-
-            // We want to `goto -> bb_first`.
-            let bb_first = iter_bbs_reachable.peek().map(|(idx, _)| *idx).unwrap_or(targets[0]);
-
-            // All successor basic blocks should have the exact same form.
-            let all_successors_equivalent =
-                iter_bbs_reachable.map(|(_, bb)| bb).tuple_windows().all(|(bb_l, bb_r)| {
-                    bb_l.is_cleanup == bb_r.is_cleanup
-                        && bb_l.terminator().kind == bb_r.terminator().kind
-                        && bb_l.statements.iter().eq_by(&bb_r.statements, |x, y| x.kind == y.kind)
-                });
-
-            if all_successors_equivalent {
-                // Replace `SwitchInt(..) -> [bb_first, ..];` with a `goto -> bb_first;`.
-                bbs[bb_idx].terminator_mut().kind = TerminatorKind::Goto { target: bb_first };
-                did_remove_blocks = true;
+                    })
+                    .peekable();
+
+                let bb_first = iter_bbs_reachable.peek().map(|(idx, _)| *idx).unwrap_or(targets[0]);
+                let mut all_successors_equivalent = StatementEquality::TrivialEqual;
+
+                // All successor basic blocks must be equal or contain statements that are pairwise considered equal.
+                for ((bb_l_idx,bb_l), (bb_r_idx,bb_r)) in iter_bbs_reachable.tuple_windows() {
+                    let trivial_checks = bb_l.is_cleanup == bb_r.is_cleanup
+                    && bb_l.terminator().kind == bb_r.terminator().kind;
+                    let statement_check = || {
+                        bb_l.statements.iter().zip(&bb_r.statements).try_fold(StatementEquality::TrivialEqual, |acc,(l,r)| {
+                            let stmt_equality = self.statement_equality(*adt_matched_on, &l, bb_l_idx, &r, bb_r_idx);
+                            if matches!(stmt_equality, StatementEquality::NotEqual) {
+                                // short circuit
+                                None
+                            } else {
+                                Some(acc.combine(&stmt_equality))
+                            }
+                        })
+                        .unwrap_or(StatementEquality::NotEqual)
+                    };
+                    if !trivial_checks {
+                        all_successors_equivalent = StatementEquality::NotEqual;
+                        break;
+                    }
+                    all_successors_equivalent = all_successors_equivalent.combine(&statement_check());
+                };
+
+                match all_successors_equivalent{
+                    StatementEquality::TrivialEqual => {
+                        // statements are trivially equal, so just take first
+                        trace!("Statements are trivially equal");
+                        Some(SimplifyBranchSameOptimization {
+                            bb_to_goto: bb_first,
+                            bb_to_opt_terminator: bb_idx,
+                        })
+                    }
+                    StatementEquality::ConsideredEqual(bb_to_choose) => {
+                        trace!("Statements are considered equal");
+                        Some(SimplifyBranchSameOptimization {
+                            bb_to_goto: bb_to_choose,
+                            bb_to_opt_terminator: bb_idx,
+                        })
+                    }
+                    StatementEquality::NotEqual => {
+                        trace!("NO: not all successors of basic block {:?} were equivalent", bb_idx);
+                        None
+                    }
+                }
+            })
+            .collect()
+    }
+
+    /// Tests if two statements can be considered equal
+    ///
+    /// Statements can be trivially equal if the kinds match.
+    /// But they can also be considered equal in the following case A:
+    /// ```
+    /// discriminant(_0) = 0;   // bb1
+    /// _0 = move _1;           // bb2
+    /// ```
+    /// In this case the two statements are equal iff
+    /// 1: _0 is an enum where the variant index 0 is fieldless, and
+    /// 2:  bb1 was targeted by a switch where the discriminant of _1 was switched on
+    fn statement_equality(
+        &self,
+        adt_matched_on: Place<'tcx>,
+        x: &Statement<'tcx>,
+        x_bb_idx: BasicBlock,
+        y: &Statement<'tcx>,
+        y_bb_idx: BasicBlock,
+    ) -> StatementEquality {
+        let helper = |rhs: &Rvalue<'tcx>,
+                      place: &Box<Place<'tcx>>,
+                      variant_index: &VariantIdx,
+                      side_to_choose| {
+            let place_type = place.ty(self.body, self.tcx).ty;
+            let adt = match place_type.kind {
+                ty::Adt(adt, _) if adt.is_enum() => adt,
+                _ => return StatementEquality::NotEqual,
+            };
+            let variant_is_fieldless = adt.variants[*variant_index].fields.is_empty();
+            if !variant_is_fieldless {
+                trace!("NO: variant {:?} was not fieldless", variant_index);
+                return StatementEquality::NotEqual;
+            }
+
+            match rhs {
+                Rvalue::Use(operand) if operand.place() == Some(adt_matched_on) => {
+                    StatementEquality::ConsideredEqual(side_to_choose)
+                }
+                _ => {
+                    trace!(
+                        "NO: RHS of assignment was {:?}, but expected it to match the adt being matched on in the switch, which is {:?}",
+                        rhs,
+                        adt_matched_on
+                    );
+                    StatementEquality::NotEqual
+                }
+            }
+        };
+        match (&x.kind, &y.kind) {
+            // trivial case
+            (x, y) if x == y => StatementEquality::TrivialEqual,
+
+            // check for case A
+            (
+                StatementKind::Assign(box (_, rhs)),
+                StatementKind::SetDiscriminant { place, variant_index },
+            ) => {
+                // choose basic block of x, as that has the assign
+                helper(rhs, place, variant_index, x_bb_idx)
+            }
+            (
+                StatementKind::SetDiscriminant { place, variant_index },
+                StatementKind::Assign(box (_, rhs)),
+            ) => {
+                // choose basic block of y, as that has the assign
+                helper(rhs, place, variant_index, y_bb_idx)
+            }
+            _ => {
+                trace!("NO: statements `{:?}` and `{:?}` not considered equal", x, y);
+                StatementEquality::NotEqual
             }
         }
+    }
+}
 
-        if did_remove_blocks {
-            // We have dead blocks now, so remove those.
-            simplify::remove_dead_blocks(body);
+#[derive(Copy, Clone, Eq, PartialEq)]
+enum StatementEquality {
+    /// The two statements are trivially equal; same kind
+    TrivialEqual,
+    /// The two statements are considered equal, but may be of different kinds. The BasicBlock field is the basic block to jump to when performing the branch-same optimization.
+    /// For example, `_0 = _1` and `discriminant(_0) = discriminant(0)` are considered equal if 0 is a fieldless variant of an enum. But we don't want to jump to the basic block with the SetDiscriminant, as that is not legal if _1 is not the 0 variant index
+    ConsideredEqual(BasicBlock),
+    /// The two statements are not equal
+    NotEqual,
+}
+
+impl StatementEquality {
+    fn combine(&self, other: &StatementEquality) -> StatementEquality {
+        use StatementEquality::*;
+        match (self, other) {
+            (TrivialEqual, TrivialEqual) => TrivialEqual,
+            (TrivialEqual, ConsideredEqual(b)) | (ConsideredEqual(b), TrivialEqual) => {
+                ConsideredEqual(*b)
+            }
+            (ConsideredEqual(b1), ConsideredEqual(b2)) => {
+                if b1 == b2 {
+                    ConsideredEqual(*b1)
+                } else {
+                    NotEqual
+                }
+            }
+            (_, NotEqual) | (NotEqual, _) => NotEqual,
         }
     }
 }
diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index c3f54b39a3f..3d623abfa6e 100644
--- a/src/librustc_mir_build/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -3,7 +3,7 @@
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::thir::*;
-use rustc_ast::ast::InlineAsmOptions;
+use rustc_ast::InlineAsmOptions;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
diff --git a/src/librustc_mir_build/thir/constant.rs b/src/librustc_mir_build/thir/constant.rs
index e5af0b5bd6b..dd5515d39b0 100644
--- a/src/librustc_mir_build/thir/constant.rs
+++ b/src/librustc_mir_build/thir/constant.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_middle::mir::interpret::{
     truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
 };
diff --git a/src/librustc_mir_build/thir/cx/mod.rs b/src/librustc_mir_build/thir/cx/mod.rs
index bb814ab8248..cf42fee873e 100644
--- a/src/librustc_mir_build/thir/cx/mod.rs
+++ b/src/librustc_mir_build/thir/cx/mod.rs
@@ -5,7 +5,7 @@
 use crate::thir::util::UserAnnotatedTyHelpers;
 use crate::thir::*;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Node;
diff --git a/src/librustc_mir_build/thir/mod.rs b/src/librustc_mir_build/thir/mod.rs
index b6ce7e0b41e..2837bfa040f 100644
--- a/src/librustc_mir_build/thir/mod.rs
+++ b/src/librustc_mir_build/thir/mod.rs
@@ -5,7 +5,7 @@
 //! structures.
 
 use self::cx::Cx;
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::infer::canonical::Canonical;
diff --git a/src/librustc_mir_build/thir/pattern/check_match.rs b/src/librustc_mir_build/thir/pattern/check_match.rs
index 1687286093d..4e7108667e1 100644
--- a/src/librustc_mir_build/thir/pattern/check_match.rs
+++ b/src/librustc_mir_build/thir/pattern/check_match.rs
@@ -4,7 +4,7 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}
 use super::{PatCtxt, PatKind, PatternError};
 
 use rustc_arena::TypedArena;
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::*;
diff --git a/src/librustc_mir_build/thir/pattern/mod.rs b/src/librustc_mir_build/thir/pattern/mod.rs
index daff10eb194..c163cb0e60c 100644
--- a/src/librustc_mir_build/thir/pattern/mod.rs
+++ b/src/librustc_mir_build/thir/pattern/mod.rs
@@ -8,7 +8,7 @@ pub(crate) use self::check_match::check_match;
 
 use crate::thir::util::UserAnnotatedTyHelpers;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 829e1a97b10..49deb3474d9 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -6,7 +6,7 @@
 #![feature(try_blocks)]
 #![feature(or_patterns)]
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
 use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index c942394fa7c..4e4429e461f 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -1,5 +1,5 @@
 use super::{Parser, PathStyle};
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast_pretty::pprust;
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 27e1bb01d52..be01c7f8498 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1,13 +1,13 @@
 use super::ty::AllowPlus;
 use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
 
-use rustc_ast::ast::{
-    self, AngleBracketedArgs, AttrVec, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind,
-    Item, ItemKind, Mutability, Param, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
-};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Lit, LitKind, TokenKind};
 use rustc_ast::util::parser::AssocOp;
+use rustc_ast::{
+    self as ast, AngleBracketedArgs, AttrVec, BinOpKind, BindingMode, BlockCheckMode, Expr,
+    ExprKind, Item, ItemKind, Mutability, Param, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
+};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err};
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 0ceb588b3af..e5c28f225c6 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -4,14 +4,14 @@ use super::{BlockMode, Parser, PathStyle, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
-use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Lit, UnOp, DUMMY_NODE_ID};
-use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
-use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::util::classify;
 use rustc_ast::util::literal::LitError;
 use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
+use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, Field, Lit, UnOp, DUMMY_NODE_ID};
+use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
+use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{self, Span, Spanned};
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index be72ed6dffb..dd99a7587dd 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -1,7 +1,9 @@
 use super::Parser;
 
-use rustc_ast::ast::{self, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause};
 use rustc_ast::token;
+use rustc_ast::{
+    self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
+};
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, sym};
 
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index ce2dd15ab26..64479bc36e0 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -4,16 +4,16 @@ use super::{FollowedByType, Parser, PathStyle};
 
 use crate::maybe_whole;
 
-use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID};
-use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod};
-use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
-use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
-use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
-use rustc_ast::ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
-use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
+use rustc_ast::{self as ast, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID};
+use rustc_ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod};
+use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
+use rustc_ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
+use rustc_ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
+use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
+use rustc_ast::{MacArgs, MacCall, MacDelimiter};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
 use rustc_span::edition::Edition;
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index a30131e4f7a..d67ed74bc99 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -13,14 +13,12 @@ use crate::lexer::UnmatchedBrace;
 use diagnostics::Error;
 pub use path::PathStyle;
 
-use rustc_ast::ast::DUMMY_NODE_ID;
-use rustc_ast::ast::{self, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
-use rustc_ast::ast::{
-    Async, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind,
-};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, DelimToken, Token, TokenKind};
 use rustc_ast::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndJoint};
+use rustc_ast::DUMMY_NODE_ID;
+use rustc_ast::{self as ast, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
+use rustc_ast::{Async, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_session::parse::ParseSess;
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index 6603d0afc02..1d8e6cc9bac 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,10 +1,10 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_ast::ast::{self, AttrVec, Attribute, FieldPat, MacCall, Pat, PatKind, RangeEnd};
-use rustc_ast::ast::{BindingMode, Expr, ExprKind, Mutability, Path, QSelf, RangeSyntax};
 use rustc_ast::mut_visit::{noop_visit_mac, noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
+use rustc_ast::{self as ast, AttrVec, Attribute, FieldPat, MacCall, Pat, PatKind, RangeEnd};
+use rustc_ast::{BindingMode, Expr, ExprKind, Mutability, Path, QSelf, RangeSyntax};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{respan, Span, Spanned};
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 0f2b46f7e16..54b4df8613f 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -1,11 +1,13 @@
 use super::ty::{AllowPlus, RecoverQPath};
 use super::{Parser, TokenType};
 use crate::maybe_whole;
-use rustc_ast::ast::{self, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs};
-use rustc_ast::ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
-use rustc_ast::ast::{Path, PathSegment, QSelf};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
+use rustc_ast::{
+    self as ast, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs,
+};
+use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
+use rustc_ast::{Path, PathSegment, QSelf};
 use rustc_errors::{pluralize, Applicability, PResult};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym, Ident};
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 5c3a5e99873..ac067cb0eab 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -6,12 +6,12 @@ use super::path::PathStyle;
 use super::{BlockMode, Parser, Restrictions, SemiColonMode};
 use crate::maybe_whole;
 
-use rustc_ast::ast;
-use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle};
-use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
+use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
 use rustc_ast::util::classify;
+use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle};
+use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
 use rustc_errors::{Applicability, PResult};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym};
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index cd66b917f23..4356850818e 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -2,11 +2,11 @@ use super::{Parser, PathStyle, TokenType};
 
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
-use rustc_ast::ast::{self, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind};
-use rustc_ast::ast::{GenericBound, GenericBounds, MacCall, Mutability};
-use rustc_ast::ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
+use rustc_ast::{self as ast, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind};
+use rustc_ast::{GenericBound, GenericBounds, MacCall, Mutability};
+use rustc_ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax};
 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym};
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index 2512878ec65..f4bb9610940 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -2,8 +2,8 @@
 
 use crate::parse_in;
 
-use rustc_ast::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
 use rustc_ast::tokenstream::DelimSpan;
+use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
 use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs
index d438fe35ff4..59edf21b733 100644
--- a/src/librustc_passes/check_attr.rs
+++ b/src/librustc_passes/check_attr.rs
@@ -8,7 +8,7 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 
-use rustc_ast::ast::{Attribute, NestedMetaItem};
+use rustc_ast::{Attribute, NestedMetaItem};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 29939c7cfaf..01da33ddd2e 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -15,7 +15,7 @@ use rustc_middle::middle::privacy;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::lint;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_span::symbol::{sym, Symbol};
 
 // Any local node that may call something in its body block should be
diff --git a/src/librustc_passes/diagnostic_items.rs b/src/librustc_passes/diagnostic_items.rs
index fa59337b0f6..df0f9f157ae 100644
--- a/src/librustc_passes/diagnostic_items.rs
+++ b/src/librustc_passes/diagnostic_items.rs
@@ -9,7 +9,7 @@
 //!
 //! * Compiler internal types like `Ty` and `TyCtxt`
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 139ffb9699a..9537321026e 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -2,8 +2,8 @@
 // pieces of AST and HIR. The resulting numbers are good approximations but not
 // completely accurate (some things might be counted twice, others missed).
 
-use rustc_ast::ast::{self, AttrId, NodeId};
 use rustc_ast::visit as ast_visit;
+use rustc_ast::{self as ast, AttrId, NodeId};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::intravisit as hir_visit;
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index 931a8cb5f7d..ebe231009d3 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast::{FloatTy, InlineAsmTemplatePiece, IntTy, UintTy};
+use rustc_ast::{FloatTy, InlineAsmTemplatePiece, IntTy, UintTy};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
diff --git a/src/librustc_passes/lang_items.rs b/src/librustc_passes/lang_items.rs
index 07415870549..0ae0c381a11 100644
--- a/src/librustc_passes/lang_items.rs
+++ b/src/librustc_passes/lang_items.rs
@@ -13,7 +13,7 @@ use crate::weak_lang_items;
 use rustc_middle::middle::cstore::ExternCrate;
 use rustc_middle::ty::TyCtxt;
 
-use rustc_ast::ast::Attribute;
+use rustc_ast::Attribute;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -30,7 +30,13 @@ struct LanguageItemCollector<'tcx> {
 
 impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        self.check_for_lang(Target::from_item(item), item.hir_id, item.attrs)
+        self.check_for_lang(Target::from_item(item), item.hir_id, item.attrs);
+
+        if let hir::ItemKind::Enum(def, ..) = &item.kind {
+            for variant in def.variants {
+                self.check_for_lang(Target::Variant, variant.id, variant.attrs);
+            }
+        }
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index 9450d75620a..504cbbfcb76 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast::Attribute;
+use rustc_ast::Attribute;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs
index 9a4aa6a68a6..7c62a234dba 100644
--- a/src/librustc_passes/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -4,7 +4,7 @@
 // and `#[unstable (..)]`), but are not declared in one single location
 // (unlike lang features), which means we need to collect them instead.
 
-use rustc_ast::ast::{Attribute, MetaItem, MetaItemKind};
+use rustc_ast::{Attribute, MetaItem, MetaItemKind};
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 6477f8da008..de21f0b5e09 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -84,7 +84,7 @@
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
-use rustc_ast::ast::InlineAsmOptions;
+use rustc_ast::InlineAsmOptions;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -526,7 +526,8 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
         | hir::ExprKind::Yield(..)
         | hir::ExprKind::Type(..)
         | hir::ExprKind::Err
-        | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
+        | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
+        | hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
             intravisit::walk_expr(ir, expr);
         }
     }
@@ -1310,7 +1311,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
             hir::ExprKind::Lit(..)
             | hir::ExprKind::Err
-            | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => succ,
+            | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
+            | hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
 
             // Note that labels have been resolved, so we don't need to look
             // at the label ident
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 1af77ae61c7..91edc7d9db7 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -1,7 +1,7 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
-use rustc_ast::ast::Attribute;
+use rustc_ast::Attribute;
 use rustc_attr::{self as attr, ConstStability, Stability};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index 2f307302db0..687f7db221f 100644
--- a/src/librustc_plugin_impl/load.rs
+++ b/src/librustc_plugin_impl/load.rs
@@ -1,7 +1,7 @@
 //! Used by `rustc` when loading a plugin.
 
 use crate::Registry;
-use rustc_ast::ast::Crate;
+use rustc_ast::Crate;
 use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
 use rustc_middle::middle::cstore::MetadataLoader;
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index a3f2668691f..deb4277cb38 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1325,7 +1325,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
                 Res::Def(kind, def_id) => Some((kind, def_id)),
                 _ => None,
             },
-            hir::QPath::TypeRelative(..) => self
+            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
                 .maybe_typeck_results
                 .and_then(|typeck_results| typeck_results.type_dependent_def(id)),
         };
@@ -1340,7 +1340,9 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
                 let sess = self.tcx.sess;
                 let sm = sess.source_map();
                 let name = match qpath {
-                    hir::QPath::Resolved(_, path) => sm.span_to_snippet(path.span).ok(),
+                    hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => {
+                        sm.span_to_snippet(qpath.span()).ok()
+                    }
                     hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                 };
                 let kind = kind.descr(def_id);
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index ddc16d18952..761724be57d 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -15,10 +15,10 @@ use crate::{
 };
 use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
 
-use rustc_ast::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
-use rustc_ast::ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use rustc_ast::token::{self, Token};
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::{self as ast, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
+use rustc_ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 1f36e1ed83d..5624a6b6acc 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -26,7 +26,7 @@
 use crate::imports::ImportKind;
 use crate::Resolver;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast_lowering::ResolverAstLowering;
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 7dbf51aab28..5d5088de31b 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -1,8 +1,8 @@
 use crate::Resolver;
-use rustc_ast::ast::*;
 use rustc_ast::token::{self, Token};
 use rustc_ast::visit::{self, FnKind};
 use rustc_ast::walk_list;
+use rustc_ast::*;
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def_id::LocalDefId;
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 1e5e937db66..48e1068b8da 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,8 +1,8 @@
 use std::cmp::Reverse;
 use std::ptr;
 
-use rustc_ast::ast::{self, Path};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_ast::{self as ast, Path};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index ef51a1c73af..b02fc427d60 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -9,9 +9,9 @@ use crate::{BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
 use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
-use rustc_ast::ast::NodeId;
 use rustc_ast::unwrap_or;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_ast::NodeId;
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 2f63257a982..0dbb6269d2e 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -11,9 +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 rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
+use rustc_ast::*;
 use rustc_ast::{unwrap_or, walk_list};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 2e606beca26..2549aee52ad 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -5,9 +5,9 @@ use crate::path_names_to_string;
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use rustc_ast::ast::{self, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_ast::visit::FnKind;
+use rustc_ast::{self as ast, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs
index e2f0d388f7e..31360d47473 100644
--- a/src/librustc_resolve/late/lifetimes.rs
+++ b/src/librustc_resolve/late/lifetimes.rs
@@ -941,6 +941,24 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
+    fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
+        match bound {
+            hir::GenericBound::LangItemTrait { .. } if !self.trait_ref_hack => {
+                let scope = Scope::Binder {
+                    lifetimes: FxHashMap::default(),
+                    s: self.scope,
+                    next_early_index: self.next_early_index(),
+                    track_lifetime_uses: true,
+                    opaque_type_parent: false,
+                };
+                self.with(scope, |_, this| {
+                    intravisit::walk_param_bound(this, bound);
+                });
+            }
+            _ => intravisit::walk_param_bound(self, bound),
+        }
+    }
+
     fn visit_poly_trait_ref(
         &mut self,
         trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
@@ -2296,6 +2314,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 self.outer_index.shift_out(1);
             }
 
+            fn visit_param_bound(&mut self, bound: &hir::GenericBound<'_>) {
+                if let hir::GenericBound::LangItemTrait { .. } = bound {
+                    self.outer_index.shift_in(1);
+                    intravisit::walk_param_bound(self, bound);
+                    self.outer_index.shift_out(1);
+                } else {
+                    intravisit::walk_param_bound(self, bound);
+                }
+            }
+
             fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
                 if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
                     match lifetime {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 339a5ae6675..36b7a430f78 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -20,12 +20,12 @@ pub use rustc_hir::def::{Namespace, PerNS};
 use Determinacy::*;
 
 use rustc_arena::TypedArena;
-use rustc_ast::ast::{self, FloatTy, IntTy, NodeId, UintTy};
-use rustc_ast::ast::{Crate, CRATE_NODE_ID};
-use rustc_ast::ast::{ItemKind, Path};
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::unwrap_or;
 use rustc_ast::visit::{self, Visitor};
+use rustc_ast::{self as ast, FloatTy, IntTy, NodeId, UintTy};
+use rustc_ast::{Crate, CRATE_NODE_ID};
+use rustc_ast::{ItemKind, Path};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
@@ -1076,37 +1076,6 @@ impl ResolverAstLowering for Resolver<'_> {
         self.cstore().item_generics_num_lifetimes(def_id, sess)
     }
 
-    fn resolve_str_path(
-        &mut self,
-        span: Span,
-        crate_root: Option<Symbol>,
-        components: &[Symbol],
-        ns: Namespace,
-    ) -> (ast::Path, Res) {
-        let root = if crate_root.is_some() { kw::PathRoot } else { kw::Crate };
-        let segments = iter::once(Ident::with_dummy_span(root))
-            .chain(
-                crate_root
-                    .into_iter()
-                    .chain(components.iter().cloned())
-                    .map(Ident::with_dummy_span),
-            )
-            .map(|i| self.new_ast_path_segment(i))
-            .collect::<Vec<_>>();
-
-        let path = ast::Path { span, segments };
-
-        let parent_scope = &ParentScope::module(self.graph_root);
-        let res = match self.resolve_ast_path(&path, ns, parent_scope) {
-            Ok(res) => res,
-            Err((span, error)) => {
-                self.report_error(span, error);
-                Res::Err
-            }
-        };
-        (path, res)
-    }
-
     fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes> {
         self.partial_res_map.get(&id).cloned()
     }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 542025ac1f4..51518d63ae9 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -6,7 +6,7 @@ use crate::Namespace::*;
 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_ast::ast::{self, NodeId};
+use rustc_ast::{self as ast, NodeId};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_ast_pretty::pprust;
 use rustc_attr::StabilityLevel;
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index f33d2f46aa2..77aecefe5a2 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -13,7 +13,7 @@
 //! DumpVisitor walks the AST and processes it, and Dumper is used for
 //! recording the output.
 
-use rustc_ast::ast::{self};
+use rustc_ast as ast;
 use rustc_ast::{token, walk_list};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -702,14 +702,18 @@ impl<'tcx> DumpVisitor<'tcx> {
 
         // super-traits
         for super_bound in trait_refs.iter() {
-            let trait_ref = match *super_bound {
-                hir::GenericBound::Trait(ref trait_ref, _) => trait_ref,
+            let (def_id, sub_span) = match *super_bound {
+                hir::GenericBound::Trait(ref trait_ref, _) => (
+                    self.lookup_def_id(trait_ref.trait_ref.hir_ref_id),
+                    trait_ref.trait_ref.path.segments.last().unwrap().ident.span,
+                ),
+                hir::GenericBound::LangItemTrait(lang_item, span, _, _) => {
+                    (Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
+                }
                 hir::GenericBound::Outlives(..) => continue,
             };
 
-            let trait_ref = &trait_ref.trait_ref;
-            if let Some(id) = self.lookup_def_id(trait_ref.hir_ref_id) {
-                let sub_span = trait_ref.path.segments.last().unwrap().ident.span;
+            if let Some(id) = def_id {
                 if !self.span.filter_generated(sub_span) {
                     let span = self.span_from_span(sub_span);
                     self.dumper.dump_ref(Ref {
@@ -762,11 +766,7 @@ impl<'tcx> DumpVisitor<'tcx> {
     }
 
     fn process_path(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
-        let span = match path {
-            hir::QPath::Resolved(_, path) => path.span,
-            hir::QPath::TypeRelative(_, segment) => segment.ident.span,
-        };
-        if self.span.filter_generated(span) {
+        if self.span.filter_generated(path.span()) {
             return;
         }
         self.dump_path_ref(id, path);
@@ -783,6 +783,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                 self.visit_ty(ty);
                 std::slice::from_ref(*segment)
             }
+            hir::QPath::LangItem(..) => return,
         };
         for seg in segments {
             if let Some(ref generic_args) = seg.args {
@@ -1355,10 +1356,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
                 }
 
                 if let Some(id) = self.lookup_def_id(t.hir_id) {
-                    let sub_span = match path {
-                        hir::QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
-                        hir::QPath::TypeRelative(_, segment) => segment.ident.span,
-                    };
+                    let sub_span = path.last_segment_span();
                     let span = self.span_from_span(sub_span);
                     self.dumper.dump_ref(Ref {
                         kind: RefKind::Type,
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index ca98ada4e57..629051c1820 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -9,7 +9,7 @@ mod dumper;
 mod span_utils;
 mod sig;
 
-use rustc_ast::ast::{self};
+use rustc_ast as ast;
 use rustc_ast::util::comments::beautify_doc_string;
 use rustc_ast_pretty::pprust::attribute_to_string;
 use rustc_hir as hir;
@@ -551,28 +551,22 @@ impl<'tcx> SaveContext<'tcx> {
                     }
                 }
             }
-            hir::ExprKind::Struct(qpath, ..) => {
-                let segment = match qpath {
-                    hir::QPath::Resolved(_, path) => path.segments.last().unwrap(),
-                    hir::QPath::TypeRelative(_, segment) => segment,
-                };
-                match ty.kind {
-                    ty::Adt(def, _) => {
-                        let sub_span = segment.ident.span;
-                        filter!(self.span_utils, sub_span);
-                        let span = self.span_from_span(sub_span);
-                        Some(Data::RefData(Ref {
-                            kind: RefKind::Type,
-                            span,
-                            ref_id: id_from_def_id(def.did),
-                        }))
-                    }
-                    _ => {
-                        debug!("expected adt, found {:?}", ty);
-                        None
-                    }
+            hir::ExprKind::Struct(qpath, ..) => match ty.kind {
+                ty::Adt(def, _) => {
+                    let sub_span = qpath.last_segment_span();
+                    filter!(self.span_utils, sub_span);
+                    let span = self.span_from_span(sub_span);
+                    Some(Data::RefData(Ref {
+                        kind: RefKind::Type,
+                        span,
+                        ref_id: id_from_def_id(def.did),
+                    }))
                 }
-            }
+                _ => {
+                    debug!("expected adt, found {:?}", ty);
+                    None
+                }
+            },
             hir::ExprKind::MethodCall(ref seg, ..) => {
                 let method_id = match self.typeck_results().type_dependent_def_id(expr.hir_id) {
                     Some(id) => id,
@@ -636,7 +630,7 @@ impl<'tcx> SaveContext<'tcx> {
             })
             | Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => match qpath {
                 hir::QPath::Resolved(_, path) => path.res,
-                hir::QPath::TypeRelative(..) => self
+                hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
                     .maybe_typeck_results
                     .map_or(Res::Err, |typeck_results| typeck_results.qpath_res(qpath, hir_id)),
             },
@@ -653,6 +647,7 @@ impl<'tcx> SaveContext<'tcx> {
         let segment = match path {
             hir::QPath::Resolved(_, path) => path.segments.last(),
             hir::QPath::TypeRelative(_, segment) => Some(*segment),
+            hir::QPath::LangItem(..) => None,
         };
         segment.and_then(|seg| {
             self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 33355c4c558..b3003cc63d3 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -29,7 +29,7 @@ use crate::{id_from_def_id, id_from_hir_id, SaveContext};
 
 use rls_data::{SigElement, Signature};
 
-use rustc_ast::ast::Mutability;
+use rustc_ast::Mutability;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir_pretty::id_to_string;
@@ -286,6 +286,9 @@ impl<'hir> Sig for hir::Ty<'hir> {
                     refs: vec![SigElement { id, start, end }],
                 })
             }
+            hir::TyKind::Path(hir::QPath::LangItem(lang_item, _)) => {
+                Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
+            }
             hir::TyKind::TraitObject(bounds, ..) => {
                 // FIXME recurse into bounds
                 let bounds: Vec<hir::GenericBound<'_>> = bounds
diff --git a/src/librustc_session/output.rs b/src/librustc_session/output.rs
index e4bce435c4b..bf9c96c6c94 100644
--- a/src/librustc_session/output.rs
+++ b/src/librustc_session/output.rs
@@ -1,7 +1,7 @@
 //! Related to out filenames of compilation (e.g. save analysis, binaries).
 use crate::config::{CrateType, Input, OutputFilenames, OutputType};
 use crate::Session;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use std::path::{Path, PathBuf};
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index f10f9b2ce93..d7da2038b54 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -7,9 +7,9 @@ use crate::lint;
 use crate::parse::ParseSess;
 use crate::search_paths::{PathKind, SearchPath};
 
-pub use rustc_ast::ast::Attribute;
 pub use rustc_ast::attr::MarkedAttrs;
 pub use rustc_ast::crate_disambiguator::CrateDisambiguator;
+pub use rustc_ast::Attribute;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::jobserver::{self, Client};
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 7843c04f255..bc7efd26f46 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -706,6 +706,7 @@ symbols! {
         never_type,
         never_type_fallback,
         new,
+        new_unchecked,
         next,
         nll,
         no,
@@ -828,6 +829,7 @@ symbols! {
         quad_precision_float,
         question_mark,
         quote,
+        range_inclusive_new,
         raw_dylib,
         raw_identifiers,
         raw_ref_op,
diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs
index 56ee492de87..f01c3da8b5f 100644
--- a/src/librustc_symbol_mangling/v0.rs
+++ b/src/librustc_symbol_mangling/v0.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast::{FloatTy, IntTy, UintTy};
+use rustc_ast::{FloatTy, IntTy, UintTy};
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
diff --git a/src/librustc_trait_selection/traits/on_unimplemented.rs b/src/librustc_trait_selection/traits/on_unimplemented.rs
index 7a9ed4b72dd..75822eadb2a 100644
--- a/src/librustc_trait_selection/traits/on_unimplemented.rs
+++ b/src/librustc_trait_selection/traits/on_unimplemented.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast::{MetaItem, NestedMetaItem};
+use rustc_ast::{MetaItem, NestedMetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{struct_span_err, ErrorReported};
diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs
index 75785076d9a..a043fa3f4c8 100644
--- a/src/librustc_traits/chalk/lowering.rs
+++ b/src/librustc_traits/chalk/lowering.rs
@@ -327,7 +327,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>>
 impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
     fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Ty<RustInterner<'tcx>> {
         use chalk_ir::TyData;
-        use rustc_ast::ast;
+        use rustc_ast as ast;
         use TyKind::*;
 
         let empty = || chalk_ir::Substitution::empty(interner);
diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs
index 0c5d57551f9..f18b4ca65f6 100644
--- a/src/librustc_traits/chalk/mod.rs
+++ b/src/librustc_traits/chalk/mod.rs
@@ -101,7 +101,7 @@ crate fn evaluate_goal<'tcx>(
             match _data {
                 chalk_ir::GenericArgData::Ty(_t) => {
                     use chalk_ir::TyData;
-                    use rustc_ast::ast;
+                    use rustc_ast as ast;
 
                     let _data = _t.data(&interner);
                     let kind = match _data {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5170a060c5f..86081b15071 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -8,7 +8,7 @@
 use crate::collect::PlaceholderHirTyCollector;
 use crate::middle::resolve_lifetime as rl;
 use crate::require_c_abi_if_c_variadic;
-use rustc_ast::{ast::ParamKindOrd, util::lev_distance::find_best_match_for_name};
+use rustc_ast::{util::lev_distance::find_best_match_for_name, ParamKindOrd};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::ErrorReported;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError};
@@ -1202,6 +1202,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         )
     }
 
+    pub fn instantiate_lang_item_trait_ref(
+        &self,
+        lang_item: hir::LangItem,
+        span: Span,
+        hir_id: hir::HirId,
+        args: &GenericArgs<'_>,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+    ) {
+        let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
+
+        let (substs, assoc_bindings, _) =
+            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+        bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in assoc_bindings {
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                hir_id,
+                poly_trait_ref,
+                &binding,
+                bounds,
+                false,
+                &mut dup_bindings,
+                span,
+            );
+        }
+    }
+
     fn ast_path_to_mono_trait_ref(
         &self,
         span: Span,
@@ -1392,6 +1422,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     trait_bounds.push((b, Constness::NotConst))
                 }
                 hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
+                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
+                    .instantiate_lang_item_trait_ref(
+                        lang_item, span, hir_id, args, param_ty, bounds,
+                    ),
                 hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
             }
         }
@@ -2960,6 +2994,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     .map(|(ty, _, _)| ty)
                     .unwrap_or_else(|_| tcx.ty_error())
             }
+            hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
+                let def_id = tcx.require_lang_item(lang_item, Some(span));
+                let (substs, _, _) = self.create_substs_for_ast_path(
+                    span,
+                    def_id,
+                    &[],
+                    &GenericArgs::none(),
+                    true,
+                    None,
+                );
+                self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
+            }
             hir::TyKind::Array(ref ty, ref length) => {
                 let length_def_id = tcx.hir().local_def_id(length.hir_id);
                 let length = ty::Const::from_anon_const(tcx, length_def_id);
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 418ea29b84f..34693a73217 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -32,7 +32,7 @@ use super::FnCtxt;
 
 use crate::hir::def_id::DefId;
 use crate::type_error_struct;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::lang_items;
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 4ea76a4a9e2..aa92d8b8b2b 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -36,6 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.suggest_missing_await(err, expr, expected, expr_ty);
         self.suggest_missing_parentheses(err, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
+        self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
     }
 
     // Requires that the two types unify, and prints an error message if
@@ -485,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
                             // parenthesize borrows of range literals (Issue #54505)
-                            _ if is_range_literal(self.tcx.sess.source_map(), expr) => true,
+                            _ if is_range_literal(expr) => true,
                             _ => false,
                         };
                         let sugg_expr = if needs_parens { format!("({})", src) } else { src };
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index e88f13a1f3a..ff0c788c18b 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -16,7 +16,7 @@ use crate::check::Needs;
 use crate::check::TupleArgumentsFlag::DontTupleArguments;
 use crate::type_error_struct;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -236,6 +236,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::AddrOf(kind, mutbl, ref oprnd) => {
                 self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
             }
+            ExprKind::Path(QPath::LangItem(lang_item, _)) => {
+                self.check_lang_item_path(lang_item, expr)
+            }
             ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr),
             ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
             ExprKind::LlvmInlineAsm(ref asm) => {
@@ -447,6 +450,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn check_lang_item_path(
+        &self,
+        lang_item: hir::LangItem,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Ty<'tcx> {
+        self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
+    }
+
     fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span);
@@ -1077,11 +1088,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return self.tcx.ty_error();
         };
 
-        let path_span = match *qpath {
-            QPath::Resolved(_, ref path) => path.span,
-            QPath::TypeRelative(ref qself, _) => qself.span,
-        };
-
         // Prohibit struct expressions when non-exhaustive flag is set.
         let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
         if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
@@ -1099,7 +1105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             adt_ty,
             expected,
             expr.hir_id,
-            path_span,
+            qpath.span(),
             variant,
             fields,
             base_expr.is_none(),
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 9078dc40041..7ac6681be1a 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -7,7 +7,7 @@ use crate::check::FnCtxt;
 use crate::hir::def::DefKind;
 use crate::hir::def_id::DefId;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::util::lev_distance::{find_best_match_for_name, lev_distance};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a625b5ea405..824e81a974c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -88,7 +88,7 @@ pub mod writeback;
 use crate::astconv::{
     AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, PathSeg,
 };
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
@@ -122,10 +122,9 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::subst::{GenericArgKind, UserSelfTy, UserSubsts};
 use rustc_middle::ty::util::{Discr, IntTypeExt, Representability};
-use rustc_middle::ty::{
-    self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef,
-    ToPredicate, Ty, TyCtxt, UserType, WithConstness,
-};
+use rustc_middle::ty::WithConstness;
+use rustc_middle::ty::{self, AdtKind, CanonicalUserType, Const, DefIdTree, GenericParamDefKind};
+use rustc_middle::ty::{RegionKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, UserType};
 use rustc_session::config::{self, EntryFnType};
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
@@ -4430,10 +4429,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &QPath<'_>,
         hir_id: hir::HirId,
     ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
-        let path_span = match *qpath {
-            QPath::Resolved(_, ref path) => path.span,
-            QPath::TypeRelative(ref qself, _) => qself.span,
-        };
+        let path_span = qpath.qself_span();
         let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
         let variant = match def {
             Res::Err => {
@@ -4511,9 +4507,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 (result.map(|(kind, def_id)| Res::Def(kind, def_id)).unwrap_or(Res::Err), ty)
             }
+            QPath::LangItem(lang_item, span) => {
+                self.resolve_lang_item_path(lang_item, span, hir_id)
+            }
         }
     }
 
+    fn resolve_lang_item_path(
+        &self,
+        lang_item: hir::LangItem,
+        span: Span,
+        hir_id: hir::HirId,
+    ) -> (Res, Ty<'tcx>) {
+        let def_id = self.tcx.require_lang_item(lang_item, Some(span));
+        let def_kind = self.tcx.def_kind(def_id);
+
+        let item_ty = if let DefKind::Variant = def_kind {
+            self.tcx.type_of(self.tcx.parent(def_id).expect("variant w/out parent"))
+        } else {
+            self.tcx.type_of(def_id)
+        };
+        let substs = self.infcx.fresh_substs_for_item(span, def_id);
+        let ty = item_ty.subst(self.tcx, substs);
+
+        self.write_resolution(hir_id, Ok((def_kind, def_id)));
+        self.add_required_obligations(span, def_id, &substs);
+        (Res::Def(def_kind, def_id), ty)
+    }
+
     /// Resolves an associated value path into a base type and associated constant, or method
     /// resolution. The newly resolved definition is written into `type_dependent_defs`.
     pub fn resolve_ty_and_res_ufcs<'b>(
@@ -4532,6 +4553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
             QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
+            QPath::LangItem(..) => bug!("`resolve_ty_and_res_ufcs` called on `LangItem`"),
         };
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
@@ -5176,6 +5198,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn note_internal_mutation_in_method(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr<'_>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if found != self.tcx.types.unit {
+            return;
+        }
+        if let ExprKind::MethodCall(path_segment, _, [rcvr, ..], _) = expr.kind {
+            if self
+                .typeck_results
+                .borrow()
+                .expr_ty_adjusted_opt(rcvr)
+                .map_or(true, |ty| expected.peel_refs() != ty.peel_refs())
+            {
+                return;
+            }
+            let mut sp = MultiSpan::from_span(path_segment.ident.span);
+            sp.push_span_label(
+                path_segment.ident.span,
+                format!(
+                    "this call modifies {} in-place",
+                    match rcvr.kind {
+                        ExprKind::Path(QPath::Resolved(
+                            None,
+                            hir::Path { segments: [segment], .. },
+                        )) => format!("`{}`", segment.ident),
+                        _ => "its receiver".to_string(),
+                    }
+                ),
+            );
+            sp.push_span_label(
+                rcvr.span,
+                "you probably want to use this value after calling the method...".to_string(),
+            );
+            err.span_note(
+                sp,
+                &format!("method `{}` modifies its receiver in-place", path_segment.ident),
+            );
+            err.note(&format!("...instead of the `()` output of method `{}`", path_segment.ident));
+        }
+    }
+
     /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`.
     fn suggest_calling_boxed_future_when_appropriate(
         &self,
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 1c78bef9852..dc1ce2d89ba 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1,5 +1,5 @@
 use crate::check::FnCtxt;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
@@ -947,13 +947,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 //   |
                 // L |     let A(()) = A(());
                 //   |          ^  ^
-                [] => {
-                    let qpath_span = match qpath {
-                        hir::QPath::Resolved(_, path) => path.span,
-                        hir::QPath::TypeRelative(_, ps) => ps.ident.span,
-                    };
-                    (qpath_span.shrink_to_hi(), pat_span)
-                }
+                [] => (qpath.span().shrink_to_hi(), pat_span),
                 // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the
                 // last sub-pattern. In the case of `A(x)` the first and last may coincide.
                 // This looks like:
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 2bde5d2c78c..d47a8273d07 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -1,7 +1,7 @@
 use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index cd7429f166f..859d510dcbe 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -13,7 +13,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt};
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_span::Span;
 
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index da1f3ea62f2..7fb4026117b 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -18,8 +18,8 @@ use crate::astconv::{AstConv, Bounds, SizedByDefault};
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::constrained_generic_params as cgp;
 use crate::middle::resolve_lifetime as rl;
-use rustc_ast::ast;
-use rustc_ast::ast::MetaItemKind;
+use rustc_ast as ast;
+use rustc_ast::MetaItemKind;
 use rustc_attr::{list_contains_name, InlineAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@@ -1959,6 +1959,20 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
                             predicates.extend(bounds.predicates(tcx, ty));
                         }
 
+                        &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
+                            let mut bounds = Bounds::default();
+                            AstConv::instantiate_lang_item_trait_ref(
+                                &icx,
+                                lang_item,
+                                span,
+                                hir_id,
+                                args,
+                                ty,
+                                &mut bounds,
+                            );
+                            predicates.extend(bounds.predicates(tcx, ty));
+                        }
+
                         &hir::GenericBound::Outlives(ref lifetime) => {
                             let region = AstConv::ast_region_to_region(&icx, lifetime, None);
                             predicates.push((
@@ -2108,6 +2122,18 @@ fn predicates_from_bound<'tcx>(
             let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds);
             bounds.predicates(astconv.tcx(), param_ty)
         }
+        hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
+            let mut bounds = Bounds::default();
+            astconv.instantiate_lang_item_trait_ref(
+                lang_item,
+                span,
+                hir_id,
+                args,
+                param_ty,
+                &mut bounds,
+            );
+            bounds.predicates(astconv.tcx(), param_ty)
+        }
         hir::GenericBound::Outlives(ref lifetime) => {
             let region = astconv.ast_region_to_region(lifetime, None);
             let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
@@ -2657,7 +2683,7 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 }
 
 fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<usize> {
-    use rustc_ast::ast::{Lit, LitIntType, LitKind};
+    use rustc_ast::{Lit, LitIntType, LitKind};
     let meta_item_list = attr.meta_item_list();
     let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref);
     let sole_meta_list = match meta_item_list {
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 53979d27052..ab0b332ee19 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -7,7 +7,7 @@ use std::fmt::{self, Write};
 use std::mem;
 use std::ops;
 
-use rustc_ast::ast::{LitKind, MetaItem, MetaItemKind, NestedMetaItem};
+use rustc_ast::{LitKind, MetaItem, MetaItemKind, NestedMetaItem};
 use rustc_feature::Features;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{sym, Symbol};
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index b4ced412e5e..96f0a1b7a7c 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -1,7 +1,7 @@
 use super::*;
 
-use rustc_ast::ast::*;
 use rustc_ast::attr;
+use rustc_ast::Path;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::with_default_session_globals;
 use rustc_span::DUMMY_SP;
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index cb7c62e3a5a..38fa8a402c4 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -2,7 +2,7 @@
 
 use std::iter::once;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 3ad357e583c..14e0fa7eabb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -9,7 +9,7 @@ mod simplify;
 pub mod types;
 pub mod utils;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
@@ -17,6 +17,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
+use rustc_middle::bug;
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::middle::stability;
 use rustc_middle::ty::fold::TypeFolder;
@@ -291,6 +292,22 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
         match *self {
             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
+            hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
+                let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
+
+                let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
+
+                let generic_args = generic_args.clean(cx);
+                let bindings = match generic_args {
+                    GenericArgs::AngleBracketed { bindings, .. } => bindings,
+                    _ => bug!("clean: parenthesized `GenericBound::LangItemTrait`"),
+                };
+
+                GenericBound::TraitBound(
+                    PolyTrait { trait_: (trait_ref, &*bindings).clean(cx), generic_params: vec![] },
+                    hir::TraitBoundModifier::None,
+                )
+            }
             hir::GenericBound::Trait(ref t, modifier) => {
                 GenericBound::TraitBound(t.clean(cx), modifier)
             }
@@ -1504,6 +1521,9 @@ impl Clean<Type> for hir::Ty<'_> {
                     trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id),
                 }
             }
+            TyKind::Path(hir::QPath::LangItem(..)) => {
+                bug!("clean: requiring documentation of lang item")
+            }
             TyKind::TraitObject(ref bounds, ref lifetime) => {
                 match bounds[0].clean(cx).trait_ {
                     ResolvedPath { path, param_names: None, did, is_generic } => {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 627f88df45c..914dc2e1b88 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -8,9 +8,9 @@ use std::rc::Rc;
 use std::sync::Arc;
 use std::{slice, vec};
 
-use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::attr;
 use rustc_ast::util::comments::beautify_doc_string;
+use rustc_ast::{self as ast, AttrStyle};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -420,7 +420,7 @@ pub struct Attributes {
 impl Attributes {
     /// Extracts the content from an attribute `#[doc(cfg(content))]`.
     pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
-        use rustc_ast::ast::NestedMetaItem::MetaItem;
+        use rustc_ast::NestedMetaItem::MetaItem;
 
         if let ast::MetaItemKind::List(ref nmis) = mi.kind {
             if nmis.len() == 1 {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index a7d03fcabf5..a502a27948e 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -335,6 +335,7 @@ pub fn qpath_to_string(p: &hir::QPath<'_>) -> String {
     let segments = match *p {
         hir::QPath::Resolved(_, ref path) => &path.segments,
         hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
+        hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
     };
 
     let mut s = String::new();
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 943729a74ab..98125adbdea 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -2,7 +2,7 @@
 //! manner (and with prettier names) before cleaning.
 pub use self::StructType::*;
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::{self, Span, Symbol};
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index f7fc3579d67..d4d6a8119c3 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtensionKind;
 use rustc_feature::UnstableFeatures;
@@ -1204,20 +1204,20 @@ fn handle_variant(
 }
 
 const PRIMITIVES: &[(&str, Res)] = &[
-    ("u8", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::ast::UintTy::U8))),
-    ("u16", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::ast::UintTy::U16))),
-    ("u32", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::ast::UintTy::U32))),
-    ("u64", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::ast::UintTy::U64))),
-    ("u128", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::ast::UintTy::U128))),
-    ("usize", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::ast::UintTy::Usize))),
-    ("i8", Res::PrimTy(hir::PrimTy::Int(rustc_ast::ast::IntTy::I8))),
-    ("i16", Res::PrimTy(hir::PrimTy::Int(rustc_ast::ast::IntTy::I16))),
-    ("i32", Res::PrimTy(hir::PrimTy::Int(rustc_ast::ast::IntTy::I32))),
-    ("i64", Res::PrimTy(hir::PrimTy::Int(rustc_ast::ast::IntTy::I64))),
-    ("i128", Res::PrimTy(hir::PrimTy::Int(rustc_ast::ast::IntTy::I128))),
-    ("isize", Res::PrimTy(hir::PrimTy::Int(rustc_ast::ast::IntTy::Isize))),
-    ("f32", Res::PrimTy(hir::PrimTy::Float(rustc_ast::ast::FloatTy::F32))),
-    ("f64", Res::PrimTy(hir::PrimTy::Float(rustc_ast::ast::FloatTy::F64))),
+    ("u8", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U8))),
+    ("u16", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U16))),
+    ("u32", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U32))),
+    ("u64", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U64))),
+    ("u128", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U128))),
+    ("usize", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::Usize))),
+    ("i8", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I8))),
+    ("i16", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I16))),
+    ("i32", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I32))),
+    ("i64", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I64))),
+    ("i128", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I128))),
+    ("isize", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::Isize))),
+    ("f32", Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F32))),
+    ("f64", Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F64))),
     ("str", Res::PrimTy(hir::PrimTy::Str)),
     ("bool", Res::PrimTy(hir::PrimTy::Bool)),
     ("char", Res::PrimTy(hir::PrimTy::Char)),
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 62f52ea5213..693d5b9fb07 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorReported;
 use rustc_feature::UnstableFeatures;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index be80193db8c..ac9f839600b 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -1,7 +1,7 @@
 //! The Rust AST Visitor. Extracts useful information and massages it into a form
 //! usable for `clean`.
 
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs
index 20b4e67f53b..9d81b7f01cf 100644
--- a/src/test/mir-opt/simplify-arm.rs
+++ b/src/test/mir-opt/simplify-arm.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=1
+// compile-flags: -Z mir-opt-level=2
 // EMIT_MIR simplify_arm.id.SimplifyArmIdentity.diff
 // EMIT_MIR simplify_arm.id.SimplifyBranchSame.diff
 // EMIT_MIR simplify_arm.id_result.SimplifyArmIdentity.diff
diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
index 0cddcb061cf..ecb4384fc6f 100644
--- a/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
@@ -8,7 +8,8 @@
       let _3: u8;                          // in scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
       let mut _4: u8;                      // in scope 0 at $DIR/simplify-arm.rs:11:25: 11:26
       scope 1 {
-          debug v => _3;                   // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15
+-         debug v => _3;                   // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15
++         debug v => ((_0 as Some).0: u8); // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15
       }
   
       bb0: {
@@ -26,14 +27,15 @@
       }
   
       bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
-          _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
-          ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
-          discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
+-         _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
+-         StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
+-         _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
+-         ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+-         discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+-         StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
++         _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
       }
   
diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
index cd5962c682a..eb1d6f656f4 100644
--- a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
@@ -8,36 +8,32 @@
       let _3: u8;                          // in scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
       let mut _4: u8;                      // in scope 0 at $DIR/simplify-arm.rs:11:25: 11:26
       scope 1 {
-          debug v => _3;                   // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15
+          debug v => ((_0 as Some).0: u8); // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15
       }
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
-          switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
+-         switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
       }
   
       bb1: {
-          discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+-         discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+-     }
+- 
+-     bb2: {
+-         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12
+-     }
+- 
+-     bb3: {
+          _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
++         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
       }
   
-      bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12
-      }
-  
-      bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
-          _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
-          ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
-          discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
-      }
-  
-      bb4: {
+-     bb4: {
++     bb2: {
           return;                          // scope 0 at $DIR/simplify-arm.rs:14:2: 14:2
       }
   }
diff --git a/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
index 642ccc1ab14..253e3236ff7 100644
--- a/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
@@ -10,10 +10,12 @@
       let _5: i32;                         // in scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
       let mut _6: i32;                     // in scope 0 at $DIR/simplify-arm.rs:19:23: 19:24
       scope 1 {
-          debug x => _3;                   // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13
+-         debug x => _3;                   // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13
++         debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13
       }
       scope 2 {
-          debug y => _5;                   // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14
+-         debug y => _5;                   // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14
++         debug y => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14
       }
   
       bb0: {
@@ -22,14 +24,15 @@
       }
   
       bb1: {
-          StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
-          _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
-          StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
-          _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
-          ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
-          discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
-          StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
-          StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:24: 19:25
+-         StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
+-         _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
+-         StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
+-         _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
+-         ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+-         discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+-         StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
+-         StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:24: 19:25
++         _0 = move _1;                    // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
       }
   
@@ -38,14 +41,15 @@
       }
   
       bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
-          _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
-          ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
-          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
+-         _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
+-         StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
+-         _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
+-         ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+-         discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+-         StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
++         _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
       }
   
diff --git a/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
index 95ce09a39ed..23cf43c5319 100644
--- a/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
@@ -10,46 +10,35 @@
       let _5: i32;                         // in scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
       let mut _6: i32;                     // in scope 0 at $DIR/simplify-arm.rs:19:23: 19:24
       scope 1 {
-          debug x => _3;                   // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13
+          debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13
       }
       scope 2 {
-          debug y => _5;                   // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14
+          debug y => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14
       }
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
+-         switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
       }
   
       bb1: {
-          StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
-          _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
-          StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
-          _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
-          ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
-          discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
-          StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
-          StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:24: 19:25
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+-         _0 = move _1;                    // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+-     }
+- 
+-     bb2: {
+-         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12
+-     }
+- 
+-     bb3: {
+          _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
++         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
       }
   
-      bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12
-      }
-  
-      bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
-          _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
-          ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
-          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
-      }
-  
-      bb4: {
+-     bb4: {
++     bb2: {
           return;                          // scope 0 at $DIR/simplify-arm.rs:21:2: 21:2
       }
   }
diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
index b46ca21fb90..063f8495960 100644
--- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
@@ -15,94 +15,88 @@
       let _10: u8;                         // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
       let mut _11: u8;                     // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
+-         debug x => _2;                   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
++         debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
       }
       scope 2 {
-          debug err => _6;                 // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
+-         debug err => _6;                 // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
++         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
           scope 3 {
+              scope 7 {
+-                 debug t => _9;           // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                 debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+              }
+              scope 8 {
+-                 debug v => _8;           // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15
+              }
           }
       }
       scope 4 {
-          debug val => _10;                // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
+-         debug val => _10;                // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
++         debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
           scope 5 {
           }
       }
+      scope 6 {
+          debug self => _4;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+      }
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
           StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
           StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
           _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-          _3 = const <std::result::Result<u8, i32> as std::ops::Try>::into_result(move _4) -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-                                           // ty::Const
-                                           // + ty: fn(std::result::Result<u8, i32>) -> std::result::Result<<std::result::Result<u8, i32> as std::ops::Try>::Ok, <std::result::Result<u8, i32> as std::ops::Try>::Error> {<std::result::Result<u8, i32> as std::ops::Try>::into_result}
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm.rs:24:13: 24:15
-                                           // + literal: Const { ty: fn(std::result::Result<u8, i32>) -> std::result::Result<<std::result::Result<u8, i32> as std::ops::Try>::Ok, <std::result::Result<u8, i32> as std::ops::Try>::Error> {<std::result::Result<u8, i32> as std::ops::Try>::into_result}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb1: {
+          _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
           _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
       }
   
-      bb2: {
-          StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-          _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-          _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+      bb1: {
+-         StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+-         _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+-         _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
+-         StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
++         _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
           StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
-          StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
-          _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
-          ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
-          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
-          StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
+-         StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
+-         _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
+-         ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+-         discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+-         StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
           StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
-          goto -> bb5;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
       }
   
-      bb3: {
+      bb2: {
           unreachable;                     // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
       }
   
-      bb4: {
-          StorageLive(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageLive(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageLive(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          _9 = _6;                         // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          _8 = const <i32 as std::convert::From<i32>>::from(move _9) -> bb6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-                                           // ty::Const
-                                           // + ty: fn(i32) -> i32 {<i32 as std::convert::From<i32>>::from}
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm.rs:24:14: 24:15
-                                           // + literal: Const { ty: fn(i32) -> i32 {<i32 as std::convert::From<i32>>::from}, val: Value(Scalar(<ZST>)) }
+      bb3: {
+-         StorageLive(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+-         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+-         StorageLive(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
+-         StorageLive(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
+-         _9 = _6;                         // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
+-         _8 = move _9;                    // scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+-         StorageDead(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
+-         StorageLive(_12);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+-         _12 = move _8;                   // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+-         ((_0 as Err).0: i32) = move _12; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+-         discriminant(_0) = 1;            // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+-         StorageDead(_12);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+-         StorageDead(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
+-         StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
++         _0 = move _3;                    // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
       }
   
-      bb5: {
+      bb4: {
           return;                          // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
       }
-  
-      bb6: {
-          StorageDead(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          _0 = const <std::result::Result<u8, i32> as std::ops::Try>::from_error(move _8) -> bb7; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-                                           // ty::Const
-                                           // + ty: fn(<std::result::Result<u8, i32> as std::ops::Try>::Error) -> std::result::Result<u8, i32> {<std::result::Result<u8, i32> as std::ops::Try>::from_error}
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm.rs:24:13: 24:15
-                                           // + literal: Const { ty: fn(<std::result::Result<u8, i32> as std::ops::Try>::Error) -> std::result::Result<u8, i32> {<std::result::Result<u8, i32> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb7: {
-          StorageDead(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
-          goto -> bb5;                     // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      }
   }
   
diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
index 93412d1a74f..7c7b1b6d6c6 100644
--- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
@@ -15,94 +15,62 @@
       let _10: u8;                         // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
       let mut _11: u8;                     // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
+          debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
       }
       scope 2 {
-          debug err => _6;                 // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
+          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
           scope 3 {
+              scope 7 {
+                  debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+              }
+              scope 8 {
+                  debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15
+              }
           }
       }
       scope 4 {
-          debug val => _10;                // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
+          debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
           scope 5 {
           }
       }
+      scope 6 {
+          debug self => _4;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+      }
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
           StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
           StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
           _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-          _3 = const <std::result::Result<u8, i32> as std::ops::Try>::into_result(move _4) -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-                                           // ty::Const
-                                           // + ty: fn(std::result::Result<u8, i32>) -> std::result::Result<<std::result::Result<u8, i32> as std::ops::Try>::Ok, <std::result::Result<u8, i32> as std::ops::Try>::Error> {<std::result::Result<u8, i32> as std::ops::Try>::into_result}
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm.rs:24:13: 24:15
-                                           // + literal: Const { ty: fn(std::result::Result<u8, i32>) -> std::result::Result<<std::result::Result<u8, i32> as std::ops::Try>::Ok, <std::result::Result<u8, i32> as std::ops::Try>::Error> {<std::result::Result<u8, i32> as std::ops::Try>::into_result}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb1: {
+          _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
           _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+-         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
       }
   
-      bb2: {
-          StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-          _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-          _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+      bb1: {
+          _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
           StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
-          StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
-          _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
-          ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
-          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
-          StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
           StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
-          goto -> bb5;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
-      }
-  
-      bb3: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
++         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
       }
   
-      bb4: {
-          StorageLive(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageLive(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageLive(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          _9 = _6;                         // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          _8 = const <i32 as std::convert::From<i32>>::from(move _9) -> bb6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-                                           // ty::Const
-                                           // + ty: fn(i32) -> i32 {<i32 as std::convert::From<i32>>::from}
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm.rs:24:14: 24:15
-                                           // + literal: Const { ty: fn(i32) -> i32 {<i32 as std::convert::From<i32>>::from}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb5: {
+      bb2: {
+-         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+-     }
+- 
+-     bb3: {
+-         _0 = move _3;                    // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
+-         StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+-     }
+- 
+-     bb4: {
           return;                          // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
       }
-  
-      bb6: {
-          StorageDead(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          _0 = const <std::result::Result<u8, i32> as std::ops::Try>::from_error(move _8) -> bb7; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-                                           // ty::Const
-                                           // + ty: fn(<std::result::Result<u8, i32> as std::ops::Try>::Error) -> std::result::Result<u8, i32> {<std::result::Result<u8, i32> as std::ops::Try>::from_error}
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm.rs:24:13: 24:15
-                                           // + literal: Const { ty: fn(<std::result::Result<u8, i32> as std::ops::Try>::Error) -> std::result::Result<u8, i32> {<std::result::Result<u8, i32> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb7: {
-          StorageDead(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
-          goto -> bb5;                     // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      }
   }
   
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit
index 0bd13e009dd..9e840553eca 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit
@@ -4,7 +4,7 @@
   fn map(_1: std::option::Option<std::boxed::Box<()>>) -> std::option::Option<std::boxed::Box<()>> {
       debug x => _1;                       // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:8: 1:9
       let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:31: 1:46
-      let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-     let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
 -     let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
 -     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26
 -     let mut _5: bool;                    // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
@@ -29,21 +29,8 @@
 -                                          // mir::Constant
 -                                          // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
 -                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
-      }
-  
-      bb1: {
+-         _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
           _0 = move _1;                    // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:20: 4:27
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6
-      }
-  
-      bb2: {
-          discriminant(_0) = 0;            // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6
-      }
-  
-      bb3: {
 -         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2
       }
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit
index 0bd13e009dd..9e840553eca 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit
@@ -4,7 +4,7 @@
   fn map(_1: std::option::Option<std::boxed::Box<()>>) -> std::option::Option<std::boxed::Box<()>> {
       debug x => _1;                       // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:8: 1:9
       let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:31: 1:46
-      let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-     let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
 -     let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
 -     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26
 -     let mut _5: bool;                    // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
@@ -29,21 +29,8 @@
 -                                          // mir::Constant
 -                                          // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
 -                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
-      }
-  
-      bb1: {
+-         _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
           _0 = move _1;                    // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:20: 4:27
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6
-      }
-  
-      bb2: {
-          discriminant(_0) = 0;            // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6
-      }
-  
-      bb3: {
 -         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2
       }
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index bb2a4d03734..8cf8b7a4493 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -14,7 +14,7 @@ extern crate rustc_session;
 
 use rustc_driver::plugin::Registry;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
-use rustc_ast::ast;
+use rustc_ast as ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
 declare_lint_pass!(Pass => [TEST_LINT]);
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index 8c517e2bb5d..08b8fb3cbae 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -12,7 +12,7 @@ extern crate rustc_session;
 
 use rustc_driver::plugin::Registry;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintId, LintPass};
-use rustc_ast::ast;
+use rustc_ast as ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
 declare_tool_lint!(
     /// Some docs
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index f0e3ab308e9..8d4101b6526 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -33,7 +33,7 @@ use rustc_session::parse::ParseSess;
 use rustc_span::source_map::{Spanned, DUMMY_SP, FileName};
 use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::Ident;
-use rustc_ast::ast::*;
+use rustc_ast::*;
 use rustc_ast::mut_visit::{self, MutVisitor, visit_clobber};
 use rustc_ast::ptr::P;
 
diff --git a/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs
new file mode 100644
index 00000000000..25dc457d144
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(const_raw_ptr_deref)]
+#![feature(raw_ref_macros)]
+
+use std::ptr;
+
+const fn test_fn(x: *const i32) {
+    let x2 = unsafe { ptr::raw_const!(*x) };
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs
index 0b1ab1c34ff..6462d736ad1 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs
@@ -1,4 +1,4 @@
-const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
+const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } }
 //~^ dereferencing raw pointers in constant functions
 
 const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr
index 97b0a778d2c..427ecff5c6d 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr
@@ -34,15 +34,7 @@ LL |     Foo { x: () }.y
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/min_const_fn_unsafe_bad.rs:1:77
-   |
-LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } }
-   |                                                                             ^^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0133, E0658, E0723.
-For more information about an error, try `rustc --explain E0133`.
+Some errors have detailed explanations: E0658, E0723.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs
new file mode 100644
index 00000000000..be998c80038
--- /dev/null
+++ b/src/test/ui/consts/ptr_comparisons.rs
@@ -0,0 +1,78 @@
+// compile-flags: --crate-type=lib
+// normalize-stderr-32bit: "offset 8" -> "offset $$TWO_WORDS"
+// normalize-stderr-64bit: "offset 16" -> "offset $$TWO_WORDS"
+// normalize-stderr-32bit: "size 4" -> "size $$WORD"
+// normalize-stderr-64bit: "size 8" -> "size $$WORD"
+
+#![feature(
+    const_panic,
+    core_intrinsics,
+    const_raw_ptr_comparison,
+    const_ptr_offset,
+    const_raw_ptr_deref,
+    raw_ref_macros
+)]
+
+const FOO: &usize = &42;
+
+macro_rules! check {
+    (eq, $a:expr, $b:expr) => {
+        pub const _: () =
+            assert!(std::intrinsics::ptr_guaranteed_eq($a as *const u8, $b as *const u8));
+    };
+    (ne, $a:expr, $b:expr) => {
+        pub const _: () =
+            assert!(std::intrinsics::ptr_guaranteed_ne($a as *const u8, $b as *const u8));
+    };
+    (!eq, $a:expr, $b:expr) => {
+        pub const _: () =
+            assert!(!std::intrinsics::ptr_guaranteed_eq($a as *const u8, $b as *const u8));
+    };
+    (!ne, $a:expr, $b:expr) => {
+        pub const _: () =
+            assert!(!std::intrinsics::ptr_guaranteed_ne($a as *const u8, $b as *const u8));
+    };
+}
+
+check!(eq, 0, 0);
+check!(ne, 0, 1);
+check!(!eq, 0, 1);
+check!(!ne, 0, 0);
+check!(ne, FOO as *const _, 0);
+check!(!eq, FOO as *const _, 0);
+// We want pointers to be equal to themselves, but aren't checking this yet because
+// there are some open questions (e.g. whether function pointers to the same function
+// compare equal, they don't necessarily at runtime).
+// The case tested here should work eventually, but does not work yet.
+check!(!eq, FOO as *const _, FOO as *const _);
+check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0);
+check!(!eq, unsafe { (FOO as *const usize).offset(1) }, 0);
+
+check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
+check!(!eq, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
+
+///////////////////////////////////////////////////////////////////////////////
+// If any of the below start compiling, make sure to add a `check` test for it.
+// These invocations exist as canaries so we don't forget to check that the
+// behaviour of `guaranteed_eq` and `guaranteed_ne` is still correct.
+// All of these try to obtain an out of bounds pointer in some manner. If we
+// can create out of bounds pointers, we can offset a pointer far enough that
+// at runtime it would be zero and at compile-time it would not be zero.
+
+const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
+//~^ NOTE
+
+const _: *const u8 =
+//~^ NOTE
+    unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
+//~^ ERROR any use of this value will cause an error
+
+const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
+//~^ ERROR any use of this value will cause an error
+//~| NOTE "pointer-to-integer cast" needs an rfc
+//~| NOTE
+
+const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
+//~^ ERROR any use of this value will cause an error
+//~| NOTE "pointer-to-integer cast" needs an rfc
+//~| NOTE
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
new file mode 100644
index 00000000000..493d9be8f71
--- /dev/null
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -0,0 +1,47 @@
+error: any use of this value will cause an error
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  inbounds test failed: pointer must be in-bounds at offset $TWO_WORDS, but is outside bounds of alloc2 which has size $WORD
+   |                  inside `std::ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  inside `_` at $DIR/ptr_comparisons.rs:62:34
+   | 
+  ::: $DIR/ptr_comparisons.rs:62:1
+   |
+LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
+   | -------------------------------------------------------------------
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: any use of this value will cause an error
+  --> $DIR/ptr_comparisons.rs:67:14
+   |
+LL | / const _: *const u8 =
+LL | |
+LL | |     unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
+   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
+   |                |
+   |                memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: any use of this value will cause an error
+  --> $DIR/ptr_comparisons.rs:70:27
+   |
+LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
+   | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                           |
+   |                           "pointer-to-integer cast" needs an rfc before being allowed inside constants
+
+error: any use of this value will cause an error
+  --> $DIR/ptr_comparisons.rs:75:27
+   |
+LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
+   | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                           |
+   |                           "pointer-to-integer cast" needs an rfc before being allowed inside constants
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/ptr_is_null.rs b/src/test/ui/consts/ptr_is_null.rs
new file mode 100644
index 00000000000..324f59443f7
--- /dev/null
+++ b/src/test/ui/consts/ptr_is_null.rs
@@ -0,0 +1,16 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+#![feature(const_ptr_is_null, const_panic)]
+
+const FOO: &usize = &42;
+
+pub const _: () = assert!(!(FOO as *const usize).is_null());
+
+pub const _: () = assert!(!(42 as *const usize).is_null());
+
+pub const _: () = assert!((0 as *const usize).is_null());
+
+pub const _: () = assert!(std::ptr::null::<usize>().is_null());
+
+pub const _: () = assert!(!("foo" as *const str).is_null());
diff --git a/src/test/ui/hygiene/hir-res-hygiene.rs b/src/test/ui/hygiene/hir-res-hygiene.rs
new file mode 100644
index 00000000000..c26cf5fdb5b
--- /dev/null
+++ b/src/test/ui/hygiene/hir-res-hygiene.rs
@@ -0,0 +1,18 @@
+// check-pass
+// edition:2018
+// aux-build:not-libstd.rs
+
+// Check that paths created in HIR are not affected by in scope names.
+
+extern crate not_libstd as std;
+
+async fn the_future() {
+    async {}.await;
+}
+
+fn main() -> Result<(), ()> {
+    for i in 0..10 {}
+    for j in 0..=10 {}
+    Ok(())?;
+    Ok(())
+}
diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr
index e179feba7a7..11cb72fa2b6 100644
--- a/src/test/ui/range/range-1.stderr
+++ b/src/test/ui/range/range-1.stderr
@@ -17,9 +17,13 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compi
    |
 LL |     let range = *arr..;
    |                 ^^^^^^ doesn't have a size known at compile-time
+   | 
+  ::: $SRC_DIR/core/src/ops/range.rs:LL:COL
+   |
+LL | pub struct RangeFrom<Idx> {
+   |                      --- required by this bound in `std::ops::RangeFrom`
    |
    = help: the trait `std::marker::Sized` is not implemented for `[{integer}]`
-   = note: required by `std::ops::RangeFrom`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs b/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs
new file mode 100644
index 00000000000..cb92ab87a8f
--- /dev/null
+++ b/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs
@@ -0,0 +1,4 @@
+fn main() {}
+fn foo(mut s: String) -> String {
+    s.push_str("asdf") //~ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr b/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr
new file mode 100644
index 00000000000..63e3bb78954
--- /dev/null
+++ b/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/chain-method-call-mutation-in-place.rs:3:5
+   |
+LL | fn foo(mut s: String) -> String {
+   |                          ------ expected `std::string::String` because of return type
+LL |     s.push_str("asdf")
+   |     ^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found `()`
+   |
+note: method `push_str` modifies its receiver in-place
+  --> $DIR/chain-method-call-mutation-in-place.rs:3:7
+   |
+LL |     s.push_str("asdf")
+   |     - ^^^^^^^^ this call modifies `s` in-place
+   |     |
+   |     you probably want to use this value after calling the method...
+   = note: ...instead of the `()` output of method `push_str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs b/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs
index 9c6be50c5c7..4b7016def9d 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs
@@ -4,7 +4,7 @@
 //
 //    error: internal compiler error: get_unique_type_id_of_type() -
 //    unexpected type: closure,
-//    Closure(rustc_ast::ast::DefId{krate: 0, node: 66},
+//    Closure(rustc_ast::DefId{krate: 0, node: 66},
 //    ReScope(63))
 //
 // This is a regression test for issue #17021.
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 376ac55f9c9..76ccf2e4bb9 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -5,7 +5,7 @@ use crate::utils::{
     span_lint_and_sugg, span_lint_and_then, without_block_comments,
 };
 use if_chain::if_chain;
-use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
+use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -570,7 +570,7 @@ declare_lint_pass!(EarlyAttributes => [
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
         check_empty_line_after_outer_attr(cx, item);
     }
 
@@ -580,7 +580,7 @@ impl EarlyLintPass for EarlyAttributes {
     }
 }
 
-fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) {
+fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
     for attr in &item.attrs {
         let attr_item = if let AttrKind::Normal(ref attr) = attr.kind {
             attr
diff --git a/src/tools/clippy/clippy_lints/src/default_trait_access.rs b/src/tools/clippy/clippy_lints/src/default_trait_access.rs
index 874e19d9e9f..067ea903bdd 100644
--- a/src/tools/clippy/clippy_lints/src/default_trait_access.rs
+++ b/src/tools/clippy/clippy_lints/src/default_trait_access.rs
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess {
                             );
                          }
                     },
-                    QPath::TypeRelative(..) => {},
+                    QPath::TypeRelative(..) | QPath::LangItem(..) => {},
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index a1f58e54ae3..90b1a529be7 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let ExprKind::Index(ref array, ref index) = &expr.kind {
             let ty = cx.typeck_results().expr_ty(array);
-            if let Some(range) = higher::range(cx, index) {
+            if let Some(range) = higher::range(index) {
                 // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
                 if let ty::Array(_, s) = ty.kind {
                     let size: u128 = if let Some(size) = s.try_eval_usize(cx.tcx, cx.param_env) {
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index e511d3ea330..129abd7d897 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -171,7 +171,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                 Finite
             }
         },
-        ExprKind::Struct(..) => higher::range(cx, expr).map_or(false, |r| r.end.is_none()).into(),
+        ExprKind::Struct(..) => higher::range(expr).map_or(false, |r| r.end.is_none()).into(),
         _ => Finite,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 00d0b8b4e5b..e5daa30f8ca 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -262,7 +262,7 @@ fn check_len(
 fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     /// Special case ranges until `range_is_empty` is stabilized. See issue 3807.
     fn should_skip_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-        higher::range(cx, expr).map_or(false, |_| {
+        higher::range(expr).map_or(false, |_| {
             !cx.tcx
                 .features()
                 .declared_lib_features
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 6ad525d7620..aa100263640 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -339,7 +339,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
 }
 
 #[doc(hidden)]
-pub fn read_conf(args: &[rustc_ast::ast::NestedMetaItem], sess: &Session) -> Conf {
+pub fn read_conf(args: &[rustc_ast::NestedMetaItem], sess: &Session) -> Conf {
     use std::path::Path;
     match utils::conf::file_from_args(args) {
         Ok(file_name) => {
diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs
index 8352a8a3d2c..8ffcd417d1d 100644
--- a/src/tools/clippy/clippy_lints/src/loops.rs
+++ b/src/tools/clippy/clippy_lints/src/loops.rs
@@ -1003,7 +1003,7 @@ fn detect_manual_memcpy<'tcx>(
         start: Some(start),
         end: Some(end),
         limits,
-    }) = higher::range(cx, arg)
+    }) = higher::range(arg)
     {
         // the var must be a single name
         if let PatKind::Binding(_, canonical_id, _, _) = pat.kind {
@@ -1177,7 +1177,7 @@ fn check_for_loop_range<'tcx>(
         start: Some(start),
         ref end,
         limits,
-    }) = higher::range(cx, arg)
+    }) = higher::range(arg)
     {
         // the var must be a single name
         if let PatKind::Binding(_, canonical_id, ident, _) = pat.kind {
@@ -1679,7 +1679,7 @@ fn check_for_mut_range_bound(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'
         start: Some(start),
         end: Some(end),
         ..
-    }) = higher::range(cx, arg)
+    }) = higher::range(arg)
     {
         let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)];
         if mut_ids[0].is_some() || mut_ids[1].is_some() {
diff --git a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
index 4f8f2cb171d..faa20687ef6 100644
--- a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
+++ b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
@@ -1,7 +1,8 @@
-use crate::utils::{self, is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty};
+use crate::utils::{is_type_diagnostic_item, is_type_lang_item, snippet, span_lint_and_sugg};
+use crate::utils::walk_ptrs_ty;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, MatchSource};
+use rustc_hir::{Expr, ExprKind, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -96,5 +97,5 @@ fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
     let ty = walk_ptrs_ty(ty);
-    match_type(cx, ty, &utils::paths::RANGE_FULL)
+    is_type_lang_item(cx, ty, LangItem::RangeFull)
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 570ae66d595..2265a188855 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -2271,7 +2271,7 @@ fn lint_iter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_
         if_chain! {
             if let hir::ExprKind::Index(ref caller_var, ref index_expr) = &caller_expr.kind;
             if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen })
-                = higher::range(cx, index_expr);
+                = higher::range(index_expr);
             if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind;
             if let ast::LitKind::Int(start_idx, _) = start_lit.node;
             then {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 26a1c32b6b3..482a563572d 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -433,6 +433,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
             return;
         }
         let binding = match expr.kind {
+            ExprKind::Path(hir::QPath::LangItem(..)) => None,
             ExprKind::Path(ref qpath) => {
                 let binding = last_path_segment(qpath).ident.as_str();
                 if binding.starts_with('_') &&
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index f88075798ca..7a75fc125d0 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for Ranges {
                     if let ExprKind::MethodCall(ref iter_path, _, ref iter_args , _) = *iter;
                     if iter_path.ident.name == sym!(iter);
                     // range expression in `.zip()` call: `0..x.len()`
-                    if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
+                    if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg);
                     if is_integer_const(cx, start, 0);
                     // `.len()` call
                     if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind;
@@ -180,7 +180,7 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
             start,
             end: Some(end),
             limits: RangeLimits::HalfOpen
-        }) = higher::range(cx, expr);
+        }) = higher::range(expr);
         if let Some(y) = y_plus_one(cx, end);
         then {
             let span = if expr.span.from_expansion() {
@@ -225,7 +225,7 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
 // inclusive range minus one: `x..=(y-1)`
 fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
+        if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr);
         if let Some(y) = y_minus_one(cx, end);
         then {
             span_lint_and_then(
@@ -279,7 +279,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
     }
 
     if_chain! {
-        if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(cx, expr);
+        if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(expr);
         let ty = cx.typeck_results().expr_ty(start);
         if let ty::Int(_) | ty::Uint(_) = ty.kind;
         if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start);
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 2e853e8301d..58bfd0bc553 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -1,6 +1,6 @@
 use crate::utils::{in_macro, span_lint_and_sugg};
 use if_chain::if_chain;
-use rustc_ast::ast::{Item, ItemKind, UseTreeKind};
+use rustc_ast::{Item, ItemKind, UseTreeKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index bada6fa7c52..7a659bf779c 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -161,7 +161,7 @@ declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]);
 impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use crate::utils::{snippet, snippet_with_applicability};
-        use rustc_ast::ast::LitKind;
+        use rustc_ast::LitKind;
 
         if_chain! {
             if let ExprKind::MethodCall(path, _, args, _) = &e.kind;
diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs
index 7b5e92eb5ee..28fd55f6ff0 100644
--- a/src/tools/clippy/clippy_lints/src/transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute.rs
@@ -3,7 +3,7 @@ use crate::utils::{
     span_lint_and_then, sugg,
 };
 use if_chain::if_chain;
-use rustc_ast::ast;
+use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs
index fbf7f0b2517..d60306336c6 100644
--- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs
@@ -1,7 +1,7 @@
 use crate::consts::{constant_context, Constant};
 use crate::utils::{match_qpath, paths, span_lint};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
+use rustc_ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs
index 3bd73d9f21a..a74104e9282 100644
--- a/src/tools/clippy/clippy_lints/src/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/try_err.rs
@@ -1,10 +1,10 @@
 use crate::utils::{
-    is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet, snippet_with_macro_callsite,
-    span_lint_and_sugg,
+    is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet,
+    snippet_with_macro_callsite, span_lint_and_sugg,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, MatchSource};
+use rustc_hir::{Expr, ExprKind, QPath, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
             if let ExprKind::Match(ref match_arg, _, MatchSource::TryDesugar) = expr.kind;
             if let ExprKind::Call(ref match_fun, ref try_args) = match_arg.kind;
             if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
-            if match_qpath(match_fun_path, &paths::TRY_INTO_RESULT);
+            if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _));
             if let Some(ref try_arg) = try_args.get(0);
             if let ExprKind::Call(ref err_fun, ref err_args) = try_arg.kind;
             if let Some(ref err_arg) = err_args.get(0);
diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs
index c3dea447521..0fd70550fa0 100644
--- a/src/tools/clippy/clippy_lints/src/types.rs
+++ b/src/tools/clippy/clippy_lints/src/types.rs
@@ -5,7 +5,7 @@ use std::cmp::Ordering;
 use std::collections::BTreeMap;
 
 use if_chain::if_chain;
-use rustc_ast::ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy};
+use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
@@ -475,6 +475,7 @@ impl Types {
                             }
                         }
                     },
+                    QPath::LangItem(..) => {},
                 }
             },
             TyKind::Rptr(ref lt, ref mut_ty) => self.check_ty_rptr(cx, hir_ty, is_local, lt, mut_ty),
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 502bf0c4279..b7e2eba0a81 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -2,7 +2,7 @@
 
 use crate::utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path};
 use crate::utils::{over, span_lint_and_then};
-use rustc_ast::ast::{self, Pat, PatKind, PatKind::*, DUMMY_NODE_ID};
+use rustc_ast::{self as ast, Pat, PatKind, PatKind::*, DUMMY_NODE_ID};
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast_pretty::pprust;
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index 1580f657d77..43166d26787 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -1,4 +1,4 @@
-use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint};
+use crate::utils::{is_try, match_trait_method, paths, span_lint};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -42,10 +42,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
         match expr.kind {
             hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => {
                 if let hir::ExprKind::Call(ref func, ref args) = res.kind {
-                    if let hir::ExprKind::Path(ref path) = func.kind {
-                        if match_qpath(path, &paths::TRY_INTO_RESULT) && args.len() == 1 {
-                            check_method_call(cx, &args[0], expr);
-                        }
+                    if matches!(
+                        func.kind,
+                        hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _))
+                    ) {
+                        check_method_call(cx, &args[0], expr);
                     }
                 } else {
                     check_method_call(cx, res, expr);
diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
index ad02bc5fd8e..c32c80dcd3c 100644
--- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
@@ -5,7 +5,7 @@
 #![allow(clippy::similar_names, clippy::wildcard_imports, clippy::enum_glob_use)]
 
 use crate::utils::{both, over};
-use rustc_ast::ast::{self, *};
+use rustc_ast::{self as ast, *};
 use rustc_ast::ptr::P;
 use rustc_span::symbol::Ident;
 use std::mem;
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 128fa87a162..9b7a268c628 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -175,9 +175,19 @@ impl PrintVisitor {
     }
 
     fn print_qpath(&mut self, path: &QPath<'_>) {
-        print!("    if match_qpath({}, &[", self.current);
-        print_path(path, &mut true);
-        println!("]);");
+        match  *path {
+            QPath::LangItem(lang_item, _) => {
+                println!(
+                    "    if matches!({}, QPath::LangItem(LangItem::{:?}, _));",
+                   self.current, lang_item,
+                );
+            },
+            _ => {
+                print!("    if match_qpath({}, &[", self.current);
+                print_path(path, &mut true);
+                println!("]);");
+            },
+        }
     }
 }
 
@@ -760,5 +770,6 @@ fn print_path(path: &QPath<'_>, first: &mut bool) {
             },
             ref other => print!("/* unimplemented: {:?}*/", other),
         },
+        QPath::LangItem(..) => panic!("print_path: called for lang item qpath"),
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/higher.rs b/src/tools/clippy/clippy_lints/src/utils/higher.rs
index f81a132c7e7..ba15456014d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/higher.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/higher.rs
@@ -3,12 +3,11 @@
 
 #![deny(clippy::missing_docs_in_private_items)]
 
-use crate::utils::{is_expn_of, match_def_path, match_qpath, paths};
+use crate::utils::{is_expn_of, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_middle::ty;
 
 /// Converts a hir binary operator to the corresponding `ast` type.
 #[must_use]
@@ -47,7 +46,7 @@ pub struct Range<'a> {
 }
 
 /// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
-pub fn range<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a hir::Expr<'_>) -> Option<Range<'a>> {
+pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> {
     /// Finds the field named `name` in the field. Always return `Some` for
     /// convenience.
     fn get_field<'c>(name: &str, fields: &'c [hir::Field<'_>]) -> Option<&'c hir::Expr<'c>> {
@@ -56,94 +55,43 @@ pub fn range<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a hir::Expr<'_>) -> Optio
         Some(expr)
     }
 
-    let def_path = match cx.typeck_results().expr_ty(expr).kind {
-        ty::Adt(def, _) => cx.tcx.def_path(def.did),
-        _ => return None,
-    };
-
-    // sanity checks for std::ops::RangeXXXX
-    if def_path.data.len() != 3 {
-        return None;
-    }
-    if def_path.data.get(0)?.data.as_symbol() != sym!(ops) {
-        return None;
-    }
-    if def_path.data.get(1)?.data.as_symbol() != sym!(range) {
-        return None;
-    }
-    let type_name = def_path.data.get(2)?.data.as_symbol();
-    let range_types = [
-        "RangeFrom",
-        "RangeFull",
-        "RangeInclusive",
-        "Range",
-        "RangeTo",
-        "RangeToInclusive",
-    ];
-    if !range_types.contains(&&*type_name.as_str()) {
-        return None;
-    }
-
-    // The range syntax is expanded to literal paths starting with `core` or `std`
-    // depending on
-    // `#[no_std]`. Testing both instead of resolving the paths.
-
     match expr.kind {
-        hir::ExprKind::Path(ref path) => {
-            if match_qpath(path, &paths::RANGE_FULL_STD) || match_qpath(path, &paths::RANGE_FULL) {
-                Some(Range {
+        hir::ExprKind::Call(ref path, ref args) if matches!(
+            path.kind,
+            hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, _))
+        ) => Some(Range {
+            start: Some(&args[0]),
+            end: Some(&args[1]),
+            limits: ast::RangeLimits::Closed,
+        }),
+        hir::ExprKind::Struct(ref path, ref fields, None) => {
+            match path {
+                hir::QPath::LangItem(hir::LangItem::RangeFull, _) => Some(Range {
                     start: None,
                     end: None,
                     limits: ast::RangeLimits::HalfOpen,
-                })
-            } else {
-                None
-            }
-        },
-        hir::ExprKind::Call(ref path, ref args) => {
-            if let hir::ExprKind::Path(ref path) = path.kind {
-                if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW)
-                {
-                    Some(Range {
-                        start: Some(&args[0]),
-                        end: Some(&args[1]),
-                        limits: ast::RangeLimits::Closed,
-                    })
-                } else {
-                    None
-                }
-            } else {
-                None
-            }
-        },
-        hir::ExprKind::Struct(ref path, ref fields, None) => {
-            if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) {
-                Some(Range {
+                }),
+                hir::QPath::LangItem(hir::LangItem::RangeFrom, _) => Some(Range {
                     start: Some(get_field("start", fields)?),
                     end: None,
                     limits: ast::RangeLimits::HalfOpen,
-                })
-            } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) {
-                Some(Range {
+                }),
+                hir::QPath::LangItem(hir::LangItem::Range, _) => Some(Range {
                     start: Some(get_field("start", fields)?),
                     end: Some(get_field("end", fields)?),
                     limits: ast::RangeLimits::HalfOpen,
-                })
-            } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE)
-            {
-                Some(Range {
+                }),
+                hir::QPath::LangItem(hir::LangItem::RangeToInclusive, _) => Some(Range {
                     start: None,
                     end: Some(get_field("end", fields)?),
                     limits: ast::RangeLimits::Closed,
-                })
-            } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) {
-                Some(Range {
+                }),
+                hir::QPath::LangItem(hir::LangItem::RangeTo, _) => Some(Range {
                     start: None,
                     end: Some(get_field("end", fields)?),
                     limits: ast::RangeLimits::HalfOpen,
-                })
-            } else {
-                None
+                }),
+                _ => None,
             }
         },
         _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
index 28fb6ed12a0..2eefd4a38a6 100644
--- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
@@ -3,9 +3,9 @@ use crate::utils::differing_macro_contexts;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::{
-    BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FnRetTy, GenericArg,
-    GenericArgs, Guard, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path, PathSegment, QPath,
-    Stmt, StmtKind, Ty, TyKind, TypeBinding,
+    BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FieldPat,
+    FnRetTy, GenericArg, GenericArgs, Guard, InlineAsmOperand, Lifetime, LifetimeName, ParamName,
+    Pat, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
 };
 use rustc_lint::LateContext;
 use rustc_middle::ich::StableHashingContextProvider;
@@ -185,10 +185,20 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
         left.name == right.name
     }
 
+    pub fn eq_fieldpat(&mut self, left: &FieldPat<'_>, right: &FieldPat<'_>) -> bool {
+        match (&left, &right) {
+            (FieldPat { ident: li, pat: lp, .. }, FieldPat { ident: ri, pat: rp, .. }) =>
+                li.name.as_str() == ri.name.as_str() && self.eq_pat(lp, rp),
+        }
+    }
+
     /// Checks whether two patterns are the same.
     pub fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
         match (&left.kind, &right.kind) {
             (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
+            (&PatKind::Struct(ref lp, ref la, ..), &PatKind::Struct(ref rp, ref ra, ..)) => {
+                self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_fieldpat(l, r))
+            },
             (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => {
                 self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
             },
@@ -223,6 +233,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
             (&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => {
                 self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
             },
+            (&QPath::LangItem(llang_item, _), &QPath::LangItem(rlang_item, _)) =>
+                llang_item == rlang_item,
             _ => false,
         }
     }
@@ -601,6 +613,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             QPath::TypeRelative(_, ref path) => {
                 self.hash_name(path.ident.name);
             },
+            QPath::LangItem(lang_item, ..) => {
+                lang_item.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+            }
         }
         // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
     }
@@ -710,6 +725,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_ty(ty);
                     segment.ident.name.hash(&mut self.s);
                 },
+                QPath::LangItem(lang_item, ..) => {
+                    lang_item.hash(&mut self.s);
+                }
             },
             TyKind::OpaqueDef(_, arg_list) => {
                 self.hash_generic_args(arg_list);
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index d8fa1fa278e..4701a3f26e6 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -266,6 +266,9 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}Relative Path, {:?}", ind, ty);
             println!("{}seg: {:?}", ind, seg);
         },
+        hir::ExprKind::Path(hir::QPath::LangItem(lang_item, ..)) => {
+            println!("{}Lang Item Path, {:?}", ind, lang_item.name());
+        },
         hir::ExprKind::AddrOf(kind, ref muta, ref e) => {
             println!("{}AddrOf", ind);
             println!("kind: {:?}", kind);
@@ -488,6 +491,9 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) {
             println!("{}Relative Path, {:?}", ind, ty);
             println!("{}seg: {:?}", ind, seg);
         },
+        hir::PatKind::Path(hir::QPath::LangItem(lang_item, ..)) => {
+            println!("{}Lang Item Path, {:?}", ind, lang_item.name());
+        },
         hir::PatKind::Tuple(pats, opt_dots_position) => {
             println!("{}Tuple", ind);
             if let Some(dot_position) = opt_dots_position {
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 223628cc610..a56b8203513 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -142,6 +142,14 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb
     }
 }
 
+/// Checks if the type is equal to a lang item
+pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
+    match ty.kind {
+        ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did,
+        _ => false,
+    }
+}
+
 /// Checks if the method call given in `expr` belongs to the given trait.
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
     let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
@@ -163,6 +171,7 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
     match *path {
         QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"),
         QPath::TypeRelative(_, ref seg) => seg,
+        QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
     }
 }
 
@@ -170,6 +179,7 @@ pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment
     match *path {
         QPath::Resolved(_, ref path) => path.segments.get(0),
         QPath::TypeRelative(_, ref seg) => Some(seg),
+        QPath::LangItem(..) => None,
     }
 }
 
@@ -196,6 +206,7 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
             },
             _ => false,
         },
+        QPath::LangItem(..) => false,
     }
 }
 
@@ -277,7 +288,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<def::Res> {
 pub fn qpath_res(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
     match qpath {
         hir::QPath::Resolved(_, path) => path.res,
-        hir::QPath::TypeRelative(..) => {
+        hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
             if cx.tcx.has_typeck_results(id.owner.to_def_id()) {
                 cx.tcx.typeck(id.owner.to_def_id().expect_local()).qpath_res(qpath, id)
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs
index 923b319d777..9c28d63d414 100644
--- a/src/tools/clippy/clippy_lints/src/utils/paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs
@@ -84,19 +84,7 @@ pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
 pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
 pub const PTR_NULL: [&str; 2] = ["ptr", "null"];
 pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"];
-pub const RANGE: [&str; 3] = ["core", "ops", "Range"];
 pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
-pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"];
-pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"];
-pub const RANGE_FULL: [&str; 4] = ["core", "ops", "range", "RangeFull"];
-pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"];
-pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"];
-pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"];
-pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"];
-pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"];
-pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"];
-pub const RANGE_TO_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeToInclusive"];
-pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"];
 pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
 pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
 pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
@@ -130,7 +118,6 @@ pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];
 pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
 pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
 pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
-pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
 pub const TRY_INTO_TRAIT: [&str; 3] = ["core", "convert", "TryInto"];
 pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
 pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
diff --git a/src/tools/clippy/clippy_lints/src/utils/sugg.rs b/src/tools/clippy/clippy_lints/src/utils/sugg.rs
index 0ac7714fbeb..2955f8d8e59 100644
--- a/src/tools/clippy/clippy_lints/src/utils/sugg.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/sugg.rs
@@ -42,7 +42,7 @@ impl<'a> Sugg<'a> {
     pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> {
         snippet_opt(cx, expr.span).map(|snippet| {
             let snippet = Cow::Owned(snippet);
-            Self::hir_from_snippet(cx, expr, snippet)
+            Self::hir_from_snippet(expr, snippet)
         })
     }
 
@@ -80,13 +80,13 @@ impl<'a> Sugg<'a> {
     pub fn hir_with_macro_callsite(cx: &LateContext<'_>, expr: &hir::Expr<'_>, default: &'a str) -> Self {
         let snippet = snippet_with_macro_callsite(cx, expr.span, default);
 
-        Self::hir_from_snippet(cx, expr, snippet)
+        Self::hir_from_snippet(expr, snippet)
     }
 
     /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*`
     /// function variants of `Sugg`, since these use different snippet functions.
-    fn hir_from_snippet(cx: &LateContext<'_>, expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self {
-        if let Some(range) = higher::range(cx, expr) {
+    fn hir_from_snippet(expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self {
+        if let Some(range) = higher::range(expr) {
             let op = match range.limits {
                 ast::RangeLimits::HalfOpen => AssocOp::DotDot,
                 ast::RangeLimits::Closed => AssocOp::DotDotEq,
diff --git a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
index 58e7c354b27..d2494b321ef 100644
--- a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
@@ -7,7 +7,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
 
 use crate::utils::{match_def_path, paths};
-use rustc_ast::ast::LitKind;
+use rustc_ast::LitKind;
 use rustc_hir as hir;
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/tests/ui/author/for_loop.stdout b/src/tools/clippy/tests/ui/author/for_loop.stdout
index 81ede955347..3bf7607c62f 100644
--- a/src/tools/clippy/tests/ui/author/for_loop.stdout
+++ b/src/tools/clippy/tests/ui/author/for_loop.stdout
@@ -3,10 +3,10 @@ if_chain! {
     if let ExprKind::Match(ref expr1, ref arms, MatchSource::ForLoopDesugar) = expr.kind;
     if let ExprKind::Call(ref func, ref args) = expr1.kind;
     if let ExprKind::Path(ref path) = func.kind;
-    if match_qpath(path, &["{{root}}", "std", "iter", "IntoIterator", "into_iter"]);
+    if matches!(path, QPath::LangItem(LangItem::IntoIterIntoIter, _));
     if args.len() == 1;
     if let ExprKind::Struct(ref path1, ref fields, None) = args[0].kind;
-    if match_qpath(path1, &["{{root}}", "std", "ops", "Range"]);
+    if matches!(path1, QPath::LangItem(LangItem::Range, _));
     if fields.len() == 2;
     // unimplemented: field checks
     if arms.len() == 1;
@@ -20,7 +20,7 @@ if_chain! {
     if let ExprKind::Match(ref expr2, ref arms1, MatchSource::ForLoopDesugar) = e.kind;
     if let ExprKind::Call(ref func1, ref args1) = expr2.kind;
     if let ExprKind::Path(ref path2) = func1.kind;
-    if match_qpath(path2, &["{{root}}", "std", "iter", "Iterator", "next"]);
+    if matches!(path2, QPath::LangItem(LangItem::IteratorNext, _));
     if args1.len() == 1;
     if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, ref inner) = args1[0].kind;
     if let ExprKind::Path(ref path3) = inner.kind;
@@ -31,13 +31,15 @@ if_chain! {
     if match_qpath(path4, &["__next"]);
     if let ExprKind::Path(ref path5) = value.kind;
     if match_qpath(path5, &["val"]);
-    if let PatKind::TupleStruct(ref path6, ref fields1, None) = arms1[0].pat.kind;
-    if match_qpath(path6, &["{{root}}", "std", "option", "Option", "Some"]);
+    if let PatKind::Struct(ref path6, ref fields1, false) = arms1[0].pat.kind;
+    if matches!(path6, QPath::LangItem(LangItem::OptionSome, _));
     if fields1.len() == 1;
     // unimplemented: field checks
     if let ExprKind::Break(ref destination, None) = arms1[1].body.kind;
-    if let PatKind::Path(ref path7) = arms1[1].pat.kind;
-    if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]);
+    if let PatKind::Struct(ref path7, ref fields2, false) = arms1[1].pat.kind;
+    if matches!(path7, QPath::LangItem(LangItem::OptionNone, _));
+    if fields2.len() == 0;
+    // unimplemented: field checks
     if let StmtKind::Local(ref local1) = body.stmts[2].kind;
     if let Some(ref init) = local1.init;
     if let ExprKind::Path(ref path8) = init.kind;