about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/bootstrap.py45
-rw-r--r--src/bootstrap/bootstrap_test.py4
-rw-r--r--src/bootstrap/builder.rs52
-rw-r--r--src/bootstrap/compile.rs2
-rw-r--r--src/bootstrap/config.rs11
-rw-r--r--src/bootstrap/flags.rs26
-rw-r--r--src/bootstrap/format.rs64
-rw-r--r--src/bootstrap/lib.rs5
-rw-r--r--src/bootstrap/test.rs8
-rw-r--r--src/bootstrap/util.rs4
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/rust-by-example0
-rw-r--r--src/liballoc/boxed.rs8
-rw-r--r--src/liballoc/collections/mod.rs2
-rw-r--r--src/liballoc/fmt.rs2
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/liballoc/raw_vec.rs2
-rw-r--r--src/liballoc/rc.rs10
-rw-r--r--src/liballoc/sync.rs10
-rw-r--r--src/libcore/any.rs3
-rw-r--r--src/libcore/array/mod.rs6
-rw-r--r--src/libcore/char/convert.rs2
-rw-r--r--src/libcore/clone.rs4
-rw-r--r--src/libcore/cmp.rs2
-rw-r--r--src/libcore/ffi.rs4
-rw-r--r--src/libcore/fmt/mod.rs14
-rw-r--r--src/libcore/hash/mod.rs2
-rw-r--r--src/libcore/hash/sip.rs10
-rw-r--r--src/libcore/internal_macros.rs2
-rw-r--r--src/libcore/intrinsics.rs6
-rw-r--r--src/libcore/macros/mod.rs2
-rw-r--r--src/libcore/mem/maybe_uninit.rs8
-rw-r--r--src/libcore/mem/mod.rs2
-rw-r--r--src/libcore/num/bignum.rs2
-rw-r--r--src/libcore/num/dec2flt/mod.rs4
-rw-r--r--src/libcore/num/diy_float.rs2
-rw-r--r--src/libcore/num/flt2dec/mod.rs2
-rw-r--r--src/libcore/num/mod.rs4
-rw-r--r--src/libcore/ops/deref.rs6
-rw-r--r--src/libcore/ops/mod.rs4
-rw-r--r--src/libcore/ops/range.rs5
-rw-r--r--src/libcore/ops/unsize.rs10
-rw-r--r--src/libcore/panic.rs8
-rw-r--r--src/libcore/panicking.rs2
-rw-r--r--src/libcore/pin.rs2
-rw-r--r--src/libcore/ptr/const_ptr.rs755
-rw-r--r--src/libcore/ptr/mod.rs1704
-rw-r--r--src/libcore/ptr/mut_ptr.rs925
-rw-r--r--src/libcore/ptr/non_null.rs4
-rw-r--r--src/libcore/ptr/unique.rs28
-rw-r--r--src/libcore/slice/mod.rs16
-rw-r--r--src/libcore/str/lossy.rs6
-rw-r--r--src/libcore/str/mod.rs8
-rw-r--r--src/libcore/tests/lib.rs3
-rw-r--r--src/libcore/tests/ptr.rs11
-rw-r--r--src/libcore/unicode/mod.rs2
-rw-r--r--src/libprofiler_builtins/lib.rs2
-rw-r--r--src/librustc/arena.rs16
-rw-r--r--src/librustc/hir/check_attr.rs36
-rw-r--r--src/librustc/hir/def.rs2
-rw-r--r--src/librustc/hir/intravisit.rs81
-rw-r--r--src/librustc/hir/itemlikevisit.rs24
-rw-r--r--src/librustc/hir/lowering.rs190
-rw-r--r--src/librustc/hir/lowering/expr.rs30
-rw-r--r--src/librustc/hir/lowering/item.rs344
-rw-r--r--src/librustc/hir/map/blocks.rs6
-rw-r--r--src/librustc/hir/map/collector.rs18
-rw-r--r--src/librustc/hir/map/hir_id_validator.rs6
-rw-r--r--src/librustc/hir/map/mod.rs52
-rw-r--r--src/librustc/hir/mod.rs189
-rw-r--r--src/librustc/hir/pat_util.rs5
-rw-r--r--src/librustc/hir/print.rs52
-rw-r--r--src/librustc/ich/hcx.rs6
-rw-r--r--src/librustc/ich/impls_hir.rs10
-rw-r--r--src/librustc/infer/error_reporting/mod.rs8
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs6
-rw-r--r--src/librustc/lint/context.rs24
-rw-r--r--src/librustc/lint/internal.rs2
-rw-r--r--src/librustc/lint/mod.rs64
-rw-r--r--src/librustc/middle/diagnostic_items.rs6
-rw-r--r--src/librustc/middle/lang_items.rs6
-rw-r--r--src/librustc/middle/lib_features.rs2
-rw-r--r--src/librustc/middle/reachable.rs10
-rw-r--r--src/librustc/middle/region.rs16
-rw-r--r--src/librustc/middle/resolve_lifetime.rs12
-rw-r--r--src/librustc/middle/stability.rs32
-rw-r--r--src/librustc/middle/weak_lang_items.rs2
-rw-r--r--src/librustc/mir/interpret/allocation.rs4
-rw-r--r--src/librustc/mir/mod.rs37
-rw-r--r--src/librustc/mir/tcx.rs15
-rw-r--r--src/librustc/mir/visit.rs16
-rw-r--r--src/librustc/traits/error_reporting.rs14
-rw-r--r--src/librustc/traits/mod.rs7
-rw-r--r--src/librustc/traits/project.rs26
-rw-r--r--src/librustc/traits/select.rs4
-rw-r--r--src/librustc/traits/structural_impls.rs9
-rw-r--r--src/librustc/ty/adjustment.rs12
-rw-r--r--src/librustc/ty/binding.rs8
-rw-r--r--src/librustc/ty/cast.rs3
-rw-r--r--src/librustc/ty/context.rs8
-rw-r--r--src/librustc/ty/error.rs4
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/mod.rs12
-rw-r--r--src/librustc/ty/print/obsolete.rs4
-rw-r--r--src/librustc/ty/print/pretty.rs4
-rw-r--r--src/librustc/ty/relate.rs4
-rw-r--r--src/librustc/ty/sty.rs10
-rw-r--r--src/librustc/ty/subst.rs5
-rw-r--r--src/librustc/ty/util.rs4
-rw-r--r--src/librustc/ty/wf.rs4
-rw-r--r--src/librustc_asan/lib.rs2
-rw-r--r--src/librustc_codegen_llvm/attributes.rs11
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs124
-rw-r--r--src/librustc_codegen_llvm/common.rs2
-rw-r--r--src/librustc_codegen_llvm/consts.rs4
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs2
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs48
-rw-r--r--src/librustc_codegen_ssa/debuginfo/type_names.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs58
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs28
-rw-r--r--src/librustc_codegen_utils/symbol_names/v0.rs8
-rw-r--r--src/librustc_codegen_utils/symbol_names_test.rs6
-rw-r--r--src/librustc_driver/pretty.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0120.md10
-rw-r--r--src/librustc_error_codes/error_codes/E0121.md24
-rw-r--r--src/librustc_error_codes/error_codes/E0734.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0743.md16
-rw-r--r--src/librustc_error_codes/error_codes/E0745.md2
-rw-r--r--src/librustc_fs_util/lib.rs37
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs8
-rw-r--r--src/librustc_incremental/assert_module_sources.rs2
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs6
-rw-r--r--src/librustc_interface/passes.rs17
-rw-r--r--src/librustc_interface/proc_macro_decls.rs6
-rw-r--r--src/librustc_interface/queries.rs7
-rw-r--r--src/librustc_interface/util.rs32
-rw-r--r--src/librustc_lint/builtin.rs85
-rw-r--r--src/librustc_lint/nonstandard_style.rs22
-rw-r--r--src/librustc_lint/types.rs4
-rw-r--r--src/librustc_lint/unused.rs10
-rw-r--r--src/librustc_lsan/lib.rs2
-rw-r--r--src/librustc_metadata/foreign_modules.rs6
-rw-r--r--src/librustc_metadata/link_args.rs6
-rw-r--r--src/librustc_metadata/native_libs.rs6
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs4
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs46
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs6
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs37
-rw-r--r--src/librustc_mir/borrow_check/invalidation.rs18
-rw-r--r--src/librustc_mir/borrow_check/mod.rs35
-rw-r--r--src/librustc_mir/borrow_check/place_ext.rs4
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs6
-rw-r--r--src/librustc_mir/borrow_check/prefixes.rs4
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs147
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs61
-rw-r--r--src/librustc_mir/build/expr/as_place.rs1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs1
-rw-r--r--src/librustc_mir/build/expr/category.rs1
-rw-r--r--src/librustc_mir/build/expr/into.rs13
-rw-r--r--src/librustc_mir/build/mod.rs4
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs32
-rw-r--r--src/librustc_mir/hair/cx/expr.rs97
-rw-r--r--src/librustc_mir/hair/mod.rs5
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs9
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs6
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs171
-rw-r--r--src/librustc_mir/interpret/intern.rs47
-rw-r--r--src/librustc_mir/interpret/memory.rs6
-rw-r--r--src/librustc_mir/interpret/operand.rs18
-rw-r--r--src/librustc_mir/interpret/place.rs11
-rw-r--r--src/librustc_mir/interpret/step.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs8
-rw-r--r--src/librustc_mir/shim.rs4
-rw-r--r--src/librustc_mir/transform/add_retag.rs18
-rw-r--r--src/librustc_mir/transform/check_consts/mod.rs4
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs17
-rw-r--r--src/librustc_mir/transform/check_consts/qualifs.rs18
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs112
-rw-r--r--src/librustc_mir/transform/const_prop.rs54
-rw-r--r--src/librustc_mir/transform/generator.rs4
-rw-r--r--src/librustc_mir/transform/inline.rs30
-rw-r--r--src/librustc_mir/transform/mod.rs2
-rw-r--r--src/librustc_mir/transform/promote_consts.rs24
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs10
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs65
-rw-r--r--src/librustc_mir/util/liveness.rs2
-rw-r--r--src/librustc_msan/lib.rs2
-rw-r--r--src/librustc_parse/config.rs8
-rw-r--r--src/librustc_parse/lib.rs6
-rw-r--r--src/librustc_parse/parser/attr.rs23
-rw-r--r--src/librustc_parse/parser/diagnostics.rs67
-rw-r--r--src/librustc_parse/parser/expr.rs822
-rw-r--r--src/librustc_parse/parser/item.rs301
-rw-r--r--src/librustc_parse/parser/mod.rs79
-rw-r--r--src/librustc_parse/parser/pat.rs27
-rw-r--r--src/librustc_parse/parser/path.rs9
-rw-r--r--src/librustc_parse/parser/stmt.rs448
-rw-r--r--src/librustc_parse/parser/ty.rs587
-rw-r--r--src/librustc_passes/ast_validation.rs165
-rw-r--r--src/librustc_passes/check_const.rs8
-rw-r--r--src/librustc_passes/dead.rs40
-rw-r--r--src/librustc_passes/entry.rs10
-rw-r--r--src/librustc_passes/hir_stats.rs24
-rw-r--r--src/librustc_passes/layout_test.rs8
-rw-r--r--src/librustc_passes/liveness.rs6
-rw-r--r--src/librustc_plugin_impl/build.rs6
-rw-r--r--src/librustc_privacy/lib.rs60
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs18
-rw-r--r--src/librustc_resolve/def_collector.rs33
-rw-r--r--src/librustc_resolve/late.rs28
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs38
-rw-r--r--src/librustc_save_analysis/lib.rs6
-rw-r--r--src/librustc_save_analysis/sig.rs10
-rw-r--r--src/librustc_session/options.rs2
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/builtin.rs4
-rw-r--r--src/librustc_traits/lowering/mod.rs8
-rw-r--r--src/librustc_tsan/lib.rs2
-rw-r--r--src/librustc_typeck/astconv.rs86
-rw-r--r--src/librustc_typeck/check/_match.rs4
-rw-r--r--src/librustc_typeck/check/callee.rs4
-rw-r--r--src/librustc_typeck/check/cast.rs80
-rw-r--r--src/librustc_typeck/check/closure.rs16
-rw-r--r--src/librustc_typeck/check/coercion.rs20
-rw-r--r--src/librustc_typeck/check/compare_method.rs180
-rw-r--r--src/librustc_typeck/check/demand.rs20
-rw-r--r--src/librustc_typeck/check/dropck.rs156
-rw-r--r--src/librustc_typeck/check/expr.rs4
-rw-r--r--src/librustc_typeck/check/generator_interior.rs21
-rw-r--r--src/librustc_typeck/check/intrinsic.rs28
-rw-r--r--src/librustc_typeck/check/method/confirm.rs10
-rw-r--r--src/librustc_typeck/check/method/probe.rs8
-rw-r--r--src/librustc_typeck/check/method/suggest.rs14
-rw-r--r--src/librustc_typeck/check/mod.rs149
-rw-r--r--src/librustc_typeck/check/op.rs8
-rw-r--r--src/librustc_typeck/check/pat.rs95
-rw-r--r--src/librustc_typeck/check/regionck.rs10
-rw-r--r--src/librustc_typeck/check/upvar.rs6
-rw-r--r--src/librustc_typeck/check/wfcheck.rs22
-rw-r--r--src/librustc_typeck/check/writeback.rs16
-rw-r--r--src/librustc_typeck/check_unused.rs12
-rw-r--r--src/librustc_typeck/coherence/builtin.rs2
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs12
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs6
-rw-r--r--src/librustc_typeck/coherence/orphan.rs6
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs8
-rw-r--r--src/librustc_typeck/collect.rs154
-rw-r--r--src/librustc_typeck/constrained_generic_params.rs2
-rw-r--r--src/librustc_typeck/expr_use_visitor.rs4
-rw-r--r--src/librustc_typeck/impl_wf_check.rs6
-rw-r--r--src/librustc_typeck/namespace.rs4
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs6
-rw-r--r--src/librustc_typeck/outlives/test.rs6
-rw-r--r--src/librustc_typeck/variance/constraints.rs14
-rw-r--r--src/librustc_typeck/variance/terms.rs10
-rw-r--r--src/librustc_typeck/variance/test.rs6
-rw-r--r--src/librustdoc/clean/mod.rs31
-rw-r--r--src/librustdoc/doctree.rs21
-rw-r--r--src/librustdoc/visit_ast.rs20
-rw-r--r--src/libstd/alloc.rs4
-rw-r--r--src/libstd/ffi/c_str.rs2
-rw-r--r--src/libstd/io/mod.rs2
-rw-r--r--src/libstd/io/stdio.rs8
-rw-r--r--src/libstd/panic.rs2
-rw-r--r--src/libstd/panicking.rs6
-rw-r--r--src/libstd/rt.rs2
-rw-r--r--src/libstd/sys/hermit/fast_thread_local.rs2
-rw-r--r--src/libstd/sys/hermit/fd.rs2
-rw-r--r--src/libstd/sys/mod.rs4
-rw-r--r--src/libstd/sys/unix/fast_thread_local.rs2
-rw-r--r--src/libstd/sys/unix/fd.rs2
-rw-r--r--src/libstd/sys/vxworks/fast_thread_local.rs2
-rw-r--r--src/libstd/sys/vxworks/fd.rs2
-rw-r--r--src/libstd/sys/wasi/ext/fs.rs2
-rw-r--r--src/libstd/sys/wasi/ext/io.rs2
-rw-r--r--src/libstd/sys/wasm/fast_thread_local.rs2
-rw-r--r--src/libstd/sys/windows/c.rs2
-rw-r--r--src/libstd/sys/windows/ext/fs.rs8
-rw-r--r--src/libstd/sys/windows/fast_thread_local.rs2
-rw-r--r--src/libstd/sys/windows/handle.rs2
-rw-r--r--src/libstd/sys/windows/net.rs4
-rw-r--r--src/libstd/sys/windows/process.rs2
-rw-r--r--src/libstd/sys/windows/stdio.rs2
-rw-r--r--src/libstd/sys/windows/stdio_uwp.rs2
-rw-r--r--src/libstd/sys_common/process.rs2
-rw-r--r--src/libstd/sys_common/thread_local.rs2
-rw-r--r--src/libstd/thread/local.rs6
-rw-r--r--src/libstd/thread/mod.rs6
-rw-r--r--src/libsyntax/ast.rs108
-rw-r--r--src/libsyntax/attr/builtin.rs6
-rw-r--r--src/libsyntax/attr/mod.rs7
-rw-r--r--src/libsyntax/feature_gate/check.rs42
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/mut_visit.rs69
-rw-r--r--src/libsyntax/print/pprust.rs204
-rw-r--r--src/libsyntax/token.rs4
-rw-r--r--src/libsyntax/util/node_count.rs8
-rw-r--r--src/libsyntax/visit.rs70
-rw-r--r--src/libsyntax_expand/base.rs27
-rw-r--r--src/libsyntax_expand/build.rs21
-rw-r--r--src/libsyntax_expand/expand.rs20
-rw-r--r--src/libsyntax_expand/mbe/macro_rules.rs46
-rw-r--r--src/libsyntax_expand/placeholders.rs26
-rw-r--r--src/libsyntax_ext/asm.rs3
-rw-r--r--src/libsyntax_ext/concat_idents.rs4
-rw-r--r--src/libsyntax_ext/deriving/debug.rs6
-rw-r--r--src/libsyntax_ext/deriving/decodable.rs2
-rw-r--r--src/libsyntax_ext/deriving/encodable.rs2
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs31
-rw-r--r--src/libsyntax_ext/deriving/generic/ty.rs4
-rw-r--r--src/libsyntax_ext/deriving/hash.rs2
-rw-r--r--src/libsyntax_ext/env.rs2
-rw-r--r--src/libsyntax_ext/global_allocator.rs2
-rw-r--r--src/libsyntax_ext/proc_macro_harness.rs4
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/stage0.txt5
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs62
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs74
-rw-r--r--src/test/mir-opt/address-of.rs112
-rw-r--r--src/test/mir-opt/array-index-is-temporary.rs19
-rw-r--r--src/test/mir-opt/const_prop/aggregate.rs2
-rw-r--r--src/test/mir-opt/const_prop/array_index.rs2
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs18
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.rs149
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.rs2
-rw-r--r--src/test/mir-opt/const_prop/repeat.rs2
-rw-r--r--src/test/mir-opt/inline/inline-any-operand.rs (renamed from src/test/mir-opt/inline-any-operand.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-closure-borrows-arg.rs (renamed from src/test/mir-opt/inline-closure-borrows-arg.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-closure-captures.rs (renamed from src/test/mir-opt/inline-closure-captures.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-closure.rs (renamed from src/test/mir-opt/inline-closure.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-into-box-place.rs71
-rw-r--r--src/test/mir-opt/inline/inline-retag.rs (renamed from src/test/mir-opt/inline-retag.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-trait-method.rs (renamed from src/test/mir-opt/inline-trait-method.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-trait-method_2.rs (renamed from src/test/mir-opt/inline-trait-method_2.rs)0
-rw-r--r--src/test/mir-opt/retag.rs10
-rw-r--r--src/test/mir-opt/slice-drop-shim.rs18
-rw-r--r--src/test/pretty/ast-stmt-expr-attr.rs175
-rw-r--r--src/test/pretty/raw-address-of.rs12
-rw-r--r--src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs2
-rw-r--r--src/test/run-make/wasm-symbols-different-module/Makefile28
-rw-r--r--src/test/run-make/wasm-symbols-different-module/bar.rs33
-rw-r--r--src/test/run-make/wasm-symbols-different-module/baz.rs22
-rw-r--r--src/test/run-make/wasm-symbols-different-module/foo.rs23
-rw-r--r--src/test/run-make/wasm-symbols-different-module/log.rs16
-rw-r--r--src/test/run-make/wasm-symbols-different-module/verify-imports.js32
-rw-r--r--src/test/rustdoc/const-display.rs8
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/macros.rs2
-rw-r--r--src/test/rustdoc/stability.rs2
-rw-r--r--src/test/ui-fulldeps/ast_stmt_expr_attr.rs311
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs2
-rw-r--r--src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs97
-rw-r--r--src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs97
-rw-r--r--src/test/ui/asm/issue-51431.rs1
-rw-r--r--src/test/ui/asm/issue-51431.stderr2
-rw-r--r--src/test/ui/auxiliary/stability-cfg2.rs2
-rw-r--r--src/test/ui/bad/bad-intrinsic-monomorphization.rs2
-rw-r--r--src/test/ui/bad/bad-intrinsic-monomorphization.stderr6
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs22
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr40
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs23
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs17
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr21
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs44
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-mutability.rs42
-rw-r--r--src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr59
-rw-r--r--src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs118
-rw-r--r--src/test/ui/borrowck/borrowck-closures-slice-patterns.rs84
-rw-r--r--src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr114
-rw-r--r--src/test/ui/borrowck/move-from-union-field-issue-66500.rs30
-rw-r--r--src/test/ui/borrowck/move-from-union-field-issue-66500.stderr27
-rw-r--r--src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr4
-rw-r--r--src/test/ui/cast/cast-as-bool.rs2
-rw-r--r--src/test/ui/cast/cast-as-bool.stderr7
-rw-r--r--src/test/ui/cdylib-deps-must-be-static.rs1
-rw-r--r--src/test/ui/commandline-argfile-badutf8.rs1
-rw-r--r--src/test/ui/commandline-argfile-missing.rs1
-rw-r--r--src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs1
-rw-r--r--src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr19
-rw-r--r--src/test/ui/consts/array-literal-index-oob.rs2
-rw-r--r--src/test/ui/consts/array-literal-index-oob.stderr4
-rw-r--r--src/test/ui/consts/assoc_const_generic_impl.rs2
-rw-r--r--src/test/ui/consts/assoc_const_generic_impl.stderr6
-rw-r--r--src/test/ui/consts/const-address-of-interior-mut.rs16
-rw-r--r--src/test/ui/consts/const-address-of-interior-mut.stderr27
-rw-r--r--src/test/ui/consts/const-address-of-mut.rs14
-rw-r--r--src/test/ui/consts/const-address-of-mut.stderr39
-rw-r--r--src/test/ui/consts/const-address-of.rs19
-rw-r--r--src/test/ui/consts/const-err.rs1
-rw-r--r--src/test/ui/consts/const-err.stderr8
-rw-r--r--src/test/ui/consts/const-err2.rs2
-rw-r--r--src/test/ui/consts/const-err2.stderr12
-rw-r--r--src/test/ui/consts/const-err3.rs2
-rw-r--r--src/test/ui/consts/const-err3.stderr12
-rw-r--r--src/test/ui/consts/const-eval/auxiliary/stability.rs2
-rw-r--r--src/test/ui/consts/const-eval/conditional_array_execution.rs2
-rw-r--r--src/test/ui/consts/const-eval/conditional_array_execution.stderr6
-rw-r--r--src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs2
-rw-r--r--src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr6
-rw-r--r--src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs4
-rw-r--r--src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs2
-rw-r--r--src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr6
-rw-r--r--src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs2
-rw-r--r--src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr2
-rw-r--r--src/test/ui/consts/const-eval/issue-43197.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-43197.stderr10
-rw-r--r--src/test/ui/consts/const-eval/issue-44578.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-44578.stderr2
-rw-r--r--src/test/ui/consts/const-eval/issue-50814-2.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-50814-2.stderr4
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.stderr4
-rw-r--r--src/test/ui/consts/const-eval/panic-assoc-never-type.rs2
-rw-r--r--src/test/ui/consts/const-eval/panic-assoc-never-type.stderr8
-rw-r--r--src/test/ui/consts/const-eval/panic-never-type.rs2
-rw-r--r--src/test/ui/consts/const-eval/panic-never-type.stderr8
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.rs1
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.stderr16
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors2.rs1
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors2.stderr18
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.rs15
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.stderr54
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_address_of.rs30
-rw-r--r--src/test/ui/consts/const-prop-ice.rs2
-rw-r--r--src/test/ui/consts/const-prop-ice.stderr2
-rw-r--r--src/test/ui/consts/const-prop-ice2.rs2
-rw-r--r--src/test/ui/consts/const-prop-ice2.stderr2
-rw-r--r--src/test/ui/consts/const-prop-ice3.rs7
-rw-r--r--src/test/ui/consts/min_const_fn/address_of.rs17
-rw-r--r--src/test/ui/consts/min_const_fn/address_of.stderr21
-rw-r--r--src/test/ui/consts/min_const_fn/address_of_const.rs19
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs8
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const.stderr4
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const_2.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const_2.stderr2
-rw-r--r--src/test/ui/consts/miri_unleashed/non_const_fn.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/non_const_fn.stderr8
-rw-r--r--src/test/ui/consts/offset_from_ub.stderr20
-rw-r--r--src/test/ui/consts/uninhabited-const-issue-61744.rs2
-rw-r--r--src/test/ui/consts/unstable-const-fn-in-libcore.rs2
-rw-r--r--src/test/ui/did_you_mean/issue-40006.rs4
-rw-r--r--src/test/ui/did_you_mean/issue-40006.stderr12
-rw-r--r--src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs31
-rw-r--r--src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr95
-rw-r--r--src/test/ui/dropck/dropck_fn_type.rs20
-rw-r--r--src/test/ui/dropck/dropck_traits.rs68
-rw-r--r--src/test/ui/duplicate/dupe-symbols-1.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-1.stderr2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-2.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-2.stderr2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-3.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-3.stderr2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-4.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-4.stderr2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-5.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-5.stderr2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-6.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-6.stderr2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-7.rs2
-rw-r--r--src/test/ui/duplicate/dupe-symbols-7.stderr2
-rw-r--r--src/test/ui/error-codes/E0511.rs2
-rw-r--r--src/test/ui/error-codes/E0511.stderr2
-rw-r--r--src/test/ui/feature-gate/stability-attribute-consistency.rs2
-rw-r--r--src/test/ui/feature-gate/stability-attribute-consistency.stderr4
-rw-r--r--src/test/ui/feature-gate/unstable-attribute-allow-issue-0.rs (renamed from src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs)2
-rw-r--r--src/test/ui/feature-gate/unstable-attribute-allow-issue-0.stderr (renamed from src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr)2
-rw-r--r--src/test/ui/feature-gates/feature-gate-generic_associated_types.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr30
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr18
-rw-r--r--src/test/ui/generic-associated-types/collections.rs (renamed from src/test/ui/rfc1598-generic-associated-types/collections.rs)12
-rw-r--r--src/test/ui/generic-associated-types/collections.stderr19
-rw-r--r--src/test/ui/generic-associated-types/construct_with_other_type.rs26
-rw-r--r--src/test/ui/generic-associated-types/construct_with_other_type.stderr13
-rw-r--r--src/test/ui/generic-associated-types/empty_generics.rs (renamed from src/test/ui/rfc1598-generic-associated-types/empty_generics.rs)2
-rw-r--r--src/test/ui/generic-associated-types/empty_generics.stderr8
-rw-r--r--src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs17
-rw-r--r--src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr29
-rw-r--r--src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.rs (renamed from src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.rs)4
-rw-r--r--src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr19
-rw-r--r--src/test/ui/generic-associated-types/gat-incomplete-warning.rs (renamed from src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs)0
-rw-r--r--src/test/ui/generic-associated-types/gat-incomplete-warning.stderr (renamed from src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr)0
-rw-r--r--src/test/ui/generic-associated-types/generic-associated-types-where.rs (renamed from src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs)10
-rw-r--r--src/test/ui/generic-associated-types/generic-associated-types-where.stderr26
-rw-r--r--src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs16
-rw-r--r--src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr15
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.rs23
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr46
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds_ok.rs30
-rw-r--r--src/test/ui/generic-associated-types/issue-47206-where-clause.rs17
-rw-r--r--src/test/ui/generic-associated-types/issue-47206-where-clause.stderr10
-rw-r--r--src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs10
-rw-r--r--src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs12
-rw-r--r--src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr15
-rw-r--r--src/test/ui/generic-associated-types/iterable.rs51
-rw-r--r--src/test/ui/generic-associated-types/iterable.stderr63
-rw-r--r--src/test/ui/generic-associated-types/parameter_number_and_kind.rs24
-rw-r--r--src/test/ui/generic-associated-types/parameter_number_and_kind.stderr53
-rw-r--r--src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs35
-rw-r--r--src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr62
-rw-r--r--src/test/ui/generic-associated-types/parse/in-trait-impl.rs (renamed from src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs)2
-rw-r--r--src/test/ui/generic-associated-types/parse/in-trait.rs (renamed from src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs)3
-rw-r--r--src/test/ui/generic-associated-types/pointer_family.rs (renamed from src/test/ui/rfc1598-generic-associated-types/pointer_family.rs)9
-rw-r--r--src/test/ui/generic-associated-types/pointer_family.stderr10
-rw-r--r--src/test/ui/generic-associated-types/shadowing.rs (renamed from src/test/ui/rfc1598-generic-associated-types/shadowing.rs)8
-rw-r--r--src/test/ui/generic-associated-types/shadowing.stderr (renamed from src/test/ui/rfc1598-generic-associated-types/shadowing.stderr)20
-rw-r--r--src/test/ui/generic-associated-types/streaming_iterator.rs (renamed from src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs)48
-rw-r--r--src/test/ui/huge-array-simple-32.rs1
-rw-r--r--src/test/ui/huge-array-simple-32.stderr2
-rw-r--r--src/test/ui/huge-array-simple-64.rs1
-rw-r--r--src/test/ui/huge-array-simple-64.stderr2
-rw-r--r--src/test/ui/huge-array.rs2
-rw-r--r--src/test/ui/huge-array.stderr2
-rw-r--r--src/test/ui/huge-enum.rs1
-rw-r--r--src/test/ui/huge-enum.stderr2
-rw-r--r--src/test/ui/huge-struct.rs1
-rw-r--r--src/test/ui/huge-struct.stderr2
-rw-r--r--src/test/ui/infinite/infinite-instantiation.rs2
-rw-r--r--src/test/ui/infinite/infinite-instantiation.stderr2
-rw-r--r--src/test/ui/inline-asm-bad-constraint.rs1
-rw-r--r--src/test/ui/inline-asm-bad-constraint.stderr6
-rw-r--r--src/test/ui/inline-asm-bad-operand.rs1
-rw-r--r--src/test/ui/inline-asm-bad-operand.stderr14
-rw-r--r--src/test/ui/internal/auxiliary/internal_unstable.rs8
-rw-r--r--src/test/ui/invalid/invalid-variadic-function.rs3
-rw-r--r--src/test/ui/invalid/invalid-variadic-function.stderr15
-rw-r--r--src/test/ui/issues/auxiliary/issue-52489.rs2
-rw-r--r--src/test/ui/issues/auxiliary/lint-stability.rs46
-rw-r--r--src/test/ui/issues/issue-11154.rs1
-rw-r--r--src/test/ui/issues/issue-15919-32.rs1
-rw-r--r--src/test/ui/issues/issue-15919-32.stderr2
-rw-r--r--src/test/ui/issues/issue-15919-64.rs1
-rw-r--r--src/test/ui/issues/issue-15919-64.stderr2
-rw-r--r--src/test/ui/issues/issue-17337.rs4
-rw-r--r--src/test/ui/issues/issue-17913.rs1
-rw-r--r--src/test/ui/issues/issue-22638.rs1
-rw-r--r--src/test/ui/issues/issue-22638.stderr2
-rw-r--r--src/test/ui/issues/issue-23458.rs1
-rw-r--r--src/test/ui/issues/issue-23458.stderr4
-rw-r--r--src/test/ui/issues/issue-26548.rs2
-rw-r--r--src/test/ui/issues/issue-26548.stderr2
-rw-r--r--src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs2
-rw-r--r--src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr2
-rw-r--r--src/test/ui/issues/issue-37433.rs1
-rw-r--r--src/test/ui/issues/issue-37433.stderr2
-rw-r--r--src/test/ui/issues/issue-53787-inline-assembler-macro.rs1
-rw-r--r--src/test/ui/issues/issue-53787-inline-assembler-macro.stderr2
-rw-r--r--src/test/ui/issues/issue-54348.rs2
-rw-r--r--src/test/ui/issues/issue-54348.stderr4
-rw-r--r--src/test/ui/issues/issue-58856-1.rs2
-rw-r--r--src/test/ui/issues/issue-58856-1.stderr17
-rw-r--r--src/test/ui/issues/issue-58857.rs2
-rw-r--r--src/test/ui/issues/issue-58857.stderr6
-rw-r--r--src/test/ui/issues/issue-60075.stderr2
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.rs15
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr19
-rw-r--r--src/test/ui/issues/issue-8460-const.rs1
-rw-r--r--src/test/ui/issues/issue-8460-const.stderr62
-rw-r--r--src/test/ui/issues/issue-8460-const2.rs1
-rw-r--r--src/test/ui/issues/issue-8460-const2.stderr42
-rw-r--r--src/test/ui/issues/issue-8727.rs2
-rw-r--r--src/test/ui/issues/issue-8727.stderr4
-rw-r--r--src/test/ui/json-and-color.rs1
-rw-r--r--src/test/ui/json-and-error-format.rs1
-rw-r--r--src/test/ui/json-bom-plus-crlf-multifile.rs1
-rw-r--r--src/test/ui/json-bom-plus-crlf.rs1
-rw-r--r--src/test/ui/json-bom-plus-crlf.stderr8
-rw-r--r--src/test/ui/json-invalid.rs1
-rw-r--r--src/test/ui/json-short.rs1
-rw-r--r--src/test/ui/json-short.stderr2
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs1
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs2
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr2
-rw-r--r--src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs1
-rw-r--r--src/test/ui/linkage-attr/linkage2.rs2
-rw-r--r--src/test/ui/linkage-attr/linkage2.stderr2
-rw-r--r--src/test/ui/linkage-attr/linkage3.rs2
-rw-r--r--src/test/ui/linkage-attr/linkage3.stderr2
-rw-r--r--src/test/ui/lint/auxiliary/inherited_stability.rs8
-rw-r--r--src/test/ui/lint/auxiliary/lint_output_format.rs6
-rw-r--r--src/test/ui/lint/auxiliary/lint_stability.rs46
-rw-r--r--src/test/ui/lint/auxiliary/lint_stability_fields.rs24
-rw-r--r--src/test/ui/lint/auxiliary/stability-cfg2.rs2
-rw-r--r--src/test/ui/lint/auxiliary/stability_cfg2.rs2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.rs1
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.stderr38
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts2.rs1
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts2.stderr10
-rw-r--r--src/test/ui/lint/lint-shorthand-field.fixed70
-rw-r--r--src/test/ui/lint/lint-shorthand-field.rs18
-rw-r--r--src/test/ui/lint/lint-shorthand-field.stderr34
-rw-r--r--src/test/ui/lint/lint-stability-2.rs46
-rw-r--r--src/test/ui/lint/lint-stability-deprecated.rs46
-rw-r--r--src/test/ui/lint/lint-stability-fields-deprecated.rs22
-rw-r--r--src/test/ui/lint/lint-stability-fields.rs22
-rw-r--r--src/test/ui/lint/lint-stability.rs46
-rw-r--r--src/test/ui/lint/lint-unused-mut-variables.rs8
-rw-r--r--src/test/ui/lint/lint-unused-mut-variables.stderr14
-rw-r--r--src/test/ui/lint/suggestions.rs2
-rw-r--r--src/test/ui/lint/suggestions.stderr4
-rw-r--r--src/test/ui/lto-duplicate-symbols.rs1
-rw-r--r--src/test/ui/macros/auxiliary/unstable-macros.rs4
-rw-r--r--src/test/ui/macros/macro-stability-rpass.rs2
-rw-r--r--src/test/ui/macros/macro-stability.rs4
-rw-r--r--src/test/ui/missing/missing-stability.rs2
-rw-r--r--src/test/ui/moves/move-out-of-array-ref.rs36
-rw-r--r--src/test/ui/moves/move-out-of-array-ref.stderr47
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.rs34
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.stderr51
-rw-r--r--src/test/ui/non-integer-atomic.rs2
-rw-r--r--src/test/ui/non-integer-atomic.stderr32
-rw-r--r--src/test/ui/packed/packed-struct-address-of-element.rs37
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element.rs2
-rw-r--r--src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs1
-rw-r--r--src/test/ui/panic-runtime/transitive-link-a-bunch.rs1
-rw-r--r--src/test/ui/panic-runtime/want-unwind-got-abort.rs1
-rw-r--r--src/test/ui/panic-runtime/want-unwind-got-abort2.rs1
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs2
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr8
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs2
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr8
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.rs107
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.stderr390
-rw-r--r--src/test/ui/parser/do-catch-suggests-try.rs7
-rw-r--r--src/test/ui/parser/do-catch-suggests-try.stderr17
-rw-r--r--src/test/ui/parser/impl-item-const-pass.rs8
-rw-r--r--src/test/ui/parser/impl-item-const-semantic-fail.rs7
-rw-r--r--src/test/ui/parser/impl-item-const-semantic-fail.stderr10
-rw-r--r--src/test/ui/parser/impl-item-fn-no-body-pass.rs8
-rw-r--r--src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs7
-rw-r--r--src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr10
-rw-r--r--src/test/ui/parser/impl-item-type-no-body-pass.rs11
-rw-r--r--src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs23
-rw-r--r--src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr79
-rw-r--r--src/test/ui/parser/issue-21153.stderr2
-rw-r--r--src/test/ui/parser/issue-32446.stderr4
-rw-r--r--src/test/ui/parser/issue-33418.fixed10
-rw-r--r--src/test/ui/parser/issue-33418.rs10
-rw-r--r--src/test/ui/parser/issue-33418.stderr30
-rw-r--r--src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs21
-rw-r--r--src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr67
-rw-r--r--src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.rs12
-rw-r--r--src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.stderr20
-rw-r--r--src/test/ui/parser/macro/trait-non-item-macros.stderr4
-rw-r--r--src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr4
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.rs5
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.stderr17
-rw-r--r--src/test/ui/parser/recovery-attr-on-if.rs9
-rw-r--r--src/test/ui/parser/recovery-attr-on-if.stderr35
-rw-r--r--src/test/ui/parser/stmt_expr_attrs_placement.rs22
-rw-r--r--src/test/ui/parser/stmt_expr_attrs_placement.stderr10
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs12
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr38
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-pass.rs13
-rw-r--r--src/test/ui/parser/variadic-ffi-3.rs5
-rw-r--r--src/test/ui/parser/variadic-ffi-3.stderr9
-rw-r--r--src/test/ui/parser/variadic-ffi-4.rs5
-rw-r--r--src/test/ui/parser/variadic-ffi-4.stderr9
-rw-r--r--src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs9
-rw-r--r--src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr24
-rw-r--r--src/test/ui/parser/variadic-ffi-semantic-restrictions.rs76
-rw-r--r--src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr206
-rw-r--r--src/test/ui/parser/variadic-ffi-syntactic-pass.rs53
-rw-r--r--src/test/ui/print_type_sizes/zero-sized-fields.rs1
-rw-r--r--src/test/ui/qualified/qualified-path-params-2.rs3
-rw-r--r--src/test/ui/qualified/qualified-path-params-2.stderr11
-rw-r--r--src/test/ui/raw-ref-op/raw-ref-op.rs6
-rw-r--r--src/test/ui/raw-ref-op/raw-ref-op.stderr18
-rw-r--r--src/test/ui/raw-ref-op/raw-ref-temp-deref.rs20
-rw-r--r--src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr74
-rw-r--r--src/test/ui/raw-ref-op/raw-ref-temp.rs6
-rw-r--r--src/test/ui/raw-ref-op/raw-ref-temp.stderr40
-rw-r--r--src/test/ui/raw-ref-op/unusual_locations.rs31
-rw-r--r--src/test/ui/raw-ref-op/unusual_locations.stderr18
-rw-r--r--src/test/ui/recursion/recursion.rs2
-rw-r--r--src/test/ui/recursion/recursion.stderr2
-rw-r--r--src/test/ui/required-lang-item.rs2
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/collections.stderr41
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs29
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr29
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr16
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr12
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr8
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs22
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr42
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/iterable.rs50
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/iterable.stderr47
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs47
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr41
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr35
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr41
-rw-r--r--src/test/ui/rmeta_lib.rs1
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs1
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr4
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs2
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr28
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs2
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr10
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs2
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr8
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs2
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr36
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs2
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr30
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs1
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr20
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs2
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr16
-rw-r--r--src/test/ui/simd-type-generic-monomorphisation.rs2
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-sanity.rs12
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-sanity.stderr12
-rw-r--r--src/test/ui/structs/struct-path-associated-type.rs1
-rw-r--r--src/test/ui/structs/struct-path-associated-type.stderr10
-rw-r--r--src/test/ui/suggestions/let-binding-init-expr-as-ty.rs1
-rw-r--r--src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr12
-rw-r--r--src/test/ui/symbol-names/basic.legacy.stderr8
-rw-r--r--src/test/ui/symbol-names/basic.rs1
-rw-r--r--src/test/ui/symbol-names/basic.v0.stderr8
-rw-r--r--src/test/ui/symbol-names/impl1.legacy.stderr24
-rw-r--r--src/test/ui/symbol-names/impl1.rs1
-rw-r--r--src/test/ui/symbol-names/impl1.v0.stderr24
-rw-r--r--src/test/ui/symbol-names/impl2.rs2
-rw-r--r--src/test/ui/symbol-names/impl2.stderr2
-rw-r--r--src/test/ui/symbol-names/issue-60925.legacy.stderr6
-rw-r--r--src/test/ui/symbol-names/issue-60925.rs1
-rw-r--r--src/test/ui/symbol-names/issue-60925.v0.stderr6
-rw-r--r--src/test/ui/type/ascription/issue-47666.stderr2
-rw-r--r--src/test/ui/type_length_limit.rs1
-rw-r--r--src/tools/build-manifest/src/main.rs16
m---------src/tools/cargo0
m---------src/tools/clippy16
-rw-r--r--src/tools/compiletest/src/common.rs9
-rw-r--r--src/tools/compiletest/src/header.rs43
-rw-r--r--src/tools/compiletest/src/runtest.rs159
-rw-r--r--src/tools/tidy/src/features.rs18
-rw-r--r--src/tools/unstable-book-gen/src/main.rs15
741 files changed, 12013 insertions, 7549 deletions
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index c27c318f5ad..3ab00a6e147 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -47,7 +47,7 @@ serde_json = "1.0.2"
 toml = "0.5"
 lazy_static = "1.3.0"
 time = "0.1"
-petgraph = "0.4.13"
+ignore = "0.4.10"
 
 [dev-dependencies]
 pretty_assertions = "0.5"
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index bb169414886..6737086f6e5 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -322,6 +322,7 @@ class RustBuild(object):
         self.date = ''
         self._download_url = ''
         self.rustc_channel = ''
+        self.rustfmt_channel = ''
         self.build = ''
         self.build_dir = os.path.join(os.getcwd(), "build")
         self.clean = False
@@ -344,6 +345,7 @@ class RustBuild(object):
         """
         rustc_channel = self.rustc_channel
         cargo_channel = self.cargo_channel
+        rustfmt_channel = self.rustfmt_channel
 
         def support_xz():
             try:
@@ -393,13 +395,29 @@ class RustBuild(object):
             with output(self.cargo_stamp()) as cargo_stamp:
                 cargo_stamp.write(self.date)
 
-    def _download_stage0_helper(self, filename, pattern, tarball_suffix):
+        if self.rustfmt() and self.rustfmt().startswith(self.bin_root()) and (
+            not os.path.exists(self.rustfmt())
+            or self.program_out_of_date(self.rustfmt_stamp())
+        ):
+            if rustfmt_channel:
+                tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
+                [channel, date] = rustfmt_channel.split('-', 1)
+                filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix)
+                self._download_stage0_helper(filename, "rustfmt-preview", tarball_suffix, date)
+                self.fix_executable("{}/bin/rustfmt".format(self.bin_root()))
+                self.fix_executable("{}/bin/cargo-fmt".format(self.bin_root()))
+                with output(self.rustfmt_stamp()) as rustfmt_stamp:
+                    rustfmt_stamp.write(self.date)
+
+    def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None):
+        if date is None:
+            date = self.date
         cache_dst = os.path.join(self.build_dir, "cache")
-        rustc_cache = os.path.join(cache_dst, self.date)
+        rustc_cache = os.path.join(cache_dst, date)
         if not os.path.exists(rustc_cache):
             os.makedirs(rustc_cache)
 
-        url = "{}/dist/{}".format(self._download_url, self.date)
+        url = "{}/dist/{}".format(self._download_url, date)
         tarball = os.path.join(rustc_cache, filename)
         if not os.path.exists(tarball):
             get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
@@ -493,6 +511,16 @@ class RustBuild(object):
         """
         return os.path.join(self.bin_root(), '.cargo-stamp')
 
+    def rustfmt_stamp(self):
+        """Return the path for .rustfmt-stamp
+
+        >>> rb = RustBuild()
+        >>> rb.build_dir = "build"
+        >>> rb.rustfmt_stamp() == os.path.join("build", "stage0", ".rustfmt-stamp")
+        True
+        """
+        return os.path.join(self.bin_root(), '.rustfmt-stamp')
+
     def program_out_of_date(self, stamp_path):
         """Check if the given program stamp is out of date"""
         if not os.path.exists(stamp_path) or self.clean:
@@ -565,6 +593,12 @@ class RustBuild(object):
         """Return config path for rustc"""
         return self.program_config('rustc')
 
+    def rustfmt(self):
+        """Return config path for rustfmt"""
+        if not self.rustfmt_channel:
+            return None
+        return self.program_config('rustfmt')
+
     def program_config(self, program):
         """Return config path for the given program
 
@@ -868,6 +902,9 @@ def bootstrap(help_triggered):
     build.rustc_channel = data['rustc']
     build.cargo_channel = data['cargo']
 
+    if "rustfmt" in data:
+        build.rustfmt_channel = data['rustfmt']
+
     if 'dev' in data:
         build.set_dev_environment()
     else:
@@ -895,6 +932,8 @@ def bootstrap(help_triggered):
     env["RUSTC_BOOTSTRAP"] = '1'
     env["CARGO"] = build.cargo()
     env["RUSTC"] = build.rustc()
+    if build.rustfmt():
+        env["RUSTFMT"] = build.rustfmt()
     run(args, env=env, verbose=build.verbose)
 
 
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 689298f32d0..0e941e13676 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -20,14 +20,14 @@ class Stage0DataTestCase(unittest.TestCase):
         os.mkdir(os.path.join(self.rust_root, "src"))
         with open(os.path.join(self.rust_root, "src",
                                "stage0.txt"), "w") as stage0:
-            stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta")
+            stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta\nrustfmt: beta")
 
     def tearDown(self):
         rmtree(self.rust_root)
 
     def test_stage0_data(self):
         """Extract data from stage0.txt"""
-        expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta"}
+        expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta", "rustfmt": "beta"}
         data = bootstrap.stage0_data(self.rust_root)
         self.assertDictEqual(data, expected)
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8b0ad169cfc..bd0462fca6d 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1,7 +1,6 @@
 use std::any::Any;
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
-use std::collections::HashMap;
 use std::env;
 use std::ffi::OsStr;
 use std::fmt::Debug;
@@ -29,9 +28,6 @@ use crate::{Build, DocTests, Mode, GitRepo};
 
 pub use crate::Compiler;
 
-use petgraph::graph::NodeIndex;
-use petgraph::Graph;
-
 pub struct Builder<'a> {
     pub build: &'a Build,
     pub top_stage: u32,
@@ -40,9 +36,6 @@ pub struct Builder<'a> {
     stack: RefCell<Vec<Box<dyn Any>>>,
     time_spent_on_dependencies: Cell<Duration>,
     pub paths: Vec<PathBuf>,
-    graph_nodes: RefCell<HashMap<String, NodeIndex>>,
-    graph: RefCell<Graph<String, bool>>,
-    parent: Cell<Option<NodeIndex>>,
 }
 
 impl<'a> Deref for Builder<'a> {
@@ -321,6 +314,7 @@ pub enum Kind {
     Check,
     Clippy,
     Fix,
+    Format,
     Test,
     Bench,
     Dist,
@@ -360,7 +354,7 @@ impl<'a> Builder<'a> {
                 tool::Miri,
                 native::Lld
             ),
-            Kind::Check | Kind::Clippy | Kind::Fix => describe!(
+            Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => describe!(
                 check::Std,
                 check::Rustc,
                 check::Rustdoc
@@ -490,9 +484,6 @@ impl<'a> Builder<'a> {
             stack: RefCell::new(Vec::new()),
             time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
             paths: vec![],
-            graph_nodes: RefCell::new(HashMap::new()),
-            graph: RefCell::new(Graph::new()),
-            parent: Cell::new(None),
         };
 
         let builder = &builder;
@@ -524,7 +515,7 @@ impl<'a> Builder<'a> {
             Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
             Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
             Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
-            Subcommand::Clean { .. } => panic!(),
+            Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
         };
 
         let builder = Builder {
@@ -535,17 +526,13 @@ impl<'a> Builder<'a> {
             stack: RefCell::new(Vec::new()),
             time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
             paths: paths.to_owned(),
-            graph_nodes: RefCell::new(HashMap::new()),
-            graph: RefCell::new(Graph::new()),
-            parent: Cell::new(None),
         };
 
         builder
     }
 
-    pub fn execute_cli(&self) -> Graph<String, bool> {
+    pub fn execute_cli(&self) {
         self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
-        self.graph.borrow().clone()
     }
 
     pub fn default_doc(&self, paths: Option<&[PathBuf]>) {
@@ -1260,41 +1247,12 @@ impl<'a> Builder<'a> {
             if let Some(out) = self.cache.get(&step) {
                 self.verbose(&format!("{}c {:?}", "  ".repeat(stack.len()), step));
 
-                {
-                    let mut graph = self.graph.borrow_mut();
-                    let parent = self.parent.get();
-                    let us = *self
-                        .graph_nodes
-                        .borrow_mut()
-                        .entry(format!("{:?}", step))
-                        .or_insert_with(|| graph.add_node(format!("{:?}", step)));
-                    if let Some(parent) = parent {
-                        graph.add_edge(parent, us, false);
-                    }
-                }
-
                 return out;
             }
             self.verbose(&format!("{}> {:?}", "  ".repeat(stack.len()), step));
             stack.push(Box::new(step.clone()));
         }
 
-        let prev_parent = self.parent.get();
-
-        {
-            let mut graph = self.graph.borrow_mut();
-            let parent = self.parent.get();
-            let us = *self
-                .graph_nodes
-                .borrow_mut()
-                .entry(format!("{:?}", step))
-                .or_insert_with(|| graph.add_node(format!("{:?}", step)));
-            self.parent.set(Some(us));
-            if let Some(parent) = parent {
-                graph.add_edge(parent, us, true);
-            }
-        }
-
         let (out, dur) = {
             let start = Instant::now();
             let zero = Duration::new(0, 0);
@@ -1305,8 +1263,6 @@ impl<'a> Builder<'a> {
             (out, dur - deps)
         };
 
-        self.parent.set(prev_parent);
-
         if self.config.print_step_timings && dur > Duration::from_millis(100) {
             println!(
                 "[TIMING] {:?} -- {}.{:03}",
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index baf9aabed00..831053bc0f7 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -563,7 +563,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interne
         // not for MSVC or macOS
         if builder.config.llvm_static_stdcpp &&
            !target.contains("freebsd") &&
-           !target.contains("windows") &&
+           !target.contains("msvc") &&
            !target.contains("apple") {
             let file = compiler_file(builder,
                                      builder.cxx(target).unwrap(),
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 5f2ef01bd5c..3e67734e690 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -5,6 +5,7 @@
 
 use std::collections::{HashMap, HashSet};
 use std::env;
+use std::ffi::OsString;
 use std::fs;
 use std::path::{Path, PathBuf};
 use std::process;
@@ -149,6 +150,7 @@ pub struct Config {
     // These are either the stage0 downloaded binaries or the locally installed ones.
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
+    pub initial_rustfmt: Option<PathBuf>,
     pub out: PathBuf,
 }
 
@@ -348,12 +350,16 @@ struct TomlTarget {
 impl Config {
     fn path_from_python(var_key: &str) -> PathBuf {
         match env::var_os(var_key) {
-            // Do not trust paths from Python and normalize them slightly (#49785).
-            Some(var_val) => Path::new(&var_val).components().collect(),
+            Some(var_val) => Self::normalize_python_path(var_val),
             _ => panic!("expected '{}' to be set", var_key),
         }
     }
 
+    /// Normalizes paths from Python slightly. We don't trust paths from Python (#49785).
+    fn normalize_python_path(path: OsString) -> PathBuf {
+        Path::new(&path).components().collect()
+    }
+
     pub fn default_opts() -> Config {
         let mut config = Config::default();
         config.llvm_optimize = true;
@@ -380,6 +386,7 @@ impl Config {
 
         config.initial_rustc = Config::path_from_python("RUSTC");
         config.initial_cargo = Config::path_from_python("CARGO");
+        config.initial_rustfmt = env::var_os("RUSTFMT").map(Config::normalize_python_path);
 
         config
     }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 7b49cc0a929..b98e2c1bf24 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -53,6 +53,9 @@ pub enum Subcommand {
     Fix {
         paths: Vec<PathBuf>,
     },
+    Format {
+        check: bool,
+    },
     Doc {
         paths: Vec<PathBuf>,
     },
@@ -102,6 +105,7 @@ Subcommands:
     check       Compile either the compiler or libraries, using cargo check
     clippy      Run clippy
     fix         Run cargo fix
+    fmt         Run rustfmt
     test        Build and run some test suites
     bench       Build and run some benchmarks
     doc         Build documentation
@@ -160,6 +164,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
                 || (s == "check")
                 || (s == "clippy")
                 || (s == "fix")
+                || (s == "fmt")
                 || (s == "test")
                 || (s == "bench")
                 || (s == "doc")
@@ -222,6 +227,9 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
             "clean" => {
                 opts.optflag("", "all", "clean all build artifacts");
             }
+            "fmt" => {
+                opts.optflag("", "check", "check formatting instead of applying.");
+            }
             _ => {}
         };
 
@@ -323,6 +331,17 @@ Arguments:
         ./x.py fix src/libcore src/libproc_macro",
                 );
             }
+            "fmt" => {
+                subcommand_help.push_str(
+                    "\n
+Arguments:
+    This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and
+    fails if it is not. For example:
+
+        ./x.py fmt
+        ./x.py fmt --check",
+                );
+            }
             "test" => {
                 subcommand_help.push_str(
                     "\n
@@ -388,7 +407,7 @@ Arguments:
 
             let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
             extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
-        } else if subcommand.as_str() != "clean" {
+        } else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") {
             extra_help.push_str(
                 format!(
                     "Run `./x.py {} -h -v` to see a list of available paths.",
@@ -439,6 +458,11 @@ Arguments:
                     all: matches.opt_present("all"),
                 }
             }
+            "fmt" => {
+                Subcommand::Format {
+                    check: matches.opt_present("check"),
+                }
+            }
             "dist" => Subcommand::Dist { paths },
             "install" => Subcommand::Install { paths },
             _ => {
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
new file mode 100644
index 00000000000..c8ae2f4e688
--- /dev/null
+++ b/src/bootstrap/format.rs
@@ -0,0 +1,64 @@
+//! Runs rustfmt on the repository.
+
+use crate::Build;
+use std::process::Command;
+use ignore::WalkBuilder;
+use std::path::Path;
+use build_helper::t;
+
+fn rustfmt(build: &Build, path: &Path, check: bool) {
+    let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| {
+        eprintln!("./x.py fmt is not supported on this channel");
+        std::process::exit(1);
+    });
+
+    let mut cmd = Command::new(&rustfmt_path);
+    // avoid the submodule config paths from coming into play,
+    // we only allow a single global config for the workspace for now
+    cmd.arg("--config-path").arg(&build.src.canonicalize().unwrap());
+    cmd.arg("--unstable-features");
+    cmd.arg("--skip-children");
+    if check {
+        cmd.arg("--check");
+    }
+    cmd.arg(&path);
+    let cmd_debug = format!("{:?}", cmd);
+    let status = cmd.status().expect("executing rustfmt");
+    assert!(status.success(), "running {} successful", cmd_debug);
+}
+
+#[derive(serde::Deserialize)]
+struct RustfmtConfig {
+    ignore: Vec<String>,
+}
+
+pub fn format(build: &Build, check: bool) {
+    let mut builder = ignore::types::TypesBuilder::new();
+    builder.add_defaults();
+    builder.select("rust");
+    let matcher = builder.build().unwrap();
+    let rustfmt_config = build.src.join("rustfmt.toml");
+    if !rustfmt_config.exists() {
+        eprintln!("Not running formatting checks; rustfmt.toml does not exist.");
+        eprintln!("This may happen in distributed tarballs.");
+        return;
+    }
+    let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config));
+    let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config));
+    let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src);
+    for ignore in rustfmt_config.ignore {
+        ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore);
+    }
+    let ignore_fmt = ignore_fmt.build().unwrap();
+
+    let walker = WalkBuilder::new(&build.src)
+        .types(matcher)
+        .overrides(ignore_fmt)
+        .build();
+    for entry in walker {
+        let entry = t!(entry);
+        if entry.file_type().map_or(false, |t| t.is_file()) {
+            rustfmt(build, &entry.path(), check);
+        }
+    }
+}
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 080bef6853a..ff9a55afa29 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -147,6 +147,7 @@ mod builder;
 mod cache;
 mod tool;
 mod toolstate;
+mod format;
 
 #[cfg(windows)]
 mod job;
@@ -421,6 +422,10 @@ impl Build {
             job::setup(self);
         }
 
+        if let Subcommand::Format { check } = self.config.cmd {
+            return format::format(self, check);
+        }
+
         if let Subcommand::Clean { all } = self.config.cmd {
             return clean::clean(self, all);
         }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index f3b2a73d3c5..17aea17e69e 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -779,6 +779,9 @@ impl Step for Tidy {
     /// This tool in `src/tools` checks up on various bits and pieces of style and
     /// otherwise just implements a few lint-like checks that are specific to the
     /// compiler itself.
+    ///
+    /// Once tidy passes, this step also runs `fmt --check` if tests are being run
+    /// for the `dev` or `nightly` channels.
     fn run(self, builder: &Builder<'_>) {
         let mut cmd = builder.tool_cmd(Tool::Tidy);
         cmd.arg(builder.src.join("src"));
@@ -792,6 +795,11 @@ impl Step for Tidy {
 
         builder.info("tidy check");
         try_run(builder, &mut cmd);
+
+        if builder.config.channel == "dev" || builder.config.channel == "nightly" {
+            builder.info("fmt check");
+            crate::format::format(&builder.build, true);
+        }
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 6824b7a58c4..085742b011c 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -270,9 +270,9 @@ pub enum CiEnv {
 impl CiEnv {
     /// Obtains the current CI environment.
     pub fn current() -> CiEnv {
-        if env::var("TF_BUILD").ok().map_or(false, |e| &*e == "True") {
+        if env::var("TF_BUILD").map_or(false, |e| e == "True") {
             CiEnv::AzurePipelines
-        } else if env::var("GITHUB_ACTIONS").ok().map_or(false, |e| &*e == "true") {
+        } else if env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") {
             CiEnv::GitHubActions
         } else {
             CiEnv::None
diff --git a/src/doc/book b/src/doc/book
-Subproject 81ebaa2a3f88d4d106516c489682e64cacba4f6
+Subproject ef8bb568035ded8ddfa30a9309026638cc3c813
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 5ca585c4a7552efb546e7681c3de0712f4ae4fd
+Subproject c26234930282210849256e4ecab925f0f2daf3b
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 041c46e692a2592853aeca132c8dfe8eb5a79a9
+Subproject 8be35b201f9cf0a4c3fcc96c83ac21671dcf311
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 4835e025826729827a94fdeb7cb85fed288d08b
+Subproject b7ac1bc76b7d02a43c83b3a931d226f708aa1ff
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 1c39a3721f4..3e4005acaf3 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -476,7 +476,7 @@ impl<T: ?Sized> Box<T> {
         Box::into_unique(b).into()
     }
 
-    #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
+    #[unstable(feature = "ptr_internals", issue = "none", reason = "use into_raw_non_null instead")]
     #[inline]
     #[doc(hidden)]
     pub fn into_unique(b: Box<T>) -> Unique<T> {
@@ -830,7 +830,7 @@ impl From<Box<str>> for Box<[u8]> {
     }
 }
 
-#[unstable(feature = "boxed_slice_try_from", issue = "0")]
+#[unstable(feature = "boxed_slice_try_from", issue = "none")]
 impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
 where
     [T; N]: LengthAtMost32,
@@ -946,7 +946,7 @@ impl<T: ?Sized> DerefMut for Box<T> {
     }
 }
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for Box<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1040,7 +1040,7 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
 
 #[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs
index f1f22fe48c5..390a48180c0 100644
--- a/src/liballoc/collections/mod.rs
+++ b/src/liballoc/collections/mod.rs
@@ -57,7 +57,7 @@ pub enum TryReserveError {
         layout: Layout,
 
         #[doc(hidden)]
-        #[unstable(feature = "container_error_extra", issue = "0", reason = "\
+        #[unstable(feature = "container_error_extra", issue = "none", reason = "\
             Enable exposing the allocator’s custom error value \
             if an associated type is added in the future: \
             https://github.com/rust-lang/wg-allocators/issues/23")]
diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index 18ebae33309..01d4913665c 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -514,7 +514,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-#[unstable(feature = "fmt_internals", issue = "0")]
+#[unstable(feature = "fmt_internals", issue = "none")]
 pub use core::fmt::rt;
 #[stable(feature = "fmt_flags_align", since = "1.28.0")]
 pub use core::fmt::Alignment;
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index be46e632be4..b549fa1ef4f 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -171,7 +171,7 @@ mod std {
 }
 
 #[doc(hidden)]
-#[unstable(feature = "liballoc_internals", issue = "0", reason = "implementation detail")]
+#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
 pub mod __export {
     pub use core::format_args;
 }
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 3201c702abb..444450f6628 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -1,4 +1,4 @@
-#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "0")]
+#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")]
 #![doc(hidden)]
 
 use core::cmp;
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 42a278de98b..fd266210519 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -291,7 +291,7 @@ impl<T: ?Sized> !marker::Sync for Rc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
 
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
 
 impl<T: ?Sized> Rc<T> {
@@ -1090,7 +1090,7 @@ impl<T: ?Sized> Deref for Rc<T> {
     }
 }
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for Rc<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1471,7 +1471,7 @@ impl<T> From<Vec<T>> for Rc<[T]> {
     }
 }
 
-#[unstable(feature = "boxed_slice_try_from", issue = "0")]
+#[unstable(feature = "boxed_slice_try_from", issue = "none")]
 impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]>
 where
     [T; N]: LengthAtMost32,
@@ -1621,7 +1621,7 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 impl<T> Weak<T> {
@@ -2106,6 +2106,8 @@ impl<T: ?Sized> Unpin for Rc<T> { }
 unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
     // Align the unsized value to the end of the `RcBox`.
     // Because it is ?Sized, it will always be the last field in memory.
+    // Note: This is a detail of the current implementation of the compiler,
+    // and is not a guaranteed language detail. Do not rely on it outside of std.
     data_offset_align(align_of_val(&*ptr))
 }
 
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index a99564c0dac..3343384754f 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -206,7 +206,7 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
 
 impl<T: ?Sized> Arc<T> {
@@ -263,7 +263,7 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
@@ -993,7 +993,7 @@ impl<T: ?Sized> Deref for Arc<T> {
     }
 }
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for Arc<T> {}
 
 impl<T: Clone> Arc<T> {
@@ -2032,7 +2032,7 @@ impl<T> From<Vec<T>> for Arc<[T]> {
     }
 }
 
-#[unstable(feature = "boxed_slice_try_from", issue = "0")]
+#[unstable(feature = "boxed_slice_try_from", issue = "none")]
 impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]>
 where
     [T; N]: LengthAtMost32,
@@ -2161,6 +2161,8 @@ impl<T: ?Sized> Unpin for Arc<T> { }
 unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
     // Align the unsized value to the end of the `ArcInner`.
     // Because it is `?Sized`, it will always be the last field in memory.
+    // Note: This is a detail of the current implementation of the compiler,
+    // and is not a guaranteed language detail. Do not rely on it outside of std.
     data_offset_align(align_of_val(&*ptr))
 }
 
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 882c4a53faf..a2aa6b3fea5 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -496,7 +496,6 @@ pub const fn type_name<T: ?Sized>() -> &'static str {
 /// ```
 #[unstable(feature = "type_name_of_val", issue = "66359")]
 #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
-pub const fn type_name_of_val<T: ?Sized>(val: &T) -> &'static str {
-    let _ = val;
+pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
     type_name::<T>()
 }
diff --git a/src/libcore/array/mod.rs b/src/libcore/array/mod.rs
index 38d248d701d..fd80000b6fb 100644
--- a/src/libcore/array/mod.rs
+++ b/src/libcore/array/mod.rs
@@ -74,7 +74,7 @@ impl TryFromSliceError {
     #[unstable(feature = "array_error_internals",
            reason = "available through Error trait and this method should not \
                      be exposed publicly",
-           issue = "0")]
+           issue = "none")]
     #[inline]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
@@ -388,14 +388,14 @@ where
 #[rustc_on_unimplemented(
     message="arrays only have std trait implementations for lengths 0..=32",
 )]
-#[unstable(feature = "const_generic_impls_guard", issue = "0",
+#[unstable(feature = "const_generic_impls_guard", issue = "none",
     reason = "will never be stable, just a temporary step until const generics are stable")]
 pub trait LengthAtMost32 {}
 
 macro_rules! array_impls {
     ($($N:literal)+) => {
         $(
-            #[unstable(feature = "const_generic_impls_guard", issue = "0")]
+            #[unstable(feature = "const_generic_impls_guard", issue = "none")]
             impl<T> LengthAtMost32 for [T; $N] {}
         )+
     }
diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs
index dd21c72e745..315020bac58 100644
--- a/src/libcore/char/convert.rs
+++ b/src/libcore/char/convert.rs
@@ -169,7 +169,7 @@ impl ParseCharError {
     #[unstable(
         feature = "char_error_internals",
         reason = "this method should not be available publicly",
-        issue = "0"
+        issue = "none"
     )]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 18f808638de..9a412e57294 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -150,7 +150,7 @@ pub macro Clone($item:item) {
 #[unstable(
     feature = "derive_clone_copy",
     reason = "deriving hack, should not be public",
-    issue = "0"
+    issue = "none"
 )]
 pub struct AssertParamIsClone<T: Clone + ?Sized> {
     _field: crate::marker::PhantomData<T>,
@@ -160,7 +160,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> {
 #[unstable(
     feature = "derive_clone_copy",
     reason = "deriving hack, should not be public",
-    issue = "0"
+    issue = "none"
 )]
 pub struct AssertParamIsCopy<T: Copy + ?Sized> {
     _field: crate::marker::PhantomData<T>,
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 4aa52a7a390..a0e72fb66b0 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -288,7 +288,7 @@ pub macro Eq($item:item) { /* compiler built-in */ }
 #[allow(missing_debug_implementations)]
 #[unstable(feature = "derive_eq",
            reason = "deriving hack, should not be public",
-           issue = "0")]
+           issue = "none")]
 pub struct AssertParamIsEq<T: Eq + ?Sized> { _field: crate::marker::PhantomData<T> }
 
 /// An `Ordering` is the result of a comparison between two values.
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
index 74ec24939a3..6277da4f123 100644
--- a/src/libcore/ffi.rs
+++ b/src/libcore/ffi.rs
@@ -38,14 +38,14 @@ pub enum c_void {
     #[unstable(
         feature = "c_void_variant",
         reason = "temporary implementation detail",
-        issue = "0"
+        issue = "none"
     )]
     #[doc(hidden)]
     __variant1,
     #[unstable(
         feature = "c_void_variant",
         reason = "temporary implementation detail",
-        issue = "0"
+        issue = "none"
     )]
     #[doc(hidden)]
     __variant2,
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 793c1f124ed..6c8d1626b09 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -35,7 +35,7 @@ pub enum Alignment {
 #[stable(feature = "debug_builders", since = "1.2.0")]
 pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
 
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
 #[doc(hidden)]
 pub mod rt {
     pub mod v1;
@@ -259,7 +259,7 @@ struct Void {
 /// types, and then this struct is used to canonicalize arguments to one type.
 #[derive(Copy, Clone)]
 #[allow(missing_debug_implementations)]
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
 #[doc(hidden)]
 pub struct ArgumentV1<'a> {
     value: &'a Void,
@@ -273,13 +273,13 @@ impl<'a> ArgumentV1<'a> {
     }
 
     #[doc(hidden)]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
         unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }
     }
 
     #[doc(hidden)]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
         ArgumentV1::new(x, ArgumentV1::show_usize)
     }
@@ -309,7 +309,7 @@ impl<'a> Arguments<'a> {
     /// Arguments structure.
     #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn new_v1(pieces: &'a [&'a str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
         Arguments { pieces, fmt: None, args }
     }
@@ -322,7 +322,7 @@ impl<'a> Arguments<'a> {
     /// unsafety, but will ignore invalid .
     #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn new_v1_formatted(
         pieces: &'a [&'a str],
         args: &'a [ArgumentV1<'a>],
@@ -337,7 +337,7 @@ impl<'a> Arguments<'a> {
     /// when using `format!`. Note: this is neither the lower nor upper bound.
     #[doc(hidden)]
     #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn estimated_capacity(&self) -> usize {
         let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();
 
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 0db8d86ebbf..2a7fa58dd30 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -90,7 +90,7 @@ use crate::marker;
 #[allow(deprecated)]
 pub use self::sip::SipHasher;
 
-#[unstable(feature = "hashmap_internals", issue = "0")]
+#[unstable(feature = "hashmap_internals", issue = "none")]
 #[allow(deprecated)]
 #[doc(hidden)]
 pub use self::sip::SipHasher13;
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index 0aa3b97ebcf..7ebe01e26dc 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -15,7 +15,7 @@ use crate::ptr;
 /// (e.g., `collections::HashMap` uses it by default).
 ///
 /// See: <https://131002.net/siphash>
-#[unstable(feature = "hashmap_internals", issue = "0")]
+#[unstable(feature = "hashmap_internals", issue = "none")]
 #[rustc_deprecated(
     since = "1.13.0",
     reason = "use `std::collections::hash_map::DefaultHasher` instead"
@@ -29,7 +29,7 @@ pub struct SipHasher13 {
 /// An implementation of SipHash 2-4.
 ///
 /// See: <https://131002.net/siphash/>
-#[unstable(feature = "hashmap_internals", issue = "0")]
+#[unstable(feature = "hashmap_internals", issue = "none")]
 #[rustc_deprecated(
     since = "1.13.0",
     reason = "use `std::collections::hash_map::DefaultHasher` instead"
@@ -172,7 +172,7 @@ impl SipHasher {
 impl SipHasher13 {
     /// Creates a new `SipHasher13` with the two initial keys set to 0.
     #[inline]
-    #[unstable(feature = "hashmap_internals", issue = "0")]
+    #[unstable(feature = "hashmap_internals", issue = "none")]
     #[rustc_deprecated(
         since = "1.13.0",
         reason = "use `std::collections::hash_map::DefaultHasher` instead"
@@ -183,7 +183,7 @@ impl SipHasher13 {
 
     /// Creates a `SipHasher13` that is keyed off the provided keys.
     #[inline]
-    #[unstable(feature = "hashmap_internals", issue = "0")]
+    #[unstable(feature = "hashmap_internals", issue = "none")]
     #[rustc_deprecated(
         since = "1.13.0",
         reason = "use `std::collections::hash_map::DefaultHasher` instead"
@@ -264,7 +264,7 @@ impl super::Hasher for SipHasher {
     }
 }
 
-#[unstable(feature = "hashmap_internals", issue = "0")]
+#[unstable(feature = "hashmap_internals", issue = "none")]
 impl super::Hasher for SipHasher13 {
     #[inline]
     fn write(&mut self, msg: &[u8]) {
diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs
index 3acf2ec837d..4ea7dfc0735 100644
--- a/src/libcore/internal_macros.rs
+++ b/src/libcore/internal_macros.rs
@@ -77,7 +77,7 @@ macro_rules! forward_ref_op_assign {
 }
 
 /// Create a zero-size type similar to a closure type, but named.
-#[unstable(feature = "std_internals", issue = "0")]
+#[unstable(feature = "std_internals", issue = "none")]
 macro_rules! impl_fn_for_zst {
     ($(
         $( #[$attr: meta] )*
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index b02acce2d00..e73d125c13f 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -33,7 +33,7 @@
             reason = "intrinsics are unlikely to ever be stabilized, instead \
                       they should be used through stabilized interfaces \
                       in the rest of the standard library",
-            issue = "0")]
+            issue = "none")]
 #![allow(missing_docs)]
 
 use crate::mem;
@@ -709,7 +709,7 @@ extern "rust-intrinsic" {
                reason = "intrinsics are unlikely to ever be stabilized, instead \
                          they should be used through stabilized interfaces \
                          in the rest of the standard library",
-               issue = "0")]
+               issue = "none")]
     #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned",
                        since = "1.38.0")]
     pub fn init<T>() -> T;
@@ -725,7 +725,7 @@ extern "rust-intrinsic" {
                reason = "intrinsics are unlikely to ever be stabilized, instead \
                          they should be used through stabilized interfaces \
                          in the rest of the standard library",
-               issue = "0")]
+               issue = "none")]
     #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned",
                        since = "1.38.0")]
     pub fn uninit<T>() -> T;
diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs
index dd06da7a6d2..6c7ec2cbfe3 100644
--- a/src/libcore/macros/mod.rs
+++ b/src/libcore/macros/mod.rs
@@ -799,7 +799,7 @@ pub(crate) mod builtin {
     /// Same as `format_args`, but adds a newline in the end.
     #[unstable(
         feature = "format_args_nl",
-        issue = "0",
+        issue = "none",
         reason = "`format_args_nl` is only for internal \
                   language use and is subject to change"
     )]
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index 7f80f61aaf9..de3b837fb68 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -301,7 +301,7 @@ impl<T> MaybeUninit<T> {
     /// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
     /// let data = read(&mut buf);
     /// ```
-    #[unstable(feature = "maybe_uninit_uninit_array", issue = "0")]
+    #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
     #[inline(always)]
     pub fn uninit_array<const LEN: usize>() -> [Self; LEN] {
         unsafe {
@@ -310,7 +310,7 @@ impl<T> MaybeUninit<T> {
     }
 
     /// A promotable constant, equivalent to `uninit()`.
-    #[unstable(feature = "internal_uninit_const", issue = "0",
+    #[unstable(feature = "internal_uninit_const", issue = "none",
         reason = "hack to work around promotability")]
     pub const UNINIT: Self = Self::uninit();
 
@@ -749,7 +749,7 @@ impl<T> MaybeUninit<T> {
     /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
     /// really are in an initialized state.
     /// Calling this when the content is not yet fully initialized causes undefined behavior.
-    #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")]
+    #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")]
     #[inline(always)]
     pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] {
         &*(slice as *const [Self] as *const [T])
@@ -762,7 +762,7 @@ impl<T> MaybeUninit<T> {
     /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
     /// really are in an initialized state.
     /// Calling this when the content is not yet fully initialized causes undefined behavior.
-    #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")]
+    #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")]
     #[inline(always)]
     pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] {
         &mut *(slice as *mut [Self] as *mut [T])
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 4e8ba8131f7..db5d2650331 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -121,7 +121,7 @@ pub fn forget<T>(t: T) {
 ///
 /// [`forget`]: fn.forget.html
 #[inline]
-#[unstable(feature = "forget_unsized", issue = "0")]
+#[unstable(feature = "forget_unsized", issue = "none")]
 pub fn forget_unsized<T: ?Sized>(t: T) {
     // SAFETY: the forget intrinsic could be safe, but there's no point in making it safe since
     // we'll be implementing this function soon via `ManuallyDrop`
diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs
index b8ddd5322a1..39cc381b64c 100644
--- a/src/libcore/num/bignum.rs
+++ b/src/libcore/num/bignum.rs
@@ -15,7 +15,7 @@
 #![unstable(
     feature = "core_private_bignum",
     reason = "internal routines only exposed for testing",
-    issue = "0"
+    issue = "none"
 )]
 #![macro_use]
 
diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs
index 6fe9af8cbd8..c83c6b0eccb 100644
--- a/src/libcore/num/dec2flt/mod.rs
+++ b/src/libcore/num/dec2flt/mod.rs
@@ -81,7 +81,7 @@
 #![unstable(
     feature = "dec2flt",
     reason = "internal routines only exposed for testing",
-    issue = "0"
+    issue = "none"
 )]
 
 use crate::fmt;
@@ -187,7 +187,7 @@ impl ParseFloatError {
         feature = "int_error_internals",
         reason = "available through Error trait and this method should \
                   not be exposed publicly",
-        issue = "0"
+        issue = "none"
     )]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs
index 0e601d45a21..0a609417dcf 100644
--- a/src/libcore/num/diy_float.rs
+++ b/src/libcore/num/diy_float.rs
@@ -6,7 +6,7 @@
 #![unstable(
     feature = "core_private_diy_float",
     reason = "internal routines only exposed for testing",
-    issue = "0"
+    issue = "none"
 )]
 
 /// A custom 64-bit floating point type, representing `f * 2^e`.
diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs
index 63df5613453..9e760c13c0c 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -119,7 +119,7 @@ functions.
 #![unstable(
     feature = "flt2dec",
     reason = "internal routines only exposed for testing",
-    issue = "0"
+    issue = "none"
 )]
 
 pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 6c864f74b1f..8a32479b2ff 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -4769,7 +4769,7 @@ impl TryFromIntError {
         feature = "int_error_internals",
         reason = "available through Error trait and this method should \
                   not be exposed publicly",
-        issue = "0"
+        issue = "none"
     )]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
@@ -4968,7 +4968,7 @@ impl ParseIntError {
         feature = "int_error_internals",
         reason = "available through Error trait and this method should \
                   not be exposed publicly",
-        issue = "0"
+        issue = "none"
     )]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index f521355a907..68244fdb381 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -178,14 +178,14 @@ impl<T: ?Sized> DerefMut for &mut T {
 /// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
 /// `Rc<T>`, `&T`, and `Pin<P>`.
 #[lang = "receiver"]
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 #[doc(hidden)]
 pub trait Receiver {
     // Empty.
 }
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for &T {}
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for &mut T {}
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs
index 80ab906961e..77b92b6ccbd 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -168,7 +168,7 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::deref::{Deref, DerefMut};
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 pub use self::deref::Receiver;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -195,5 +195,5 @@ pub use self::generator::{Generator, GeneratorState};
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 pub use self::unsize::CoerceUnsized;
 
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 pub use self::unsize::DispatchFromDyn;
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index be6d8edb99f..d38b3516569 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -333,6 +333,11 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 #[derive(Clone)] // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
+    // Note that the fields here are not public to allow changing the
+    // representation in the future; in particular, while we could plausibly
+    // expose start/end, modifying them without changing (future/current)
+    // private fields may lead to incorrect behavior, so we don't want to
+    // support that mode.
     pub(crate) start: Idx,
     pub(crate) end: Idx,
     pub(crate) is_empty: Option<bool>,
diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs
index 80fb5642a6a..95a4393592b 100644
--- a/src/libcore/ops/unsize.rs
+++ b/src/libcore/ops/unsize.rs
@@ -81,21 +81,21 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
 ///     T: Unsize<U>,
 /// {}
 /// ```
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 #[lang = "dispatch_from_dyn"]
 pub trait DispatchFromDyn<T> {
     // Empty.
 }
 
 // &T -> &U
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
 // &mut T -> &mut U
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
 // *const T -> *const U
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
 // *mut T -> *mut U
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs
index c9a1c4b0049..a90b025c093 100644
--- a/src/libcore/panic.rs
+++ b/src/libcore/panic.rs
@@ -40,7 +40,7 @@ impl<'a> PanicInfo<'a> {
     #[unstable(feature = "panic_internals",
                reason = "internal details of the implementation of the `panic!` \
                          and related macros",
-               issue = "0")]
+               issue = "none")]
     #[doc(hidden)]
     #[inline]
     pub fn internal_constructor(
@@ -58,7 +58,7 @@ impl<'a> PanicInfo<'a> {
     #[unstable(feature = "panic_internals",
                reason = "internal details of the implementation of the `panic!` \
                          and related macros",
-               issue = "0")]
+               issue = "none")]
     #[doc(hidden)]
     #[inline]
     pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
@@ -235,7 +235,7 @@ impl<'a> Location<'a> {
     #![unstable(feature = "panic_internals",
                 reason = "internal details of the implementation of the `panic!` \
                           and related macros",
-                issue = "0")]
+                issue = "none")]
     #[doc(hidden)]
     pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
         Location { file, line, col }
@@ -318,7 +318,7 @@ impl fmt::Display for Location<'_> {
 /// An internal trait used by libstd to pass data from libstd to `panic_unwind`
 /// and other panic runtimes. Not intended to be stabilized any time soon, do
 /// not use.
-#[unstable(feature = "std_internals", issue = "0")]
+#[unstable(feature = "std_internals", issue = "none")]
 #[doc(hidden)]
 pub unsafe trait BoxMeUp {
     /// Take full ownership of the contents.
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 4857b114595..7ebb72e3ce7 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -26,7 +26,7 @@
     feature = "core_panic",
     reason = "internal details of the implementation of the `panic!` \
               and related macros",
-    issue = "0"
+    issue = "none"
 )]
 
 use crate::fmt;
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 6a0c5bbebc1..aca6fb20138 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -786,7 +786,7 @@ impl<P: DerefMut<Target: Unpin>> DerefMut for Pin<P> {
     }
 }
 
-#[unstable(feature = "receiver_trait", issue = "0")]
+#[unstable(feature = "receiver_trait", issue = "none")]
 impl<P: Receiver> Receiver for Pin<P> {}
 
 #[stable(feature = "pin", since = "1.33.0")]
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
new file mode 100644
index 00000000000..be2b7ff5f77
--- /dev/null
+++ b/src/libcore/ptr/const_ptr.rs
@@ -0,0 +1,755 @@
+use crate::cmp::Ordering::{self, Less, Equal, Greater};
+use crate::intrinsics;
+use crate::mem;
+use super::*;
+
+// ignore-tidy-undocumented-unsafe
+
+#[lang = "const_ptr"]
+impl<T: ?Sized> *const T {
+    /// Returns `true` if the pointer is null.
+    ///
+    /// Note that unsized types have many possible null pointers, as only the
+    /// raw data pointer is considered, not their length, vtable, etc.
+    /// Therefore, two pointers that are null may still not compare equal to
+    /// each other.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s: &str = "Follow the rabbit";
+    /// let ptr: *const u8 = s.as_ptr();
+    /// assert!(!ptr.is_null());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub 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()
+    }
+
+    /// Casts to a pointer of another type.
+    #[stable(feature = "ptr_cast", since = "1.38.0")]
+    #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
+    #[inline]
+    pub const fn cast<U>(self) -> *const U {
+        self as _
+    }
+
+    /// Returns `None` if the pointer is null, or else returns a reference to
+    /// the value wrapped in `Some`.
+    ///
+    /// # Safety
+    ///
+    /// 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.
+    ///
+    /// 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].
+    ///
+    /// 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
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let ptr: *const u8 = &10u8 as *const u8;
+    ///
+    /// unsafe {
+    ///     if let Some(val_back) = ptr.as_ref() {
+    ///         println!("We got back the value: {}!", val_back);
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// # Null-unchecked version
+    ///
+    /// If you are sure the pointer can never be null and are looking for some kind of
+    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
+    /// dereference the pointer directly.
+    ///
+    /// ```
+    /// let ptr: *const u8 = &10u8 as *const u8;
+    ///
+    /// unsafe {
+    ///     let val_back = &*ptr;
+    ///     println!("We got back the value: {}!", val_back);
+    /// }
+    /// ```
+    #[stable(feature = "ptr_as_ref", since = "1.9.0")]
+    #[inline]
+    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+        if self.is_null() { None } else { Some(&*self) }
+    }
+
+    /// Calculates the offset from a pointer.
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_offset`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// [`wrapping_offset`]: #method.wrapping_offset
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s: &str = "123";
+    /// let ptr: *const u8 = s.as_ptr();
+    ///
+    /// unsafe {
+    ///     println!("{}", *ptr.offset(1) as char);
+    ///     println!("{}", *ptr.offset(2) as char);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn offset(self, count: isize) -> *const T
+        where
+            T: Sized,
+    {
+        intrinsics::offset(self, count)
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// In particular, the resulting pointer remains attached to the same allocated
+    /// object that `self` points to. It may *not* be used to access a
+    /// different allocated object. Note that in Rust,
+    /// every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
+    /// *not* the same as `y`, and dereferencing it is undefined behavior
+    /// unless `x` and `y` point into the same allocated object.
+    ///
+    /// Compared to [`offset`], this method basically delays the requirement of staying
+    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
+    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
+    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`offset`]: #method.offset
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // Iterate using a raw pointer in increments of two elements
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let step = 2;
+    /// let end_rounded_up = ptr.wrapping_offset(6);
+    ///
+    /// // This loop prints "1, 3, 5, "
+    /// while ptr != end_rounded_up {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_offset(step);
+    /// }
+    /// ```
+    #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
+    #[inline]
+    pub fn wrapping_offset(self, count: isize) -> *const T
+        where
+            T: Sized,
+    {
+        unsafe { intrinsics::arith_offset(self, count) }
+    }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// This function is the inverse of [`offset`].
+    ///
+    /// [`offset`]: #method.offset
+    /// [`wrapping_offset_from`]: #method.wrapping_offset_from
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and other pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
+    ///
+    /// * The distance between the pointers, in bytes, must be an exact multiple
+    ///   of the size of `T`.
+    ///
+    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
+    ///
+    /// The compiler and standard library generally try to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_offset_from`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// # Panics
+    ///
+    /// This function panics if `T` is a Zero-Sized Type ("ZST").
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_offset_from)]
+    ///
+    /// let a = [0; 5];
+    /// let ptr1: *const i32 = &a[1];
+    /// let ptr2: *const i32 = &a[3];
+    /// unsafe {
+    ///     assert_eq!(ptr2.offset_from(ptr1), 2);
+    ///     assert_eq!(ptr1.offset_from(ptr2), -2);
+    ///     assert_eq!(ptr1.offset(2), ptr2);
+    ///     assert_eq!(ptr2.offset(-2), ptr1);
+    /// }
+    /// ```
+    #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
+    #[inline]
+    pub const unsafe fn offset_from(self, origin: *const T) -> isize
+        where
+            T: Sized,
+    {
+        let pointee_size = mem::size_of::<T>();
+        let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize;
+        // assert that the pointee size is valid in a const eval compatible way
+        // FIXME: do this with a real assert at some point
+        [()][(!ok) as usize];
+        intrinsics::ptr_offset_from(self, origin)
+    }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// If the address different between the two pointers is not a multiple of
+    /// `mem::size_of::<T>()` then the result of the division is rounded towards
+    /// zero.
+    ///
+    /// Though this method is safe for any two pointers, note that its result
+    /// will be mostly useless if the two pointers aren't into the same allocated
+    /// object, for example if they point to two different local variables.
+    ///
+    /// # Panics
+    ///
+    /// This function panics if `T` is a zero-sized type.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_wrapping_offset_from)]
+    ///
+    /// let a = [0; 5];
+    /// let ptr1: *const i32 = &a[1];
+    /// let ptr2: *const i32 = &a[3];
+    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+    /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
+    /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
+    /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
+    ///
+    /// let ptr1: *const i32 = 3 as _;
+    /// let ptr2: *const i32 = 13 as _;
+    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+    /// ```
+    #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
+    #[inline]
+    pub fn wrapping_offset_from(self, origin: *const T) -> isize
+        where
+            T: Sized,
+    {
+        let pointee_size = mem::size_of::<T>();
+        assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
+
+        let d = isize::wrapping_sub(self as _, origin as _);
+        d.wrapping_div(pointee_size as _)
+    }
+
+    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a `usize`.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_add`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// [`wrapping_add`]: #method.wrapping_add
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s: &str = "123";
+    /// let ptr: *const u8 = s.as_ptr();
+    ///
+    /// unsafe {
+    ///     println!("{}", *ptr.add(1) as char);
+    ///     println!("{}", *ptr.add(2) as char);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn add(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer (convenience for
+    /// `.offset((count as isize).wrapping_neg())`).
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_sub`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// [`wrapping_sub`]: #method.wrapping_sub
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s: &str = "123";
+    ///
+    /// unsafe {
+    ///     let end: *const u8 = s.as_ptr().add(3);
+    ///     println!("{}", *end.sub(1) as char);
+    ///     println!("{}", *end.sub(2) as char);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn sub(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.offset((count as isize).wrapping_neg())
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset(count as isize)`)
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// In particular, the resulting pointer remains attached to the same allocated
+    /// object that `self` points to. It may *not* be used to access a
+    /// different allocated object. Note that in Rust,
+    /// every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// Compared to [`add`], this method basically delays the requirement of staying
+    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
+    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
+    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`add`]: #method.add
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // Iterate using a raw pointer in increments of two elements
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let step = 2;
+    /// let end_rounded_up = ptr.wrapping_add(6);
+    ///
+    /// // This loop prints "1, 3, 5, "
+    /// while ptr != end_rounded_up {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_add(step);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub fn wrapping_add(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.wrapping_offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// In particular, the resulting pointer remains attached to the same allocated
+    /// object that `self` points to. It may *not* be used to access a
+    /// different allocated object. Note that in Rust,
+    /// every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// Compared to [`sub`], this method basically delays the requirement of staying
+    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
+    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
+    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`sub`]: #method.sub
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // Iterate using a raw pointer in increments of two elements (backwards)
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let start_rounded_down = ptr.wrapping_sub(2);
+    /// ptr = ptr.wrapping_add(4);
+    /// let step = 2;
+    /// // This loop prints "5, 3, 1, "
+    /// while ptr != start_rounded_down {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_sub(step);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub fn wrapping_sub(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.wrapping_offset((count as isize).wrapping_neg())
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// See [`ptr::read`] for safety concerns and examples.
+    ///
+    /// [`ptr::read`]: ./ptr/fn.read.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn read(self) -> T
+        where
+            T: Sized,
+    {
+        read(self)
+    }
+
+    /// Performs a volatile read of the value from `self` without moving it. This
+    /// leaves the memory in `self` unchanged.
+    ///
+    /// Volatile operations are intended to act on I/O memory, and are guaranteed
+    /// to not be elided or reordered by the compiler across other volatile
+    /// operations.
+    ///
+    /// See [`ptr::read_volatile`] for safety concerns and examples.
+    ///
+    /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn read_volatile(self) -> T
+        where
+            T: Sized,
+    {
+        read_volatile(self)
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// Unlike `read`, the pointer may be unaligned.
+    ///
+    /// See [`ptr::read_unaligned`] for safety concerns and examples.
+    ///
+    /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn read_unaligned(self) -> T
+        where
+            T: Sized,
+    {
+        read_unaligned(self)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may overlap.
+    ///
+    /// NOTE: this has the *same* argument order as [`ptr::copy`].
+    ///
+    /// See [`ptr::copy`] for safety concerns and examples.
+    ///
+    /// [`ptr::copy`]: ./ptr/fn.copy.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+        where
+            T: Sized,
+    {
+        copy(self, dest, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may *not* overlap.
+    ///
+    /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
+    ///
+    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
+    ///
+    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+        where
+            T: Sized,
+    {
+        copy_nonoverlapping(self, dest, count)
+    }
+
+    /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
+    /// `align`.
+    ///
+    /// If it is not possible to align the pointer, the implementation returns
+    /// `usize::max_value()`. It is permissible for the implementation to *always*
+    /// return `usize::max_value()`. Only your algorithm's performance can depend
+    /// on getting a usable offset here, not its correctness.
+    ///
+    /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
+    /// used with the `wrapping_add` method.
+    ///
+    /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
+    /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
+    /// the returned offset is correct in all terms other than alignment.
+    ///
+    /// # Panics
+    ///
+    /// The function panics if `align` is not a power-of-two.
+    ///
+    /// # Examples
+    ///
+    /// Accessing adjacent `u8` as `u16`
+    ///
+    /// ```
+    /// # fn foo(n: usize) {
+    /// # use std::mem::align_of;
+    /// # unsafe {
+    /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
+    /// let ptr = &x[n] as *const u8;
+    /// let offset = ptr.align_offset(align_of::<u16>());
+    /// if offset < x.len() - n - 1 {
+    ///     let u16_ptr = ptr.add(offset) as *const u16;
+    ///     assert_ne!(*u16_ptr, 500);
+    /// } else {
+    ///     // while the pointer can be aligned via `offset`, it would point
+    ///     // outside the allocation
+    /// }
+    /// # } }
+    /// ```
+    #[stable(feature = "align_offset", since = "1.36.0")]
+    pub fn align_offset(self, align: usize) -> usize
+        where
+            T: Sized,
+    {
+        if !align.is_power_of_two() {
+            panic!("align_offset: align is not a power-of-two");
+        }
+        unsafe { align_offset(self, align) }
+    }
+}
+
+// Equality for pointers
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialEq for *const T {
+    #[inline]
+    fn eq(&self, other: &*const T) -> bool { *self == *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Eq for *const T {}
+
+// Comparison for pointers
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Ord for *const T {
+    #[inline]
+    fn cmp(&self, other: &*const T) -> Ordering {
+        if self < other {
+            Less
+        } else if self == other {
+            Equal
+        } else {
+            Greater
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialOrd for *const T {
+    #[inline]
+    fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+
+    #[inline]
+    fn lt(&self, other: &*const T) -> bool { *self < *other }
+
+    #[inline]
+    fn le(&self, other: &*const T) -> bool { *self <= *other }
+
+    #[inline]
+    fn gt(&self, other: &*const T) -> bool { *self > *other }
+
+    #[inline]
+    fn ge(&self, other: &*const T) -> bool { *self >= *other }
+}
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 776165e7bd7..d42b673ff65 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -65,16 +65,15 @@
 //! [`write_volatile`]: ./fn.write_volatile.html
 //! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
 
-// ignore-tidy-filelength
 // ignore-tidy-undocumented-unsafe
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::cmp::Ordering::{self, Equal, Greater, Less};
+use crate::intrinsics;
 use crate::fmt;
 use crate::hash;
-use crate::intrinsics;
 use crate::mem::{self, MaybeUninit};
+use crate::cmp::Ordering;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use crate::intrinsics::copy_nonoverlapping;
@@ -90,9 +89,12 @@ mod non_null;
 pub use non_null::NonNull;
 
 mod unique;
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 pub use unique::Unique;
 
+mod const_ptr;
+mod mut_ptr;
+
 /// Executes the destructor (if any) of the pointed-to value.
 ///
 /// This is semantically equivalent to calling [`ptr::read`] and discarding
@@ -257,7 +259,8 @@ pub(crate) struct FatPtr<T> {
 /// ```
 #[inline]
 #[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")]
-pub fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
     unsafe { Repr { raw: FatPtr { data, len } }.rust }
 }
 
@@ -273,7 +276,8 @@ pub fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
 /// [`from_raw_parts_mut`]: ../../std/slice/fn.from_raw_parts_mut.html
 #[inline]
 #[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")]
-pub fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
+#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
     unsafe { Repr { raw: FatPtr { data, len } }.rust_mut }
 }
 
@@ -1034,1586 +1038,6 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     intrinsics::volatile_store(dst, src);
 }
 
-#[lang = "const_ptr"]
-impl<T: ?Sized> *const T {
-    /// Returns `true` if the pointer is null.
-    ///
-    /// Note that unsized types have many possible null pointers, as only the
-    /// raw data pointer is considered, not their length, vtable, etc.
-    /// Therefore, two pointers that are null may still not compare equal to
-    /// each other.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s: &str = "Follow the rabbit";
-    /// let ptr: *const u8 = s.as_ptr();
-    /// assert!(!ptr.is_null());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub 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()
-    }
-
-    /// Casts to a pointer of another type.
-    #[stable(feature = "ptr_cast", since = "1.38.0")]
-    #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
-    #[inline]
-    pub const fn cast<U>(self) -> *const U {
-        self as _
-    }
-
-    /// Returns `None` if the pointer is null, or else returns a reference to
-    /// the value wrapped in `Some`.
-    ///
-    /// # Safety
-    ///
-    /// 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.
-    ///
-    /// 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].
-    ///
-    /// 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
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let ptr: *const u8 = &10u8 as *const u8;
-    ///
-    /// unsafe {
-    ///     if let Some(val_back) = ptr.as_ref() {
-    ///         println!("We got back the value: {}!", val_back);
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// # Null-unchecked version
-    ///
-    /// If you are sure the pointer can never be null and are looking for some kind of
-    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
-    /// dereference the pointer directly.
-    ///
-    /// ```
-    /// let ptr: *const u8 = &10u8 as *const u8;
-    ///
-    /// unsafe {
-    ///     let val_back = &*ptr;
-    ///     println!("We got back the value: {}!", val_back);
-    /// }
-    /// ```
-    #[stable(feature = "ptr_as_ref", since = "1.9.0")]
-    #[inline]
-    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
-        if self.is_null() { None } else { Some(&*self) }
-    }
-
-    /// Calculates the offset from a pointer.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_offset`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_offset`]: #method.wrapping_offset
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s: &str = "123";
-    /// let ptr: *const u8 = s.as_ptr();
-    ///
-    /// unsafe {
-    ///     println!("{}", *ptr.offset(1) as char);
-    ///     println!("{}", *ptr.offset(2) as char);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn offset(self, count: isize) -> *const T
-    where
-        T: Sized,
-    {
-        intrinsics::offset(self, count)
-    }
-
-    /// Calculates the offset from a pointer using wrapping arithmetic.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
-    ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
-    /// *not* the same as `y`, and dereferencing it is undefined behavior
-    /// unless `x` and `y` point into the same allocated object.
-    ///
-    /// Compared to [`offset`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
-    ///
-    /// If you need to cross object boundaries, cast the pointer to an integer and
-    /// do the arithmetic there.
-    ///
-    /// [`offset`]: #method.offset
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // Iterate using a raw pointer in increments of two elements
-    /// let data = [1u8, 2, 3, 4, 5];
-    /// let mut ptr: *const u8 = data.as_ptr();
-    /// let step = 2;
-    /// let end_rounded_up = ptr.wrapping_offset(6);
-    ///
-    /// // This loop prints "1, 3, 5, "
-    /// while ptr != end_rounded_up {
-    ///     unsafe {
-    ///         print!("{}, ", *ptr);
-    ///     }
-    ///     ptr = ptr.wrapping_offset(step);
-    /// }
-    /// ```
-    #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
-    #[inline]
-    pub fn wrapping_offset(self, count: isize) -> *const T
-    where
-        T: Sized,
-    {
-        unsafe { intrinsics::arith_offset(self, count) }
-    }
-
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// This function is the inverse of [`offset`].
-    ///
-    /// [`offset`]: #method.offset
-    /// [`wrapping_offset_from`]: #method.wrapping_offset_from
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and other pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The distance between the pointers, in bytes, must be an exact multiple
-    ///   of the size of `T`.
-    ///
-    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
-    ///
-    /// The compiler and standard library generally try to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_offset_from`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// # Panics
-    ///
-    /// This function panics if `T` is a Zero-Sized Type ("ZST").
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(ptr_offset_from)]
-    ///
-    /// let a = [0; 5];
-    /// let ptr1: *const i32 = &a[1];
-    /// let ptr2: *const i32 = &a[3];
-    /// unsafe {
-    ///     assert_eq!(ptr2.offset_from(ptr1), 2);
-    ///     assert_eq!(ptr1.offset_from(ptr2), -2);
-    ///     assert_eq!(ptr1.offset(2), ptr2);
-    ///     assert_eq!(ptr2.offset(-2), ptr1);
-    /// }
-    /// ```
-    #[unstable(feature = "ptr_offset_from", issue = "41079")]
-    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
-    #[inline]
-    pub const unsafe fn offset_from(self, origin: *const T) -> isize
-    where
-        T: Sized,
-    {
-        let pointee_size = mem::size_of::<T>();
-        let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize;
-        // assert that the pointee size is valid in a const eval compatible way
-        // FIXME: do this with a real assert at some point
-        [()][(!ok) as usize];
-        intrinsics::ptr_offset_from(self, origin)
-    }
-
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// If the address different between the two pointers is not a multiple of
-    /// `mem::size_of::<T>()` then the result of the division is rounded towards
-    /// zero.
-    ///
-    /// Though this method is safe for any two pointers, note that its result
-    /// will be mostly useless if the two pointers aren't into the same allocated
-    /// object, for example if they point to two different local variables.
-    ///
-    /// # Panics
-    ///
-    /// This function panics if `T` is a zero-sized type.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(ptr_wrapping_offset_from)]
-    ///
-    /// let a = [0; 5];
-    /// let ptr1: *const i32 = &a[1];
-    /// let ptr2: *const i32 = &a[3];
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
-    /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
-    /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
-    ///
-    /// let ptr1: *const i32 = 3 as _;
-    /// let ptr2: *const i32 = 13 as _;
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// ```
-    #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
-    #[inline]
-    pub fn wrapping_offset_from(self, origin: *const T) -> isize
-    where
-        T: Sized,
-    {
-        let pointee_size = mem::size_of::<T>();
-        assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
-
-        let d = isize::wrapping_sub(self as _, origin as _);
-        d.wrapping_div(pointee_size as _)
-    }
-
-    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a `usize`.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_add`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_add`]: #method.wrapping_add
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s: &str = "123";
-    /// let ptr: *const u8 = s.as_ptr();
-    ///
-    /// unsafe {
-    ///     println!("{}", *ptr.add(1) as char);
-    ///     println!("{}", *ptr.add(2) as char);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn add(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.offset(count as isize)
-    }
-
-    /// Calculates the offset from a pointer (convenience for
-    /// `.offset((count as isize).wrapping_neg())`).
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
-    ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_sub`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_sub`]: #method.wrapping_sub
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s: &str = "123";
-    ///
-    /// unsafe {
-    ///     let end: *const u8 = s.as_ptr().add(3);
-    ///     println!("{}", *end.sub(1) as char);
-    ///     println!("{}", *end.sub(2) as char);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn sub(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.offset((count as isize).wrapping_neg())
-    }
-
-    /// Calculates the offset from a pointer using wrapping arithmetic.
-    /// (convenience for `.wrapping_offset(count as isize)`)
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
-    ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// Compared to [`add`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
-    ///
-    /// If you need to cross object boundaries, cast the pointer to an integer and
-    /// do the arithmetic there.
-    ///
-    /// [`add`]: #method.add
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // Iterate using a raw pointer in increments of two elements
-    /// let data = [1u8, 2, 3, 4, 5];
-    /// let mut ptr: *const u8 = data.as_ptr();
-    /// let step = 2;
-    /// let end_rounded_up = ptr.wrapping_add(6);
-    ///
-    /// // This loop prints "1, 3, 5, "
-    /// while ptr != end_rounded_up {
-    ///     unsafe {
-    ///         print!("{}, ", *ptr);
-    ///     }
-    ///     ptr = ptr.wrapping_add(step);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub fn wrapping_add(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.wrapping_offset(count as isize)
-    }
-
-    /// Calculates the offset from a pointer using wrapping arithmetic.
-    /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
-    ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// Compared to [`sub`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
-    ///
-    /// If you need to cross object boundaries, cast the pointer to an integer and
-    /// do the arithmetic there.
-    ///
-    /// [`sub`]: #method.sub
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // Iterate using a raw pointer in increments of two elements (backwards)
-    /// let data = [1u8, 2, 3, 4, 5];
-    /// let mut ptr: *const u8 = data.as_ptr();
-    /// let start_rounded_down = ptr.wrapping_sub(2);
-    /// ptr = ptr.wrapping_add(4);
-    /// let step = 2;
-    /// // This loop prints "5, 3, 1, "
-    /// while ptr != start_rounded_down {
-    ///     unsafe {
-    ///         print!("{}, ", *ptr);
-    ///     }
-    ///     ptr = ptr.wrapping_sub(step);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub fn wrapping_sub(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.wrapping_offset((count as isize).wrapping_neg())
-    }
-
-    /// Reads the value from `self` without moving it. This leaves the
-    /// memory in `self` unchanged.
-    ///
-    /// See [`ptr::read`] for safety concerns and examples.
-    ///
-    /// [`ptr::read`]: ./ptr/fn.read.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn read(self) -> T
-    where
-        T: Sized,
-    {
-        read(self)
-    }
-
-    /// Performs a volatile read of the value from `self` without moving it. This
-    /// leaves the memory in `self` unchanged.
-    ///
-    /// Volatile operations are intended to act on I/O memory, and are guaranteed
-    /// to not be elided or reordered by the compiler across other volatile
-    /// operations.
-    ///
-    /// See [`ptr::read_volatile`] for safety concerns and examples.
-    ///
-    /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn read_volatile(self) -> T
-    where
-        T: Sized,
-    {
-        read_volatile(self)
-    }
-
-    /// Reads the value from `self` without moving it. This leaves the
-    /// memory in `self` unchanged.
-    ///
-    /// Unlike `read`, the pointer may be unaligned.
-    ///
-    /// See [`ptr::read_unaligned`] for safety concerns and examples.
-    ///
-    /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn read_unaligned(self) -> T
-    where
-        T: Sized,
-    {
-        read_unaligned(self)
-    }
-
-    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
-    /// and destination may overlap.
-    ///
-    /// NOTE: this has the *same* argument order as [`ptr::copy`].
-    ///
-    /// See [`ptr::copy`] for safety concerns and examples.
-    ///
-    /// [`ptr::copy`]: ./ptr/fn.copy.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
-    where
-        T: Sized,
-    {
-        copy(self, dest, count)
-    }
-
-    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
-    /// and destination may *not* overlap.
-    ///
-    /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
-    ///
-    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
-    ///
-    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
-    where
-        T: Sized,
-    {
-        copy_nonoverlapping(self, dest, count)
-    }
-
-    /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
-    /// `align`.
-    ///
-    /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::max_value()`. It is permissible for the implementation to *always*
-    /// return `usize::max_value()`. Only your algorithm's performance can depend
-    /// on getting a usable offset here, not its correctness.
-    ///
-    /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
-    /// used with the `wrapping_add` method.
-    ///
-    /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
-    /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
-    /// the returned offset is correct in all terms other than alignment.
-    ///
-    /// # Panics
-    ///
-    /// The function panics if `align` is not a power-of-two.
-    ///
-    /// # Examples
-    ///
-    /// Accessing adjacent `u8` as `u16`
-    ///
-    /// ```
-    /// # fn foo(n: usize) {
-    /// # use std::mem::align_of;
-    /// # unsafe {
-    /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
-    /// let ptr = &x[n] as *const u8;
-    /// let offset = ptr.align_offset(align_of::<u16>());
-    /// if offset < x.len() - n - 1 {
-    ///     let u16_ptr = ptr.add(offset) as *const u16;
-    ///     assert_ne!(*u16_ptr, 500);
-    /// } else {
-    ///     // while the pointer can be aligned via `offset`, it would point
-    ///     // outside the allocation
-    /// }
-    /// # } }
-    /// ```
-    #[stable(feature = "align_offset", since = "1.36.0")]
-    pub fn align_offset(self, align: usize) -> usize
-    where
-        T: Sized,
-    {
-        if !align.is_power_of_two() {
-            panic!("align_offset: align is not a power-of-two");
-        }
-        unsafe { align_offset(self, align) }
-    }
-}
-
-#[lang = "mut_ptr"]
-impl<T: ?Sized> *mut T {
-    /// Returns `true` if the pointer is null.
-    ///
-    /// Note that unsized types have many possible null pointers, as only the
-    /// raw data pointer is considered, not their length, vtable, etc.
-    /// Therefore, two pointers that are null may still not compare equal to
-    /// each other.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = [1, 2, 3];
-    /// let ptr: *mut u32 = s.as_mut_ptr();
-    /// assert!(!ptr.is_null());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub 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()
-    }
-
-    /// Casts to a pointer of another type.
-    #[stable(feature = "ptr_cast", since = "1.38.0")]
-    #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
-    #[inline]
-    pub const fn cast<U>(self) -> *mut U {
-        self as _
-    }
-
-    /// Returns `None` if the pointer is null, or else returns a reference to
-    /// the value wrapped in `Some`.
-    ///
-    /// # Safety
-    ///
-    /// 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.
-    ///
-    /// When calling this method, you have to ensure that if the pointer is
-    /// non-NULL, then it is properly aligned, dereferencable (for the whole
-    /// size of `T`) and points to an initialized instance of `T`. 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. It is up to the
-    /// caller to ensure that for the duration of this lifetime, the memory this
-    /// pointer points to does not get written to outside of `UnsafeCell<U>`.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
-    ///
-    /// unsafe {
-    ///     if let Some(val_back) = ptr.as_ref() {
-    ///         println!("We got back the value: {}!", val_back);
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// # Null-unchecked version
-    ///
-    /// If you are sure the pointer can never be null and are looking for some kind of
-    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
-    /// dereference the pointer directly.
-    ///
-    /// ```
-    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
-    ///
-    /// unsafe {
-    ///     let val_back = &*ptr;
-    ///     println!("We got back the value: {}!", val_back);
-    /// }
-    /// ```
-    #[stable(feature = "ptr_as_ref", since = "1.9.0")]
-    #[inline]
-    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
-        if self.is_null() { None } else { Some(&*self) }
-    }
-
-    /// Calculates the offset from a pointer.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_offset`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_offset`]: #method.wrapping_offset
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = [1, 2, 3];
-    /// let ptr: *mut u32 = s.as_mut_ptr();
-    ///
-    /// unsafe {
-    ///     println!("{}", *ptr.offset(1));
-    ///     println!("{}", *ptr.offset(2));
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn offset(self, count: isize) -> *mut T
-    where
-        T: Sized,
-    {
-        intrinsics::offset(self, count) as *mut T
-    }
-
-    /// Calculates the offset from a pointer using wrapping arithmetic.
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
-    ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
-    /// *not* the same as `y`, and dereferencing it is undefined behavior
-    /// unless `x` and `y` point into the same allocated object.
-    ///
-    /// Compared to [`offset`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
-    ///
-    /// If you need to cross object boundaries, cast the pointer to an integer and
-    /// do the arithmetic there.
-    ///
-    /// [`offset`]: #method.offset
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // Iterate using a raw pointer in increments of two elements
-    /// let mut data = [1u8, 2, 3, 4, 5];
-    /// let mut ptr: *mut u8 = data.as_mut_ptr();
-    /// let step = 2;
-    /// let end_rounded_up = ptr.wrapping_offset(6);
-    ///
-    /// while ptr != end_rounded_up {
-    ///     unsafe {
-    ///         *ptr = 0;
-    ///     }
-    ///     ptr = ptr.wrapping_offset(step);
-    /// }
-    /// assert_eq!(&data, &[0, 2, 0, 4, 0]);
-    /// ```
-    #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
-    #[inline]
-    pub fn wrapping_offset(self, count: isize) -> *mut T
-    where
-        T: Sized,
-    {
-        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`.
-    ///
-    /// # Safety
-    ///
-    /// 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.
-    ///
-    /// 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].
-    ///
-    /// 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.
-    ///
-    /// [here]: crate::ptr#safety
-    /// [`as_ref`]: #method.as_ref
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = [1, 2, 3];
-    /// let ptr: *mut u32 = s.as_mut_ptr();
-    /// let first_value = unsafe { ptr.as_mut().unwrap() };
-    /// *first_value = 4;
-    /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
-    /// ```
-    #[stable(feature = "ptr_as_ref", since = "1.9.0")]
-    #[inline]
-    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
-        if self.is_null() { None } else { Some(&mut *self) }
-    }
-
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// This function is the inverse of [`offset`].
-    ///
-    /// [`offset`]: #method.offset-1
-    /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and other pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The distance between the pointers, in bytes, must be an exact multiple
-    ///   of the size of `T`.
-    ///
-    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
-    ///
-    /// The compiler and standard library generally try to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_offset_from`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// # Panics
-    ///
-    /// This function panics if `T` is a Zero-Sized Type ("ZST").
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(ptr_offset_from)]
-    ///
-    /// let mut a = [0; 5];
-    /// let ptr1: *mut i32 = &mut a[1];
-    /// let ptr2: *mut i32 = &mut a[3];
-    /// unsafe {
-    ///     assert_eq!(ptr2.offset_from(ptr1), 2);
-    ///     assert_eq!(ptr1.offset_from(ptr2), -2);
-    ///     assert_eq!(ptr1.offset(2), ptr2);
-    ///     assert_eq!(ptr2.offset(-2), ptr1);
-    /// }
-    /// ```
-    #[unstable(feature = "ptr_offset_from", issue = "41079")]
-    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
-    #[inline]
-    pub const unsafe fn offset_from(self, origin: *const T) -> isize
-    where
-        T: Sized,
-    {
-        (self as *const T).offset_from(origin)
-    }
-
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// If the address different between the two pointers is not a multiple of
-    /// `mem::size_of::<T>()` then the result of the division is rounded towards
-    /// zero.
-    ///
-    /// Though this method is safe for any two pointers, note that its result
-    /// will be mostly useless if the two pointers aren't into the same allocated
-    /// object, for example if they point to two different local variables.
-    ///
-    /// # Panics
-    ///
-    /// This function panics if `T` is a zero-sized type.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(ptr_wrapping_offset_from)]
-    ///
-    /// let mut a = [0; 5];
-    /// let ptr1: *mut i32 = &mut a[1];
-    /// let ptr2: *mut i32 = &mut a[3];
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
-    /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
-    /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
-    ///
-    /// let ptr1: *mut i32 = 3 as _;
-    /// let ptr2: *mut i32 = 13 as _;
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// ```
-    #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
-    #[inline]
-    pub fn wrapping_offset_from(self, origin: *const T) -> isize
-    where
-        T: Sized,
-    {
-        (self as *const T).wrapping_offset_from(origin)
-    }
-
-    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a `usize`.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_add`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_add`]: #method.wrapping_add
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s: &str = "123";
-    /// let ptr: *const u8 = s.as_ptr();
-    ///
-    /// unsafe {
-    ///     println!("{}", *ptr.add(1) as char);
-    ///     println!("{}", *ptr.add(2) as char);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn add(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.offset(count as isize)
-    }
-
-    /// Calculates the offset from a pointer (convenience for
-    /// `.offset((count as isize).wrapping_neg())`).
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object. Note that in Rust,
-    ///   every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
-    ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    ///
-    /// Consider using [`wrapping_sub`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_sub`]: #method.wrapping_sub
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s: &str = "123";
-    ///
-    /// unsafe {
-    ///     let end: *const u8 = s.as_ptr().add(3);
-    ///     println!("{}", *end.sub(1) as char);
-    ///     println!("{}", *end.sub(2) as char);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn sub(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.offset((count as isize).wrapping_neg())
-    }
-
-    /// Calculates the offset from a pointer using wrapping arithmetic.
-    /// (convenience for `.wrapping_offset(count as isize)`)
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
-    ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// Compared to [`add`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
-    ///
-    /// If you need to cross object boundaries, cast the pointer to an integer and
-    /// do the arithmetic there.
-    ///
-    /// [`add`]: #method.add
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // Iterate using a raw pointer in increments of two elements
-    /// let data = [1u8, 2, 3, 4, 5];
-    /// let mut ptr: *const u8 = data.as_ptr();
-    /// let step = 2;
-    /// let end_rounded_up = ptr.wrapping_add(6);
-    ///
-    /// // This loop prints "1, 3, 5, "
-    /// while ptr != end_rounded_up {
-    ///     unsafe {
-    ///         print!("{}, ", *ptr);
-    ///     }
-    ///     ptr = ptr.wrapping_add(step);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub fn wrapping_add(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.wrapping_offset(count as isize)
-    }
-
-    /// Calculates the offset from a pointer using wrapping arithmetic.
-    /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
-    ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
-    ///
-    /// Compared to [`sub`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
-    ///
-    /// If you need to cross object boundaries, cast the pointer to an integer and
-    /// do the arithmetic there.
-    ///
-    /// [`sub`]: #method.sub
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // Iterate using a raw pointer in increments of two elements (backwards)
-    /// let data = [1u8, 2, 3, 4, 5];
-    /// let mut ptr: *const u8 = data.as_ptr();
-    /// let start_rounded_down = ptr.wrapping_sub(2);
-    /// ptr = ptr.wrapping_add(4);
-    /// let step = 2;
-    /// // This loop prints "5, 3, 1, "
-    /// while ptr != start_rounded_down {
-    ///     unsafe {
-    ///         print!("{}, ", *ptr);
-    ///     }
-    ///     ptr = ptr.wrapping_sub(step);
-    /// }
-    /// ```
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub fn wrapping_sub(self, count: usize) -> Self
-    where
-        T: Sized,
-    {
-        self.wrapping_offset((count as isize).wrapping_neg())
-    }
-
-    /// Reads the value from `self` without moving it. This leaves the
-    /// memory in `self` unchanged.
-    ///
-    /// See [`ptr::read`] for safety concerns and examples.
-    ///
-    /// [`ptr::read`]: ./ptr/fn.read.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn read(self) -> T
-    where
-        T: Sized,
-    {
-        read(self)
-    }
-
-    /// Performs a volatile read of the value from `self` without moving it. This
-    /// leaves the memory in `self` unchanged.
-    ///
-    /// Volatile operations are intended to act on I/O memory, and are guaranteed
-    /// to not be elided or reordered by the compiler across other volatile
-    /// operations.
-    ///
-    /// See [`ptr::read_volatile`] for safety concerns and examples.
-    ///
-    /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn read_volatile(self) -> T
-    where
-        T: Sized,
-    {
-        read_volatile(self)
-    }
-
-    /// Reads the value from `self` without moving it. This leaves the
-    /// memory in `self` unchanged.
-    ///
-    /// Unlike `read`, the pointer may be unaligned.
-    ///
-    /// See [`ptr::read_unaligned`] for safety concerns and examples.
-    ///
-    /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn read_unaligned(self) -> T
-    where
-        T: Sized,
-    {
-        read_unaligned(self)
-    }
-
-    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
-    /// and destination may overlap.
-    ///
-    /// NOTE: this has the *same* argument order as [`ptr::copy`].
-    ///
-    /// See [`ptr::copy`] for safety concerns and examples.
-    ///
-    /// [`ptr::copy`]: ./ptr/fn.copy.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
-    where
-        T: Sized,
-    {
-        copy(self, dest, count)
-    }
-
-    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
-    /// and destination may *not* overlap.
-    ///
-    /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
-    ///
-    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
-    ///
-    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
-    where
-        T: Sized,
-    {
-        copy_nonoverlapping(self, dest, count)
-    }
-
-    /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
-    /// and destination may overlap.
-    ///
-    /// NOTE: this has the *opposite* argument order of [`ptr::copy`].
-    ///
-    /// See [`ptr::copy`] for safety concerns and examples.
-    ///
-    /// [`ptr::copy`]: ./ptr/fn.copy.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn copy_from(self, src: *const T, count: usize)
-    where
-        T: Sized,
-    {
-        copy(src, self, count)
-    }
-
-    /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
-    /// and destination may *not* overlap.
-    ///
-    /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`].
-    ///
-    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
-    ///
-    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
-    where
-        T: Sized,
-    {
-        copy_nonoverlapping(src, self, count)
-    }
-
-    /// Executes the destructor (if any) of the pointed-to value.
-    ///
-    /// See [`ptr::drop_in_place`] for safety concerns and examples.
-    ///
-    /// [`ptr::drop_in_place`]: ./ptr/fn.drop_in_place.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn drop_in_place(self) {
-        drop_in_place(self)
-    }
-
-    /// Overwrites a memory location with the given value without reading or
-    /// dropping the old value.
-    ///
-    /// See [`ptr::write`] for safety concerns and examples.
-    ///
-    /// [`ptr::write`]: ./ptr/fn.write.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn write(self, val: T)
-    where
-        T: Sized,
-    {
-        write(self, val)
-    }
-
-    /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
-    /// bytes of memory starting at `self` to `val`.
-    ///
-    /// See [`ptr::write_bytes`] for safety concerns and examples.
-    ///
-    /// [`ptr::write_bytes`]: ./ptr/fn.write_bytes.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn write_bytes(self, val: u8, count: usize)
-    where
-        T: Sized,
-    {
-        write_bytes(self, val, count)
-    }
-
-    /// Performs a volatile write of a memory location with the given value without
-    /// reading or dropping the old value.
-    ///
-    /// Volatile operations are intended to act on I/O memory, and are guaranteed
-    /// to not be elided or reordered by the compiler across other volatile
-    /// operations.
-    ///
-    /// See [`ptr::write_volatile`] for safety concerns and examples.
-    ///
-    /// [`ptr::write_volatile`]: ./ptr/fn.write_volatile.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn write_volatile(self, val: T)
-    where
-        T: Sized,
-    {
-        write_volatile(self, val)
-    }
-
-    /// Overwrites a memory location with the given value without reading or
-    /// dropping the old value.
-    ///
-    /// Unlike `write`, the pointer may be unaligned.
-    ///
-    /// See [`ptr::write_unaligned`] for safety concerns and examples.
-    ///
-    /// [`ptr::write_unaligned`]: ./ptr/fn.write_unaligned.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn write_unaligned(self, val: T)
-    where
-        T: Sized,
-    {
-        write_unaligned(self, val)
-    }
-
-    /// Replaces the value at `self` with `src`, returning the old
-    /// value, without dropping either.
-    ///
-    /// See [`ptr::replace`] for safety concerns and examples.
-    ///
-    /// [`ptr::replace`]: ./ptr/fn.replace.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn replace(self, src: T) -> T
-    where
-        T: Sized,
-    {
-        replace(self, src)
-    }
-
-    /// Swaps the values at two mutable locations of the same type, without
-    /// deinitializing either. They may overlap, unlike `mem::swap` which is
-    /// otherwise equivalent.
-    ///
-    /// See [`ptr::swap`] for safety concerns and examples.
-    ///
-    /// [`ptr::swap`]: ./ptr/fn.swap.html
-    #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[inline]
-    pub unsafe fn swap(self, with: *mut T)
-    where
-        T: Sized,
-    {
-        swap(self, with)
-    }
-
-    /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
-    /// `align`.
-    ///
-    /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::max_value()`. It is permissible for the implementation to *always*
-    /// return `usize::max_value()`. Only your algorithm's performance can depend
-    /// on getting a usable offset here, not its correctness.
-    ///
-    /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
-    /// used with the `wrapping_add` method.
-    ///
-    /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
-    /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
-    /// the returned offset is correct in all terms other than alignment.
-    ///
-    /// # Panics
-    ///
-    /// The function panics if `align` is not a power-of-two.
-    ///
-    /// # Examples
-    ///
-    /// Accessing adjacent `u8` as `u16`
-    ///
-    /// ```
-    /// # fn foo(n: usize) {
-    /// # use std::mem::align_of;
-    /// # unsafe {
-    /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
-    /// let ptr = &x[n] as *const u8;
-    /// let offset = ptr.align_offset(align_of::<u16>());
-    /// if offset < x.len() - n - 1 {
-    ///     let u16_ptr = ptr.add(offset) as *const u16;
-    ///     assert_ne!(*u16_ptr, 500);
-    /// } else {
-    ///     // while the pointer can be aligned via `offset`, it would point
-    ///     // outside the allocation
-    /// }
-    /// # } }
-    /// ```
-    #[stable(feature = "align_offset", since = "1.36.0")]
-    pub fn align_offset(self, align: usize) -> usize
-    where
-        T: Sized,
-    {
-        if !align.is_power_of_two() {
-            panic!("align_offset: align is not a power-of-two");
-        }
-        unsafe { align_offset(self, align) }
-    }
-}
-
 /// Align pointer `p`.
 ///
 /// Calculate offset (in terms of elements of `stride` stride) that has to be applied
@@ -2728,29 +1152,6 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
     usize::max_value()
 }
 
-// Equality for pointers
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialEq for *const T {
-    #[inline]
-    fn eq(&self, other: &*const T) -> bool {
-        *self == *other
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Eq for *const T {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialEq for *mut T {
-    #[inline]
-    fn eq(&self, other: &*mut T) -> bool {
-        *self == *other
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Eq for *mut T {}
-
 /// Compares raw pointers for equality.
 ///
 /// This is the same as using the `==` operator, but less generic:
@@ -2944,88 +1345,3 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
 fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
 fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
 fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
-
-// Comparison for pointers
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Ord for *const T {
-    #[inline]
-    fn cmp(&self, other: &*const T) -> Ordering {
-        if self < other {
-            Less
-        } else if self == other {
-            Equal
-        } else {
-            Greater
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialOrd for *const T {
-    #[inline]
-    fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-
-    #[inline]
-    fn lt(&self, other: &*const T) -> bool {
-        *self < *other
-    }
-
-    #[inline]
-    fn le(&self, other: &*const T) -> bool {
-        *self <= *other
-    }
-
-    #[inline]
-    fn gt(&self, other: &*const T) -> bool {
-        *self > *other
-    }
-
-    #[inline]
-    fn ge(&self, other: &*const T) -> bool {
-        *self >= *other
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Ord for *mut T {
-    #[inline]
-    fn cmp(&self, other: &*mut T) -> Ordering {
-        if self < other {
-            Less
-        } else if self == other {
-            Equal
-        } else {
-            Greater
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialOrd for *mut T {
-    #[inline]
-    fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-
-    #[inline]
-    fn lt(&self, other: &*mut T) -> bool {
-        *self < *other
-    }
-
-    #[inline]
-    fn le(&self, other: &*mut T) -> bool {
-        *self <= *other
-    }
-
-    #[inline]
-    fn gt(&self, other: &*mut T) -> bool {
-        *self > *other
-    }
-
-    #[inline]
-    fn ge(&self, other: &*mut T) -> bool {
-        *self >= *other
-    }
-}
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
new file mode 100644
index 00000000000..fd5decbd7ea
--- /dev/null
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -0,0 +1,925 @@
+use crate::cmp::Ordering::{self, Less, Equal, Greater};
+use crate::intrinsics;
+use super::*;
+
+// ignore-tidy-undocumented-unsafe
+
+#[lang = "mut_ptr"]
+impl<T: ?Sized> *mut T {
+    /// Returns `true` if the pointer is null.
+    ///
+    /// Note that unsized types have many possible null pointers, as only the
+    /// raw data pointer is considered, not their length, vtable, etc.
+    /// Therefore, two pointers that are null may still not compare equal to
+    /// each other.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = [1, 2, 3];
+    /// let ptr: *mut u32 = s.as_mut_ptr();
+    /// assert!(!ptr.is_null());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub 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()
+    }
+
+    /// Casts to a pointer of another type.
+    #[stable(feature = "ptr_cast", since = "1.38.0")]
+    #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
+    #[inline]
+    pub const fn cast<U>(self) -> *mut U {
+        self as _
+    }
+
+    /// Returns `None` if the pointer is null, or else returns a reference to
+    /// the value wrapped in `Some`.
+    ///
+    /// # Safety
+    ///
+    /// 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.
+    ///
+    /// When calling this method, you have to ensure that if the pointer is
+    /// non-NULL, then it is properly aligned, dereferencable (for the whole
+    /// size of `T`) and points to an initialized instance of `T`. 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. It is up to the
+    /// caller to ensure that for the duration of this lifetime, the memory this
+    /// pointer points to does not get written to outside of `UnsafeCell<U>`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+    ///
+    /// unsafe {
+    ///     if let Some(val_back) = ptr.as_ref() {
+    ///         println!("We got back the value: {}!", val_back);
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// # Null-unchecked version
+    ///
+    /// If you are sure the pointer can never be null and are looking for some kind of
+    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
+    /// dereference the pointer directly.
+    ///
+    /// ```
+    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+    ///
+    /// unsafe {
+    ///     let val_back = &*ptr;
+    ///     println!("We got back the value: {}!", val_back);
+    /// }
+    /// ```
+    #[stable(feature = "ptr_as_ref", since = "1.9.0")]
+    #[inline]
+    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+        if self.is_null() { None } else { Some(&*self) }
+    }
+
+    /// Calculates the offset from a pointer.
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_offset`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// [`wrapping_offset`]: #method.wrapping_offset
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = [1, 2, 3];
+    /// let ptr: *mut u32 = s.as_mut_ptr();
+    ///
+    /// unsafe {
+    ///     println!("{}", *ptr.offset(1));
+    ///     println!("{}", *ptr.offset(2));
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn offset(self, count: isize) -> *mut T
+        where
+            T: Sized,
+    {
+        intrinsics::offset(self, count) as *mut T
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// In particular, the resulting pointer remains attached to the same allocated
+    /// object that `self` points to. It may *not* be used to access a
+    /// different allocated object. Note that in Rust,
+    /// every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
+    /// *not* the same as `y`, and dereferencing it is undefined behavior
+    /// unless `x` and `y` point into the same allocated object.
+    ///
+    /// Compared to [`offset`], this method basically delays the requirement of staying
+    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
+    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
+    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`offset`]: #method.offset
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // Iterate using a raw pointer in increments of two elements
+    /// let mut data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *mut u8 = data.as_mut_ptr();
+    /// let step = 2;
+    /// let end_rounded_up = ptr.wrapping_offset(6);
+    ///
+    /// while ptr != end_rounded_up {
+    ///     unsafe {
+    ///         *ptr = 0;
+    ///     }
+    ///     ptr = ptr.wrapping_offset(step);
+    /// }
+    /// assert_eq!(&data, &[0, 2, 0, 4, 0]);
+    /// ```
+    #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
+    #[inline]
+    pub fn wrapping_offset(self, count: isize) -> *mut T
+        where
+            T: Sized,
+    {
+        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`.
+    ///
+    /// # Safety
+    ///
+    /// 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.
+    ///
+    /// 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].
+    ///
+    /// 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.
+    ///
+    /// [here]: crate::ptr#safety
+    /// [`as_ref`]: #method.as_ref
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = [1, 2, 3];
+    /// let ptr: *mut u32 = s.as_mut_ptr();
+    /// let first_value = unsafe { ptr.as_mut().unwrap() };
+    /// *first_value = 4;
+    /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
+    /// ```
+    #[stable(feature = "ptr_as_ref", since = "1.9.0")]
+    #[inline]
+    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
+        if self.is_null() { None } else { Some(&mut *self) }
+    }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// This function is the inverse of [`offset`].
+    ///
+    /// [`offset`]: #method.offset-1
+    /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and other pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
+    ///
+    /// * The distance between the pointers, in bytes, must be an exact multiple
+    ///   of the size of `T`.
+    ///
+    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
+    ///
+    /// The compiler and standard library generally try to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_offset_from`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// # Panics
+    ///
+    /// This function panics if `T` is a Zero-Sized Type ("ZST").
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_offset_from)]
+    ///
+    /// let mut a = [0; 5];
+    /// let ptr1: *mut i32 = &mut a[1];
+    /// let ptr2: *mut i32 = &mut a[3];
+    /// unsafe {
+    ///     assert_eq!(ptr2.offset_from(ptr1), 2);
+    ///     assert_eq!(ptr1.offset_from(ptr2), -2);
+    ///     assert_eq!(ptr1.offset(2), ptr2);
+    ///     assert_eq!(ptr2.offset(-2), ptr1);
+    /// }
+    /// ```
+    #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
+    #[inline]
+    pub const unsafe fn offset_from(self, origin: *const T) -> isize
+        where
+            T: Sized,
+    {
+        (self as *const T).offset_from(origin)
+    }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// If the address different between the two pointers is not a multiple of
+    /// `mem::size_of::<T>()` then the result of the division is rounded towards
+    /// zero.
+    ///
+    /// Though this method is safe for any two pointers, note that its result
+    /// will be mostly useless if the two pointers aren't into the same allocated
+    /// object, for example if they point to two different local variables.
+    ///
+    /// # Panics
+    ///
+    /// This function panics if `T` is a zero-sized type.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_wrapping_offset_from)]
+    ///
+    /// let mut a = [0; 5];
+    /// let ptr1: *mut i32 = &mut a[1];
+    /// let ptr2: *mut i32 = &mut a[3];
+    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+    /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
+    /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
+    /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
+    ///
+    /// let ptr1: *mut i32 = 3 as _;
+    /// let ptr2: *mut i32 = 13 as _;
+    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+    /// ```
+    #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
+    #[inline]
+    pub fn wrapping_offset_from(self, origin: *const T) -> isize
+        where
+            T: Sized,
+    {
+        (self as *const T).wrapping_offset_from(origin)
+    }
+
+    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a `usize`.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_add`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// [`wrapping_add`]: #method.wrapping_add
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s: &str = "123";
+    /// let ptr: *const u8 = s.as_ptr();
+    ///
+    /// unsafe {
+    ///     println!("{}", *ptr.add(1) as char);
+    ///     println!("{}", *ptr.add(2) as char);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn add(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer (convenience for
+    /// `.offset((count as isize).wrapping_neg())`).
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using [`wrapping_sub`] instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// [`wrapping_sub`]: #method.wrapping_sub
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s: &str = "123";
+    ///
+    /// unsafe {
+    ///     let end: *const u8 = s.as_ptr().add(3);
+    ///     println!("{}", *end.sub(1) as char);
+    ///     println!("{}", *end.sub(2) as char);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn sub(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.offset((count as isize).wrapping_neg())
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset(count as isize)`)
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// In particular, the resulting pointer remains attached to the same allocated
+    /// object that `self` points to. It may *not* be used to access a
+    /// different allocated object. Note that in Rust,
+    /// every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// Compared to [`add`], this method basically delays the requirement of staying
+    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
+    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
+    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`add`]: #method.add
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // Iterate using a raw pointer in increments of two elements
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let step = 2;
+    /// let end_rounded_up = ptr.wrapping_add(6);
+    ///
+    /// // This loop prints "1, 3, 5, "
+    /// while ptr != end_rounded_up {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_add(step);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub fn wrapping_add(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.wrapping_offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
+    ///
+    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// In particular, the resulting pointer remains attached to the same allocated
+    /// object that `self` points to. It may *not* be used to access a
+    /// different allocated object. Note that in Rust,
+    /// every (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// Compared to [`sub`], this method basically delays the requirement of staying
+    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
+    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
+    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`sub`]: #method.sub
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // Iterate using a raw pointer in increments of two elements (backwards)
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let start_rounded_down = ptr.wrapping_sub(2);
+    /// ptr = ptr.wrapping_add(4);
+    /// let step = 2;
+    /// // This loop prints "5, 3, 1, "
+    /// while ptr != start_rounded_down {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_sub(step);
+    /// }
+    /// ```
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub fn wrapping_sub(self, count: usize) -> Self
+        where
+            T: Sized,
+    {
+        self.wrapping_offset((count as isize).wrapping_neg())
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// See [`ptr::read`] for safety concerns and examples.
+    ///
+    /// [`ptr::read`]: ./ptr/fn.read.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn read(self) -> T
+        where
+            T: Sized,
+    {
+        read(self)
+    }
+
+    /// Performs a volatile read of the value from `self` without moving it. This
+    /// leaves the memory in `self` unchanged.
+    ///
+    /// Volatile operations are intended to act on I/O memory, and are guaranteed
+    /// to not be elided or reordered by the compiler across other volatile
+    /// operations.
+    ///
+    /// See [`ptr::read_volatile`] for safety concerns and examples.
+    ///
+    /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn read_volatile(self) -> T
+        where
+            T: Sized,
+    {
+        read_volatile(self)
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// Unlike `read`, the pointer may be unaligned.
+    ///
+    /// See [`ptr::read_unaligned`] for safety concerns and examples.
+    ///
+    /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn read_unaligned(self) -> T
+        where
+            T: Sized,
+    {
+        read_unaligned(self)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may overlap.
+    ///
+    /// NOTE: this has the *same* argument order as [`ptr::copy`].
+    ///
+    /// See [`ptr::copy`] for safety concerns and examples.
+    ///
+    /// [`ptr::copy`]: ./ptr/fn.copy.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+        where
+            T: Sized,
+    {
+        copy(self, dest, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may *not* overlap.
+    ///
+    /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
+    ///
+    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
+    ///
+    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+        where
+            T: Sized,
+    {
+        copy_nonoverlapping(self, dest, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
+    /// and destination may overlap.
+    ///
+    /// NOTE: this has the *opposite* argument order of [`ptr::copy`].
+    ///
+    /// See [`ptr::copy`] for safety concerns and examples.
+    ///
+    /// [`ptr::copy`]: ./ptr/fn.copy.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn copy_from(self, src: *const T, count: usize)
+        where
+            T: Sized,
+    {
+        copy(src, self, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
+    /// and destination may *not* overlap.
+    ///
+    /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`].
+    ///
+    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
+    ///
+    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
+        where
+            T: Sized,
+    {
+        copy_nonoverlapping(src, self, count)
+    }
+
+    /// Executes the destructor (if any) of the pointed-to value.
+    ///
+    /// See [`ptr::drop_in_place`] for safety concerns and examples.
+    ///
+    /// [`ptr::drop_in_place`]: ./ptr/fn.drop_in_place.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn drop_in_place(self) {
+        drop_in_place(self)
+    }
+
+    /// Overwrites a memory location with the given value without reading or
+    /// dropping the old value.
+    ///
+    /// See [`ptr::write`] for safety concerns and examples.
+    ///
+    /// [`ptr::write`]: ./ptr/fn.write.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn write(self, val: T)
+        where
+            T: Sized,
+    {
+        write(self, val)
+    }
+
+    /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
+    /// bytes of memory starting at `self` to `val`.
+    ///
+    /// See [`ptr::write_bytes`] for safety concerns and examples.
+    ///
+    /// [`ptr::write_bytes`]: ./ptr/fn.write_bytes.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn write_bytes(self, val: u8, count: usize)
+        where
+            T: Sized,
+    {
+        write_bytes(self, val, count)
+    }
+
+    /// Performs a volatile write of a memory location with the given value without
+    /// reading or dropping the old value.
+    ///
+    /// Volatile operations are intended to act on I/O memory, and are guaranteed
+    /// to not be elided or reordered by the compiler across other volatile
+    /// operations.
+    ///
+    /// See [`ptr::write_volatile`] for safety concerns and examples.
+    ///
+    /// [`ptr::write_volatile`]: ./ptr/fn.write_volatile.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn write_volatile(self, val: T)
+        where
+            T: Sized,
+    {
+        write_volatile(self, val)
+    }
+
+    /// Overwrites a memory location with the given value without reading or
+    /// dropping the old value.
+    ///
+    /// Unlike `write`, the pointer may be unaligned.
+    ///
+    /// See [`ptr::write_unaligned`] for safety concerns and examples.
+    ///
+    /// [`ptr::write_unaligned`]: ./ptr/fn.write_unaligned.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn write_unaligned(self, val: T)
+        where
+            T: Sized,
+    {
+        write_unaligned(self, val)
+    }
+
+    /// Replaces the value at `self` with `src`, returning the old
+    /// value, without dropping either.
+    ///
+    /// See [`ptr::replace`] for safety concerns and examples.
+    ///
+    /// [`ptr::replace`]: ./ptr/fn.replace.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn replace(self, src: T) -> T
+        where
+            T: Sized,
+    {
+        replace(self, src)
+    }
+
+    /// Swaps the values at two mutable locations of the same type, without
+    /// deinitializing either. They may overlap, unlike `mem::swap` which is
+    /// otherwise equivalent.
+    ///
+    /// See [`ptr::swap`] for safety concerns and examples.
+    ///
+    /// [`ptr::swap`]: ./ptr/fn.swap.html
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[inline]
+    pub unsafe fn swap(self, with: *mut T)
+        where
+            T: Sized,
+    {
+        swap(self, with)
+    }
+
+    /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
+    /// `align`.
+    ///
+    /// If it is not possible to align the pointer, the implementation returns
+    /// `usize::max_value()`. It is permissible for the implementation to *always*
+    /// return `usize::max_value()`. Only your algorithm's performance can depend
+    /// on getting a usable offset here, not its correctness.
+    ///
+    /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
+    /// used with the `wrapping_add` method.
+    ///
+    /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
+    /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
+    /// the returned offset is correct in all terms other than alignment.
+    ///
+    /// # Panics
+    ///
+    /// The function panics if `align` is not a power-of-two.
+    ///
+    /// # Examples
+    ///
+    /// Accessing adjacent `u8` as `u16`
+    ///
+    /// ```
+    /// # fn foo(n: usize) {
+    /// # use std::mem::align_of;
+    /// # unsafe {
+    /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
+    /// let ptr = &x[n] as *const u8;
+    /// let offset = ptr.align_offset(align_of::<u16>());
+    /// if offset < x.len() - n - 1 {
+    ///     let u16_ptr = ptr.add(offset) as *const u16;
+    ///     assert_ne!(*u16_ptr, 500);
+    /// } else {
+    ///     // while the pointer can be aligned via `offset`, it would point
+    ///     // outside the allocation
+    /// }
+    /// # } }
+    /// ```
+    #[stable(feature = "align_offset", since = "1.36.0")]
+    pub fn align_offset(self, align: usize) -> usize
+        where
+            T: Sized,
+    {
+        if !align.is_power_of_two() {
+            panic!("align_offset: align is not a power-of-two");
+        }
+        unsafe { align_offset(self, align) }
+    }
+}
+
+// Equality for pointers
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialEq for *mut T {
+    #[inline]
+    fn eq(&self, other: &*mut T) -> bool { *self == *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Eq for *mut T {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Ord for *mut T {
+    #[inline]
+    fn cmp(&self, other: &*mut T) -> Ordering {
+        if self < other {
+            Less
+        } else if self == other {
+            Equal
+        } else {
+            Greater
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialOrd for *mut T {
+    #[inline]
+    fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+
+    #[inline]
+    fn lt(&self, other: &*mut T) -> bool { *self < *other }
+
+    #[inline]
+    fn le(&self, other: &*mut T) -> bool { *self <= *other }
+
+    #[inline]
+    fn gt(&self, other: &*mut T) -> bool { *self > *other }
+
+    #[inline]
+    fn ge(&self, other: &*mut T) -> bool { *self >= *other }
+}
diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs
index 6946fd2413e..626e58d4930 100644
--- a/src/libcore/ptr/non_null.rs
+++ b/src/libcore/ptr/non_null.rs
@@ -149,7 +149,7 @@ impl<T: ?Sized> Copy for NonNull<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
 
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
 
 #[stable(feature = "nonnull", since = "1.25.0")]
@@ -201,7 +201,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
     #[inline]
     fn from(unique: Unique<T>) -> Self {
diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs
index 546b7c9d777..87b56d951c6 100644
--- a/src/libcore/ptr/unique.rs
+++ b/src/libcore/ptr/unique.rs
@@ -29,7 +29,7 @@ use crate::ptr::NonNull;
 /// for any type which upholds Unique's aliasing requirements.
 #[unstable(
     feature = "ptr_internals",
-    issue = "0",
+    issue = "none",
     reason = "use `NonNull` instead and consider `PhantomData<T>` \
               (if you also use `#[may_dangle]`), `Send`, and/or `Sync`"
 )]
@@ -50,17 +50,17 @@ pub struct Unique<T: ?Sized> {
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 unsafe impl<T: Send + ?Sized> Send for Unique<T> {}
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: Sized> Unique<T> {
     /// Creates a new `Unique` that is dangling, but well-aligned.
     ///
@@ -78,7 +78,7 @@ impl<T: Sized> Unique<T> {
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> Unique<T> {
     /// Creates a new `Unique`.
     ///
@@ -133,7 +133,7 @@ impl<T: ?Sized> Unique<T> {
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> Clone for Unique<T> {
     #[inline]
     fn clone(&self) -> Self {
@@ -141,30 +141,30 @@ impl<T: ?Sized> Clone for Unique<T> {
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> Copy for Unique<T> {}
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> fmt::Debug for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> fmt::Pointer for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> From<&mut T> for Unique<T> {
     #[inline]
     fn from(reference: &mut T) -> Self {
@@ -172,7 +172,7 @@ impl<T: ?Sized> From<&mut T> for Unique<T> {
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> From<&T> for Unique<T> {
     #[inline]
     fn from(reference: &T) -> Self {
@@ -180,7 +180,7 @@ impl<T: ?Sized> From<&T> for Unique<T> {
     }
 }
 
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
     #[inline]
     fn from(p: NonNull<T>) -> Self {
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 05baa1899b3..68e12e87789 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -38,7 +38,7 @@ use crate::ptr;
 use crate::mem;
 use crate::marker::{Copy, Send, Sync, Sized, self};
 
-#[unstable(feature = "slice_internals", issue = "0",
+#[unstable(feature = "slice_internals", issue = "none",
            reason = "exposed from core to be reused in std; use the memchr crate")]
 /// Pure rust memchr implementation, taken from rust-memchr
 pub mod memchr;
@@ -2723,12 +2723,12 @@ pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
 
     /// Returns a shared reference to the output at this location, if in
     /// bounds.
-    #[unstable(feature = "slice_index_methods", issue = "0")]
+    #[unstable(feature = "slice_index_methods", issue = "none")]
     fn get(self, slice: &T) -> Option<&Self::Output>;
 
     /// Returns a mutable reference to the output at this location, if in
     /// bounds.
-    #[unstable(feature = "slice_index_methods", issue = "0")]
+    #[unstable(feature = "slice_index_methods", issue = "none")]
     fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
 
     /// Returns a shared reference to the output at this location, without
@@ -2736,7 +2736,7 @@ pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     /// Calling this method with an out-of-bounds index is *[undefined behavior]*
     /// even if the resulting reference is not used.
     /// [undefined behavior]: ../../reference/behavior-considered-undefined.html
-    #[unstable(feature = "slice_index_methods", issue = "0")]
+    #[unstable(feature = "slice_index_methods", issue = "none")]
     unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
 
     /// Returns a mutable reference to the output at this location, without
@@ -2744,17 +2744,17 @@ pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     /// Calling this method with an out-of-bounds index is *[undefined behavior]*
     /// even if the resulting reference is not used.
     /// [undefined behavior]: ../../reference/behavior-considered-undefined.html
-    #[unstable(feature = "slice_index_methods", issue = "0")]
+    #[unstable(feature = "slice_index_methods", issue = "none")]
     unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
 
     /// Returns a shared reference to the output at this location, panicking
     /// if out of bounds.
-    #[unstable(feature = "slice_index_methods", issue = "0")]
+    #[unstable(feature = "slice_index_methods", issue = "none")]
     fn index(self, slice: &T) -> &Self::Output;
 
     /// Returns a mutable reference to the output at this location, panicking
     /// if out of bounds.
-    #[unstable(feature = "slice_index_methods", issue = "0")]
+    #[unstable(feature = "slice_index_methods", issue = "none")]
     fn index_mut(self, slice: &mut T) -> &mut Self::Output;
 }
 
@@ -5382,7 +5382,7 @@ pub fn from_mut<T>(s: &mut T) -> &mut [T] {
 }
 
 // This function is public only because there is no other way to unit test heapsort.
-#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "0")]
+#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
 #[doc(hidden)]
 pub fn heapsort<T, F>(v: &mut [T], mut is_less: F)
     where F: FnMut(&T, &T) -> bool
diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs
index 762de0489a9..cf6ee6ed593 100644
--- a/src/libcore/str/lossy.rs
+++ b/src/libcore/str/lossy.rs
@@ -6,7 +6,7 @@ use crate::mem;
 // ignore-tidy-undocumented-unsafe
 
 /// Lossy UTF-8 string.
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
 pub struct Utf8Lossy {
     bytes: [u8]
 }
@@ -27,13 +27,13 @@ impl Utf8Lossy {
 
 
 /// Iterator over lossy UTF-8 string
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
 #[allow(missing_debug_implementations)]
 pub struct Utf8LossyChunksIter<'a> {
     source: &'a [u8],
 }
 
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
 #[derive(PartialEq, Eq, Debug)]
 pub struct Utf8LossyChunk<'a> {
     /// Sequence of valid chars.
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 3da992dca30..15b65ed7655 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -21,7 +21,7 @@ use crate::option;
 
 pub mod pattern;
 
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
 #[allow(missing_docs)]
 pub mod lossy;
 
@@ -496,7 +496,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 {
 
 /// Reads the next code point out of a byte iterator (assuming a
 /// UTF-8-like encoding).
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
 #[inline]
 pub fn next_code_point<'a, I: Iterator<Item = &'a u8>>(bytes: &mut I) -> Option<u32> {
     // Decode UTF-8
@@ -1583,7 +1583,7 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [
 ];
 
 /// Given a first byte, determines how many bytes are in this UTF-8 character.
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
 #[inline]
 pub fn utf8_char_width(b: u8) -> usize {
     UTF8_CHAR_WIDTH[b as usize] as usize
@@ -2325,7 +2325,7 @@ impl str {
         i.get_mut(self)
     }
 
-    /// Returns a unchecked subslice of `str`.
+    /// Returns an unchecked subslice of `str`.
     ///
     /// This is the unchecked alternative to indexing the `str`.
     ///
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index b28ed2eaa08..1f20ebc01e9 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -36,6 +36,9 @@
 #![feature(iter_is_partitioned)]
 #![feature(iter_order_by)]
 #![feature(cmp_min_max_by)]
+#![feature(slice_from_raw_parts)]
+#![feature(const_slice_from_raw_parts)]
+#![feature(const_raw_ptr_deref)]
 
 extern crate test;
 
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index eea736bc88f..473bc881d29 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -2,6 +2,17 @@ use core::cell::RefCell;
 use core::ptr::*;
 
 #[test]
+fn test_const_from_raw_parts() {
+    const SLICE: &[u8] = &[1, 2, 3, 4];
+    const FROM_RAW: &[u8] = unsafe { &*slice_from_raw_parts(SLICE.as_ptr(), SLICE.len()) };
+    assert_eq!(SLICE, FROM_RAW);
+
+    let slice = &[1, 2, 3, 4, 5];
+    let from_raw = unsafe { &*slice_from_raw_parts(slice.as_ptr(), 2) } ;
+    assert_eq!(&slice[..2], from_raw);
+}
+
+#[test]
 fn test() {
     unsafe {
         struct Pair {
diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs
index a3ec9fd51f0..e424174f554 100644
--- a/src/libcore/unicode/mod.rs
+++ b/src/libcore/unicode/mod.rs
@@ -1,4 +1,4 @@
-#![unstable(feature = "unicode_internals", issue = "0")]
+#![unstable(feature = "unicode_internals", issue = "none")]
 #![allow(missing_docs)]
 
 mod bool_trie;
diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs
index 0d12ba01c87..e503795c519 100644
--- a/src/libprofiler_builtins/lib.rs
+++ b/src/libprofiler_builtins/lib.rs
@@ -3,7 +3,7 @@
 #![profiler_runtime]
 #![unstable(feature = "profiler_runtime_lib",
             reason = "internal implementation detail of rustc right now",
-            issue = "0")]
+            issue = "none")]
 #![allow(unused_features)]
 #![feature(nll)]
 #![feature(staged_api)]
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index eb7a1709801..3695607ff3c 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -93,7 +93,6 @@ macro_rules! arena_types {
                         rustc::hir::def_id::CrateNum
                     >
                 >,
-            [few] hir_forest: rustc::hir::map::Forest,
             [few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
                 syntax::symbol::Symbol,
                 rustc::hir::def_id::DefId,
@@ -123,6 +122,21 @@ macro_rules! arena_types {
             [few] crate_variances: rustc::ty::CrateVariancesMap<'tcx>,
             [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
             [] upvars: rustc_data_structures::fx::FxIndexMap<rustc::hir::HirId, rustc::hir::Upvar>,
+
+            // HIR types
+            [few] hir_forest: rustc::hir::map::Forest<$tcx>,
+            [] attribute: syntax::ast::Attribute,
+            [few] global_asm: rustc::hir::GlobalAsm,
+            [] fn_decl: rustc::hir::FnDecl,
+            [] foreign_item: rustc::hir::ForeignItem<$tcx>,
+            [] impl_item_ref: rustc::hir::ImplItemRef,
+            [few] macro_def: rustc::hir::MacroDef<$tcx>,
+            [] param: rustc::hir::Param,
+            [] path: rustc::hir::Path,
+            [] struct_field: rustc::hir::StructField<$tcx>,
+            [] trait_item_ref: rustc::hir::TraitItemRef,
+            [] ty: rustc::hir::Ty,
+            [] variant: rustc::hir::Variant<$tcx>,
         ], $tcx);
     )
 }
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index ea1c585176d..9e95cba7fcb 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -4,7 +4,7 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use crate::hir::{self, HirId, HirVec, Attribute, Item, ItemKind, TraitItem, TraitItemKind};
+use crate::hir::{self, HirId, Attribute, Item, ItemKind, TraitItem, TraitItemKind};
 use crate::hir::DUMMY_HIR_ID;
 use crate::hir::def_id::DefId;
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -86,7 +86,7 @@ impl Display for Target {
 }
 
 impl Target {
-    pub(crate) fn from_item(item: &Item) -> Target {
+    pub(crate) fn from_item(item: &Item<'_>) -> Target {
         match item.kind {
             ItemKind::ExternCrate(..) => Target::ExternCrate,
             ItemKind::Use(..) => Target::Use,
@@ -107,7 +107,7 @@ impl Target {
         }
     }
 
-    fn from_trait_item(trait_item: &TraitItem) -> Target {
+    fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
         match trait_item.kind {
             TraitItemKind::Const(..) => Target::AssocConst,
             TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
@@ -120,7 +120,7 @@ impl Target {
         }
     }
 
-    fn from_foreign_item(foreign_item: &hir::ForeignItem) -> Target {
+    fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target {
         match foreign_item.kind {
             hir::ForeignItemKind::Fn(..) => Target::ForeignFn,
             hir::ForeignItemKind::Static(..) => Target::ForeignStatic,
@@ -128,7 +128,7 @@ impl Target {
         }
     }
 
-    fn from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem) -> Target {
+    fn from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
         match impl_item.kind {
             hir::ImplItemKind::Const(..) => Target::AssocConst,
             hir::ImplItemKind::Method(..) => {
@@ -158,10 +158,10 @@ impl CheckAttrVisitor<'tcx> {
     fn check_attributes(
         &self,
         hir_id: HirId,
-        attrs: &HirVec<Attribute>,
+        attrs: &'hir [Attribute],
         span: &Span,
         target: Target,
-        item: Option<&Item>,
+        item: Option<&Item<'_>>,
     ) {
         let mut is_valid = true;
         for attr in attrs {
@@ -241,7 +241,7 @@ impl CheckAttrVisitor<'tcx> {
     fn check_track_caller(
         &self,
         attr_span: &Span,
-        attrs: &HirVec<Attribute>,
+        attrs: &'hir [Attribute],
         span: &Span,
         target: Target,
     ) -> bool {
@@ -332,10 +332,10 @@ impl CheckAttrVisitor<'tcx> {
     /// Checks if the `#[repr]` attributes on `item` are valid.
     fn check_repr(
         &self,
-        attrs: &HirVec<Attribute>,
+        attrs: &'hir [Attribute],
         span: &Span,
         target: Target,
-        item: Option<&Item>,
+        item: Option<&Item<'_>>,
     ) {
         // Extract the names of all repr hints, e.g., [foo, bar, align] for:
         // ```
@@ -477,7 +477,7 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_used(&self, attrs: &HirVec<Attribute>, target: Target) {
+    fn check_used(&self, attrs: &'hir [Attribute], target: Target) {
         for attr in attrs {
             if attr.check_name(sym::used) && target != Target::Static {
                 self.tcx.sess
@@ -492,25 +492,25 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx Item) {
+    fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         let target = Target::from_item(item);
-        self.check_attributes(item.hir_id, &item.attrs, &item.span, target, Some(item));
+        self.check_attributes(item.hir_id, item.attrs, &item.span, target, Some(item));
         intravisit::walk_item(self, item)
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
         let target = Target::from_trait_item(trait_item);
         self.check_attributes(trait_item.hir_id, &trait_item.attrs, &trait_item.span, target, None);
         intravisit::walk_trait_item(self, trait_item)
     }
 
-    fn visit_foreign_item(&mut self, f_item: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, f_item: &'tcx hir::ForeignItem<'tcx>) {
         let target = Target::from_foreign_item(f_item);
         self.check_attributes(f_item.hir_id, &f_item.attrs, &f_item.span, target, None);
         intravisit::walk_foreign_item(self, f_item)
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         let target = Target::from_impl_item(self.tcx, impl_item);
         self.check_attributes(impl_item.hir_id, &impl_item.attrs, &impl_item.span, target, None);
         intravisit::walk_impl_item(self, impl_item)
@@ -527,9 +527,9 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
     }
 }
 
-fn is_c_like_enum(item: &Item) -> bool {
+fn is_c_like_enum(item: &Item<'_>) -> bool {
     if let ItemKind::Enum(ref def, _) = item.kind {
-        for variant in &def.variants {
+        for variant in def.variants {
             match variant.data {
                 hir::VariantData::Unit(..) => { /* continue */ }
                 _ => return false,
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 231b054f974..d4e89c5f047 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -340,7 +340,7 @@ impl CtorKind {
         }
     }
 
-    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
+    pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
         match *vdata {
             hir::VariantData::Tuple(..) => CtorKind::Fn,
             hir::VariantData::Unit(..) => CtorKind::Const,
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index a4557a0776c..26e287037f7 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -218,11 +218,11 @@ pub trait Visitor<'v>: Sized {
 
     /// Visits the top-level item and (optionally) nested items / impl items. See
     /// `visit_nested_item` for details.
-    fn visit_item(&mut self, i: &'v Item) {
+    fn visit_item(&mut self, i: &'v Item<'v>) {
         walk_item(self, i)
     }
 
-    fn visit_body(&mut self, b: &'v Body) {
+    fn visit_body(&mut self, b: &'v Body<'v>) {
         walk_body(self, b);
     }
 
@@ -247,10 +247,10 @@ pub trait Visitor<'v>: Sized {
     fn visit_ident(&mut self, ident: Ident) {
         walk_ident(self, ident)
     }
-    fn visit_mod(&mut self, m: &'v Mod, _s: Span, n: HirId) {
+    fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) {
         walk_mod(self, m, n)
     }
-    fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) {
         walk_foreign_item(self, i)
     }
     fn visit_local(&mut self, l: &'v Local) {
@@ -295,13 +295,13 @@ pub trait Visitor<'v>: Sized {
     fn visit_use(&mut self, path: &'v Path, hir_id: HirId) {
         walk_use(self, path, hir_id)
     }
-    fn visit_trait_item(&mut self, ti: &'v TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
         walk_trait_item(self, ti)
     }
     fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
         walk_trait_item_ref(self, ii)
     }
-    fn visit_impl_item(&mut self, ii: &'v ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
         walk_impl_item(self, ii)
     }
     fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) {
@@ -317,24 +317,24 @@ pub trait Visitor<'v>: Sized {
         walk_poly_trait_ref(self, t, m)
     }
     fn visit_variant_data(&mut self,
-                          s: &'v VariantData,
+                          s: &'v VariantData<'v>,
                           _: Name,
                           _: &'v Generics,
                           _parent_id: HirId,
                           _: Span) {
         walk_struct_def(self, s)
     }
-    fn visit_struct_field(&mut self, s: &'v StructField) {
+    fn visit_struct_field(&mut self, s: &'v StructField<'v>) {
         walk_struct_field(self, s)
     }
     fn visit_enum_def(&mut self,
-                      enum_definition: &'v EnumDef,
+                      enum_definition: &'v EnumDef<'v>,
                       generics: &'v Generics,
                       item_id: HirId,
                       _: Span) {
         walk_enum_def(self, enum_definition, generics, item_id)
     }
-    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: HirId) {
+    fn visit_variant(&mut self, v: &'v Variant<'v>, g: &'v Generics, item_id: HirId) {
         walk_variant(self, v, g, item_id)
     }
     fn visit_label(&mut self, label: &'v Label) {
@@ -367,7 +367,7 @@ pub trait Visitor<'v>: Sized {
     }
     fn visit_attribute(&mut self, _attr: &'v Attribute) {
     }
-    fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
+    fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) {
         walk_macro_def(self, macro_def)
     }
     fn visit_vis(&mut self, vis: &'v Visibility) {
@@ -382,27 +382,27 @@ pub trait Visitor<'v>: Sized {
 }
 
 /// Walks the contents of a crate. See also `Crate::visit_all_items`.
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
+pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
     visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID);
-    walk_list!(visitor, visit_attribute, &krate.attrs);
-    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
+    walk_list!(visitor, visit_attribute, krate.attrs);
+    walk_list!(visitor, visit_macro_def, krate.exported_macros);
 }
 
-pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
+pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
     visitor.visit_id(macro_def.hir_id);
     visitor.visit_name(macro_def.span, macro_def.name);
-    walk_list!(visitor, visit_attribute, &macro_def.attrs);
+    walk_list!(visitor, visit_attribute, macro_def.attrs);
 }
 
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id: HirId) {
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
     visitor.visit_id(mod_hir_id);
-    for &item_id in &module.item_ids {
+    for &item_id in module.item_ids {
         visitor.visit_nested_item(item_id);
     }
 }
 
-pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
-    walk_list!(visitor, visit_param, &body.params);
+pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) {
+    walk_list!(visitor, visit_param, body.params);
     visitor.visit_expr(&body.value);
 }
 
@@ -462,7 +462,7 @@ pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param) {
     walk_list!(visitor, visit_attribute, &param.attrs);
 }
 
-pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
+pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
     visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.ident);
     match item.kind {
@@ -498,7 +498,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
         }
         ItemKind::ForeignMod(ref foreign_module) => {
             visitor.visit_id(item.hir_id);
-            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
+            walk_list!(visitor, visit_foreign_item, foreign_module.items);
         }
         ItemKind::GlobalAsm(_) => {
             visitor.visit_id(item.hir_id);
@@ -527,7 +527,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             ref generics,
             ref opt_trait_reference,
             ref typ,
-            ref impl_item_refs
+            impl_item_refs
         ) => {
             visitor.visit_id(item.hir_id);
             visitor.visit_generics(generics);
@@ -542,7 +542,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_variant_data(struct_definition, item.ident.name, generics, item.hir_id,
                                        item.span);
         }
-        ItemKind::Trait(.., ref generics, ref bounds, ref trait_item_refs) => {
+        ItemKind::Trait(.., ref generics, ref bounds, trait_item_refs) => {
             visitor.visit_id(item.hir_id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
@@ -554,7 +554,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             walk_list!(visitor, visit_param_bound, bounds);
         }
     }
-    walk_list!(visitor, visit_attribute, &item.attrs);
+    walk_list!(visitor, visit_attribute, item.attrs);
 }
 
 pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V,
@@ -565,19 +565,19 @@ pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V,
 }
 
 pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
-                                         enum_definition: &'v EnumDef,
+                                         enum_definition: &'v EnumDef<'v>,
                                          generics: &'v Generics,
                                          item_id: HirId) {
     visitor.visit_id(item_id);
     walk_list!(visitor,
                visit_variant,
-               &enum_definition.variants,
+               enum_definition.variants,
                generics,
                item_id);
 }
 
 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
-                                        variant: &'v Variant,
+                                        variant: &'v Variant<'v>,
                                         generics: &'v Generics,
                                         parent_item_id: HirId) {
     visitor.visit_ident(variant.ident);
@@ -588,7 +588,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                parent_item_id,
                                variant.span);
     walk_list!(visitor, visit_anon_const, &variant.disr_expr);
-    walk_list!(visitor, visit_attribute, &variant.attrs);
+    walk_list!(visitor, visit_attribute, variant.attrs);
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
@@ -735,13 +735,13 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
     }
 }
 
-pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
     visitor.visit_id(foreign_item.hir_id);
     visitor.visit_vis(&foreign_item.vis);
     visitor.visit_ident(foreign_item.ident);
 
     match foreign_item.kind {
-        ForeignItemKind::Fn(ref function_declaration, ref param_names, ref generics) => {
+        ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
             visitor.visit_generics(generics);
             visitor.visit_fn_decl(function_declaration);
             for &param_name in param_names {
@@ -752,7 +752,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
         ForeignItemKind::Type => (),
     }
 
-    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
+    walk_list!(visitor, visit_attribute, foreign_item.attrs);
 }
 
 pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound) {
@@ -849,9 +849,9 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
     visitor.visit_nested_body(body_id)
 }
 
-pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
+pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
     visitor.visit_ident(trait_item.ident);
-    walk_list!(visitor, visit_attribute, &trait_item.attrs);
+    walk_list!(visitor, visit_attribute, trait_item.attrs);
     visitor.visit_generics(&trait_item.generics);
     match trait_item.kind {
         TraitItemKind::Const(ref ty, default) => {
@@ -893,14 +893,14 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
     visitor.visit_defaultness(defaultness);
 }
 
-pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
+pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItem {
         hir_id: _,
         ident,
         ref vis,
         ref defaultness,
-        ref attrs,
+        attrs,
         ref generics,
         ref kind,
         span: _,
@@ -948,19 +948,22 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'
     visitor.visit_defaultness(defaultness);
 }
 
-pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
+pub fn walk_struct_def<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    struct_definition: &'v VariantData<'v>,
+) {
     if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() {
         visitor.visit_id(ctor_hir_id);
     }
     walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
-pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
+pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField<'v>) {
     visitor.visit_id(struct_field.hir_id);
     visitor.visit_vis(&struct_field.vis);
     visitor.visit_ident(struct_field.ident);
     visitor.visit_ty(&struct_field.ty);
-    walk_list!(visitor, visit_attribute, &struct_field.attrs);
+    walk_list!(visitor, visit_attribute, struct_field.attrs);
 }
 
 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs
index 39dd46c2d29..30b41ea4acb 100644
--- a/src/librustc/hir/itemlikevisit.rs
+++ b/src/librustc/hir/itemlikevisit.rs
@@ -45,9 +45,9 @@ use super::intravisit::Visitor;
 /// existing `fn visit_nested` methods to see where changes are
 /// needed.
 pub trait ItemLikeVisitor<'hir> {
-    fn visit_item(&mut self, item: &'hir Item);
-    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem);
-    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem);
+    fn visit_item(&mut self, item: &'hir Item<'hir>);
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>);
+    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>);
 }
 
 pub struct DeepVisitor<'v, V> {
@@ -65,24 +65,24 @@ impl<'v, 'hir, V> DeepVisitor<'v, V>
 impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
     where V: Visitor<'hir>
 {
-    fn visit_item(&mut self, item: &'hir Item) {
+    fn visit_item(&mut self, item: &'hir Item<'hir>) {
         self.visitor.visit_item(item);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>) {
         self.visitor.visit_trait_item(trait_item);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) {
         self.visitor.visit_impl_item(impl_item);
     }
 }
 
 /// A parallel variant of `ItemLikeVisitor`.
 pub trait ParItemLikeVisitor<'hir> {
-    fn visit_item(&self, item: &'hir Item);
-    fn visit_trait_item(&self, trait_item: &'hir TraitItem);
-    fn visit_impl_item(&self, impl_item: &'hir ImplItem);
+    fn visit_item(&self, item: &'hir Item<'hir>);
+    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
+    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
 }
 
 pub trait IntoVisitor<'hir> {
@@ -95,15 +95,15 @@ pub struct ParDeepVisitor<V>(pub V);
 impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
     where V: IntoVisitor<'hir>
 {
-    fn visit_item(&self, item: &'hir Item) {
+    fn visit_item(&self, item: &'hir Item<'hir>) {
         self.0.into_visitor().visit_item(item);
     }
 
-    fn visit_trait_item(&self, trait_item: &'hir TraitItem) {
+    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>) {
         self.0.into_visitor().visit_trait_item(trait_item);
     }
 
-    fn visit_impl_item(&self, impl_item: &'hir ImplItem) {
+    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
         self.0.into_visitor().visit_impl_item(impl_item);
     }
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index ec9d6802def..83869951ea2 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -35,6 +35,7 @@
 mod expr;
 mod item;
 
+use crate::arena::Arena;
 use crate::dep_graph::DepGraph;
 use crate::hir::{self, ParamName};
 use crate::hir::HirVec;
@@ -53,7 +54,6 @@ use crate::util::nodemap::{DefIdMap, NodeMap};
 use errors::Applicability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::vec::IndexVec;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::sync::Lrc;
 
 use std::collections::BTreeMap;
@@ -78,7 +78,7 @@ use rustc_error_codes::*;
 
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
-pub struct LoweringContext<'a> {
+pub struct LoweringContext<'a, 'hir: 'a> {
     crate_root: Option<Symbol>,
 
     /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
@@ -91,13 +91,16 @@ pub struct LoweringContext<'a> {
     /// librustc is independent of the parser, we use dynamic dispatch here.
     nt_to_tokenstream: NtToTokenstream,
 
+    /// Used to allocate HIR nodes
+    arena: &'hir Arena<'hir>,
+
     /// The items being lowered are collected here.
-    items: BTreeMap<hir::HirId, hir::Item>,
+    items: BTreeMap<hir::HirId, hir::Item<'hir>>,
 
-    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
-    impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
-    bodies: BTreeMap<hir::BodyId, hir::Body>,
-    exported_macros: Vec<hir::MacroDef>,
+    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
+    impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
+    bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
+    exported_macros: Vec<hir::MacroDef<'hir>>,
     non_exported_macro_attrs: Vec<ast::Attribute>,
 
     trait_impls: BTreeMap<DefId, Vec<hir::HirId>>,
@@ -241,13 +244,14 @@ impl<'a> ImplTraitContext<'a> {
     }
 }
 
-pub fn lower_crate(
-    sess: &Session,
-    dep_graph: &DepGraph,
-    krate: &Crate,
-    resolver: &mut dyn Resolver,
+pub fn lower_crate<'a, 'hir>(
+    sess: &'a Session,
+    dep_graph: &'a DepGraph,
+    krate: &'a Crate,
+    resolver: &'a mut dyn Resolver,
     nt_to_tokenstream: NtToTokenstream,
-) -> hir::Crate {
+    arena: &'hir Arena<'hir>,
+) -> hir::Crate<'hir> {
     // We're constructing the HIR here; we don't care what we will
     // read, since we haven't even constructed the *input* to
     // incr. comp. yet.
@@ -260,6 +264,7 @@ pub fn lower_crate(
         sess,
         resolver,
         nt_to_tokenstream,
+        arena,
         items: BTreeMap::new(),
         trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
@@ -383,19 +388,19 @@ impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> {
     }
 }
 
-impl<'a> LoweringContext<'a> {
-    fn lower_crate(mut self, c: &Crate) -> hir::Crate {
+impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> {
         /// Full-crate AST visitor that inserts into a fresh
         /// `LoweringContext` any information that may be
         /// needed from arbitrary locations in the crate,
         /// e.g., the number of lifetime generic parameters
         /// declared for every type and trait definition.
-        struct MiscCollector<'tcx, 'interner> {
-            lctx: &'tcx mut LoweringContext<'interner>,
+        struct MiscCollector<'tcx, 'lowering, 'hir> {
+            lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
             hir_id_owner: Option<NodeId>,
         }
 
-        impl MiscCollector<'_, '_> {
+        impl MiscCollector<'_, '_, '_> {
             fn allocate_use_tree_hir_id_counters(
                 &mut self,
                 tree: &UseTree,
@@ -435,7 +440,7 @@ impl<'a> LoweringContext<'a> {
             }
         }
 
-        impl<'tcx, 'interner> Visitor<'tcx> for MiscCollector<'tcx, 'interner> {
+        impl<'tcx, 'lowering, 'hir> Visitor<'tcx> for MiscCollector<'tcx, 'lowering, 'hir> {
             fn visit_pat(&mut self, p: &'tcx Pat) {
                 if let PatKind::Paren(..) | PatKind::Rest = p.kind {
                     // Doesn't generate a HIR node
@@ -477,11 +482,11 @@ impl<'a> LoweringContext<'a> {
                 });
             }
 
-            fn visit_trait_item(&mut self, item: &'tcx TraitItem) {
+            fn visit_trait_item(&mut self, item: &'tcx AssocItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
 
                 match item.kind {
-                    TraitItemKind::Method(_, None) => {
+                    AssocItemKind::Fn(_, None) => {
                         // Ignore patterns in trait methods without bodies
                         self.with_hir_id_owner(None, |this| {
                             visit::walk_trait_item(this, item)
@@ -493,7 +498,7 @@ impl<'a> LoweringContext<'a> {
                 }
             }
 
-            fn visit_impl_item(&mut self, item: &'tcx ImplItem) {
+            fn visit_impl_item(&mut self, item: &'tcx AssocItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
                 self.with_hir_id_owner(Some(item.id), |this| {
                     visit::walk_impl_item(this, item);
@@ -538,7 +543,7 @@ impl<'a> LoweringContext<'a> {
         visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
 
         let module = self.lower_mod(&c.module);
-        let attrs = self.lower_attrs(&c.attrs);
+        let attrs = self.arena.alloc_from_iter(self.lower_attrs(&c.attrs).into_iter());
         let body_ids = body_ids(&self.bodies);
 
         self.resolver
@@ -549,8 +554,8 @@ impl<'a> LoweringContext<'a> {
             module,
             attrs,
             span: c.span,
-            exported_macros: hir::HirVec::from(self.exported_macros),
-            non_exported_macro_attrs: hir::HirVec::from(self.non_exported_macro_attrs),
+            exported_macros: self.arena.alloc_from_iter(self.exported_macros),
+            non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
             items: self.items,
             trait_items: self.trait_items,
             impl_items: self.impl_items,
@@ -561,7 +566,7 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn insert_item(&mut self, item: hir::Item) {
+    fn insert_item(&mut self, item: hir::Item<'hir>) {
         let id = item.hir_id;
         // FIXME: Use `debug_asset-rt`.
         assert_eq!(id.local_id, hir::ItemLocalId::from_u32(0));
@@ -751,7 +756,7 @@ impl<'a> LoweringContext<'a> {
         f: F,
     ) -> (Vec<hir::GenericParam>, T)
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> (Vec<hir::GenericParam>, T),
+        F: FnOnce(&mut LoweringContext<'_, '_>) -> (Vec<hir::GenericParam>, T),
     {
         assert!(!self.is_collecting_in_band_lifetimes);
         assert!(self.lifetimes_to_define.is_empty());
@@ -868,7 +873,7 @@ impl<'a> LoweringContext<'a> {
     // for them.
     fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, 'hir>) -> T,
     {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
@@ -897,7 +902,7 @@ impl<'a> LoweringContext<'a> {
         f: F,
     ) -> (hir::Generics, T)
     where
-        F: FnOnce(&mut LoweringContext<'_>, &mut Vec<hir::GenericParam>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, '_>, &mut Vec<hir::GenericParam>) -> T,
     {
         let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
             &generics.params,
@@ -946,7 +951,7 @@ impl<'a> LoweringContext<'a> {
 
     fn with_dyn_type_scope<T, F>(&mut self, in_scope: bool, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
     {
         let was_in_dyn_type = self.is_in_dyn_type;
         self.is_in_dyn_type = in_scope;
@@ -960,7 +965,7 @@ impl<'a> LoweringContext<'a> {
 
     fn with_new_scopes<T, F>(&mut self, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
@@ -984,15 +989,14 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn lower_attrs_extendable(&mut self, attrs: &[Attribute]) -> Vec<Attribute> {
-        attrs
-            .iter()
-            .map(|a| self.lower_attr(a))
-            .collect()
+    fn lower_attrs_arena(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] {
+        self.arena.alloc_from_iter(
+            attrs.iter().map(|a| self.lower_attr(a))
+        )
     }
 
     fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
-        self.lower_attrs_extendable(attrs).into()
+        attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into()
     }
 
     fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
@@ -1205,13 +1209,13 @@ impl<'a> LoweringContext<'a> {
                                 id: ty.id,
                                 kind: ExprKind::Path(qself.clone(), path.clone()),
                                 span: ty.span,
-                                attrs: ThinVec::new(),
+                                attrs: AttrVec::new(),
                             };
 
                             let ct = self.with_new_scopes(|this| {
                                 hir::AnonConst {
                                     hir_id: this.lower_node_id(node_id),
-                                    body: this.lower_const_body(&path_expr),
+                                    body: this.lower_const_body(path_expr.span, Some(&path_expr)),
                                 }
                             });
                             return GenericArg::Const(ConstArg {
@@ -1253,6 +1257,14 @@ impl<'a> LoweringContext<'a> {
         ty
     }
 
+    fn ty(&mut self, span: Span, kind: hir::TyKind) -> hir::Ty {
+        hir::Ty { hir_id: self.next_id(), kind, span }
+    }
+
+    fn ty_tup(&mut self, span: Span, tys: HirVec<hir::Ty>) -> hir::Ty {
+        self.ty(span, hir::TyKind::Tup(tys))
+    }
+
     fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
         let kind = match t.kind {
             TyKind::Infer => hir::TyKind::Infer,
@@ -1418,7 +1430,13 @@ impl<'a> LoweringContext<'a> {
                 }
             }
             TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
-            TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"),
+            TyKind::CVarArgs => {
+                self.sess.delay_span_bug(
+                    t.span,
+                    "`TyKind::CVarArgs` should have been handled elsewhere",
+                );
+                hir::TyKind::Err
+            }
         };
 
         hir::Ty {
@@ -1433,7 +1451,7 @@ impl<'a> LoweringContext<'a> {
         span: Span,
         fn_def_id: Option<DefId>,
         opaque_ty_node_id: NodeId,
-        lower_bounds: impl FnOnce(&mut LoweringContext<'_>) -> hir::GenericBounds,
+        lower_bounds: impl FnOnce(&mut LoweringContext<'_, '_>) -> hir::GenericBounds,
     ) -> hir::TyKind {
         debug!(
             "lower_opaque_impl_trait(fn_def_id={:?}, opaque_ty_node_id={:?}, span={:?})",
@@ -1550,8 +1568,8 @@ impl<'a> LoweringContext<'a> {
         // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
         // appear in the bounds, excluding lifetimes that are created within the bounds.
         // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
-        struct ImplTraitLifetimeCollector<'r, 'a> {
-            context: &'r mut LoweringContext<'a>,
+        struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
+            context: &'r mut LoweringContext<'a, 'hir>,
             parent: DefIndex,
             opaque_ty_id: NodeId,
             collect_elided_lifetimes: bool,
@@ -1561,7 +1579,9 @@ impl<'a> LoweringContext<'a> {
             output_lifetime_params: Vec<hir::GenericParam>,
         }
 
-        impl<'r, 'a, 'v> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a> {
+        impl<'r, 'a, 'v, 'hir> hir::intravisit::Visitor<'v>
+        for ImplTraitLifetimeCollector<'r, 'a, 'hir>
+        {
             fn nested_visit_map<'this>(
                 &'this mut self,
             ) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
@@ -2084,32 +2104,19 @@ impl<'a> LoweringContext<'a> {
                     .iter()
                     .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
                     .collect();
-                let mk_tup = |this: &mut Self, tys, span| {
-                    hir::Ty { kind: hir::TyKind::Tup(tys), hir_id: this.next_id(), span }
+                let output_ty = match output {
+                    FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
+                    FunctionRetTy::Default(_) => P(this.ty_tup(span, hir::HirVec::new())),
+                };
+                let args = hir_vec![GenericArg::Type(this.ty_tup(span, inputs))];
+                let binding = hir::TypeBinding {
+                    hir_id: this.next_id(),
+                    ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
+                    span: output_ty.span,
+                    kind: hir::TypeBindingKind::Equality { ty: output_ty },
                 };
                 (
-                    hir::GenericArgs {
-                        args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
-                        bindings: hir_vec![
-                            hir::TypeBinding {
-                                hir_id: this.next_id(),
-                                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
-                                kind: hir::TypeBindingKind::Equality {
-                                    ty: output
-                                        .as_ref()
-                                        .map(|ty| this.lower_ty(
-                                            &ty,
-                                            ImplTraitContext::disallowed()
-                                        ))
-                                        .unwrap_or_else(||
-                                            P(mk_tup(this, hir::HirVec::new(), span))
-                                        ),
-                                },
-                                span: output.as_ref().map_or(span, |ty| ty.span),
-                            }
-                        ],
-                        parenthesized: true,
-                    },
+                    hir::GenericArgs { args, bindings: hir_vec![binding], parenthesized: true },
                     false,
                 )
             }
@@ -2253,7 +2260,7 @@ impl<'a> LoweringContext<'a> {
                     let is_mutable_pat = match arg.pat.kind {
                         PatKind::Ident(BindingMode::ByValue(mt), _, _) |
                         PatKind::Ident(BindingMode::ByRef(mt), _, _) =>
-                            mt == Mutability::Mutable,
+                            mt == Mutability::Mut,
                         _ => false,
                     };
 
@@ -2264,7 +2271,7 @@ impl<'a> LoweringContext<'a> {
                         // the case where we have a mutable pattern to a reference as that would
                         // no longer be an `ImplicitSelf`.
                         TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() &&
-                            mt.mutbl == ast::Mutability::Mutable =>
+                            mt.mutbl == ast::Mutability::Mut =>
                                 hir::ImplicitSelfKind::MutRef,
                         TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() =>
                             hir::ImplicitSelfKind::ImmRef,
@@ -2474,17 +2481,13 @@ impl<'a> LoweringContext<'a> {
             })
         );
 
-        // Create the `Foo<...>` refernece itself. Note that the `type
+        // Create the `Foo<...>` reference itself. Note that the `type
         // Foo = impl Trait` is, internally, created as a child of the
         // async fn, so the *type parameters* are inherited.  It's
         // only the lifetime parameters that we must supply.
         let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into());
-
-        hir::FunctionRetTy::Return(P(hir::Ty {
-            kind: opaque_ty_ref,
-            span: opaque_ty_span,
-            hir_id: self.next_id(),
-        }))
+        let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
+        hir::FunctionRetTy::Return(P(opaque_ty))
     }
 
     /// Transforms `-> T` into `Future<Output = T>`
@@ -2496,16 +2499,8 @@ impl<'a> LoweringContext<'a> {
     ) -> hir::GenericBound {
         // Compute the `T` in `Future<Output = T>` from the return type.
         let output_ty = match output {
-            FunctionRetTy::Ty(ty) => {
-                self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id)))
-            }
-            FunctionRetTy::Default(ret_ty_span) => {
-                P(hir::Ty {
-                    hir_id: self.next_id(),
-                    kind: hir::TyKind::Tup(hir_vec![]),
-                    span: *ret_ty_span,
-                })
-            }
+            FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))),
+            FunctionRetTy::Default(ret_ty_span) => P(self.ty_tup(*ret_ty_span, hir_vec![])),
         };
 
         // "<Output = T>"
@@ -2762,15 +2757,16 @@ impl<'a> LoweringContext<'a> {
     /// has no attributes and is not targeted by a `break`.
     fn lower_block_expr(&mut self, b: &Block) -> hir::Expr {
         let block = self.lower_block(b, false);
-        self.expr_block(block, ThinVec::new())
+        self.expr_block(block, AttrVec::new())
     }
 
     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
         let node = match p.kind {
             PatKind::Wild => hir::PatKind::Wild,
             PatKind::Ident(ref binding_mode, ident, ref sub) => {
-                let lower_sub = |this: &mut Self| sub.as_ref().map(|x| this.lower_pat(x));
-                self.lower_pat_ident(p, binding_mode, ident, lower_sub)
+                let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
+                let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
+                node
             }
             PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
             PatKind::TupleStruct(ref path, ref pats) => {
@@ -3017,7 +3013,7 @@ impl<'a> LoweringContext<'a> {
         self.with_new_scopes(|this| {
             hir::AnonConst {
                 hir_id: this.lower_node_id(c.id),
-                body: this.lower_const_body(&c.value),
+                body: this.lower_const_body(c.value.span, Some(&c.value)),
             }
         })
     }
@@ -3080,10 +3076,10 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
         match *b {
-            BindingMode::ByValue(Mutability::Immutable) => hir::BindingAnnotation::Unannotated,
-            BindingMode::ByRef(Mutability::Immutable) => hir::BindingAnnotation::Ref,
-            BindingMode::ByValue(Mutability::Mutable) => hir::BindingAnnotation::Mutable,
-            BindingMode::ByRef(Mutability::Mutable) => hir::BindingAnnotation::RefMut,
+            BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
+            BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
+            BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
+            BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
         }
     }
 
@@ -3113,7 +3109,7 @@ impl<'a> LoweringContext<'a> {
 
     fn stmt_let_pat(
         &mut self,
-        attrs: ThinVec<Attribute>,
+        attrs: AttrVec,
         span: Span,
         init: Option<P<hir::Expr>>,
         pat: P<hir::Pat>,
@@ -3434,7 +3430,7 @@ impl<'a> LoweringContext<'a> {
     }
 }
 
-fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
+fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId> {
     // Sorting by span ensures that we get things in order within a
     // file, and also puts the files in a sensible order.
     let mut body_ids: Vec<_> = bodies.keys().cloned().collect();
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index f8465baeb13..08b00ce69ad 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -13,7 +13,7 @@ use syntax::symbol::{sym, Symbol};
 
 use rustc_error_codes::*;
 
-impl LoweringContext<'_> {
+impl LoweringContext<'_, '_> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> HirVec<hir::Expr> {
         exprs.iter().map(|x| self.lower_expr(x)).collect()
     }
@@ -473,7 +473,7 @@ impl LoweringContext<'_> {
         ret_ty: Option<AstP<Ty>>,
         span: Span,
         async_gen_kind: hir::AsyncGeneratorKind,
-        body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
+        body: impl FnOnce(&mut LoweringContext<'_, '_>) -> hir::Expr,
     ) -> hir::ExprKind {
         let output = match ret_ty {
             Some(ty) => FunctionRetTy::Ty(ty),
@@ -909,7 +909,7 @@ impl LoweringContext<'_> {
 
     fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
     {
         let len = self.catch_scopes.len();
         self.catch_scopes.push(catch_id);
@@ -928,7 +928,7 @@ impl LoweringContext<'_> {
 
     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
     {
         // We're no longer in the base loop's condition; we're in another loop.
         let was_in_loop_condition = self.is_in_loop_condition;
@@ -953,7 +953,7 @@ impl LoweringContext<'_> {
 
     fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
+        F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = true;
@@ -1318,8 +1318,7 @@ impl LoweringContext<'_> {
         &mut self,
         span: Span,
         expr: P<hir::Expr>,
-        attrs: ThinVec<Attribute>
-    ) -> hir::Expr {
+        attrs: AttrVec) -> hir::Expr {
         self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
     }
 
@@ -1333,7 +1332,7 @@ impl LoweringContext<'_> {
         self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
     }
 
-    fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
+    fn expr_break(&mut self, span: Span, attrs: AttrVec) -> P<hir::Expr> {
         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
         P(self.expr(span, expr_break, attrs))
     }
@@ -1341,7 +1340,7 @@ impl LoweringContext<'_> {
     fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
         self.expr(
             span,
-            hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mutable, e),
+            hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
             ThinVec::new(),
         )
     }
@@ -1404,7 +1403,7 @@ impl LoweringContext<'_> {
         span: Span,
         components: &[Symbol],
         params: Option<P<hir::GenericArgs>>,
-        attrs: ThinVec<Attribute>,
+        attrs: AttrVec,
     ) -> hir::Expr {
         let path = self.std_path(span, components, params, true);
         self.expr(
@@ -1423,7 +1422,7 @@ impl LoweringContext<'_> {
         span: Span,
         ident: Ident,
         binding: hir::HirId,
-        attrs: ThinVec<Attribute>,
+        attrs: AttrVec,
     ) -> hir::Expr {
         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
             None,
@@ -1459,16 +1458,11 @@ impl LoweringContext<'_> {
         self.expr_block(P(blk), ThinVec::new())
     }
 
-    pub(super) fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr {
+    pub(super) fn expr_block(&mut self, b: P<hir::Block>, attrs: AttrVec) -> hir::Expr {
         self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
     }
 
-    pub(super) fn expr(
-        &mut self,
-        span: Span,
-        kind: hir::ExprKind,
-        attrs: ThinVec<Attribute>
-    ) -> hir::Expr {
+    pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind, attrs: AttrVec) -> hir::Expr {
         hir::Expr { hir_id: self.next_id(), kind, span, attrs }
     }
 
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index ff9d8c85df8..4492845acb8 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -5,13 +5,12 @@ use super::ImplTraitTypeIdVisitor;
 use super::AnonymousLifetimeMode;
 use super::ParamMode;
 
-use crate::hir::{self, HirVec};
+use crate::hir;
 use crate::hir::ptr::P;
 use crate::hir::def_id::DefId;
 use crate::hir::def::{Res, DefKind};
 use crate::util::nodemap::NodeMap;
 
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_target::spec::abi;
 
 use std::collections::BTreeSet;
@@ -25,11 +24,11 @@ use syntax_pos::Span;
 
 use rustc_error_codes::*;
 
-pub(super) struct ItemLowerer<'tcx, 'interner> {
-    pub(super) lctx: &'tcx mut LoweringContext<'interner>,
+pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
+    pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
 }
 
-impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> {
+impl<'a, 'lowering, 'hir> ItemLowerer<'a, 'lowering, 'hir> {
     fn with_trait_impl_ref<F>(&mut self, trait_impl_ref: &Option<TraitRef>, f: F)
     where
         F: FnOnce(&mut Self),
@@ -45,8 +44,8 @@ impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> {
     }
 }
 
-impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
-    fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
+impl<'a, 'lowering, 'hir> Visitor<'a> for ItemLowerer<'a, 'lowering, 'hir> {
+    fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
         let hir_id = self.lctx.lower_node_id(n);
 
         self.lctx.modules.insert(hir_id, hir::ModuleItems {
@@ -61,7 +60,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
         self.lctx.current_module = old;
     }
 
-    fn visit_item(&mut self, item: &'tcx Item) {
+    fn visit_item(&mut self, item: &'a Item) {
         let mut item_hir_id = None;
         self.lctx.with_hir_id_owner(item.id, |lctx| {
             lctx.without_in_scope_lifetime_defs(|lctx| {
@@ -86,7 +85,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
         }
     }
 
-    fn visit_trait_item(&mut self, item: &'tcx TraitItem) {
+    fn visit_trait_item(&mut self, item: &'a AssocItem) {
         self.lctx.with_hir_id_owner(item.id, |lctx| {
             let hir_item = lctx.lower_trait_item(item);
             let id = hir::TraitItemId { hir_id: hir_item.hir_id };
@@ -97,7 +96,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
         visit::walk_trait_item(self, item);
     }
 
-    fn visit_impl_item(&mut self, item: &'tcx ImplItem) {
+    fn visit_impl_item(&mut self, item: &'a AssocItem) {
         self.lctx.with_hir_id_owner(item.id, |lctx| {
             let hir_item = lctx.lower_impl_item(item);
             let id = hir::ImplItemId { hir_id: hir_item.hir_id };
@@ -108,7 +107,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
     }
 }
 
-impl LoweringContext<'_> {
+impl<'hir> LoweringContext<'_, 'hir> {
     // Same as the method above, but accepts `hir::GenericParam`s
     // instead of `ast::GenericParam`s.
     // This should only be used with generics that have already had their
@@ -117,7 +116,7 @@ impl LoweringContext<'_> {
     fn with_parent_item_lifetime_defs<T>(
         &mut self,
         parent_hir_id: hir::HirId,
-        f: impl FnOnce(&mut LoweringContext<'_>) -> T,
+        f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
 
@@ -145,7 +144,7 @@ impl LoweringContext<'_> {
     // from their surrounding environment.
     fn without_in_scope_lifetime_defs<T>(
         &mut self,
-        f: impl FnOnce(&mut LoweringContext<'_>) -> T,
+        f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
     ) -> T {
         let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]);
 
@@ -162,10 +161,12 @@ impl LoweringContext<'_> {
         res
     }
 
-    pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
+    pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod<'hir> {
         hir::Mod {
             inner: m.inner,
-            item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
+            item_ids: self.arena.alloc_from_iter(
+                m.items.iter().flat_map(|x| self.lower_item_id(x))
+            ),
         }
     }
 
@@ -226,10 +227,10 @@ impl LoweringContext<'_> {
         }
     }
 
-    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
+    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
         let mut ident = i.ident;
         let mut vis = self.lower_visibility(&i.vis, None);
-        let attrs = self.lower_attrs(&i.attrs);
+        let attrs = self.lower_attrs_arena(&i.attrs);
 
         if let ItemKind::MacroDef(ref def) = i.kind {
             if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
@@ -245,12 +246,12 @@ impl LoweringContext<'_> {
                     legacy: def.legacy,
                 });
             } else {
-                self.non_exported_macro_attrs.extend(attrs.into_iter());
+                self.non_exported_macro_attrs.extend(attrs.iter().cloned());
             }
             return None;
         }
 
-        let kind = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.kind);
+        let kind = self.lower_item_kind(i.span, i.id, &mut ident, attrs, &mut vis, &i.kind);
 
         Some(hir::Item {
             hir_id: self.lower_node_id(i.id),
@@ -264,12 +265,13 @@ impl LoweringContext<'_> {
 
     fn lower_item_kind(
         &mut self,
+        span: Span,
         id: NodeId,
         ident: &mut Ident,
-        attrs: &hir::HirVec<Attribute>,
+        attrs: &'hir [Attribute],
         vis: &mut hir::Visibility,
         i: &ItemKind,
-    ) -> hir::ItemKind {
+    ) -> hir::ItemKind<'hir> {
         match *i {
             ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(orig_name),
             ItemKind::Use(ref use_tree) => {
@@ -282,30 +284,32 @@ impl LoweringContext<'_> {
                 self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
             }
             ItemKind::Static(ref t, m, ref e) => {
+                let ty = self.lower_ty(
+                    t,
+                    if self.sess.features_untracked().impl_trait_in_bindings {
+                        ImplTraitContext::OpaqueTy(None)
+                    } else {
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
+                    }
+                );
                 hir::ItemKind::Static(
-                    self.lower_ty(
-                        t,
-                        if self.sess.features_untracked().impl_trait_in_bindings {
-                            ImplTraitContext::OpaqueTy(None)
-                        } else {
-                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-                        }
-                    ),
+                    self.arena.alloc(ty.into_inner()),
                     m,
-                    self.lower_const_body(e),
+                    self.lower_const_body(span, Some(e)),
                 )
             }
             ItemKind::Const(ref t, ref e) => {
+                let ty = self.lower_ty(
+                    t,
+                    if self.sess.features_untracked().impl_trait_in_bindings {
+                        ImplTraitContext::OpaqueTy(None)
+                    } else {
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
+                    }
+                );
                 hir::ItemKind::Const(
-                    self.lower_ty(
-                        t,
-                        if self.sess.features_untracked().impl_trait_in_bindings {
-                            ImplTraitContext::OpaqueTy(None)
-                        } else {
-                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-                        }
-                    ),
-                    self.lower_const_body(e)
+                    self.arena.alloc(ty.into_inner()),
+                    self.lower_const_body(span, Some(e))
                 )
             }
             ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
@@ -317,7 +321,12 @@ impl LoweringContext<'_> {
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
                     // declaration (decl), not the return types.
-                    let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
+                    let body_id = this.lower_maybe_async_body(
+                        span,
+                        &decl,
+                        header.asyncness.node,
+                        Some(body),
+                    );
 
                     let (generics, decl) = this.add_in_band_defs(
                         generics,
@@ -341,7 +350,7 @@ impl LoweringContext<'_> {
                 None => {
                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                     let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
-                    hir::ItemKind::TyAlias(ty, generics)
+                    hir::ItemKind::TyAlias(self.arena.alloc(ty.into_inner()), generics)
                 },
                 Some(bounds) => {
                     let ty = hir::OpaqueTy {
@@ -356,11 +365,12 @@ impl LoweringContext<'_> {
             ItemKind::Enum(ref enum_definition, ref generics) => {
                 hir::ItemKind::Enum(
                     hir::EnumDef {
-                        variants: enum_definition
+                        variants: self.arena.alloc_from_iter(
+                            enum_definition
                             .variants
                             .iter()
                             .map(|x| self.lower_variant(x))
-                            .collect(),
+                        ),
                     },
                     self.lower_generics(generics, ImplTraitContext::disallowed()),
                 )
@@ -429,10 +439,11 @@ impl LoweringContext<'_> {
                 let new_impl_items = self.with_in_scope_lifetime_defs(
                     &ast_generics.params,
                     |this| {
-                        impl_items
-                            .iter()
-                            .map(|item| this.lower_impl_item_ref(item))
-                            .collect()
+                        this.arena.alloc_from_iter(
+                            impl_items
+                                .iter()
+                                .map(|item| this.lower_impl_item_ref(item))
+                        )
                     },
                 );
 
@@ -442,16 +453,16 @@ impl LoweringContext<'_> {
                     self.lower_defaultness(defaultness, true /* [1] */),
                     generics,
                     trait_ref,
-                    lowered_ty,
+                    self.arena.alloc(lowered_ty.into_inner()),
                     new_impl_items,
                 )
             }
             ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
-                let items = items
+                let items = self.arena.alloc_from_iter(items
                     .iter()
                     .map(|item| self.lower_trait_item_ref(item))
-                    .collect();
+                );
                 hir::ItemKind::Trait(
                     is_auto,
                     unsafety,
@@ -479,8 +490,8 @@ impl LoweringContext<'_> {
         id: NodeId,
         vis: &mut hir::Visibility,
         ident: &mut Ident,
-        attrs: &hir::HirVec<Attribute>,
-    ) -> hir::ItemKind {
+        attrs: &'hir [Attribute],
+    ) -> hir::ItemKind<'hir> {
         debug!("lower_use_tree(tree={:?})", tree);
         debug!("lower_use_tree: vis = {:?}", vis);
 
@@ -535,14 +546,14 @@ impl LoweringContext<'_> {
                         let res = this.lower_res(res);
                         let path =
                             this.lower_path_extra(res, &path, ParamMode::Explicit, None);
-                        let kind = hir::ItemKind::Use(P(path), hir::UseKind::Single);
+                        let kind = hir::ItemKind::Use(this.arena.alloc(path), hir::UseKind::Single);
                         let vis = this.rebuild_vis(&vis);
 
                         this.insert_item(
                             hir::Item {
                                 hir_id: new_id,
                                 ident,
-                                attrs: attrs.into_iter().cloned().collect(),
+                                attrs,
                                 kind,
                                 vis,
                                 span,
@@ -551,11 +562,12 @@ impl LoweringContext<'_> {
                     });
                 }
 
-                let path = P(self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None));
+                let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None);
+                let path = self.arena.alloc(path);
                 hir::ItemKind::Use(path, hir::UseKind::Single)
             }
             UseTreeKind::Glob => {
-                let path = P(self.lower_path(
+                let path = self.arena.alloc(self.lower_path(
                     id,
                     &Path {
                         segments,
@@ -626,7 +638,7 @@ impl LoweringContext<'_> {
                             hir::Item {
                                 hir_id: new_hir_id,
                                 ident,
-                                attrs: attrs.into_iter().cloned().collect(),
+                                attrs,
                                 kind,
                                 vis,
                                 span: use_tree.span,
@@ -658,7 +670,8 @@ impl LoweringContext<'_> {
 
                 let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
                 let res = self.lower_res(res);
-                let path = P(self.lower_path_extra(res, &prefix, ParamMode::Explicit, None));
+                let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None);
+                let path = self.arena.alloc(path);
                 hir::ItemKind::Use(path, hir::UseKind::ListStem)
             }
         }
@@ -698,12 +711,12 @@ impl LoweringContext<'_> {
         respan(vis.span, vis_kind)
     }
 
-    fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
+    fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
         let def_id = self.resolver.definitions().local_def_id(i.id);
         hir::ForeignItem {
             hir_id: self.lower_node_id(i.id),
             ident: i.ident,
-            attrs: self.lower_attrs(&i.attrs),
+            attrs: self.lower_attrs_arena(&i.attrs),
             kind: match i.kind {
                 ForeignItemKind::Fn(ref fdec, ref generics) => {
                     let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
@@ -718,12 +731,14 @@ impl LoweringContext<'_> {
                             )
                         },
                     );
+                    let fn_dec = self.arena.alloc(fn_dec.into_inner());
+                    let fn_args = self.arena.alloc_from_iter(fn_args.into_iter());
 
                     hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
                 }
                 ForeignItemKind::Static(ref t, m) => {
-                    hir::ForeignItemKind::Static(
-                        self.lower_ty(t, ImplTraitContext::disallowed()), m)
+                    let ty = self.lower_ty(t, ImplTraitContext::disallowed());
+                    hir::ForeignItemKind::Static(self.arena.alloc(ty.into_inner()), m)
                 }
                 ForeignItemKind::Ty => hir::ForeignItemKind::Type,
                 ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
@@ -733,23 +748,22 @@ impl LoweringContext<'_> {
         }
     }
 
-    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
+    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod<'hir> {
         hir::ForeignMod {
             abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
-            items: fm.items
+            items: self.arena.alloc_from_iter(fm.items
                 .iter()
-                .map(|x| self.lower_foreign_item(x))
-                .collect(),
+                .map(|x| self.lower_foreign_item(x))),
         }
     }
 
-    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
-        P(hir::GlobalAsm { asm: ga.asm })
+    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> &'hir hir::GlobalAsm {
+        self.arena.alloc(hir::GlobalAsm { asm: ga.asm })
     }
 
-    fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
+    fn lower_variant(&mut self, v: &Variant) -> hir::Variant<'hir> {
         hir::Variant {
-            attrs: self.lower_attrs(&v.attrs),
+            attrs: self.lower_attrs_arena(&v.attrs),
             data: self.lower_variant_data(&v.data),
             disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
             id: self.lower_node_id(v.id),
@@ -758,19 +772,22 @@ impl LoweringContext<'_> {
         }
     }
 
-    fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
+    fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData<'hir> {
         match *vdata {
             VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
-                fields.iter().enumerate().map(|f| self.lower_struct_field(f)).collect(),
+                self.arena.alloc_from_iter(
+                    fields.iter().enumerate().map(|f| self.lower_struct_field(f))
+                ),
                 recovered,
             ),
             VariantData::Tuple(ref fields, id) => {
                 hir::VariantData::Tuple(
-                    fields
+                    self.arena.alloc_from_iter(
+                        fields
                         .iter()
                         .enumerate()
                         .map(|f| self.lower_struct_field(f))
-                        .collect(),
+                    ),
                     self.lower_node_id(id),
                 )
             },
@@ -780,7 +797,7 @@ impl LoweringContext<'_> {
         }
     }
 
-    fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
+    fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField<'hir> {
         let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
             let t = self.lower_path_ty(
                 &f.ty,
@@ -789,9 +806,10 @@ impl LoweringContext<'_> {
                 ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
                 ImplTraitContext::disallowed()
             );
-            P(t)
+            self.arena.alloc(t)
         } else {
-            self.lower_ty(&f.ty, ImplTraitContext::disallowed())
+            let t = self.lower_ty(&f.ty, ImplTraitContext::disallowed());
+            self.arena.alloc(t.into_inner())
         };
         hir::StructField {
             span: f.span,
@@ -803,24 +821,26 @@ impl LoweringContext<'_> {
             },
             vis: self.lower_visibility(&f.vis, None),
             ty,
-            attrs: self.lower_attrs(&f.attrs),
+            attrs: self.lower_attrs_arena(&f.attrs),
         }
     }
 
-    fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
+    fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
         let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
 
         let (generics, kind) = match i.kind {
-            TraitItemKind::Const(ref ty, ref default) => (
-                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                hir::TraitItemKind::Const(
-                    self.lower_ty(ty, ImplTraitContext::disallowed()),
+            AssocItemKind::Const(ref ty, ref default) => {
+                let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
+                let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
+                let ty = self.arena.alloc(ty.into_inner());
+                (generics, hir::TraitItemKind::Const(
+                    ty,
                     default
                         .as_ref()
-                        .map(|x| self.lower_const_body(x)),
-                ),
-            ),
-            TraitItemKind::Method(ref sig, None) => {
+                        .map(|x| self.lower_const_body(i.span, Some(x))),
+                ))
+            },
+            AssocItemKind::Fn(ref sig, None) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) = self.lower_method_sig(
                     &i.generics,
@@ -831,8 +851,8 @@ impl LoweringContext<'_> {
                 );
                 (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
             }
-            TraitItemKind::Method(ref sig, Some(ref body)) => {
-                let body_id = self.lower_fn_body_block(&sig.decl, body);
+            AssocItemKind::Fn(ref sig, Some(ref body)) => {
+                let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
                 let (generics, sig) = self.lower_method_sig(
                     &i.generics,
                     sig,
@@ -842,45 +862,46 @@ impl LoweringContext<'_> {
                 );
                 (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
             }
-            TraitItemKind::Type(ref bounds, ref default) => {
+            AssocItemKind::TyAlias(ref bounds, ref default) => {
+                let ty = default.as_ref().map(|x| -> &'hir hir::Ty { self.arena.alloc(
+                        self.lower_ty(x, ImplTraitContext::disallowed()).into_inner())
+                });
                 let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
                 let kind = hir::TraitItemKind::Type(
                     self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
-                    default
-                        .as_ref()
-                        .map(|x| self.lower_ty(x, ImplTraitContext::disallowed())),
+                    ty,
                 );
 
                 (generics, kind)
             },
-            TraitItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
+            AssocItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
         };
 
         hir::TraitItem {
             hir_id: self.lower_node_id(i.id),
             ident: i.ident,
-            attrs: self.lower_attrs(&i.attrs),
+            attrs: self.lower_attrs_arena(&i.attrs),
             generics,
             kind,
             span: i.span,
         }
     }
 
-    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
+    fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         let (kind, has_default) = match i.kind {
-            TraitItemKind::Const(_, ref default) => {
+            AssocItemKind::Const(_, ref default) => {
                 (hir::AssocItemKind::Const, default.is_some())
             }
-            TraitItemKind::Type(_, ref default) => {
+            AssocItemKind::TyAlias(_, ref default) => {
                 (hir::AssocItemKind::Type, default.is_some())
             }
-            TraitItemKind::Method(ref sig, ref default) => (
+            AssocItemKind::Fn(ref sig, ref default) => (
                 hir::AssocItemKind::Method {
                     has_self: sig.decl.has_self(),
                 },
                 default.is_some(),
             ),
-            TraitItemKind::Macro(..) => unimplemented!(),
+            AssocItemKind::Macro(..) => unimplemented!(),
         };
         hir::TraitItemRef {
             id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) },
@@ -891,21 +912,31 @@ impl LoweringContext<'_> {
         }
     }
 
-    fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
+    /// Construct `ExprKind::Err` for the given `span`.
+    fn expr_err(&mut self, span: Span) -> hir::Expr {
+        self.expr(span, hir::ExprKind::Err, AttrVec::new())
+    }
+
+    fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
         let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
 
         let (generics, kind) = match i.kind {
-            ImplItemKind::Const(ref ty, ref expr) => (
-                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                hir::ImplItemKind::Const(
-                    self.lower_ty(ty, ImplTraitContext::disallowed()),
-                    self.lower_const_body(expr),
-                ),
-            ),
-            ImplItemKind::Method(ref sig, ref body) => {
+            AssocItemKind::Const(ref ty, ref expr) => {
+                let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
+                let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
+                let ty = self.arena.alloc(ty.into_inner());
+                (generics, hir::ImplItemKind::Const(
+                    ty,
+                    self.lower_const_body(i.span, expr.as_deref()),
+                ))
+            },
+            AssocItemKind::Fn(ref sig, ref body) => {
                 self.current_item = Some(i.span);
                 let body_id = self.lower_maybe_async_body(
-                    &sig.decl, sig.header.asyncness.node, body
+                    i.span,
+                    &sig.decl,
+                    sig.header.asyncness.node,
+                    body.as_deref(),
                 );
                 let impl_trait_return_allow = !self.is_in_trait_impl;
                 let (generics, sig) = self.lower_method_sig(
@@ -918,27 +949,34 @@ impl LoweringContext<'_> {
 
                 (generics, hir::ImplItemKind::Method(sig, body_id))
             }
-            ImplItemKind::TyAlias(ref ty) => {
+            AssocItemKind::TyAlias(_, ref ty) => {
                 let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
-                let kind = match ty.kind.opaque_top_hack() {
+                let kind = match ty {
                     None => {
-                        let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
+                        let ty = self.arena.alloc(self.ty(i.span, hir::TyKind::Err));
                         hir::ImplItemKind::TyAlias(ty)
                     }
-                    Some(bs) => {
-                        let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
-                        hir::ImplItemKind::OpaqueTy(bounds)
+                    Some(ty) => match ty.kind.opaque_top_hack() {
+                        None => {
+                            let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
+                            let ty = self.arena.alloc(ty.into_inner());
+                            hir::ImplItemKind::TyAlias(ty)
+                        }
+                        Some(bs) => {
+                            let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
+                            hir::ImplItemKind::OpaqueTy(bs)
+                        }
                     }
                 };
                 (generics, kind)
             },
-            ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
+            AssocItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
         };
 
         hir::ImplItem {
             hir_id: self.lower_node_id(i.id),
             ident: i.ident,
-            attrs: self.lower_attrs(&i.attrs),
+            attrs: self.lower_attrs_arena(&i.attrs),
             generics,
             vis: self.lower_visibility(&i.vis, None),
             defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
@@ -949,7 +987,7 @@ impl LoweringContext<'_> {
         // [1] since `default impl` is not yet implemented, this is always true in impls
     }
 
-    fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
+    fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
         hir::ImplItemRef {
             id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) },
             ident: i.ident,
@@ -957,15 +995,18 @@ impl LoweringContext<'_> {
             vis: self.lower_visibility(&i.vis, Some(i.id)),
             defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
             kind: match &i.kind {
-                ImplItemKind::Const(..) => hir::AssocItemKind::Const,
-                ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() {
+                AssocItemKind::Const(..) => hir::AssocItemKind::Const,
+                AssocItemKind::TyAlias(_, ty) => match ty
+                    .as_deref()
+                    .and_then(|ty| ty.kind.opaque_top_hack())
+                {
                     None => hir::AssocItemKind::Type,
                     Some(_) => hir::AssocItemKind::OpaqueTy,
                 },
-                ImplItemKind::Method(sig, _) => hir::AssocItemKind::Method {
+                AssocItemKind::Fn(sig, _) => hir::AssocItemKind::Method {
                     has_self: sig.decl.has_self(),
                 },
-                ImplItemKind::Macro(..) => unimplemented!(),
+                AssocItemKind::Macro(..) => unimplemented!(),
             },
         }
 
@@ -1021,7 +1062,7 @@ impl LoweringContext<'_> {
         }
     }
 
-    fn record_body(&mut self, params: HirVec<hir::Param>, value: hir::Expr) -> hir::BodyId {
+    fn record_body(&mut self, params: &'hir [hir::Param], value: hir::Expr) -> hir::BodyId {
         let body = hir::Body {
             generator_kind: self.generator_kind,
             params,
@@ -1034,7 +1075,7 @@ impl LoweringContext<'_> {
 
     fn lower_body(
         &mut self,
-        f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec<hir::Param>, hir::Expr),
+        f: impl FnOnce(&mut Self) -> (&'hir [hir::Param], hir::Expr),
     ) -> hir::BodyId {
         let prev_gen_kind = self.generator_kind.take();
         let (parameters, result) = f(self);
@@ -1055,31 +1096,49 @@ impl LoweringContext<'_> {
     pub(super) fn lower_fn_body(
         &mut self,
         decl: &FnDecl,
-        body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
+        body: impl FnOnce(&mut LoweringContext<'_, '_>) -> hir::Expr,
     ) -> hir::BodyId {
         self.lower_body(|this| (
-            decl.inputs.iter().map(|x| this.lower_param(x)).collect(),
+            this.arena.alloc_from_iter(
+                decl.inputs.iter().map(|x| this.lower_param(x))
+            ),
             body(this),
         ))
     }
 
-    fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
-        self.lower_fn_body(decl, |this| this.lower_block_expr(body))
+    fn lower_fn_body_block(
+        &mut self,
+        span: Span,
+        decl: &FnDecl,
+        body: Option<&Block>,
+    ) -> hir::BodyId {
+        self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body))
+    }
+
+    fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr {
+        match block {
+            Some(block) => self.lower_block_expr(block),
+            None => self.expr_err(span),
+        }
     }
 
-    pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
-        self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
+    pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
+        self.lower_body(|this| (&[], match expr {
+            Some(expr) => this.lower_expr(expr),
+            None => this.expr_err(span),
+        }))
     }
 
     fn lower_maybe_async_body(
         &mut self,
+        span: Span,
         decl: &FnDecl,
         asyncness: IsAsync,
-        body: &Block,
+        body: Option<&Block>,
     ) -> hir::BodyId {
         let closure_id = match asyncness {
             IsAsync::Async { closure_id, .. } => closure_id,
-            IsAsync::NotAsync => return self.lower_fn_body_block(decl, body),
+            IsAsync::NotAsync => return self.lower_fn_body_block(span, decl, body),
         };
 
         self.lower_body(|this| {
@@ -1144,7 +1203,7 @@ impl LoweringContext<'_> {
                 //
                 // If this is the simple case, this parameter will end up being the same as the
                 // original parameter, but with a different pattern id.
-                let mut stmt_attrs = ThinVec::new();
+                let mut stmt_attrs = AttrVec::new();
                 stmt_attrs.extend(parameter.attrs.iter().cloned());
                 let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident);
                 let new_parameter = hir::Param {
@@ -1188,7 +1247,7 @@ impl LoweringContext<'_> {
                         desugared_span, ident, hir::BindingAnnotation::Mutable);
                     let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
                     let move_stmt = this.stmt_let_pat(
-                        ThinVec::new(),
+                        AttrVec::new(),
                         desugared_span,
                         Some(P(move_expr)),
                         move_pat,
@@ -1213,15 +1272,16 @@ impl LoweringContext<'_> {
                 parameters.push(new_parameter);
             }
 
+            let body_span = body.map_or(span, |b| b.span);
             let async_expr = this.make_async_expr(
                 CaptureBy::Value,
                 closure_id,
                 None,
-                body.span,
+                body_span,
                 hir::AsyncGeneratorKind::Fn,
                 |this| {
                     // Create a block from the user's function body:
-                    let user_body = this.lower_block_expr(body);
+                    let user_body = this.lower_block_expr_opt(body_span, body);
 
                     // Transform into `drop-temps { <user-body> }`, an expression:
                     let desugared_span = this.mark_span_with_reason(
@@ -1232,7 +1292,7 @@ impl LoweringContext<'_> {
                     let user_body = this.expr_drop_temps(
                         desugared_span,
                         P(user_body),
-                        ThinVec::new(),
+                        AttrVec::new(),
                     );
 
                     // As noted above, create the final block like
@@ -1249,9 +1309,13 @@ impl LoweringContext<'_> {
                         statements.into(),
                         Some(P(user_body)),
                     );
-                    this.expr_block(P(body), ThinVec::new())
+                    this.expr_block(P(body), AttrVec::new())
                 });
-            (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
+
+            (
+                this.arena.alloc_from_iter(parameters),
+                this.expr(body_span, async_expr, AttrVec::new()),
+            )
         })
     }
 
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 8f9f3983262..ab04a8a10aa 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -35,7 +35,7 @@ pub struct FnLikeNode<'a> { node: Node<'a> }
 /// corresponds to some FnLikeNode.
 trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
 
-impl MaybeFnLike for ast::Item {
+impl MaybeFnLike for ast::Item<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
             ast::ItemKind::Fn(..) => true,
@@ -44,7 +44,7 @@ impl MaybeFnLike for ast::Item {
     }
 }
 
-impl MaybeFnLike for ast::ImplItem {
+impl MaybeFnLike for ast::ImplItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
             ast::ImplItemKind::Method(..) => true,
@@ -53,7 +53,7 @@ impl MaybeFnLike for ast::ImplItem {
     }
 }
 
-impl MaybeFnLike for ast::TraitItem {
+impl MaybeFnLike for ast::TraitItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
             ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index b0fa844c818..faf2a0c7010 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -22,7 +22,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
     /// The crate
-    krate: &'hir Crate,
+    krate: &'hir Crate<'hir>,
 
     /// Source map
     source_map: &'a SourceMap,
@@ -99,7 +99,7 @@ where
 
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(sess: &'a Session,
-                       krate: &'hir Crate,
+                       krate: &'hir Crate<'hir>,
                        dep_graph: &'a DepGraph,
                        definitions: &'a definitions::Definitions,
                        hir_to_node_id: &'a FxHashMap<HirId, NodeId>,
@@ -367,7 +367,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_item(&mut self, i: &'hir Item) {
+    fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug!("visit_item: {:?}", i);
         debug_assert_eq!(i.hir_id.owner,
                          self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap());
@@ -385,7 +385,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) {
+    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
         self.insert(foreign_item.span, foreign_item.hir_id, Node::ForeignItem(foreign_item));
 
         self.with_parent(foreign_item.hir_id, |this| {
@@ -398,7 +398,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         intravisit::walk_generic_param(self, param);
     }
 
-    fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
         debug_assert_eq!(ti.hir_id.owner,
                          self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap());
         self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
@@ -410,7 +410,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
         debug_assert_eq!(ii.hir_id.owner,
                          self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap());
         self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
@@ -530,7 +530,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         }
     }
 
-    fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) {
+    fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
         let node_id = self.hir_to_node_id[&macro_def.hir_id];
         let def_index = self.definitions.opt_def_index(node_id).unwrap();
 
@@ -539,7 +539,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
+    fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics, item_id: HirId) {
         self.insert(v.span, v.id, Node::Variant(v));
         self.with_parent(v.id, |this| {
             // Register the constructor of this variant.
@@ -550,7 +550,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_struct_field(&mut self, field: &'hir StructField) {
+    fn visit_struct_field(&mut self, field: &'hir StructField<'hir>) {
         self.insert(field.span, field.hir_id, Node::Field(field));
         self.with_parent(field.hir_id, |this| {
             intravisit::walk_struct_field(this, field);
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index b66c2ce1178..0a06473ed30 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -53,17 +53,17 @@ impl<'a, 'hir> OuterVisitor<'a, 'hir> {
 }
 
 impl<'a, 'hir> ItemLikeVisitor<'hir> for OuterVisitor<'a, 'hir> {
-    fn visit_item(&mut self, i: &'hir hir::Item) {
+    fn visit_item(&mut self, i: &'hir hir::Item<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
         inner_visitor.check(i.hir_id, |this| intravisit::walk_item(this, i));
     }
 
-    fn visit_trait_item(&mut self, i: &'hir hir::TraitItem) {
+    fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
         inner_visitor.check(i.hir_id, |this| intravisit::walk_trait_item(this, i));
     }
 
-    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
+    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
         inner_visitor.check(i.hir_id, |this| intravisit::walk_impl_item(this, i));
     }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 69e772697f8..71addc123b8 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -153,20 +153,20 @@ impl<'hir> Entry<'hir> {
 }
 
 /// Stores a crate and any number of inlined items from other crates.
-pub struct Forest {
-    krate: Crate,
+pub struct Forest<'hir> {
+    krate: Crate<'hir>,
     pub dep_graph: DepGraph,
 }
 
-impl Forest {
-    pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest {
+impl Forest<'hir> {
+    pub fn new(krate: Crate<'hir>, dep_graph: &DepGraph) -> Forest<'hir> {
         Forest {
             krate,
             dep_graph: dep_graph.clone(),
         }
     }
 
-    pub fn krate(&self) -> &Crate {
+    pub fn krate(&self) -> &Crate<'hir> {
         self.dep_graph.read(DepNode::new_no_params(DepKind::Krate));
         &self.krate
     }
@@ -174,7 +174,7 @@ impl Forest {
     /// This is used internally in the dependency tracking system.
     /// Use the `krate` method to ensure your dependency on the
     /// crate is tracked.
-    pub fn untracked_krate(&self) -> &Crate {
+    pub fn untracked_krate(&self) -> &Crate<'hir> {
         &self.krate
     }
 }
@@ -189,7 +189,7 @@ pub(super) type HirEntryMap<'hir> = IndexVec<DefIndex, IndexVec<ItemLocalId, Opt
 #[derive(Clone)]
 pub struct Map<'hir> {
     /// The backing storage for all the AST nodes.
-    pub forest: &'hir Forest,
+    pub forest: &'hir Forest<'hir>,
 
     /// Same as the dep_graph in forest, just available with one fewer
     /// deref. This is a gratuitous micro-optimization.
@@ -439,11 +439,11 @@ impl<'hir> Map<'hir> {
         self.lookup(id).cloned()
     }
 
-    pub fn krate(&self) -> &'hir Crate {
+    pub fn krate(&self) -> &'hir Crate<'hir> {
         self.forest.krate()
     }
 
-    pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem {
+    pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
         self.read(id.hir_id);
 
         // N.B., intentionally bypass `self.forest.krate()` so that we
@@ -451,7 +451,7 @@ impl<'hir> Map<'hir> {
         self.forest.krate.trait_item(id)
     }
 
-    pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem {
+    pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
         self.read(id.hir_id);
 
         // N.B., intentionally bypass `self.forest.krate()` so that we
@@ -459,7 +459,7 @@ impl<'hir> Map<'hir> {
         self.forest.krate.impl_item(id)
     }
 
-    pub fn body(&self, id: BodyId) -> &'hir Body {
+    pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
         self.read(id.hir_id);
 
         // N.B., intentionally bypass `self.forest.krate()` so that we
@@ -580,7 +580,7 @@ impl<'hir> Map<'hir> {
         &self.forest.krate.attrs
     }
 
-    pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) {
+    pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) {
         let hir_id = self.as_local_hir_id(module).unwrap();
         self.read(hir_id);
         match self.find_entry(hir_id).unwrap().node {
@@ -959,28 +959,28 @@ impl<'hir> Map<'hir> {
         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
     }
 
-    pub fn expect_item(&self, id: HirId) -> &'hir Item {
+    pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
         match self.find(id) { // read recorded by `find`
             Some(Node::Item(item)) => item,
             _ => bug!("expected item, found {}", self.node_to_string(id))
         }
     }
 
-    pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem {
+    pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
         match self.find(id) {
             Some(Node::ImplItem(item)) => item,
             _ => bug!("expected impl item, found {}", self.node_to_string(id))
         }
     }
 
-    pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem {
+    pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
         match self.find(id) {
             Some(Node::TraitItem(item)) => item,
             _ => bug!("expected trait item, found {}", self.node_to_string(id))
         }
     }
 
-    pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData {
+    pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData<'hir> {
         match self.find(id) {
             Some(Node::Item(i)) => {
                 match i.kind {
@@ -995,14 +995,14 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    pub fn expect_variant(&self, id: HirId) -> &'hir Variant {
+    pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> {
         match self.find(id) {
             Some(Node::Variant(variant)) => variant,
             _ => bug!("expected variant, found {}", self.node_to_string(id)),
         }
     }
 
-    pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem {
+    pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
         match self.find(id) {
             Some(Node::ForeignItem(item)) => item,
             _ => bug!("expected foreign item, found {}", self.node_to_string(id))
@@ -1213,7 +1213,7 @@ impl<'a> NodesMatchingSuffix<'a> {
                 id = parent;
             }
 
-            fn item_is_mod(item: &Item) -> bool {
+            fn item_is_mod(item: &Item<'_>) -> bool {
                 match item.kind {
                     ItemKind::Mod(_) => true,
                     _ => false,
@@ -1248,16 +1248,16 @@ trait Named {
 
 impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() } }
 
-impl Named for Item { fn name(&self) -> Name { self.ident.name } }
-impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
-impl Named for Variant { fn name(&self) -> Name { self.ident.name } }
-impl Named for StructField { fn name(&self) -> Name { self.ident.name } }
-impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
-impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
+impl Named for Item<'_> { fn name(&self) -> Name { self.ident.name } }
+impl Named for ForeignItem<'_> { fn name(&self) -> Name { self.ident.name } }
+impl Named for Variant<'_> { fn name(&self) -> Name { self.ident.name } }
+impl Named for StructField<'_> { fn name(&self) -> Name { self.ident.name } }
+impl Named for TraitItem<'_> { fn name(&self) -> Name { self.ident.name } }
+impl Named for ImplItem<'_> { fn name(&self) -> Name { self.ident.name } }
 
 pub fn map_crate<'hir>(sess: &crate::session::Session,
                        cstore: &CrateStoreDyn,
-                       forest: &'hir Forest,
+                       forest: &'hir Forest<'hir>,
                        definitions: Definitions)
                        -> Map<'hir> {
     let _prof_timer = sess.prof.generic_activity("build_hir_map");
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 6b354b01518..ff6801a85c7 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -20,7 +20,7 @@ use errors::FatalError;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use syntax::source_map::Spanned;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
-use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
+use syntax::ast::{AttrVec, Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
 pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
 pub use syntax::ast::{IsAuto, ImplPolarity, BorrowKind};
 use syntax::attr::{InlineAttr, OptimizeAttr};
@@ -29,7 +29,6 @@ use syntax::tokenstream::TokenStream;
 use syntax::util::parser::ExprPrecedence;
 use rustc_target::spec::abi::Abi;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_macros::HashStable;
 use rustc_serialize::{self, Encoder, Encodable, Decoder, Decodable};
 use std::collections::{BTreeSet, BTreeMap};
@@ -743,13 +742,13 @@ pub struct ModuleItems {
 ///
 /// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
 #[derive(RustcEncodable, RustcDecodable, Debug)]
-pub struct Crate {
-    pub module: Mod,
-    pub attrs: HirVec<Attribute>,
+pub struct Crate<'hir> {
+    pub module: Mod<'hir>,
+    pub attrs: &'hir [Attribute],
     pub span: Span,
-    pub exported_macros: HirVec<MacroDef>,
+    pub exported_macros: &'hir [MacroDef<'hir>],
     // Attributes from non-exported macros, kept only for collecting the library feature list.
-    pub non_exported_macro_attrs: HirVec<Attribute>,
+    pub non_exported_macro_attrs: &'hir [Attribute],
 
     // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates
     // over the ids in increasing order. In principle it should not
@@ -757,11 +756,11 @@ pub struct Crate {
     // does, because it can affect the order in which errors are
     // detected, which in turn can make compile-fail tests yield
     // slightly different results.
-    pub items: BTreeMap<HirId, Item>,
+    pub items: BTreeMap<HirId, Item<'hir>>,
 
-    pub trait_items: BTreeMap<TraitItemId, TraitItem>,
-    pub impl_items: BTreeMap<ImplItemId, ImplItem>,
-    pub bodies: BTreeMap<BodyId, Body>,
+    pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
+    pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
+    pub bodies: BTreeMap<BodyId, Body<'hir>>,
     pub trait_impls: BTreeMap<DefId, Vec<HirId>>,
 
     /// A list of the body ids written out in the order in which they
@@ -775,19 +774,25 @@ pub struct Crate {
     pub modules: BTreeMap<HirId, ModuleItems>,
 }
 
-impl Crate {
-    pub fn item(&self, id: HirId) -> &Item {
+impl Crate<'hir> {
+    pub fn item(&self, id: HirId) -> &Item<'hir> {
         &self.items[&id]
     }
 
-    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem {
+    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem<'hir> {
         &self.trait_items[&id]
     }
 
-    pub fn impl_item(&self, id: ImplItemId) -> &ImplItem {
+    pub fn impl_item(&self, id: ImplItemId) -> &ImplItem<'hir> {
         &self.impl_items[&id]
     }
 
+    pub fn body(&self, id: BodyId) -> &Body<'hir> {
+        &self.bodies[&id]
+    }
+}
+
+impl Crate<'_> {
     /// Visits all items in the crate in some deterministic (but
     /// unspecified) order. If you just need to process every item,
     /// but don't care about nesting, this method is the best choice.
@@ -830,20 +835,16 @@ impl Crate {
             });
         });
     }
-
-    pub fn body(&self, id: BodyId) -> &Body {
-        &self.bodies[&id]
-    }
 }
 
 /// A macro definition, in this crate or imported from another.
 ///
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct MacroDef {
+pub struct MacroDef<'hir> {
     pub name: Name,
     pub vis: Visibility,
-    pub attrs: HirVec<Attribute>,
+    pub attrs: &'hir [Attribute],
     pub hir_id: HirId,
     pub span: Span,
     pub body: TokenStream,
@@ -1274,7 +1275,7 @@ pub struct Local {
     pub init: Option<P<Expr>>,
     pub hir_id: HirId,
     pub span: Span,
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
     /// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop
     /// desugaring. Otherwise will be `Normal`.
     pub source: LocalSource,
@@ -1352,13 +1353,13 @@ pub struct BodyId {
 /// All bodies have an **owner**, which can be accessed via the HIR
 /// map using `body_owner_def_id()`.
 #[derive(RustcEncodable, RustcDecodable, Debug)]
-pub struct Body {
-    pub params: HirVec<Param>,
+pub struct Body<'hir> {
+    pub params: &'hir [Param],
     pub value: Expr,
     pub generator_kind: Option<GeneratorKind>,
 }
 
-impl Body {
+impl Body<'hir> {
     pub fn id(&self) -> BodyId {
         BodyId {
             hir_id: self.value.hir_id,
@@ -1459,7 +1460,7 @@ pub struct AnonConst {
 pub struct Expr {
     pub hir_id: HirId,
     pub kind: ExprKind,
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
     pub span: Span,
 }
 
@@ -1857,6 +1858,16 @@ impl fmt::Display for YieldSource {
     }
 }
 
+impl From<GeneratorKind> for YieldSource {
+    fn from(kind: GeneratorKind) -> Self {
+        match kind {
+            // Guess based on the kind of the current generator.
+            GeneratorKind::Gen => Self::Yield,
+            GeneratorKind::Async(_) => Self::Await,
+        }
+    }
+}
+
 // N.B., if you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
@@ -1886,12 +1897,12 @@ pub struct TraitItemId {
 /// either required (meaning it doesn't have an implementation, just a
 /// signature) or provided (meaning it has a default implementation).
 #[derive(RustcEncodable, RustcDecodable, Debug)]
-pub struct TraitItem {
+pub struct TraitItem<'hir> {
     pub ident: Ident,
     pub hir_id: HirId,
-    pub attrs: HirVec<Attribute>,
+    pub attrs: &'hir [Attribute],
     pub generics: Generics,
-    pub kind: TraitItemKind,
+    pub kind: TraitItemKind<'hir>,
     pub span: Span,
 }
 
@@ -1907,14 +1918,14 @@ pub enum TraitMethod {
 
 /// Represents a trait method or associated constant or type
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub enum TraitItemKind {
+pub enum TraitItemKind<'hir> {
     /// An associated constant with an optional value (otherwise `impl`s must contain a value).
-    Const(P<Ty>, Option<BodyId>),
+    Const(&'hir Ty, Option<BodyId>),
     /// A method with an optional body.
     Method(FnSig, TraitMethod),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type.
-    Type(GenericBounds, Option<P<Ty>>),
+    Type(GenericBounds, Option<&'hir Ty>),
 }
 
 // The bodies for items are stored "out of line", in a separate
@@ -1927,27 +1938,27 @@ pub struct ImplItemId {
 
 /// Represents anything within an `impl` block.
 #[derive(RustcEncodable, RustcDecodable, Debug)]
-pub struct ImplItem {
+pub struct ImplItem<'hir> {
     pub ident: Ident,
     pub hir_id: HirId,
     pub vis: Visibility,
     pub defaultness: Defaultness,
-    pub attrs: HirVec<Attribute>,
+    pub attrs: &'hir [Attribute],
     pub generics: Generics,
-    pub kind: ImplItemKind,
+    pub kind: ImplItemKind<'hir>,
     pub span: Span,
 }
 
 /// Represents various kinds of content within an `impl`.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub enum ImplItemKind {
+pub enum ImplItemKind<'hir> {
     /// An associated constant of the given type, set to the constant result
     /// of the expression.
-    Const(P<Ty>, BodyId),
+    Const(&'hir Ty, BodyId),
     /// A method implementation with the given signature and body.
     Method(FnSig, BodyId),
     /// An associated type.
-    TyAlias(P<Ty>),
+    TyAlias(&'hir Ty),
     /// An associated `type = impl Trait`.
     OpaqueTy(GenericBounds),
 }
@@ -2232,18 +2243,18 @@ impl FunctionRetTy {
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug)]
-pub struct Mod {
+pub struct Mod<'hir> {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
     /// to the last token in the external file.
     pub inner: Span,
-    pub item_ids: HirVec<ItemId>,
+    pub item_ids: &'hir [ItemId],
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct ForeignMod {
+pub struct ForeignMod<'hir> {
     pub abi: Abi,
-    pub items: HirVec<ForeignItem>,
+    pub items: &'hir [ForeignItem<'hir>],
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
@@ -2252,21 +2263,21 @@ pub struct GlobalAsm {
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct EnumDef {
-    pub variants: HirVec<Variant>,
+pub struct EnumDef<'hir> {
+    pub variants: &'hir [Variant<'hir>],
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct Variant {
+pub struct Variant<'hir> {
     /// Name of the variant.
     #[stable_hasher(project(name))]
     pub ident: Ident,
     /// Attributes of the variant.
-    pub attrs: HirVec<Attribute>,
+    pub attrs: &'hir [Attribute],
     /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`).
     pub id: HirId,
     /// Fields and constructor id of the variant.
-    pub data: VariantData,
+    pub data: VariantData<'hir>,
     /// Explicit discriminant (e.g., `Foo = 1`).
     pub disr_expr: Option<AnonConst>,
     /// Span
@@ -2366,17 +2377,17 @@ impl VisibilityKind {
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct StructField {
+pub struct StructField<'hir> {
     pub span: Span,
     #[stable_hasher(project(name))]
     pub ident: Ident,
     pub vis: Visibility,
     pub hir_id: HirId,
-    pub ty: P<Ty>,
-    pub attrs: HirVec<Attribute>,
+    pub ty: &'hir Ty,
+    pub attrs: &'hir [Attribute],
 }
 
-impl StructField {
+impl StructField<'_> {
     // Still necessary in couple of places
     pub fn is_positional(&self) -> bool {
         let first = self.ident.as_str().as_bytes()[0];
@@ -2386,24 +2397,24 @@ impl StructField {
 
 /// Fields and constructor IDs of enum variants and structs.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub enum VariantData {
+pub enum VariantData<'hir> {
     /// A struct variant.
     ///
     /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct(HirVec<StructField>, /* recovered */ bool),
+    Struct(&'hir [StructField<'hir>], /* recovered */ bool),
     /// A tuple variant.
     ///
     /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
-    Tuple(HirVec<StructField>, HirId),
+    Tuple(&'hir [StructField<'hir>], HirId),
     /// A unit variant.
     ///
     /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
     Unit(HirId),
 }
 
-impl VariantData {
+impl VariantData<'hir> {
     /// Return the fields of this variant.
-    pub fn fields(&self) -> &[StructField] {
+    pub fn fields(&self) -> &'hir [StructField<'hir>] {
         match *self {
             VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields,
             _ => &[],
@@ -2431,11 +2442,11 @@ pub struct ItemId {
 ///
 /// The name might be a dummy name in case of anonymous items
 #[derive(RustcEncodable, RustcDecodable, Debug)]
-pub struct Item {
+pub struct Item<'hir> {
     pub ident: Ident,
     pub hir_id: HirId,
-    pub attrs: HirVec<Attribute>,
-    pub kind: ItemKind,
+    pub attrs: &'hir [Attribute],
+    pub kind: ItemKind<'hir>,
     pub vis: Visibility,
     pub span: Span,
 }
@@ -2458,7 +2469,7 @@ impl FnHeader {
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub enum ItemKind {
+pub enum ItemKind<'hir> {
     /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
     /// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
@@ -2469,32 +2480,32 @@ pub enum ItemKind {
     /// or just
     ///
     /// `use foo::bar::baz;` (with `as baz` implicitly on the right).
-    Use(P<Path>, UseKind),
+    Use(&'hir Path, UseKind),
 
     /// A `static` item.
-    Static(P<Ty>, Mutability, BodyId),
+    Static(&'hir Ty, Mutability, BodyId),
     /// A `const` item.
-    Const(P<Ty>, BodyId),
+    Const(&'hir Ty, BodyId),
     /// A function declaration.
     Fn(FnSig, Generics, BodyId),
     /// A module.
-    Mod(Mod),
+    Mod(Mod<'hir>),
     /// An external module, e.g. `extern { .. }`.
-    ForeignMod(ForeignMod),
+    ForeignMod(ForeignMod<'hir>),
     /// Module-level inline assembly (from `global_asm!`).
-    GlobalAsm(P<GlobalAsm>),
+    GlobalAsm(&'hir GlobalAsm),
     /// A type alias, e.g., `type Foo = Bar<u8>`.
-    TyAlias(P<Ty>, Generics),
+    TyAlias(&'hir Ty, Generics),
     /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
     OpaqueTy(OpaqueTy),
     /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
-    Enum(EnumDef, Generics),
+    Enum(EnumDef<'hir>, Generics),
     /// A struct definition, e.g., `struct Foo<A> {x: A}`.
-    Struct(VariantData, Generics),
+    Struct(VariantData<'hir>, Generics),
     /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
-    Union(VariantData, Generics),
+    Union(VariantData<'hir>, Generics),
     /// A trait definition.
-    Trait(IsAuto, Unsafety, Generics, GenericBounds, HirVec<TraitItemRef>),
+    Trait(IsAuto, Unsafety, Generics, GenericBounds, &'hir [TraitItemRef]),
     /// A trait alias.
     TraitAlias(Generics, GenericBounds),
 
@@ -2504,11 +2515,11 @@ pub enum ItemKind {
          Defaultness,
          Generics,
          Option<TraitRef>, // (optional) trait this impl implements
-         P<Ty>, // self
-         HirVec<ImplItemRef>),
+         &'hir Ty, // self
+         &'hir [ImplItemRef]),
 }
 
-impl ItemKind {
+impl ItemKind<'_> {
     pub fn descriptive_variant(&self) -> &str {
         match *self {
             ItemKind::ExternCrate(..) => "extern crate",
@@ -2596,11 +2607,11 @@ pub enum AssocItemKind {
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct ForeignItem {
+pub struct ForeignItem<'hir> {
     #[stable_hasher(project(name))]
     pub ident: Ident,
-    pub attrs: HirVec<Attribute>,
-    pub kind: ForeignItemKind,
+    pub attrs: &'hir [Attribute],
+    pub kind: ForeignItemKind<'hir>,
     pub hir_id: HirId,
     pub span: Span,
     pub vis: Visibility,
@@ -2608,16 +2619,16 @@ pub struct ForeignItem {
 
 /// An item within an `extern` block.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub enum ForeignItemKind {
+pub enum ForeignItemKind<'hir> {
     /// A foreign function.
-    Fn(P<FnDecl>, HirVec<Ident>, Generics),
+    Fn(&'hir FnDecl, &'hir [Ident], Generics),
     /// A foreign static item (`static ext: u8`).
-    Static(P<Ty>, Mutability),
+    Static(&'hir Ty, Mutability),
     /// A foreign type.
     Type,
 }
 
-impl ForeignItemKind {
+impl ForeignItemKind<'hir> {
     pub fn descriptive_variant(&self) -> &str {
         match *self {
             ForeignItemKind::Fn(..) => "foreign function",
@@ -2776,12 +2787,12 @@ impl CodegenFnAttrs {
 #[derive(Copy, Clone, Debug)]
 pub enum Node<'hir> {
     Param(&'hir Param),
-    Item(&'hir Item),
-    ForeignItem(&'hir ForeignItem),
-    TraitItem(&'hir TraitItem),
-    ImplItem(&'hir ImplItem),
-    Variant(&'hir Variant),
-    Field(&'hir StructField),
+    Item(&'hir Item<'hir>),
+    ForeignItem(&'hir ForeignItem<'hir>),
+    TraitItem(&'hir TraitItem<'hir>),
+    ImplItem(&'hir ImplItem<'hir>),
+    Variant(&'hir Variant<'hir>),
+    Field(&'hir StructField<'hir>),
     AnonConst(&'hir AnonConst),
     Expr(&'hir Expr),
     Stmt(&'hir Stmt),
@@ -2793,11 +2804,11 @@ pub enum Node<'hir> {
     Arm(&'hir Arm),
     Block(&'hir Block),
     Local(&'hir Local),
-    MacroDef(&'hir MacroDef),
+    MacroDef(&'hir MacroDef<'hir>),
 
     /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
     /// with synthesized constructors.
-    Ctor(&'hir VariantData),
+    Ctor(&'hir VariantData<'hir>),
 
     Lifetime(&'hir Lifetime),
     GenericParam(&'hir GenericParam),
diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs
index 97228c8f240..b59c7438005 100644
--- a/src/librustc/hir/pat_util.rs
+++ b/src/librustc/hir/pat_util.rs
@@ -169,11 +169,10 @@ impl hir::Pat {
         self.each_binding(|annotation, _, _, _| {
             match annotation {
                 hir::BindingAnnotation::Ref => match result {
-                    None | Some(hir::Mutability::Immutable) =>
-                        result = Some(hir::Mutability::Immutable),
+                    None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
                     _ => {}
                 }
-                hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mutable),
+                hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut),
                 _ => {}
             }
         });
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index a069331582e..85747cadbd7 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -21,7 +21,7 @@ use std::vec;
 pub enum AnnNode<'a> {
     Name(&'a ast::Name),
     Block(&'a hir::Block),
-    Item(&'a hir::Item),
+    Item(&'a hir::Item<'a>),
     SubItem(hir::HirId),
     Expr(&'a hir::Expr),
     Pat(&'a hir::Pat),
@@ -43,7 +43,7 @@ pub trait PpAnn {
     }
     fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {
     }
-    fn try_fetch_item(&self, _: hir::HirId) -> Option<&hir::Item> {
+    fn try_fetch_item(&self, _: hir::HirId) -> Option<&hir::Item<'_>> {
         None
     }
 }
@@ -52,8 +52,8 @@ pub struct NoAnn;
 impl PpAnn for NoAnn {}
 pub const NO_ANN: &dyn PpAnn = &NoAnn;
 
-impl PpAnn for hir::Crate {
-    fn try_fetch_item(&self, item: hir::HirId) -> Option<&hir::Item> {
+impl PpAnn for hir::Crate<'a> {
+    fn try_fetch_item(&self, item: hir::HirId) -> Option<&hir::Item<'_>> {
         Some(self.item(item))
     }
     fn nested(&self, state: &mut State<'_>, nested: Nested) {
@@ -107,7 +107,7 @@ pub const INDENT_UNIT: usize = 4;
 /// it can scan the input text for comments to copy forward.
 pub fn print_crate<'a>(cm: &'a SourceMap,
                        sess: &ParseSess,
-                       krate: &hir::Crate,
+                       krate: &hir::Crate<'_>,
                        filename: FileName,
                        input: String,
                        ann: &'a dyn PpAnn) -> String {
@@ -259,19 +259,19 @@ impl<'a> State<'a> {
         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
     }
 
-    pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) {
+    pub fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
         self.print_inner_attributes(attrs);
-        for &item_id in &_mod.item_ids {
+        for &item_id in _mod.item_ids {
             self.ann.nested(self, Nested::Item(item_id));
         }
     }
 
     pub fn print_foreign_mod(&mut self,
-                             nmod: &hir::ForeignMod,
+                             nmod: &hir::ForeignMod<'_>,
                              attrs: &[ast::Attribute])
                              {
         self.print_inner_attributes(attrs);
-        for item in &nmod.items {
+        for item in nmod.items {
             self.print_foreign_item(item);
         }
     }
@@ -361,7 +361,7 @@ impl<'a> State<'a> {
         self.end()
     }
 
-    pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) {
+    pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(item.span.lo());
         self.print_outer_attributes(&item.attrs);
@@ -386,7 +386,7 @@ impl<'a> State<'a> {
             }
             hir::ForeignItemKind::Static(ref t, m) => {
                 self.head(visibility_qualified(&item.vis, "static"));
-                if m == hir::Mutability::Mutable {
+                if m == hir::Mutability::Mut {
                     self.word_space("mut");
                 }
                 self.print_ident(item.ident);
@@ -445,7 +445,7 @@ impl<'a> State<'a> {
 
     fn print_item_type(
         &mut self,
-        item: &hir::Item,
+        item: &hir::Item<'_>,
         generics: &hir::Generics,
         inner: impl Fn(&mut Self),
     ) {
@@ -462,7 +462,7 @@ impl<'a> State<'a> {
     }
 
     /// Pretty-print an item
-    pub fn print_item(&mut self, item: &hir::Item) {
+    pub fn print_item(&mut self, item: &hir::Item<'_>) {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(item.span.lo());
         self.print_outer_attributes(&item.attrs);
@@ -502,7 +502,7 @@ impl<'a> State<'a> {
             }
             hir::ItemKind::Static(ref ty, m, expr) => {
                 self.head(visibility_qualified(&item.vis, "static"));
-                if m == hir::Mutability::Mutable {
+                if m == hir::Mutability::Mut {
                     self.word_space("mut");
                 }
                 self.print_ident(item.ident);
@@ -601,7 +601,7 @@ impl<'a> State<'a> {
                           ref generics,
                           ref opt_trait,
                           ref ty,
-                          ref impl_items) => {
+                          impl_items) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
@@ -634,7 +634,7 @@ impl<'a> State<'a> {
                 }
                 self.bclose(item.span);
             }
-            hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
+            hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_is_auto(is_auto);
@@ -708,7 +708,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_enum_def(&mut self,
-                          enum_definition: &hir::EnumDef,
+                          enum_definition: &hir::EnumDef<'_>,
                           generics: &hir::Generics,
                           name: ast::Name,
                           span: syntax_pos::Span,
@@ -723,7 +723,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_variants(&mut self,
-                          variants: &[hir::Variant],
+                          variants: &[hir::Variant<'_>],
                           span: syntax_pos::Span)
                           {
         self.bopen();
@@ -770,7 +770,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_struct(&mut self,
-                        struct_def: &hir::VariantData,
+                        struct_def: &hir::VariantData<'_>,
                         generics: &hir::Generics,
                         name: ast::Name,
                         span: syntax_pos::Span,
@@ -819,7 +819,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_variant(&mut self, v: &hir::Variant) {
+    pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
         self.head("");
         let generics = hir::Generics::empty();
         self.print_struct(&v.data, &generics, v.ident.name, v.span, false);
@@ -846,7 +846,7 @@ impl<'a> State<'a> {
                       body_id)
     }
 
-    pub fn print_trait_item(&mut self, ti: &hir::TraitItem) {
+    pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
         self.ann.pre(self, AnnNode::SubItem(ti.hir_id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(ti.span.lo());
@@ -882,7 +882,7 @@ impl<'a> State<'a> {
         self.ann.post(self, AnnNode::SubItem(ti.hir_id))
     }
 
-    pub fn print_impl_item(&mut self, ii: &hir::ImplItem) {
+    pub fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
         self.ann.pre(self, AnnNode::SubItem(ii.hir_id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(ii.span.lo());
@@ -1632,11 +1632,11 @@ impl<'a> State<'a> {
                 match binding_mode {
                     hir::BindingAnnotation::Ref => {
                         self.word_nbsp("ref");
-                        self.print_mutability(hir::Mutability::Immutable, false);
+                        self.print_mutability(hir::Mutability::Not, false);
                     }
                     hir::BindingAnnotation::RefMut => {
                         self.word_nbsp("ref");
-                        self.print_mutability(hir::Mutability::Mutable, false);
+                        self.print_mutability(hir::Mutability::Mut, false);
                     }
                     hir::BindingAnnotation::Unannotated => {}
                     hir::BindingAnnotation::Mutable => {
@@ -2065,8 +2065,8 @@ impl<'a> State<'a> {
 
     pub fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) {
         match mutbl {
-            hir::Mutability::Mutable => self.word_nbsp("mut"),
-            hir::Mutability::Immutable => if print_const { self.word_nbsp("const") },
+            hir::Mutability::Mut => self.word_nbsp("mut"),
+            hir::Mutability::Not => if print_const { self.word_nbsp("const") },
         }
     }
 
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 8b35839c182..af5e167faa8 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -56,12 +56,12 @@ pub enum NodeIdHashingMode {
 /// We could also just store a plain reference to the `hir::Crate` but we want
 /// to avoid that the crate is used to get untracked access to all of the HIR.
 #[derive(Clone, Copy)]
-struct BodyResolver<'tcx>(&'tcx hir::Crate);
+struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>);
 
 impl<'tcx> BodyResolver<'tcx> {
     /// Returns a reference to the `hir::Body` with the given `BodyId`.
     /// **Does not do any tracking**; use carefully.
-    fn body(self, id: hir::BodyId) -> &'tcx hir::Body {
+    fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> {
         self.0.body(id)
     }
 }
@@ -72,7 +72,7 @@ impl<'a> StableHashingContext<'a> {
     /// leaking data out of the tracking system.
     #[inline]
     pub fn new(sess: &'a Session,
-               krate: &'a hir::Crate,
+               krate: &'a hir::Crate<'a>,
                definitions: &'a Definitions,
                cstore: &'a dyn CrateStore)
                -> Self {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 066359bd4e0..1f96f4c65ef 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -150,7 +150,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::TraitItem {
             hir_id: _,
@@ -172,7 +172,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
 }
 
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::ImplItem {
             hir_id: _,
@@ -218,7 +218,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::Mod {
             inner: ref inner_span,
@@ -245,7 +245,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Item<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::Item {
             ident,
@@ -266,7 +266,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::Body {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::Body {
             params,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index c9d57706d55..052f33dc2a6 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -252,7 +252,7 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    fn item_scope_tag(item: &hir::Item) -> &'static str {
+    fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
         match item.kind {
             hir::ItemKind::Impl(..) => "impl",
             hir::ItemKind::Struct(..) => "struct",
@@ -264,14 +264,14 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str {
+    fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
         match item.kind {
             hir::TraitItemKind::Method(..) => "method body",
             hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
         }
     }
 
-    fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
+    fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
         match item.kind {
             hir::ImplItemKind::Method(..) => "method body",
             hir::ImplItemKind::Const(..)
@@ -1912,6 +1912,7 @@ impl<'tcx> ObligationCause<'tcx> {
         use crate::traits::ObligationCauseCode::*;
         match self.code {
             CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
+            CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =>
                 Error0308(match source {
                     hir::MatchSource::IfLetDesugar { .. } =>
@@ -1948,6 +1949,7 @@ impl<'tcx> ObligationCause<'tcx> {
         use crate::traits::ObligationCauseCode::*;
         match self.code {
             CompareImplMethodObligation { .. } => "method type is compatible with trait",
+            CompareImplTypeObligation { .. } => "associated type is compatible with trait",
             ExprAssignable => "expression is assignable",
             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
                 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index ebb94cc72ff..378d6d78d32 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -83,8 +83,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
         intravisit::walk_local(self, local);
     }
 
-    fn visit_body(&mut self, body: &'tcx Body) {
-        for param in &body.params {
+    fn visit_body(&mut self, body: &'tcx Body<'tcx>) {
+        for param in body.params {
             if let (None, Some(ty)) = (
                 self.found_arg_pattern,
                 self.node_matches_type(param.hir_id),
@@ -113,7 +113,7 @@ fn closure_return_type_suggestion(
     span: Span,
     err: &mut DiagnosticBuilder<'_>,
     output: &FunctionRetTy,
-    body: &Body,
+    body: &Body<'_>,
     descr: &str,
     name: &str,
     ret: &str,
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 7f72154e42c..b7d01306343 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -883,7 +883,7 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> {
         self.context.param_env = old_param_env;
     }
 
-    fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
+    fn process_mod(&mut self, m: &'tcx hir::Mod<'tcx>, s: Span, n: hir::HirId) {
         lint_callback!(self, check_mod, m, s, n);
         hir_visit::walk_mod(self, m, n);
         lint_callback!(self, check_mod_post, m, s, n);
@@ -924,13 +924,13 @@ for LateContextAndPass<'a, 'tcx, T> {
         });
     }
 
-    fn visit_body(&mut self, body: &'tcx hir::Body) {
+    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
         lint_callback!(self, check_body, body);
         hir_visit::walk_body(self, body);
         lint_callback!(self, check_body_post, body);
     }
 
-    fn visit_item(&mut self, it: &'tcx hir::Item) {
+    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         let generics = self.context.generics.take();
         self.context.generics = it.kind.generics();
         self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
@@ -943,7 +943,7 @@ for LateContextAndPass<'a, 'tcx, T> {
         self.context.generics = generics;
     }
 
-    fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
         self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
             cx.with_param_env(it.hir_id, |cx| {
                 lint_callback!(cx, check_foreign_item, it);
@@ -990,7 +990,7 @@ for LateContextAndPass<'a, 'tcx, T> {
     }
 
     fn visit_variant_data(&mut self,
-                        s: &'tcx hir::VariantData,
+                        s: &'tcx hir::VariantData<'tcx>,
                         _: ast::Name,
                         _: &'tcx hir::Generics,
                         _: hir::HirId,
@@ -1000,7 +1000,7 @@ for LateContextAndPass<'a, 'tcx, T> {
         lint_callback!(self, check_struct_def_post, s);
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
         self.with_lint_attrs(s.hir_id, &s.attrs, |cx| {
             lint_callback!(cx, check_struct_field, s);
             hir_visit::walk_struct_field(cx, s);
@@ -1008,7 +1008,7 @@ for LateContextAndPass<'a, 'tcx, T> {
     }
 
     fn visit_variant(&mut self,
-                     v: &'tcx hir::Variant,
+                     v: &'tcx hir::Variant<'tcx>,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
         self.with_lint_attrs(v.id, &v.attrs, |cx| {
@@ -1027,7 +1027,7 @@ for LateContextAndPass<'a, 'tcx, T> {
         lint_callback!(self, check_name, sp, name);
     }
 
-    fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
+    fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, s: Span, n: hir::HirId) {
         if !self.context.only_module {
             self.process_mod(m, s, n);
         }
@@ -1072,7 +1072,7 @@ for LateContextAndPass<'a, 'tcx, T> {
         hir_visit::walk_poly_trait_ref(self, t, m);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         let generics = self.context.generics.take();
         self.context.generics = Some(&trait_item.generics);
         self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |cx| {
@@ -1085,7 +1085,7 @@ for LateContextAndPass<'a, 'tcx, T> {
         self.context.generics = generics;
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         let generics = self.context.generics.take();
         self.context.generics = Some(&impl_item.generics);
         self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |cx| {
@@ -1249,7 +1249,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         ast_visit::walk_poly_trait_ref(self, t, m);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'a ast::AssocItem) {
         self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| {
             run_early_pass!(cx, check_trait_item, trait_item);
             ast_visit::walk_trait_item(cx, trait_item);
@@ -1257,7 +1257,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         });
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'a ast::AssocItem) {
         self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| {
             run_early_pass!(cx, check_impl_item, impl_item);
             ast_visit::walk_impl_item(cx, impl_item);
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
index 10c0c63995c..f80a72365e3 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc/lint/internal.rs
@@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
                     }
                 }
             }
-            TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Immutable }) => {
+            TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
                 if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
                     if cx.tcx.impl_trait_ref(impl_did).is_some() {
                         return;
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index a8d88686679..3d6015ecfbf 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -87,17 +87,17 @@ macro_rules! late_lint_methods {
     ($macro:path, $args:tt, [$hir:tt]) => (
         $macro!($args, [$hir], [
             fn check_param(a: &$hir hir::Param);
-            fn check_body(a: &$hir hir::Body);
-            fn check_body_post(a: &$hir hir::Body);
+            fn check_body(a: &$hir hir::Body<$hir>);
+            fn check_body_post(a: &$hir hir::Body<$hir>);
             fn check_name(a: Span, b: ast::Name);
-            fn check_crate(a: &$hir hir::Crate);
-            fn check_crate_post(a: &$hir hir::Crate);
-            fn check_mod(a: &$hir hir::Mod, b: Span, c: hir::HirId);
-            fn check_mod_post(a: &$hir hir::Mod, b: Span, c: hir::HirId);
-            fn check_foreign_item(a: &$hir hir::ForeignItem);
-            fn check_foreign_item_post(a: &$hir hir::ForeignItem);
-            fn check_item(a: &$hir hir::Item);
-            fn check_item_post(a: &$hir hir::Item);
+            fn check_crate(a: &$hir hir::Crate<$hir>);
+            fn check_crate_post(a: &$hir hir::Crate<$hir>);
+            fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
+            fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
+            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
+            fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
+            fn check_item(a: &$hir hir::Item<$hir>);
+            fn check_item_post(a: &$hir hir::Item<$hir>);
             fn check_local(a: &$hir hir::Local);
             fn check_block(a: &$hir hir::Block);
             fn check_block_post(a: &$hir hir::Block);
@@ -114,25 +114,25 @@ macro_rules! late_lint_methods {
             fn check_fn(
                 a: hir::intravisit::FnKind<$hir>,
                 b: &$hir hir::FnDecl,
-                c: &$hir hir::Body,
+                c: &$hir hir::Body<$hir>,
                 d: Span,
                 e: hir::HirId);
             fn check_fn_post(
                 a: hir::intravisit::FnKind<$hir>,
                 b: &$hir hir::FnDecl,
-                c: &$hir hir::Body,
+                c: &$hir hir::Body<$hir>,
                 d: Span,
                 e: hir::HirId
             );
-            fn check_trait_item(a: &$hir hir::TraitItem);
-            fn check_trait_item_post(a: &$hir hir::TraitItem);
-            fn check_impl_item(a: &$hir hir::ImplItem);
-            fn check_impl_item_post(a: &$hir hir::ImplItem);
-            fn check_struct_def(a: &$hir hir::VariantData);
-            fn check_struct_def_post(a: &$hir hir::VariantData);
-            fn check_struct_field(a: &$hir hir::StructField);
-            fn check_variant(a: &$hir hir::Variant);
-            fn check_variant_post(a: &$hir hir::Variant);
+            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
+            fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
+            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
+            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
+            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
+            fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
+            fn check_struct_field(a: &$hir hir::StructField<$hir>);
+            fn check_variant(a: &$hir hir::Variant<$hir>);
+            fn check_variant_post(a: &$hir hir::Variant<$hir>);
             fn check_lifetime(a: &$hir hir::Lifetime);
             fn check_path(a: &$hir hir::Path, b: hir::HirId);
             fn check_attribute(a: &$hir ast::Attribute);
@@ -258,10 +258,10 @@ macro_rules! early_lint_methods {
                 c: Span,
                 d: ast::NodeId
             );
-            fn check_trait_item(a: &ast::TraitItem);
-            fn check_trait_item_post(a: &ast::TraitItem);
-            fn check_impl_item(a: &ast::ImplItem);
-            fn check_impl_item_post(a: &ast::ImplItem);
+            fn check_trait_item(a: &ast::AssocItem);
+            fn check_trait_item_post(a: &ast::AssocItem);
+            fn check_impl_item(a: &ast::AssocItem);
+            fn check_impl_item_post(a: &ast::AssocItem);
             fn check_struct_def(a: &ast::VariantData);
             fn check_struct_def_post(a: &ast::VariantData);
             fn check_struct_field(a: &ast::StructField);
@@ -562,7 +562,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
 
     let push = builder.levels.push(&krate.attrs, &store);
     builder.levels.register_id(hir::CRATE_HIR_ID);
-    for macro_def in &krate.exported_macros {
+    for macro_def in krate.exported_macros {
        builder.levels.register_id(macro_def.hir_id);
     }
     intravisit::walk_crate(&mut builder, krate);
@@ -604,13 +604,13 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
         });
     }
 
-    fn visit_item(&mut self, it: &'tcx hir::Item) {
+    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
             intravisit::walk_item(builder, it);
         });
     }
 
-    fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
         self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
             intravisit::walk_foreign_item(builder, it);
         })
@@ -622,14 +622,14 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
         })
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
         self.with_lint_attrs(s.hir_id, &s.attrs, |builder| {
             intravisit::walk_struct_field(builder, s);
         })
     }
 
     fn visit_variant(&mut self,
-                     v: &'tcx hir::Variant,
+                     v: &'tcx hir::Variant<'tcx>,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
         self.with_lint_attrs(v.id, &v.attrs, |builder| {
@@ -649,13 +649,13 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
         })
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |builder| {
             intravisit::walk_trait_item(builder, trait_item);
         });
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |builder| {
             intravisit::walk_impl_item(builder, impl_item);
         });
diff --git a/src/librustc/middle/diagnostic_items.rs b/src/librustc/middle/diagnostic_items.rs
index dfae169b278..96faf567463 100644
--- a/src/librustc/middle/diagnostic_items.rs
+++ b/src/librustc/middle/diagnostic_items.rs
@@ -25,15 +25,15 @@ struct DiagnosticItemCollector<'tcx> {
 }
 
 impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         self.observe_item(&item.attrs, item.hir_id);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         self.observe_item(&trait_item.attrs, trait_item.hir_id);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         self.observe_item(&impl_item.attrs, impl_item.hir_id);
     }
 }
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6f7a022eccf..d87eec05866 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -113,7 +113,7 @@ struct LanguageItemCollector<'tcx> {
 }
 
 impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let Some((value, span)) = extract(&item.attrs) {
             let actual_target = Target::from_item(item);
             match self.item_refs.get(&*value.as_str()).cloned() {
@@ -151,11 +151,11 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
         // At present, lang items are always items, not trait items.
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
         // At present, lang items are always items, not impl items.
     }
 }
diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs
index e6f8521216b..c38ab525ce4 100644
--- a/src/librustc/middle/lib_features.rs
+++ b/src/librustc/middle/lib_features.rs
@@ -157,7 +157,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
 pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
     let krate = tcx.hir().krate();
-    for attr in &krate.non_exported_macro_attrs {
+    for attr in krate.non_exported_macro_attrs {
         collector.visit_attribute(attr);
     }
     intravisit::walk_crate(&mut collector, krate);
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index f77f5a72e60..6746df6c7de 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -27,7 +27,7 @@ use crate::hir::intravisit;
 // Returns true if the given item must be inlined because it may be
 // monomorphized or it was marked with `#[inline]`. This will only return
 // true for functions.
-fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item, attrs: CodegenFnAttrs) -> bool {
+fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: CodegenFnAttrs) -> bool {
     if attrs.requests_inline() {
         return true
     }
@@ -47,7 +47,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item, attrs: CodegenFnAt
 
 fn method_might_be_inlined(
     tcx: TyCtxt<'_>,
-    impl_item: &hir::ImplItem,
+    impl_item: &hir::ImplItem<'_>,
     impl_src: DefId,
 ) -> bool {
     let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
@@ -349,7 +349,7 @@ struct CollectPrivateImplItemsVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         // Anything which has custom linkage gets thrown on the worklist no
         // matter where it is in the crate, along with "special std symbols"
         // which are currently akin to allocator symbols.
@@ -387,9 +387,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
         // processed in visit_item above
     }
 }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index aa6f2839828..c5d5bc58112 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -715,7 +715,7 @@ impl<'tcx> ScopeTree {
     pub fn yield_in_scope_for_expr(&self,
                                    scope: Scope,
                                    expr_hir_id: hir::HirId,
-                                   body: &'tcx hir::Body) -> Option<Span> {
+                                   body: &'tcx hir::Body<'tcx>) -> Option<Span> {
         self.yield_in_scope(scope).and_then(|YieldData { span, expr_and_pat_count, .. }| {
             let mut visitor = ExprLocatorVisitor {
                 hir_id: expr_hir_id,
@@ -1173,6 +1173,7 @@ fn resolve_local<'tcx>(
     ///        | VariantName(..., P&, ...)
     ///        | [ ..., P&, ... ]
     ///        | ( ..., P&, ... )
+    ///        | ... "|" P& "|" ...
     ///        | box P&
     fn is_binding_pat(pat: &hir::Pat) -> bool {
         // Note that the code below looks for *explicit* refs only, that is, it won't
@@ -1212,6 +1213,7 @@ fn resolve_local<'tcx>(
                 pats3.iter().any(|p| is_binding_pat(&p))
             }
 
+            PatKind::Or(ref subpats) |
             PatKind::TupleStruct(_, ref subpats, _) |
             PatKind::Tuple(ref subpats, _) => {
                 subpats.iter().any(|p| is_binding_pat(&p))
@@ -1221,7 +1223,13 @@ fn resolve_local<'tcx>(
                 is_binding_pat(&subpat)
             }
 
-            _ => false,
+            PatKind::Ref(_, _) |
+            PatKind::Binding(hir::BindingAnnotation::Unannotated, ..) |
+            PatKind::Binding(hir::BindingAnnotation::Mutable, ..) |
+            PatKind::Wild |
+            PatKind::Path(_) |
+            PatKind::Lit(_) |
+            PatKind::Range(_, _, _) => false,
         }
     }
 
@@ -1354,7 +1362,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
         resolve_block(self, b);
     }
 
-    fn visit_body(&mut self, body: &'tcx hir::Body) {
+    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
         let body_id = body.id();
         let owner_id = self.tcx.hir().body_owner(body_id);
 
@@ -1379,7 +1387,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
 
         // The arguments and `self` are parented to the fn.
         self.cx.var_parent = self.cx.parent.take();
-        for param in &body.params {
+        for param in body.params {
             self.visit_pat(&param.pat);
         }
 
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index c13c44c413d..4b838d04059 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -421,7 +421,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
 /// In traits, there is an implicit `Self` type parameter which comes before the generics.
 /// We have to account for this when computing the index of the other generic parameters.
 /// This function returns whether there is such an implicit parameter defined on the given item.
-fn sub_items_have_self_param(node: &hir::ItemKind) -> bool {
+fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool {
     match *node {
         hir::ItemKind::Trait(..) |
         hir::ItemKind::TraitAlias(..) => true,
@@ -454,7 +454,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         replace(&mut self.labels_in_fn, saved);
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         match item.kind {
             hir::ItemKind::Fn(ref sig, ref generics, _) => {
                 self.visit_early_late(None, &sig.decl, generics, |this| {
@@ -536,7 +536,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         match item.kind {
             hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
                 self.visit_early_late(None, decl, generics, |this| {
@@ -771,7 +771,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
         match trait_item.kind {
             Method(ref sig, _) => {
@@ -823,7 +823,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         use self::hir::ImplItemKind::*;
         match impl_item.kind {
             Method(ref sig, _) => {
@@ -1167,7 +1167,7 @@ fn signal_shadowing_problem(tcx: TyCtxt<'_>, name: ast::Name, orig: Original, sh
 
 // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
 // if one of the label shadows a lifetime or another label.
-fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body) {
+fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) {
     struct GatherLabels<'a, 'tcx> {
         tcx: TyCtxt<'tcx>,
         scope: ScopeRef<'a>,
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 51756084f24..e1838b13fef 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -254,7 +254,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, i: &'tcx Item) {
+    fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
         let orig_in_trait_impl = self.in_trait_impl;
         let mut kind = AnnotationKind::Required;
         match i.kind {
@@ -283,13 +283,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         self.in_trait_impl = orig_in_trait_impl;
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
         self.annotate(ti.hir_id, &ti.attrs, ti.span, AnnotationKind::Required, |v| {
             intravisit::walk_trait_item(v, ti);
         });
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
         let kind = if self.in_trait_impl {
             AnnotationKind::Prohibited
         } else {
@@ -300,7 +300,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         });
     }
 
-    fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
+    fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics, item_id: HirId) {
         self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required,
             |v| {
                 if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
@@ -312,19 +312,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             })
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) {
         self.annotate(s.hir_id, &s.attrs, s.span, AnnotationKind::Required, |v| {
             intravisit::walk_struct_field(v, s);
         });
     }
 
-    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
         self.annotate(i.hir_id, &i.attrs, i.span, AnnotationKind::Required, |v| {
             intravisit::walk_foreign_item(v, i);
         });
     }
 
-    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
+    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
         self.annotate(md.hir_id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
     }
 }
@@ -354,7 +354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, i: &'tcx Item) {
+    fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
         match i.kind {
             // Inherent impls and foreign modules serve only as containers for other items,
             // they don't have their own stability. They still can be annotated as unstable
@@ -368,12 +368,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
         intravisit::walk_item(self, i)
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
         self.check_missing_stability(ti.hir_id, ti.span, "item");
         intravisit::walk_trait_item(self, ti);
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
         let impl_def_id = self.tcx.hir().local_def_id(
             self.tcx.hir().get_parent_item(ii.hir_id));
         if self.tcx.impl_trait_ref(impl_def_id).is_none() {
@@ -382,22 +382,22 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
         intravisit::walk_impl_item(self, ii);
     }
 
-    fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
+    fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics, item_id: HirId) {
         self.check_missing_stability(var.id, var.span, "variant");
         intravisit::walk_variant(self, var, g, item_id);
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) {
         self.check_missing_stability(s.hir_id, s.span, "field");
         intravisit::walk_struct_field(self, s);
     }
 
-    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
         self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant());
         intravisit::walk_foreign_item(self, i);
     }
 
-    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
+    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
         self.check_missing_stability(md.hir_id, md.span, "macro");
     }
 }
@@ -816,7 +816,7 @@ impl Visitor<'tcx> for Checker<'tcx> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         match item.kind {
             hir::ItemKind::ExternCrate(_) => {
                 // compiler-generated `extern crate` items have a dummy span.
@@ -834,7 +834,7 @@ impl Visitor<'tcx> for Checker<'tcx> {
             // For implementations of traits, check the stability of each item
             // individually as it's possible to have a stable trait with unstable
             // items.
-            hir::ItemKind::Impl(.., Some(ref t), _, ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., Some(ref t), _, impl_item_refs) => {
                 if let Res::Def(DefKind::Trait, trait_did) = t.path.res {
                     for impl_item_ref in impl_item_refs {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index 48c1226232f..2acea7c5b68 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -136,7 +136,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
         NestedVisitorMap::None
     }
 
-    fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
         if let Some((lang_item, _)) = lang_items::extract(&i.attrs) {
             self.register(lang_item, i.span);
         }
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index f849361e08b..a1bb80f6179 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -106,7 +106,7 @@ impl<Tag> Allocation<Tag> {
             undef_mask: UndefMask::new(size, true),
             size,
             align,
-            mutability: Mutability::Immutable,
+            mutability: Mutability::Not,
             extra: (),
         }
     }
@@ -123,7 +123,7 @@ impl<Tag> Allocation<Tag> {
             undef_mask: UndefMask::new(size, false),
             size,
             align,
-            mutability: Mutability::Mutable,
+            mutability: Mutability::Mut,
             extra: (),
         }
     }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index ba8feb4ee73..0757e02da97 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -34,6 +34,7 @@ use std::ops::Index;
 use std::slice;
 use std::{iter, mem, option, u32};
 use syntax::ast::Name;
+pub use syntax::ast::Mutability;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -396,22 +397,7 @@ pub struct SourceInfo {
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Mutability and borrow kinds
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
-pub enum Mutability {
-    Mut,
-    Not,
-}
-
-impl From<Mutability> for hir::Mutability {
-    fn from(m: Mutability) -> Self {
-        match m {
-            Mutability::Mut => hir::Mutability::Mutable,
-            Mutability::Not => hir::Mutability::Immutable,
-        }
-    }
-}
+// Borrow kinds
 
 #[derive(
     Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, HashStable,
@@ -2060,6 +2046,11 @@ pub enum Rvalue<'tcx> {
     /// &x or &mut x
     Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
 
+    /// Create a raw pointer to the given place
+    /// Can be generated by raw address of expressions (`&raw const x`),
+    /// or when casting a reference to a raw pointer.
+    AddressOf(Mutability, Place<'tcx>),
+
     /// length of a [X] or [X;n] value
     Len(Place<'tcx>),
 
@@ -2214,6 +2205,15 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                 write!(fmt, "&{}{}{:?}", region, kind_str, place)
             }
 
+            AddressOf(mutability, ref place) => {
+                let kind_str = match mutability {
+                    Mutability::Mut => "mut",
+                    Mutability::Not => "const",
+                };
+
+                write!(fmt, "&raw {} {:?}", kind_str, place)
+            }
+
             Aggregate(ref kind, ref places) => {
                 fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
                     let mut tuple_fmt = fmt.debug_tuple("");
@@ -2872,7 +2872,6 @@ pub enum ClosureOutlivesSubject<'tcx> {
 CloneTypeFoldableAndLiftImpls! {
     BlockTailInfo,
     MirPhase,
-    Mutability,
     SourceInfo,
     FakeReadCause,
     RetagKind,
@@ -3085,6 +3084,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
             Ref(region, bk, ref place) => {
                 Ref(region.fold_with(folder), bk, place.fold_with(folder))
             }
+            AddressOf(mutability, ref place) => {
+                AddressOf(mutability, place.fold_with(folder))
+            }
             Len(ref place) => Len(place.fold_with(folder)),
             Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
             BinaryOp(op, ref rhs, ref lhs) => {
@@ -3125,6 +3127,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
             Use(ref op) => op.visit_with(visitor),
             Repeat(ref op, _) => op.visit_with(visitor),
             Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
+            AddressOf(_, ref place) => place.visit_with(visitor),
             Len(ref place) => place.visit_with(visitor),
             Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
             BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 445fa6ea8ca..841c0b458d1 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -172,6 +172,13 @@ impl<'tcx> Rvalue<'tcx> {
                     }
                 )
             }
+            Rvalue::AddressOf(mutability, ref place) => {
+                let place_ty = place.ty(local_decls, tcx).ty;
+                tcx.mk_ptr(ty::TypeAndMut {
+                    ty: place_ty,
+                    mutbl: mutability.into(),
+                })
+            }
             Rvalue::Len(..) => tcx.types.usize,
             Rvalue::Cast(.., ty) => ty,
             Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
@@ -272,17 +279,17 @@ impl<'tcx> BinOp {
 impl BorrowKind {
     pub fn to_mutbl_lossy(self) -> hir::Mutability {
         match self {
-            BorrowKind::Mut { .. } => hir::Mutability::Mutable,
-            BorrowKind::Shared => hir::Mutability::Immutable,
+            BorrowKind::Mut { .. } => hir::Mutability::Mut,
+            BorrowKind::Shared => hir::Mutability::Not,
 
             // We have no type corresponding to a unique imm borrow, so
             // use `&mut`. It gives all the capabilities of an `&uniq`
             // and hence is a safe "over approximation".
-            BorrowKind::Unique => hir::Mutability::Mutable,
+            BorrowKind::Unique => hir::Mutability::Mut,
 
             // We have no type corresponding to a shallow borrow, so use
             // `&` as an approximation.
-            BorrowKind::Shallow => hir::Mutability::Immutable,
+            BorrowKind::Shallow => hir::Mutability::Not,
         }
     }
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 5d273fe85b6..fa96b51347d 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -570,6 +570,18 @@ macro_rules! make_mir_visitor {
                         self.visit_place(path, ctx, location);
                     }
 
+                    Rvalue::AddressOf(m, path) => {
+                        let ctx = match m {
+                            Mutability::Mut => PlaceContext::MutatingUse(
+                                MutatingUseContext::AddressOf
+                            ),
+                            Mutability::Not => PlaceContext::NonMutatingUse(
+                                NonMutatingUseContext::AddressOf
+                            ),
+                        };
+                        self.visit_place(path, ctx, location);
+                    }
+
                     Rvalue::Len(path) => {
                         self.visit_place(
                             path,
@@ -1031,6 +1043,8 @@ pub enum NonMutatingUseContext {
     ShallowBorrow,
     /// Unique borrow.
     UniqueBorrow,
+    /// AddressOf for *const pointer.
+    AddressOf,
     /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
     /// For example, the projection `x.y` is not marked as a mutation in these cases:
     ///
@@ -1054,6 +1068,8 @@ pub enum MutatingUseContext {
     Drop,
     /// Mutable borrow.
     Borrow,
+    /// AddressOf for *mut pointer.
+    AddressOf,
     /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
     /// For example, the projection `x.y` is marked as a mutation in these cases:
     ///
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 4839974d625..b299fd6117e 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -702,6 +702,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             SelectionError::Unimplemented => {
                 if let ObligationCauseCode::CompareImplMethodObligation {
                     item_name, impl_item_def_id, trait_item_def_id,
+                } | ObligationCauseCode::CompareImplTypeObligation {
+                    item_name, impl_item_def_id, trait_item_def_id,
                 } = obligation.cause.code {
                     self.report_extra_impl_obligation(
                         span,
@@ -1548,8 +1550,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
             if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
                 let trait_type = match mutability {
-                    hir::Mutability::Mutable => self.tcx.mk_imm_ref(region, t_type),
-                    hir::Mutability::Immutable => self.tcx.mk_mut_ref(region, t_type),
+                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
+                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
                 };
 
                 let new_obligation = self.mk_obligation_for_def_id(
@@ -1565,7 +1567,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     let sp = self.tcx.sess.source_map()
                         .span_take_while(span, |c| c.is_whitespace() || *c == '&');
                     if points_at_arg &&
-                        mutability == hir::Mutability::Immutable &&
+                        mutability == hir::Mutability::Not &&
                         refs_number > 0
                     {
                         err.span_suggestion(
@@ -2631,6 +2633,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                               but not on the corresponding trait method",
                              predicate));
             }
+            ObligationCauseCode::CompareImplTypeObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the associated impl type\
+                     but not on the corresponding associated trait type",
+                     predicate));
+            }
             ObligationCauseCode::ReturnType |
             ObligationCauseCode::ReturnValue(_) |
             ObligationCauseCode::BlockTailExpression(_) => (),
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index d94e004db29..8baedfed9d6 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -230,6 +230,13 @@ pub enum ObligationCauseCode<'tcx> {
         trait_item_def_id: DefId,
     },
 
+    /// Error derived when matching traits/impls; see ObligationCause for more details
+    CompareImplTypeObligation {
+        item_name: ast::Name,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    },
+
     /// Checking that this expression can be assigned where it needs to be
     // FIXME(eddyb) #11161 is the original Expr required?
     ExprAssignable,
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 1fdec5f0152..408743d5788 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -23,6 +23,7 @@ use crate::ty::subst::{Subst, InternalSubsts};
 use crate::ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
 use crate::util::common::FN_OUTPUT_NAME;
+use syntax_pos::DUMMY_SP;
 
 /// Depending on the stage of compilation, we want projection to be
 /// more or less conservative.
@@ -1437,11 +1438,14 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+
     let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
+    let assoc_item_id = obligation.predicate.item_def_id;
+    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
-    let tcx = selcx.tcx();
     let param_env = obligation.param_env;
-    let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_def_id);
+    let assoc_ty = assoc_ty_def(selcx, impl_def_id, assoc_item_id);
 
     if !assoc_ty.item.defaultness.has_value() {
         // This means that the impl is missing a definition for the
@@ -1456,6 +1460,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
             obligations: nested,
         };
     }
+    let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
     let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
     let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
         let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
@@ -1463,9 +1468,20 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         tcx.type_of(assoc_ty.item.def_id)
     };
-    Progress {
-        ty: ty.subst(tcx, substs),
-        obligations: nested,
+    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
+        tcx.sess.delay_span_bug(
+            DUMMY_SP,
+            "impl item and trait item have different parameter counts",
+        );
+        Progress {
+            ty: tcx.types.err,
+            obligations: nested,
+        }
+    } else {
+        Progress {
+            ty: ty.subst(tcx, substs),
+            obligations: nested,
+        }
     }
 }
 
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 8d04c832f26..afc8a4d9e14 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2612,7 +2612,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Char
             | ty::RawPtr(..)
             | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Immutable) => {
+            | ty::Ref(_, _, hir::Mutability::Not) => {
                 // Implementations provided in libcore
                 None
             }
@@ -2623,7 +2623,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Generator(..)
             | ty::GeneratorWitness(..)
             | ty::Foreign(..)
-            | ty::Ref(_, _, hir::Mutability::Mutable) => None,
+            | ty::Ref(_, _, hir::Mutability::Mut) => None,
 
             ty::Array(element_ty, _) => {
                 // (*) binder moved here
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 8c300da11fc..1e78b79ebb6 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -514,6 +514,15 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                 impl_item_def_id,
                 trait_item_def_id,
             }),
+            super::CompareImplTypeObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => Some(super::CompareImplTypeObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            }),
             super::ExprAssignable => Some(super::ExprAssignable),
             super::MatchExpressionArm(box super::MatchExpressionArmCause {
                 arm_span,
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 342644752b6..0c04ba96365 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -109,8 +109,8 @@ pub struct OverloadedDeref<'tcx> {
 impl<'tcx> OverloadedDeref<'tcx> {
     pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) {
         let trait_def_id = match self.mutbl {
-            hir::Mutability::Immutable => tcx.lang_items().deref_trait(),
-            hir::Mutability::Mutable => tcx.lang_items().deref_mut_trait()
+            hir::Mutability::Not => tcx.lang_items().deref_trait(),
+            hir::Mutability::Mut => tcx.lang_items().deref_mut_trait()
         };
         let method_def_id = tcx.associated_items(trait_def_id.unwrap())
             .find(|m| m.kind == ty::AssocKind::Method).unwrap().def_id;
@@ -138,15 +138,15 @@ pub enum AllowTwoPhase {
 
 #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub enum AutoBorrowMutability {
-    Mutable { allow_two_phase_borrow: AllowTwoPhase },
-    Immutable,
+    Mut { allow_two_phase_borrow: AllowTwoPhase },
+    Not,
 }
 
 impl From<AutoBorrowMutability> for hir::Mutability {
     fn from(m: AutoBorrowMutability) -> Self {
         match m {
-            AutoBorrowMutability::Mutable { .. } => hir::Mutability::Mutable,
-            AutoBorrowMutability::Immutable => hir::Mutability::Immutable,
+            AutoBorrowMutability::Mut { .. } => hir::Mutability::Mut,
+            AutoBorrowMutability::Not => hir::Mutability::Not,
         }
     }
 }
diff --git a/src/librustc/ty/binding.rs b/src/librustc/ty/binding.rs
index 491e09dff09..00cff1f1be1 100644
--- a/src/librustc/ty/binding.rs
+++ b/src/librustc/ty/binding.rs
@@ -13,10 +13,10 @@ CloneTypeFoldableAndLiftImpls! { BindingMode, }
 impl BindingMode {
     pub fn convert(ba: BindingAnnotation) -> BindingMode {
         match ba {
-            Unannotated => BindingMode::BindByValue(Mutability::Immutable),
-            Mutable => BindingMode::BindByValue(Mutability::Mutable),
-            Ref => BindingMode::BindByReference(Mutability::Immutable),
-            RefMut => BindingMode::BindByReference(Mutability::Mutable),
+            Unannotated => BindingMode::BindByValue(Mutability::Not),
+            Mutable => BindingMode::BindByValue(Mutability::Mut),
+            Ref => BindingMode::BindByReference(Mutability::Not),
+            RefMut => BindingMode::BindByReference(Mutability::Mut),
         }
     }
 }
diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs
index bc12412312d..fca53db1475 100644
--- a/src/librustc/ty/cast.rs
+++ b/src/librustc/ty/cast.rs
@@ -28,8 +28,6 @@ pub enum CastTy<'tcx> {
     FnPtr,
     /// Raw pointers
     Ptr(ty::TypeAndMut<'tcx>),
-    /// References
-    RPtr(ty::TypeAndMut<'tcx>),
 }
 
 /// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
@@ -63,7 +61,6 @@ impl<'tcx> CastTy<'tcx> {
             ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() =>
                 Some(CastTy::Int(IntTy::CEnum)),
             ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
-            ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })),
             ty::FnPtr(..) => Some(CastTy::FnPtr),
             _ => None,
         }
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 595ea40b2ff..0806e2d7765 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2406,22 +2406,22 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Mutable})
+        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Mut })
     }
 
     #[inline]
     pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Immutable})
+        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Not })
     }
 
     #[inline]
     pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Mutable})
+        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Mut })
     }
 
     #[inline]
     pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Immutable})
+        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Not })
     }
 
     #[inline]
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index be6d21564a0..0218cb1d6fd 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -248,7 +248,7 @@ impl<'tcx> ty::TyS<'tcx> {
                     format!("`&{}`", tymut_string).into()
                 } else { // Unknown type name, it's long or has type arguments
                     match mutbl {
-                        hir::Mutability::Mutable => "mutable reference",
+                        hir::Mutability::Mut => "mutable reference",
                         _ => "reference",
                     }.into()
                 }
@@ -293,7 +293,7 @@ impl<'tcx> ty::TyS<'tcx> {
             ty::Slice(_) => "slice".into(),
             ty::RawPtr(_) => "raw pointer".into(),
             ty::Ref(.., mutbl) => match mutbl {
-                hir::Mutability::Mutable => "mutable reference",
+                hir::Mutability::Mut => "mutable reference",
                 _ => "reference"
             }.into(),
             ty::FnDef(..) => "fn item".into(),
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index c7278dc4fac..a8c44aa507c 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2221,12 +2221,12 @@ where
                 let tcx = cx.tcx();
                 let is_freeze = ty.is_freeze(tcx, cx.param_env(), DUMMY_SP);
                 let kind = match mt {
-                    hir::Mutability::Immutable => if is_freeze {
+                    hir::Mutability::Not => if is_freeze {
                         PointerKind::Frozen
                     } else {
                         PointerKind::Shared
                     },
-                    hir::Mutability::Mutable => {
+                    hir::Mutability::Mut => {
                         // Previously we would only emit noalias annotations for LLVM >= 6 or in
                         // panic=abort mode. That was deemed right, as prior versions had many bugs
                         // in conjunction with unwinding, but later versions didn’t seem to have
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c60d4a46935..30356d59a7c 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1305,7 +1305,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
     }
 
     #[inline]
-    pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'_>) -> PolyTraitRef<'tcx> {
+    pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
         // Note: unlike with `TraitRef::to_poly_trait_ref()`,
         // `self.0.trait_ref` is permitted to have escaping regions.
         // This is because here `self` has a `Binder` and so does our
@@ -2651,8 +2651,8 @@ impl<'tcx> TyS<'tcx> {
 impl BorrowKind {
     pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
         match m {
-            hir::Mutability::Mutable => MutBorrow,
-            hir::Mutability::Immutable => ImmBorrow,
+            hir::Mutability::Mut => MutBorrow,
+            hir::Mutability::Not => ImmBorrow,
         }
     }
 
@@ -2662,13 +2662,13 @@ impl BorrowKind {
     /// question.
     pub fn to_mutbl_lossy(self) -> hir::Mutability {
         match self {
-            MutBorrow => hir::Mutability::Mutable,
-            ImmBorrow => hir::Mutability::Immutable,
+            MutBorrow => hir::Mutability::Mut,
+            ImmBorrow => hir::Mutability::Not,
 
             // We have no type corresponding to a unique imm borrow, so
             // use `&mut`. It gives all the capabilities of an `&uniq`
             // and hence is a safe "over approximation".
-            UniqueImmBorrow => hir::Mutability::Mutable,
+            UniqueImmBorrow => hir::Mutability::Mut,
         }
     }
 
diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs
index 7eb774849b1..5e146119b51 100644
--- a/src/librustc/ty/print/obsolete.rs
+++ b/src/librustc/ty/print/obsolete.rs
@@ -59,8 +59,8 @@ impl DefPathBasedNames<'tcx> {
             ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
                 output.push('*');
                 match mutbl {
-                    hir::Mutability::Immutable => output.push_str("const "),
-                    hir::Mutability::Mutable => output.push_str("mut "),
+                    hir::Mutability::Not => output.push_str("const "),
+                    hir::Mutability::Mut => output.push_str("mut "),
                 }
 
                 self.push_type_name(inner_type, output, debug);
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 745f7d0276d..b4f1f9d779a 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -490,8 +490,8 @@ pub trait PrettyPrinter<'tcx>:
             ty::Float(t) => p!(write("{}", t.name_str())),
             ty::RawPtr(ref tm) => {
                 p!(write("*{} ", match tm.mutbl {
-                    hir::Mutability::Mutable => "mut",
-                    hir::Mutability::Immutable => "const",
+                    hir::Mutability::Mut => "mut",
+                    hir::Mutability::Not => "const",
                 }));
                 p!(print(tm.ty))
             }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index efdf40fd6b8..15b14c51c78 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -121,8 +121,8 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
         } else {
             let mutbl = a.mutbl;
             let variance = match mutbl {
-                ast::Mutability::Immutable => ty::Covariant,
-                ast::Mutability::Mutable => ty::Invariant,
+                ast::Mutability::Not => ty::Covariant,
+                ast::Mutability::Mut => ty::Invariant,
             };
             let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?;
             Ok(ty::TypeAndMut { ty, mutbl })
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 1e08c36ca50..604dc03ea17 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1026,11 +1026,11 @@ impl<'tcx> ProjectionTy<'tcx> {
     /// Extracts the underlying trait reference from this projection.
     /// For example, if this is a projection of `<T as Iterator>::Item`,
     /// then this function would return a `T: Iterator` trait reference.
-    pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::TraitRef<'tcx> {
+    pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = tcx.associated_item(self.item_def_id).container.id();
         ty::TraitRef {
             def_id,
-            substs: self.substs,
+            substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)),
         }
     }
 
@@ -1853,8 +1853,8 @@ impl<'tcx> TyS<'tcx> {
     #[inline]
     pub fn is_mutable_ptr(&self) -> bool {
         match self.kind {
-            RawPtr(TypeAndMut { mutbl: hir::Mutability::Mutable, .. }) |
-            Ref(_, _, hir::Mutability::Mutable) => true,
+            RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. }) |
+            Ref(_, _, hir::Mutability::Mut) => true,
             _ => false
         }
     }
@@ -2044,7 +2044,7 @@ impl<'tcx> TyS<'tcx> {
             Adt(def, _) if def.is_box() => {
                 Some(TypeAndMut {
                     ty: self.boxed_ty(),
-                    mutbl: hir::Mutability::Immutable,
+                    mutbl: hir::Mutability::Not,
                 })
             },
             Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }),
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index a8a17fe9d7d..217188a6f04 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -234,7 +234,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
                 ty::GenericParamDefKind::Const => {
                     tcx.mk_const(ty::Const {
                         val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
-                        ty: tcx.type_of(def_id),
+                        ty: tcx.type_of(param.def_id),
                     }).into()
                 }
             }
@@ -533,8 +533,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
                             data.name,
                             self.root_ty,
                             data.index);
-                        self.tcx.sess.delay_span_bug(span, &msg);
-                        r
+                        span_bug!(span, "{}", msg);
                     }
                 }
             }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 0b11a9efd81..f054a630e4b 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -183,7 +183,7 @@ impl<'tcx> ty::ParamEnv<'tcx> {
                 // Now libcore provides that impl.
                 ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
                 ty::Char | ty::RawPtr(..) | ty::Never |
-                ty::Ref(_, _, hir::Mutability::Immutable) => return Ok(()),
+                ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
 
                 ty::Adt(adt, substs) => (adt, substs),
 
@@ -679,7 +679,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Returns `true` if the node pointed to by `def_id` is a mutable `static` item.
     pub fn is_mutable_static(&self, def_id: DefId) -> bool {
-        self.static_mutability(def_id) == Some(hir::Mutability::Mutable)
+        self.static_mutability(def_id) == Some(hir::Mutability::Mut)
     }
 
     /// Get the type of the pointer to the static that we use in MIR.
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 276fc8c1dec..8af98c6117e 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -50,7 +50,7 @@ pub fn trait_obligations<'a, 'tcx>(
     body_id: hir::HirId,
     trait_ref: &ty::TraitRef<'tcx>,
     span: Span,
-    item: Option<&'tcx hir::Item>,
+    item: Option<&'tcx hir::Item<'tcx>>,
 ) -> Vec<traits::PredicateObligation<'tcx>> {
     let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
     wf.compute_trait_ref(trait_ref, Elaborate::All);
@@ -111,7 +111,7 @@ struct WfPredicates<'a, 'tcx> {
     body_id: hir::HirId,
     span: Span,
     out: Vec<traits::PredicateObligation<'tcx>>,
-    item: Option<&'tcx hir::Item>,
+    item: Option<&'tcx hir::Item<'tcx>>,
 }
 
 /// Controls whether we "elaborate" supertraits and so forth on the WF
diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs
index d6c8e54c18d..4c8c9d15d56 100644
--- a/src/librustc_asan/lib.rs
+++ b/src/librustc_asan/lib.rs
@@ -5,4 +5,4 @@
 #![no_std]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
-            issue = "0")]
+            issue = "none")]
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 5479a1f3144..3f2a51b45bd 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -344,6 +344,17 @@ pub fn from_fn_attrs(
                 const_cstr!("wasm-import-module"),
                 &module,
             );
+
+            let name = codegen_fn_attrs.link_name.unwrap_or_else(|| {
+                cx.tcx.item_name(instance.def_id())
+            });
+            let name = CString::new(&name.as_str()[..]).unwrap();
+            llvm::AddFunctionAttrStringValue(
+                llfn,
+                llvm::AttributePlace::Function,
+                const_cstr!("wasm-import-name"),
+                &name,
+            );
         }
     }
 }
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 0e4e4e2f983..6481ef5c73c 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -16,15 +16,24 @@ use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::session::config::{self, Lto};
 use rustc::util::common::time_ext;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, ModuleKind};
 use log::{info, debug};
 
 use std::ffi::{CStr, CString};
+use std::fs::File;
+use std::io;
+use std::mem;
+use std::path::Path;
 use std::ptr;
 use std::slice;
 use std::sync::Arc;
 
+/// We keep track of past LTO imports that were used to produce the current set
+/// of compiled object files that we might choose to reuse during this
+/// compilation session.
+pub const THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-imports.bin";
+
 pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
     match crate_type {
         config::CrateType::Executable |
@@ -472,13 +481,26 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
 
         info!("thin LTO data created");
 
-        let import_map = if cgcx.incr_comp_session_dir.is_some() {
-            ThinLTOImports::from_thin_lto_data(data)
+        let (import_map_path, prev_import_map, curr_import_map) =
+            if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir
+        {
+            let path = incr_comp_session_dir.join(THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME);
+            // If previous imports have been deleted, or we get an IO error
+            // reading the file storing them, then we'll just use `None` as the
+            // prev_import_map, which will force the code to be recompiled.
+            let prev = if path.exists() {
+                ThinLTOImports::load_from_file(&path).ok()
+            } else {
+                None
+            };
+            let curr = ThinLTOImports::from_thin_lto_data(data);
+            (Some(path), prev, curr)
         } else {
             // If we don't compile incrementally, we don't need to load the
             // import data from LLVM.
             assert!(green_modules.is_empty());
-            ThinLTOImports::default()
+            let curr = ThinLTOImports::default();
+            (None, None, curr)
         };
         info!("thin LTO import map loaded");
 
@@ -502,18 +524,36 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
         for (module_index, module_name) in shared.module_names.iter().enumerate() {
             let module_name = module_name_to_str(module_name);
 
-            // If the module hasn't changed and none of the modules it imports
-            // from has changed, we can re-use the post-ThinLTO version of the
-            // module.
-            if green_modules.contains_key(module_name) {
-                let imports_all_green = import_map.modules_imported_by(module_name)
+            // If (1.) the module hasn't changed, and (2.) none of the modules
+            // it imports from has changed, *and* (3.) the import-set itself has
+            // not changed from the previous compile when it was last
+            // ThinLTO'ed, then we can re-use the post-ThinLTO version of the
+            // module. Otherwise, freshly perform LTO optimization.
+            //
+            // This strategy means we can always save the computed imports as
+            // canon: when we reuse the post-ThinLTO version, condition (3.)
+            // ensures that the curent import set is the same as the previous
+            // one. (And of course, when we don't reuse the post-ThinLTO
+            // version, the current import set *is* the correct one, since we
+            // are doing the ThinLTO in this current compilation cycle.)
+            //
+            // See rust-lang/rust#59535.
+            if let (Some(prev_import_map), true) =
+                (prev_import_map.as_ref(), green_modules.contains_key(module_name))
+            {
+                assert!(cgcx.incr_comp_session_dir.is_some());
+
+                let prev_imports = prev_import_map.modules_imported_by(module_name);
+                let curr_imports = curr_import_map.modules_imported_by(module_name);
+                let imports_all_green = curr_imports
                     .iter()
                     .all(|imported_module| green_modules.contains_key(imported_module));
 
-                if imports_all_green {
+                if imports_all_green && equivalent_as_sets(prev_imports, curr_imports) {
                     let work_product = green_modules[module_name].clone();
                     copy_jobs.push(work_product);
                     info!(" - {}: re-used", module_name);
+                    assert!(cgcx.incr_comp_session_dir.is_some());
                     cgcx.cgu_reuse_tracker.set_actual_reuse(module_name,
                                                             CguReuse::PostLto);
                     continue
@@ -527,10 +567,33 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
             }));
         }
 
+        // Save the curent ThinLTO import information for the next compilation
+        // session, overwriting the previous serialized imports (if any).
+        if let Some(path) = import_map_path {
+            if let Err(err) = curr_import_map.save_to_file(&path) {
+                let msg = format!("Error while writing ThinLTO import data: {}", err);
+                return Err(write::llvm_err(&diag_handler, &msg));
+            }
+        }
+
         Ok((opt_jobs, copy_jobs))
     }
 }
 
+/// Given two slices, each with no repeat elements. returns true if and only if
+/// the two slices have the same contents when considered as sets (i.e. when
+/// element order is disregarded).
+fn equivalent_as_sets(a: &[String], b: &[String]) -> bool {
+    // cheap path: unequal lengths means cannot possibly be set equivalent.
+    if a.len() != b.len() { return false; }
+    // fast path: before building new things, check if inputs are equivalent as is.
+    if a == b { return true; }
+    // slow path: general set comparison.
+    let a: FxHashSet<&str> = a.iter().map(|s| s.as_str()).collect();
+    let b: FxHashSet<&str> = b.iter().map(|s| s.as_str()).collect();
+    a == b
+}
+
 pub(crate) fn run_pass_manager(cgcx: &CodegenContext<LlvmCodegenBackend>,
                     module: &ModuleCodegen<ModuleLlvm>,
                     config: &ModuleConfig,
@@ -832,6 +895,47 @@ impl ThinLTOImports {
         self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
     }
 
+    fn save_to_file(&self, path: &Path) -> io::Result<()> {
+        use std::io::Write;
+        let file = File::create(path)?;
+        let mut writer = io::BufWriter::new(file);
+        for (importing_module_name, imported_modules) in &self.imports {
+            writeln!(writer, "{}", importing_module_name)?;
+            for imported_module in imported_modules {
+                writeln!(writer, " {}", imported_module)?;
+            }
+            writeln!(writer)?;
+        }
+        Ok(())
+    }
+
+    fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> {
+        use std::io::BufRead;
+        let mut imports = FxHashMap::default();
+        let mut current_module = None;
+        let mut current_imports = vec![];
+        let file = File::open(path)?;
+        for line in io::BufReader::new(file).lines() {
+            let line = line?;
+            if line.is_empty() {
+                let importing_module = current_module
+                    .take()
+                    .expect("Importing module not set");
+                imports.insert(importing_module,
+                               mem::replace(&mut current_imports, vec![]));
+            } else if line.starts_with(" ") {
+                // Space marks an imported module
+                assert_ne!(current_module, None);
+                current_imports.push(line.trim().to_string());
+            } else {
+                // Otherwise, beginning of a new module (must be start or follow empty line)
+                assert_eq!(current_module, None);
+                current_module = Some(line.trim().to_string());
+            }
+        }
+        Ok(ThinLTOImports { imports })
+    }
+
     /// Loads the ThinLTO import map from ThinLTOData.
     unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
         unsafe extern "C" fn imported_module_callback(payload: *mut libc::c_void,
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index ff03c1f76d8..cda8fbc3517 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -277,7 +277,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 let base_addr = match alloc_kind {
                     Some(GlobalAlloc::Memory(alloc)) => {
                         let init = const_alloc_to_llvm(self, alloc);
-                        if alloc.mutability == Mutability::Mutable {
+                        if alloc.mutability == Mutability::Mut {
                             self.static_addr_of_mut(init, alloc.align, None)
                         } else {
                             self.static_addr_of(init, alloc.align, None)
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index c048321e383..78a86d33a14 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -226,7 +226,7 @@ impl CodegenCx<'ll, 'tcx> {
             let llty = self.layout_of(ty).llvm_type(self);
             let (g, attrs) = match self.tcx.hir().get(id) {
                 Node::Item(&hir::Item {
-                    ref attrs, span, kind: hir::ItemKind::Static(..), ..
+                    attrs, span, kind: hir::ItemKind::Static(..), ..
                 }) => {
                     let sym_str = sym.as_str();
                     if let Some(g) = self.get_declared_value(&sym_str) {
@@ -250,7 +250,7 @@ impl CodegenCx<'ll, 'tcx> {
                     ref attrs, span, kind: hir::ForeignItemKind::Static(..), ..
                 }) => {
                     let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
-                    (check_and_apply_linkage(&self, &fn_attrs, ty, sym, span), attrs)
+                    (check_and_apply_linkage(&self, &fn_attrs, ty, sym, span), &**attrs)
                 }
 
                 item => bug!("get_static: expected static, found {:?}", item)
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index da776757fdf..e5a7583a8cc 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1579,7 +1579,7 @@ fn generic_simd_intrinsic(
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
         let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind {
-            ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mutable
+            ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut
                 => (ptr_count(arg_tys[1].simd_type(tcx)),
                     non_ptr(arg_tys[1].simd_type(tcx))),
             _ => {
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 40739387b00..3145b0df63b 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -3,6 +3,7 @@ use crate::llvm;
 use syntax_pos::symbol::Symbol;
 use rustc::session::Session;
 use rustc::session::config::PrintRequest;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
 use libc::c_int;
 use std::ffi::CString;
@@ -51,20 +52,37 @@ unsafe fn configure_llvm(sess: &Session) {
 
     llvm::LLVMRustInstallFatalErrorHandler();
 
+    fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
+        full_arg.trim().split(|c: char| {
+            c == '=' || c.is_whitespace()
+        }).next().unwrap_or("")
+    }
+
+    let user_specified_args: FxHashSet<_> = sess
+        .opts
+        .cg
+        .llvm_args
+        .iter()
+        .map(|s| llvm_arg_to_arg_name(s))
+        .filter(|s| s.len() > 0)
+        .collect();
+
     {
-        let mut add = |arg: &str| {
-            let s = CString::new(arg).unwrap();
-            llvm_args.push(s.as_ptr());
-            llvm_c_strs.push(s);
+        // This adds the given argument to LLVM. Unless `force` is true
+        // user specified arguments are *not* overridden.
+        let mut add = |arg: &str, force: bool| {
+            if force || !user_specified_args.contains(llvm_arg_to_arg_name(arg)) {
+                let s = CString::new(arg).unwrap();
+                llvm_args.push(s.as_ptr());
+                llvm_c_strs.push(s);
+            }
         };
-        add("rustc"); // fake program name
-        if sess.time_llvm_passes() { add("-time-passes"); }
-        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
-        if sess.opts.debugging_opts.disable_instrumentation_preinliner {
-            add("-disable-preinline");
-        }
+        add("rustc", true); // fake program name
+        if sess.time_llvm_passes() { add("-time-passes", false); }
+        if sess.print_llvm_passes() { add("-debug-pass=Structure", false); }
+
         if sess.opts.debugging_opts.generate_arange_section {
-            add("-generate-arange-section");
+            add("-generate-arange-section", false);
         }
         if get_major_version() >= 8 {
             match sess.opts.debugging_opts.merge_functions
@@ -72,22 +90,22 @@ unsafe fn configure_llvm(sess: &Session) {
                 MergeFunctions::Disabled |
                 MergeFunctions::Trampolines => {}
                 MergeFunctions::Aliases => {
-                    add("-mergefunc-use-aliases");
+                    add("-mergefunc-use-aliases", false);
                 }
             }
         }
 
         if sess.target.target.target_os == "emscripten" &&
             sess.panic_strategy() == PanicStrategy::Unwind {
-            add("-enable-emscripten-cxx-exceptions");
+            add("-enable-emscripten-cxx-exceptions", false);
         }
 
         // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
         // during inlining. Unfortunately these may block other optimizations.
-        add("-preserve-alignment-assumptions-during-inlining=false");
+        add("-preserve-alignment-assumptions-during-inlining=false", false);
 
         for arg in &sess.opts.cg.llvm_args {
-            add(&(*arg));
+            add(&(*arg), true);
         }
     }
 
diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs
index 8ff08e832dc..c5340892daf 100644
--- a/src/librustc_codegen_ssa/debuginfo/type_names.rs
+++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs
@@ -62,8 +62,8 @@ pub fn push_debuginfo_type_name<'tcx>(
                 output.push('*');
             }
             match mutbl {
-                hir::Mutability::Immutable => output.push_str("const "),
-                hir::Mutability::Mutable => output.push_str("mut "),
+                hir::Mutability::Not => output.push_str("const "),
+                hir::Mutability::Mut => output.push_str("mut "),
             }
 
             push_debuginfo_type_name(tcx, inner_type, true, output, visited);
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 6c627085b2e..7bcd9816786 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -340,10 +340,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
             PlaceContext::MutatingUse(MutatingUseContext::Store) |
             PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
             PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
+            PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
             PlaceContext::MutatingUse(MutatingUseContext::Projection) |
             PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
             PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
             PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
             PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
                 self.not_ssa(local);
             }
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 1132f9b2f03..98d239d353d 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -448,7 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let cx = self.cx;
         let tcx = self.cx.tcx();
 
-        let result = match &place_ref {
+        let result = match place_ref {
             mir::PlaceRef {
                 base: mir::PlaceBase::Local(index),
                 projection: [],
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 55d63f18cd9..09405cc02b3 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -7,7 +7,7 @@ use crate::MemFlags;
 use crate::common::{self, RealPredicate, IntPredicate};
 use crate::traits::*;
 
-use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance};
+use rustc::ty::{self, Ty, TyCtxt, adjustment::{PointerCast}, Instance};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
 use rustc::mir;
@@ -349,8 +349,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 }
                             }
                             (CastTy::Ptr(_), CastTy::Ptr(_)) |
-                            (CastTy::FnPtr, CastTy::Ptr(_)) |
-                            (CastTy::RPtr(_), CastTy::Ptr(_)) =>
+                            (CastTy::FnPtr, CastTy::Ptr(_)) =>
                                 bx.pointercast(llval, ll_t_out),
                             (CastTy::Ptr(_), CastTy::Int(_)) |
                             (CastTy::FnPtr, CastTy::Int(_)) =>
@@ -375,24 +374,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             mir::Rvalue::Ref(_, bk, ref place) => {
-                let cg_place = self.codegen_place(&mut bx, &place.as_ref());
-
-                let ty = cg_place.layout.ty;
+                let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ref(
+                    tcx.lifetimes.re_erased,
+                    ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
+                );
+                self.codegen_place_to_pointer(bx, place, mk_ref)
+            }
 
-                // Note: places are indirect, so storing the `llval` into the
-                // destination effectively creates a reference.
-                let val = if !bx.cx().type_has_metadata(ty) {
-                    OperandValue::Immediate(cg_place.llval)
-                } else {
-                    OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
-                };
-                (bx, OperandRef {
-                    val,
-                    layout: self.cx.layout_of(self.cx.tcx().mk_ref(
-                        self.cx.tcx().lifetimes.re_erased,
-                        ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
-                    )),
-                })
+            mir::Rvalue::AddressOf(mutability, ref place) => {
+                let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ptr(
+                    ty::TypeAndMut { ty, mutbl: mutability.into() }
+                );
+                self.codegen_place_to_pointer(bx, place, mk_ptr)
             }
 
             mir::Rvalue::Len(ref place) => {
@@ -548,6 +541,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         cg_value.len(bx.cx())
     }
 
+    /// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref`
+    fn codegen_place_to_pointer(
+        &mut self,
+        mut bx: Bx,
+        place: &mir::Place<'tcx>,
+        mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>,
+    ) -> (Bx, OperandRef<'tcx, Bx::Value>) {
+        let cg_place = self.codegen_place(&mut bx, &place.as_ref());
+
+        let ty = cg_place.layout.ty;
+
+        // Note: places are indirect, so storing the `llval` into the
+        // destination effectively creates a reference.
+        let val = if !bx.cx().type_has_metadata(ty) {
+            OperandValue::Immediate(cg_place.llval)
+        } else {
+            OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
+        };
+        (bx, OperandRef {
+            val,
+            layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)),
+        })
+    }
+
     pub fn codegen_scalar_binop(
         &mut self,
         bx: &mut Bx,
@@ -704,6 +721,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool {
         match *rvalue {
             mir::Rvalue::Ref(..) |
+            mir::Rvalue::AddressOf(..) |
             mir::Rvalue::Len(..) |
             mir::Rvalue::Cast(..) | // (*)
             mir::Rvalue::BinaryOp(..) |
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index c52c6cfa83c..922964ee45f 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -142,12 +142,32 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
     };
 
     let attrs = tcx.codegen_fn_attrs(def_id);
+
+    // Foreign items by default use no mangling for their symbol name. There's a
+    // few exceptions to this rule though:
+    //
+    // * This can be overridden with the `#[link_name]` attribute
+    //
+    // * On the wasm32 targets there is a bug (or feature) in LLD [1] where the
+    //   same-named symbol when imported from different wasm modules will get
+    //   hooked up incorectly. As a result foreign symbols, on the wasm target,
+    //   with a wasm import module, get mangled. Additionally our codegen will
+    //   deduplicate symbols based purely on the symbol name, but for wasm this
+    //   isn't quite right because the same-named symbol on wasm can come from
+    //   different modules. For these reasons if `#[link(wasm_import_module)]`
+    //   is present we mangle everything on wasm because the demangled form will
+    //   show up in the `wasm-import-name` custom attribute in LLVM IR.
+    //
+    // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
     if is_foreign {
-        if let Some(name) = attrs.link_name {
-            return name;
+        if tcx.sess.target.target.arch != "wasm32" ||
+            !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id)
+        {
+            if let Some(name) = attrs.link_name {
+                return name;
+            }
+            return tcx.item_name(def_id);
         }
-        // Don't mangle foreign items.
-        return tcx.item_name(def_id);
     }
 
     if let Some(name) = attrs.export_name {
diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs
index 1dfcc21f390..858ad9f1cfd 100644
--- a/src/librustc_codegen_utils/symbol_names/v0.rs
+++ b/src/librustc_codegen_utils/symbol_names/v0.rs
@@ -373,8 +373,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
 
             ty::Ref(r, ty, mutbl) => {
                 self.push(match mutbl {
-                    hir::Mutability::Immutable => "R",
-                    hir::Mutability::Mutable => "Q",
+                    hir::Mutability::Not => "R",
+                    hir::Mutability::Mut => "Q",
                 });
                 if *r != ty::ReErased {
                     self = r.print(self)?;
@@ -384,8 +384,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
 
             ty::RawPtr(mt) => {
                 self.push(match mt.mutbl {
-                    hir::Mutability::Immutable => "P",
-                    hir::Mutability::Mutable => "O",
+                    hir::Mutability::Not => "P",
+                    hir::Mutability::Mut => "O",
                 });
                 self = mt.ty.print(self)?;
             }
diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs
index 51269be4e9f..893aea16fd2 100644
--- a/src/librustc_codegen_utils/symbol_names_test.rs
+++ b/src/librustc_codegen_utils/symbol_names_test.rs
@@ -57,15 +57,15 @@ impl SymbolNamesTest<'tcx> {
 }
 
 impl hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         self.process_attrs(item.hir_id);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         self.process_attrs(trait_item.hir_id);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         self.process_attrs(impl_item.hir_id);
     }
 }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 11603f6d9c1..97e4cf72124 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -73,7 +73,7 @@ where
 }
 fn call_with_pp_support_hir<A, F>(ppmode: &PpSourceMode, tcx: TyCtxt<'_>, f: F) -> A
 where
-    F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A,
+    F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate<'_>) -> A,
 {
     match *ppmode {
         PpmNormal => {
diff --git a/src/librustc_error_codes/error_codes/E0120.md b/src/librustc_error_codes/error_codes/E0120.md
index 99c2a493a46..dc7258d8731 100644
--- a/src/librustc_error_codes/error_codes/E0120.md
+++ b/src/librustc_error_codes/error_codes/E0120.md
@@ -1,5 +1,7 @@
-An attempt was made to implement Drop on a trait, which is not allowed: only
-structs and enums can implement Drop. An example causing this error:
+Drop was implemented on a trait, which is not allowed: only structs and
+enums can implement Drop.
+
+Erroneous code example:
 
 ```compile_fail,E0120
 trait MyTrait {}
@@ -10,7 +12,7 @@ impl Drop for MyTrait {
 ```
 
 A workaround for this problem is to wrap the trait up in a struct, and implement
-Drop on that. An example is shown below:
+Drop on that:
 
 ```
 trait MyTrait {}
@@ -22,7 +24,7 @@ impl <T: MyTrait> Drop for MyWrapper<T> {
 
 ```
 
-Alternatively, wrapping trait objects requires something like the following:
+Alternatively, wrapping trait objects requires something:
 
 ```
 trait MyTrait {}
diff --git a/src/librustc_error_codes/error_codes/E0121.md b/src/librustc_error_codes/error_codes/E0121.md
index 069d0fc48fb..06fe396d50d 100644
--- a/src/librustc_error_codes/error_codes/E0121.md
+++ b/src/librustc_error_codes/error_codes/E0121.md
@@ -1,10 +1,24 @@
-In order to be consistent with Rust's lack of global type inference,
-type and const placeholders are disallowed by design in item signatures.
+The type placeholder `_` was used within a type on an item's signature.
 
-Examples of this error include:
+Erroneous code example:
 
 ```compile_fail,E0121
-fn foo() -> _ { 5 } // error, explicitly write out the return type instead
+fn foo() -> _ { 5 } // error
 
-static BAR: _ = "test"; // error, explicitly write out the type instead
+static BAR: _ = "test"; // error
+```
+
+In those cases, you need to provide the type explicitly:
+
+```
+fn foo() -> i32 { 5 } // ok!
+
+static BAR: &str = "test"; // ok!
+```
+
+The type placeholder `_` can be used outside item's signature as follows:
+
+```
+let x = "a4a".split('4')
+    .collect::<Vec<_>>(); // No need to precise the Vec's generic type.
 ```
diff --git a/src/librustc_error_codes/error_codes/E0734.md b/src/librustc_error_codes/error_codes/E0734.md
index 913801d2236..7506c8e693e 100644
--- a/src/librustc_error_codes/error_codes/E0734.md
+++ b/src/librustc_error_codes/error_codes/E0734.md
@@ -5,7 +5,7 @@ Erroneous code examples:
 ```compile_fail,E0734
 #[rustc_deprecated(since = "b", reason = "text")] // invalid
 #[stable(feature = "a", since = "b")] // invalid
-#[unstable(feature = "b", issue = "0")] // invalid
+#[unstable(feature = "b", issue = "none")] // invalid
 fn foo(){}
 ```
 
diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md
index aaf19d8478c..1780fe59cbd 100644
--- a/src/librustc_error_codes/error_codes/E0743.md
+++ b/src/librustc_error_codes/error_codes/E0743.md
@@ -1,11 +1,17 @@
-C-variadic has been used on a non-foreign function.
+The C-variadic type `...` has been nested inside another type.
 
 Erroneous code example:
 
 ```compile_fail,E0743
-fn foo2(x: u8, ...) {} // error!
+#![feature(c_variadic)]
+
+fn foo2(x: u8, y: &...) {} // error!
 ```
 
-Only foreign functions can use C-variadic (`...`). It is used to give an
-undefined number of parameters to a given function (like `printf` in C). The
-equivalent in Rust would be to use macros directly.
+Only foreign functions can use the C-variadic type (`...`).
+In such functions, `...` may only occur non-nested.
+That is, `y: &'a ...` is not allowed.
+
+A C-variadic type is used to give an undefined number
+of parameters to a given function (like `printf` in C).
+The equivalent in Rust would be to use macros directly.
diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md
index 39bebdcd375..6595691ce78 100644
--- a/src/librustc_error_codes/error_codes/E0745.md
+++ b/src/librustc_error_codes/error_codes/E0745.md
@@ -11,7 +11,7 @@ fn temp_address() {
 
 To avoid the error, first bind the temporary to a named local variable.
 
-```ignore (not yet implemented)
+```
 # #![feature(raw_ref_op)]
 fn temp_address() {
     let val = 2;
diff --git a/src/librustc_fs_util/lib.rs b/src/librustc_fs_util/lib.rs
index eaf08d76b99..289b9f30c3b 100644
--- a/src/librustc_fs_util/lib.rs
+++ b/src/librustc_fs_util/lib.rs
@@ -1,7 +1,7 @@
-use std::path::{Path, PathBuf};
 use std::ffi::CString;
 use std::fs;
 use std::io;
+use std::path::{Path, PathBuf};
 
 // Unfortunately, on windows, it looks like msvcrt.dll is silently translating
 // verbatim paths under the hood to non-verbatim paths! This manifests itself as
@@ -21,8 +21,8 @@ use std::io;
 //   https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737
 #[cfg(windows)]
 pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
-    use std::path;
     use std::ffi::OsString;
+    use std::path;
     let mut components = p.components();
     let prefix = match components.next() {
         Some(path::Component::Prefix(p)) => p,
@@ -68,12 +68,10 @@ pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<Li
 
     match fs::hard_link(p, q) {
         Ok(()) => Ok(LinkOrCopy::Link),
-        Err(_) => {
-            match fs::copy(p, q) {
-                Ok(_) => Ok(LinkOrCopy::Copy),
-                Err(e) => Err(e),
-            }
-        }
+        Err(_) => match fs::copy(p, q) {
+            Ok(_) => Ok(LinkOrCopy::Copy),
+            Err(e) => Err(e),
+        },
     }
 }
 
@@ -86,29 +84,28 @@ pub enum RenameOrCopyRemove {
 /// Rename `p` into `q`, preferring to use `rename` if possible.
 /// If `rename` fails (rename may fail for reasons such as crossing
 /// filesystem), fallback to copy & remove
-pub fn rename_or_copy_remove<P: AsRef<Path>, Q: AsRef<Path>>(p: P,
-                                                             q: Q)
-                                                             -> io::Result<RenameOrCopyRemove> {
+pub fn rename_or_copy_remove<P: AsRef<Path>, Q: AsRef<Path>>(
+    p: P,
+    q: Q,
+) -> io::Result<RenameOrCopyRemove> {
     let p = p.as_ref();
     let q = q.as_ref();
     match fs::rename(p, q) {
         Ok(()) => Ok(RenameOrCopyRemove::Rename),
-        Err(_) => {
-            match fs::copy(p, q) {
-                Ok(_) => {
-                    fs::remove_file(p)?;
-                    Ok(RenameOrCopyRemove::CopyRemove)
-                }
-                Err(e) => Err(e),
+        Err(_) => match fs::copy(p, q) {
+            Ok(_) => {
+                fs::remove_file(p)?;
+                Ok(RenameOrCopyRemove::CopyRemove)
             }
-        }
+            Err(e) => Err(e),
+        },
     }
 }
 
 #[cfg(unix)]
 pub fn path_to_c_string(p: &Path) -> CString {
-    use std::os::unix::ffi::OsStrExt;
     use std::ffi::OsStr;
+    use std::os::unix::ffi::OsStrExt;
     let p: &OsStr = p.as_ref();
     CString::new(p.as_bytes()).unwrap()
 }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index e3e3b0b1748..44b610e487b 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -162,22 +162,22 @@ impl Visitor<'tcx> for IfThisChanged<'tcx> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         self.process_attrs(item.hir_id, &item.attrs);
         intravisit::walk_item(self, item);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         self.process_attrs(trait_item.hir_id, &trait_item.attrs);
         intravisit::walk_trait_item(self, trait_item);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         self.process_attrs(impl_item.hir_id, &impl_item.attrs);
         intravisit::walk_impl_item(self, impl_item);
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
         self.process_attrs(s.hir_id, &s.attrs);
         intravisit::walk_struct_field(self, s);
     }
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 1a675ea002c..8b692d84b11 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -47,7 +47,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
             available_cgus
         };
 
-        for attr in &tcx.hir().krate().attrs {
+        for attr in tcx.hir().krate().attrs {
             ams.check_attr(attr);
         }
     })
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index c919db070a6..7c9ed24f53b 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -532,15 +532,15 @@ impl DirtyCleanVisitor<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         self.check_item(item.hir_id, item.span);
     }
 
-    fn visit_trait_item(&mut self, item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
         self.check_item(item.hir_id, item.span);
     }
 
-    fn visit_impl_item(&mut self, item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
         self.check_item(item.hir_id, item.span);
     }
 }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 2a4bc41f850..e1c4c86d9d6 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -446,17 +446,18 @@ fn configure_and_expand_inner<'a>(
     Ok((krate, resolver))
 }
 
-pub fn lower_to_hir(
-    sess: &Session,
+pub fn lower_to_hir<'res, 'tcx>(
+    sess: &'tcx Session,
     lint_store: &lint::LintStore,
-    resolver: &mut Resolver<'_>,
-    dep_graph: &DepGraph,
-    krate: &ast::Crate,
-) -> Result<hir::map::Forest> {
+    resolver: &'res mut Resolver<'_>,
+    dep_graph: &'res DepGraph,
+    krate: &'res ast::Crate,
+    arena: &'tcx Arena<'tcx>,
+) -> Result<hir::map::Forest<'tcx>> {
     // Lower AST to HIR.
     let hir_forest = time(sess, "lowering AST -> HIR", || {
         let nt_to_tokenstream = rustc_parse::nt_to_tokenstream;
-        let hir_crate = lower_crate(sess, &dep_graph, &krate, resolver, nt_to_tokenstream);
+        let hir_crate = lower_crate(sess, &dep_graph, &krate, resolver, nt_to_tokenstream, arena);
 
         if sess.opts.debugging_opts.hir_stats {
             hir_stats::print_hir_stats(&hir_crate);
@@ -738,7 +739,7 @@ impl<'tcx> QueryContext<'tcx> {
 pub fn create_global_ctxt<'tcx>(
     compiler: &'tcx Compiler,
     lint_store: Lrc<lint::LintStore>,
-    hir_forest: &'tcx hir::map::Forest,
+    hir_forest: &'tcx hir::map::Forest<'tcx>,
     mut resolver_outputs: ResolverOutputs,
     outputs: OutputFilenames,
     crate_name: &str,
diff --git a/src/librustc_interface/proc_macro_decls.rs b/src/librustc_interface/proc_macro_decls.rs
index 56180bcad06..e3def175626 100644
--- a/src/librustc_interface/proc_macro_decls.rs
+++ b/src/librustc_interface/proc_macro_decls.rs
@@ -24,16 +24,16 @@ struct Finder {
 }
 
 impl<'v> ItemLikeVisitor<'v> for Finder {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         if attr::contains_name(&item.attrs, sym::rustc_proc_macro_decls) {
             self.decls = Some(item.hir_id);
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
 
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index e429b4d101a..d6de9d5f4e4 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -82,7 +82,7 @@ pub struct Queries<'tcx> {
     register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
     expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
-    lower_to_hir: Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>,
+    lower_to_hir: Query<(&'tcx hir::map::Forest<'tcx>, Steal<ResolverOutputs>)>,
     prepare_outputs: Query<OutputFilenames>,
     global_ctxt: Query<QueryContext<'tcx>>,
     ongoing_codegen: Query<Box<dyn Any>>,
@@ -216,7 +216,7 @@ impl<'tcx> Queries<'tcx> {
 
     pub fn lower_to_hir(
         &'tcx self,
-    ) -> Result<&Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>> {
+    ) -> Result<&Query<(&'tcx hir::map::Forest<'tcx>, Steal<ResolverOutputs>)>> {
         self.lower_to_hir.compute(|| {
             let expansion_result = self.expansion()?;
             let peeked = expansion_result.peek();
@@ -229,7 +229,8 @@ impl<'tcx> Queries<'tcx> {
                     lint_store,
                     resolver,
                     &*self.dep_graph()?.peek(),
-                    &krate
+                    &krate,
+                    &self.arena,
                 )
             })?;
             let hir = self.arena.alloc(hir);
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index c78b3ee0767..a8800082c9a 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -10,7 +10,6 @@ use rustc_data_structures::jobserver;
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
@@ -24,7 +23,7 @@ use std::ops::DerefMut;
 use smallvec::SmallVec;
 use syntax::ptr::P;
 use syntax::mut_visit::{*, MutVisitor, visit_clobber};
-use syntax::ast::BlockCheckMode;
+use syntax::ast::{AttrVec, BlockCheckMode};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::source_map::{FileLoader, RealFileLoader, SourceMap};
 use syntax::symbol::{Symbol, sym};
@@ -643,8 +642,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
         ret
     }
 
-    fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool {
-        if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output {
+    fn should_ignore_fn(ret_ty: &ast::FunctionRetTy) -> bool {
+        if let ast::FunctionRetTy::Ty(ref ty) = ret_ty {
             fn involves_impl_trait(ty: &ast::Ty) -> bool {
                 match ty.kind {
                     ast::TyKind::ImplTrait(..) => true,
@@ -673,7 +672,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
                             },
                             Some(&ast::GenericArgs::Parenthesized(ref data)) => {
                                 any_involves_impl_trait(data.inputs.iter()) ||
-                                any_involves_impl_trait(data.output.iter())
+                                ReplaceBodyWithLoop::should_ignore_fn(&data.output)
                             }
                         }
                     }),
@@ -693,7 +692,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
 
     fn is_sig_const(sig: &ast::FnSig) -> bool {
         sig.header.constness.node == ast::Constness::Const ||
-            ReplaceBodyWithLoop::should_ignore_fn(&sig.decl)
+            ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output)
     }
 }
 
@@ -707,22 +706,17 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
         self.run(is_const, |s| noop_visit_item_kind(i, s))
     }
 
-    fn flat_map_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
+    fn flat_map_trait_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
         let is_const = match i.kind {
-            ast::TraitItemKind::Const(..) => true,
-            ast::TraitItemKind::Method(ref sig, _) => Self::is_sig_const(sig),
+            ast::AssocItemKind::Const(..) => true,
+            ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig),
             _ => false,
         };
-        self.run(is_const, |s| noop_flat_map_trait_item(i, s))
+        self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
     }
 
-    fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
-        let is_const = match i.kind {
-            ast::ImplItemKind::Const(..) => true,
-            ast::ImplItemKind::Method(ref sig, _) => Self::is_sig_const(sig),
-            _ => false,
-        };
-        self.run(is_const, |s| noop_flat_map_impl_item(i, s))
+    fn flat_map_impl_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+        self.flat_map_trait_item(i)
     }
 
     fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
@@ -746,7 +740,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
                 id: resolver.next_node_id(),
                 kind: ast::ExprKind::Block(P(b), None),
                 span: syntax_pos::DUMMY_SP,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
             });
 
             ast::Stmt {
@@ -761,7 +755,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
             kind: ast::ExprKind::Loop(P(empty_block), None),
             id: self.resolver.next_node_id(),
             span: syntax_pos::DUMMY_SP,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
         });
 
         let loop_stmt = ast::Stmt {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index b46e8a8438f..340af64adad 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -117,7 +117,7 @@ impl BoxPointers {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         match it.kind {
             hir::ItemKind::Fn(..) |
             hir::ItemKind::TyAlias(..) |
@@ -174,18 +174,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
                     // (Issue #49588)
                     continue;
                 }
-                if let PatKind::Binding(_, _, ident, None) = fieldpat.pat.kind {
+                if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
                     if cx.tcx.find_field_index(ident, &variant) ==
                        Some(cx.tcx.field_index(fieldpat.hir_id, cx.tables)) {
                         let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
                                      fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant", ident));
-                        let subspan = cx.tcx.sess.source_map().span_through_char(fieldpat.span,
-                                                                                 ':');
-                        err.span_suggestion_short(
-                            subspan,
-                            "remove this",
-                            ident.to_string(),
+                        let binding = match binding_annot {
+                            hir::BindingAnnotation::Unannotated => None,
+                            hir::BindingAnnotation::Mutable => Some("mut"),
+                            hir::BindingAnnotation::Ref => Some("ref"),
+                            hir::BindingAnnotation::RefMut => Some("ref mut"),
+                        };
+                        let ident = if let Some(binding) = binding {
+                            format!("{} {}", binding, ident)
+                        } else {
+                            ident.to_string()
+                        };
+                        err.span_suggestion(
+                            fieldpat.span,
+                            "use shorthand field pattern",
+                            ident,
                             Applicability::MachineApplicable
                         );
                         err.emit();
@@ -268,8 +277,8 @@ impl EarlyLintPass for UnsafeCode {
         }
     }
 
-    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::TraitItem) {
-        if let ast::TraitItemKind::Method(ref sig, None) = item.kind {
+    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) {
+        if let ast::AssocItemKind::Fn(ref sig, None) = item.kind {
             if sig.header.unsafety == ast::Unsafety::Unsafe {
                 self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
             }
@@ -378,10 +387,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
         self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
     }
 
-    fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate) {
+    fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) {
         self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate");
 
-        for macro_def in &krate.exported_macros {
+        for macro_def in krate.exported_macros {
             let has_doc = macro_def.attrs.iter().any(|a| has_doc(a));
             if !has_doc {
                 cx.span_lint(MISSING_DOCS,
@@ -391,14 +400,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
         }
     }
 
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         let desc = match it.kind {
             hir::ItemKind::Fn(..) => "a function",
             hir::ItemKind::Mod(..) => "a module",
             hir::ItemKind::Enum(..) => "an enum",
             hir::ItemKind::Struct(..) => "a struct",
             hir::ItemKind::Union(..) => "a union",
-            hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            hir::ItemKind::Trait(.., trait_item_refs) => {
                 // Issue #11592: traits are always considered exported, even when private.
                 if let hir::VisibilityKind::Inherited = it.vis.node {
                     self.private_traits.insert(it.hir_id);
@@ -410,7 +419,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
                 "a trait"
             }
             hir::ItemKind::TyAlias(..) => "a type alias",
-            hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., Some(ref trait_ref), _, impl_item_refs) => {
                 // If the trait is private, add the impl items to `private_traits` so they don't get
                 // reported for missing docs.
                 let real_trait = trait_ref.path.res.def_id();
@@ -436,7 +445,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
         self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, desc);
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem) {
+    fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem<'_>) {
         if self.private_traits.contains(&trait_item.hir_id) {
             return;
         }
@@ -454,7 +463,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
                                       desc);
     }
 
-    fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem) {
+    fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem<'_>) {
         // If the method is an impl for a trait, don't doc.
         if method_context(cx, impl_item.hir_id) == MethodLateContext::TraitImpl {
             return;
@@ -473,7 +482,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
                                       desc);
     }
 
-    fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField) {
+    fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField<'_>) {
         if !sf.is_positional() {
             self.check_missing_docs_attrs(cx,
                                           Some(sf.hir_id),
@@ -483,7 +492,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
         }
     }
 
-    fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant) {
+    fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant<'_>) {
         self.check_missing_docs_attrs(cx,
                                       Some(v.id),
                                       &v.attrs,
@@ -501,7 +510,7 @@ declare_lint! {
 declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) {
         if !cx.access_levels.is_reachable(item.hir_id) {
             return;
         }
@@ -559,7 +568,7 @@ pub struct MissingDebugImplementations {
 impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) {
         if !cx.access_levels.is_reachable(item.hir_id) {
             return;
         }
@@ -615,9 +624,9 @@ declare_lint_pass!(
 );
 
 impl EarlyLintPass for AnonymousParameters {
-    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) {
+    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
         match it.kind {
-            ast::TraitItemKind::Method(ref sig, _) => {
+            ast::AssocItemKind::Fn(ref sig, _) => {
                 for arg in sig.decl.inputs.iter() {
                     match arg.pat.kind {
                         ast::PatKind::Ident(_, ident, None) => {
@@ -815,7 +824,7 @@ declare_lint! {
 declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         match it.kind {
             hir::ItemKind::Fn(.., ref generics, _) => {
                 if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
@@ -887,8 +896,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
                    consider instead using an UnsafeCell";
         match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) {
             Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
-                if to_mt == hir::Mutability::Mutable &&
-                   from_mt == hir::Mutability::Immutable {
+                if to_mt == hir::Mutability::Mut &&
+                   from_mt == hir::Mutability::Not {
                     cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
                 }
             }
@@ -992,20 +1001,24 @@ impl UnreachablePub {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) {
         self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
     }
 
-    fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, foreign_item: &hir::ForeignItem) {
+    fn check_foreign_item(
+        &mut self,
+        cx: &LateContext<'_, '_>,
+        foreign_item: &hir::ForeignItem<'tcx>,
+    ) {
         self.perform_lint(cx, "item", foreign_item.hir_id, &foreign_item.vis,
                           foreign_item.span, true);
     }
 
-    fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField) {
+    fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField<'_>) {
         self.perform_lint(cx, "field", field.hir_id, &field.vis, field.span, false);
     }
 
-    fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem) {
+    fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem<'_>) {
         self.perform_lint(cx, "item", impl_item.hir_id, &impl_item.vis, impl_item.span, false);
     }
 }
@@ -1074,7 +1087,7 @@ impl TypeAliasBounds {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) {
         let (ty, type_alias_generics) = match item.kind {
             hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics),
             _ => return,
@@ -1140,7 +1153,7 @@ fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         match it.kind {
             hir::ItemKind::Const(_, body_id) => {
                 check_const(cx, body_id);
@@ -1169,7 +1182,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     fn check_item(
         &mut self,
         cx: &LateContext<'a, 'tcx>,
-        item: &'tcx hir::Item,
+        item: &'tcx hir::Item<'tcx>,
     ) {
         use rustc::ty::fold::TypeFoldable;
         use rustc::ty::Predicate::*;
@@ -1328,7 +1341,7 @@ impl UnnameableTestItems {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         if self.items_nameable {
             if let hir::ItemKind::Mod(..) = it.kind {}
             else {
@@ -1347,7 +1360,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
         }
     }
 
-    fn check_item_post(&mut self, _cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item_post(&mut self, _cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         if !self.items_nameable && self.boundary == it.hir_id {
             self.items_nameable = true;
         }
@@ -1606,7 +1619,7 @@ impl ExplicitOutlivesRequirements {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
-    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) {
         use rustc::middle::resolve_lifetime::Region;
 
         let infer_static = cx.tcx.features().infer_static_outlives_requirements;
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index dceb79fd309..bd2cbee2c34 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -246,7 +246,13 @@ impl NonSnakeCase {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
-    fn check_mod(&mut self, cx: &LateContext<'_, '_>, _: &'tcx hir::Mod, _: Span, id: hir::HirId) {
+    fn check_mod(
+        &mut self,
+        cx: &LateContext<'_, '_>,
+        _: &'tcx hir::Mod<'tcx>,
+        _: Span,
+        id: hir::HirId,
+    ) {
         if id != hir::CRATE_HIR_ID {
             return;
         }
@@ -298,7 +304,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
         cx: &LateContext<'_, '_>,
         fk: FnKind<'_>,
         _: &hir::FnDecl,
-        _: &hir::Body,
+        _: &hir::Body<'_>,
         _: Span,
         id: hir::HirId,
     ) {
@@ -325,13 +331,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
         }
     }
 
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         if let hir::ItemKind::Mod(_) = it.kind {
             self.check_snake_case(cx, "module", &it.ident);
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem) {
+    fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) {
         if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(pnames)) = &item.kind {
             self.check_snake_case(cx, "trait method", &item.ident);
             for param_name in pnames {
@@ -349,7 +355,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     fn check_struct_def(
         &mut self,
         cx: &LateContext<'_, '_>,
-        s: &hir::VariantData,
+        s: &hir::VariantData<'_>,
     ) {
         for sf in s.fields() {
             self.check_snake_case(cx, "structure field", &sf.ident);
@@ -386,7 +392,7 @@ impl NonUpperCaseGlobals {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         match it.kind {
             hir::ItemKind::Static(..) if !attr::contains_name(&it.attrs, sym::no_mangle) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident);
@@ -398,13 +404,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, ti: &hir::TraitItem) {
+    fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, ti: &hir::TraitItem<'_>) {
         if let hir::TraitItemKind::Const(..) = ti.kind {
             NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ti.ident);
         }
     }
 
-    fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, ii: &hir::ImplItem) {
+    fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, ii: &hir::ImplItem<'_>) {
         if let hir::ImplItemKind::Const(..) = ii.kind {
             NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
         }
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 34241b845be..f1cd2037edd 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1009,7 +1009,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
-    fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
+    fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem<'_>) {
         let mut vis = ImproperCTypesVisitor { cx };
         let abi = cx.tcx.hir().get_foreign_abi(it.hir_id);
         if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
@@ -1031,7 +1031,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
 declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
-    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
         if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind {
             let item_def_id = cx.tcx.hir().local_def_id(it.hir_id);
             let t = cx.tcx.type_of(item_def_id);
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index e6f39cca6dc..06ec3f38009 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -392,7 +392,7 @@ impl UnusedParens {
         avoid_or: bool,
         avoid_mut: bool,
     ) {
-        use ast::{PatKind, BindingMode::ByValue, Mutability::Mutable};
+        use ast::{PatKind, BindingMode, Mutability};
 
         if let PatKind::Paren(inner) = &value.kind {
             match inner.kind {
@@ -404,7 +404,7 @@ impl UnusedParens {
                 // Avoid `p0 | .. | pn` if we should.
                 PatKind::Or(..) if avoid_or => return,
                 // Avoid `mut x` and `mut x @ p` if we should:
-                PatKind::Ident(ByValue(Mutable), ..) if avoid_mut => return,
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return,
                 // Otherwise proceed with linting.
                 _ => {}
             }
@@ -560,7 +560,7 @@ impl EarlyLintPass for UnusedParens {
             Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false),
             // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
             // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
-            Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Immutable),
+            Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not),
         }
     }
 
@@ -668,9 +668,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
         for adj in cx.tables.expr_adjustments(e) {
             if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
                 let msg = match m {
-                    adjustment::AutoBorrowMutability::Immutable =>
+                    adjustment::AutoBorrowMutability::Not =>
                         "unnecessary allocation, use `&` instead",
-                    adjustment::AutoBorrowMutability::Mutable { .. }=>
+                    adjustment::AutoBorrowMutability::Mut { .. }=>
                         "unnecessary allocation, use `&mut` instead"
                 };
                 cx.span_lint(UNUSED_ALLOCATION, e.span, msg);
diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs
index d6c8e54c18d..4c8c9d15d56 100644
--- a/src/librustc_lsan/lib.rs
+++ b/src/librustc_lsan/lib.rs
@@ -5,4 +5,4 @@
 #![no_std]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
-            issue = "0")]
+            issue = "none")]
diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs
index fa1402584ed..2311e0422f6 100644
--- a/src/librustc_metadata/foreign_modules.rs
+++ b/src/librustc_metadata/foreign_modules.rs
@@ -18,7 +18,7 @@ struct Collector<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
-    fn visit_item(&mut self, it: &'tcx hir::Item) {
+    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         let fm = match it.kind {
             hir::ItemKind::ForeignMod(ref fm) => fm,
             _ => return,
@@ -33,6 +33,6 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
         });
     }
 
-    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {}
-    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {}
+    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
+    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
 }
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
index b40d58a6819..10dfc3c72e5 100644
--- a/src/librustc_metadata/link_args.rs
+++ b/src/librustc_metadata/link_args.rs
@@ -26,7 +26,7 @@ struct Collector {
 }
 
 impl<'tcx> ItemLikeVisitor<'tcx> for Collector {
-    fn visit_item(&mut self, it: &'tcx hir::Item) {
+    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         let fm = match it.kind {
             hir::ItemKind::ForeignMod(ref fm) => fm,
             _ => return,
@@ -45,8 +45,8 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector {
         }
     }
 
-    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {}
-    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {}
+    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
+    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
 }
 
 impl Collector {
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 425e5d1d821..6ab20271774 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -36,7 +36,7 @@ struct Collector<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
-    fn visit_item(&mut self, it: &'tcx hir::Item) {
+    fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         let fm = match it.kind {
             hir::ItemKind::ForeignMod(ref fm) => fm,
             _ => return,
@@ -129,8 +129,8 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {}
-    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {}
+    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
+    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
 }
 
 impl Collector<'tcx> {
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index a1f95e35cbe..eb2fb39fb2f 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -1401,9 +1401,9 @@ impl<'a, 'tcx> CrateMetadata {
     fn static_mutability(&self, id: DefIndex) -> Option<hir::Mutability> {
         match self.kind(id) {
             EntryKind::ImmStatic |
-            EntryKind::ForeignImmStatic => Some(hir::Mutability::Immutable),
+            EntryKind::ForeignImmStatic => Some(hir::Mutability::Not),
             EntryKind::MutStatic |
-            EntryKind::ForeignMutStatic => Some(hir::Mutability::Mutable),
+            EntryKind::ForeignMutStatic => Some(hir::Mutability::Mut),
             _ => None,
         }
     }
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index c1562a77342..cfe5ea65fca 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -342,7 +342,7 @@ impl<'tcx> EncodeContext<'tcx> {
         let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
         self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis);
         krate.visit_all_item_likes(&mut self.as_deep_visitor());
-        for macro_def in &krate.exported_macros {
+        for macro_def in krate.exported_macros {
             self.visit_macro_def(macro_def);
         }
     }
@@ -682,7 +682,7 @@ impl EncodeContext<'tcx> {
     fn encode_info_for_mod(
         &mut self,
         id: hir::HirId,
-        md: &hir::Mod,
+        md: &hir::Mod<'_>,
         attrs: &[ast::Attribute],
         vis: &hir::Visibility,
     ) {
@@ -727,7 +727,7 @@ impl EncodeContext<'tcx> {
         record!(self.per_def.kind[def_id] <- EntryKind::Field);
         record!(self.per_def.visibility[def_id] <- field.vis);
         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
-        record!(self.per_def.attributes[def_id] <- &variant_data.fields()[field_index].attrs);
+        record!(self.per_def.attributes[def_id] <- variant_data.fields()[field_index].attrs);
         self.encode_stability(def_id);
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
@@ -864,7 +864,7 @@ impl EncodeContext<'tcx> {
         });
         record!(self.per_def.visibility[def_id] <- trait_item.vis);
         record!(self.per_def.span[def_id] <- ast_item.span);
-        record!(self.per_def.attributes[def_id] <- &ast_item.attrs);
+        record!(self.per_def.attributes[def_id] <- ast_item.attrs);
         self.encode_stability(def_id);
         self.encode_const_stability(def_id);
         self.encode_deprecation(def_id);
@@ -945,7 +945,7 @@ impl EncodeContext<'tcx> {
         });
         record!(self.per_def.visibility[def_id] <- impl_item.vis);
         record!(self.per_def.span[def_id] <- ast_item.span);
-        record!(self.per_def.attributes[def_id] <- &ast_item.attrs);
+        record!(self.per_def.attributes[def_id] <- ast_item.attrs);
         self.encode_stability(def_id);
         self.encode_const_stability(def_id);
         self.encode_deprecation(def_id);
@@ -1048,14 +1048,14 @@ impl EncodeContext<'tcx> {
         self.lazy(rendered_const)
     }
 
-    fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) {
+    fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
         let tcx = self.tcx;
 
         debug!("EncodeContext::encode_info_for_item({:?})", def_id);
 
         record!(self.per_def.kind[def_id] <- match item.kind {
-            hir::ItemKind::Static(_, hir::Mutability::Mutable, _) => EntryKind::MutStatic,
-            hir::ItemKind::Static(_, hir::Mutability::Immutable, _) => EntryKind::ImmStatic,
+            hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic,
+            hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic,
             hir::ItemKind::Const(_, body_id) => {
                 let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id);
                 EntryKind::Const(
@@ -1160,7 +1160,7 @@ impl EncodeContext<'tcx> {
         record!(self.per_def.visibility[def_id] <-
             ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
         record!(self.per_def.span[def_id] <- item.span);
-        record!(self.per_def.attributes[def_id] <- &item.attrs);
+        record!(self.per_def.attributes[def_id] <- item.attrs);
         // FIXME(eddyb) there should be a nicer way to do this.
         match item.kind {
             hir::ItemKind::ForeignMod(ref fm) => record!(self.per_def.children[def_id] <-
@@ -1271,7 +1271,7 @@ impl EncodeContext<'tcx> {
     }
 
     /// Serialize the text of exported macros
-    fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) {
+    fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
         use syntax::print::pprust;
         let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
         record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef {
@@ -1280,7 +1280,7 @@ impl EncodeContext<'tcx> {
         })));
         record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
         record!(self.per_def.span[def_id] <- macro_def.span);
-        record!(self.per_def.attributes[def_id] <- &macro_def.attrs);
+        record!(self.per_def.attributes[def_id] <- macro_def.attrs);
         self.encode_stability(def_id);
         self.encode_deprecation(def_id);
     }
@@ -1525,7 +1525,7 @@ impl EncodeContext<'tcx> {
     fn encode_info_for_foreign_item(
         &mut self,
         def_id: DefId,
-        nitem: &hir::ForeignItem,
+        nitem: &hir::ForeignItem<'_>,
     )  {
         let tcx = self.tcx;
 
@@ -1544,16 +1544,14 @@ impl EncodeContext<'tcx> {
                 };
                 EntryKind::ForeignFn(self.lazy(data))
             }
-            hir::ForeignItemKind::Static(_, hir::Mutability::Mutable) =>
-                EntryKind::ForeignMutStatic,
-            hir::ForeignItemKind::Static(_, hir::Mutability::Immutable) =>
-                EntryKind::ForeignImmStatic,
+            hir::ForeignItemKind::Static(_, hir::Mutability::Mut) => EntryKind::ForeignMutStatic,
+            hir::ForeignItemKind::Static(_, hir::Mutability::Not) => EntryKind::ForeignImmStatic,
             hir::ForeignItemKind::Type => EntryKind::ForeignType,
         });
         record!(self.per_def.visibility[def_id] <-
             ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx));
         record!(self.per_def.span[def_id] <- nitem.span);
-        record!(self.per_def.attributes[def_id] <- &nitem.attrs);
+        record!(self.per_def.attributes[def_id] <- nitem.attrs);
         self.encode_stability(def_id);
         self.encode_const_stability(def_id);
         self.encode_deprecation(def_id);
@@ -1582,7 +1580,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> {
         let def_id = self.tcx.hir().local_def_id(c.hir_id);
         self.encode_info_for_anon_const(def_id);
     }
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         intravisit::walk_item(self, item);
         let def_id = self.tcx.hir().local_def_id(item.hir_id);
         match item.kind {
@@ -1592,7 +1590,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> {
         }
         self.encode_addl_info_for_item(item);
     }
-    fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
         intravisit::walk_foreign_item(self, ni);
         let def_id = self.tcx.hir().local_def_id(ni.hir_id);
         self.encode_info_for_foreign_item(def_id, ni);
@@ -1601,7 +1599,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> {
         intravisit::walk_generics(self, generics);
         self.encode_info_for_generics(generics);
     }
-    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
+    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
         self.encode_info_for_macro_def(macro_def);
     }
 }
@@ -1651,7 +1649,7 @@ impl EncodeContext<'tcx> {
     /// encode some sub-items. Usually we want some info from the item
     /// so it's easier to do that here then to wait until we would encounter
     /// normally in the visitor walk.
-    fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
+    fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
         let def_id = self.tcx.hir().local_def_id(item.hir_id);
         match item.kind {
             hir::ItemKind::Static(..) |
@@ -1715,7 +1713,7 @@ struct ImplVisitor<'tcx> {
 }
 
 impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let hir::ItemKind::Impl(..) = item.kind {
             let impl_id = self.tcx.hir().local_def_id(item.hir_id);
             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
@@ -1727,9 +1725,9 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
+    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem<'v>) {}
 
-    fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem<'v>) {
         // handled in `visit_item` above
     }
 }
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index 016a3195c98..38101c35dcc 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -261,7 +261,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         // we have an explicit self. Do the same thing in this case and check
                         // for a `self: &mut Self` to suggest removing the `&mut`.
                         if let ty::Ref(
-                            _, _, hir::Mutability::Mutable
+                            _, _, hir::Mutability::Mut
                         ) = local_decl.ty.kind {
                             true
                         } else {
@@ -578,7 +578,7 @@ fn suggest_ampmut<'tcx>(
     }
 
     let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
-    assert_eq!(ty_mut.mutbl, hir::Mutability::Immutable);
+    assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
     (highlight_span,
      if local_decl.ty.is_region_ptr() {
          format!("&mut {}", ty_mut.ty)
@@ -614,7 +614,7 @@ fn annotate_struct_field(
             // we can expect a field that is an immutable reference to a type.
             if let hir::Node::Field(field) = node {
                 if let hir::TyKind::Rptr(lifetime, hir::MutTy {
-                    mutbl: hir::Mutability::Immutable,
+                    mutbl: hir::Mutability::Not,
                     ref ty
                 }) = field.ty.kind {
                     // Get the snippets in two parts - the named lifetime (if there is one) and
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 8a37e2d02ec..b78cd6bccf8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -1,10 +1,13 @@
 //! Error reporting machinery for lifetime errors.
 
 use rustc::hir::def_id::DefId;
-use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
-use rustc::infer::InferCtxt;
-use rustc::infer::NLLRegionVariableOrigin;
-use rustc::mir::{ConstraintCategory, Local, Location, Body};
+use rustc::infer::{
+    error_reporting::nice_region_error::NiceRegionError,
+    InferCtxt, NLLRegionVariableOrigin,
+};
+use rustc::mir::{
+    ConstraintCategory, Local, Location, Body,
+};
 use rustc::ty::{self, RegionVid};
 use rustc_index::vec::IndexVec;
 use rustc_errors::DiagnosticBuilder;
@@ -93,6 +96,32 @@ pub struct ErrorConstraintInfo {
 }
 
 impl<'tcx> RegionInferenceContext<'tcx> {
+    /// Converts a region inference variable into a `ty::Region` that
+    /// we can use for error reporting. If `r` is universally bound,
+    /// then we use the name that we have on record for it. If `r` is
+    /// existentially bound, then we check its inferred value and try
+    /// to find a good name from that. Returns `None` if we can't find
+    /// one (e.g., this is just some random part of the CFG).
+    pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
+        self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
+    }
+
+    /// Returns the [RegionVid] corresponding to the region returned by
+    /// `to_error_region`.
+    pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
+        if self.universal_regions.is_universal_region(r) {
+            Some(r)
+        } else {
+            let r_scc = self.constraint_sccs.scc(r);
+            let upper_bound = self.universal_upper_bound(r);
+            if self.scc_values.contains(r_scc, upper_bound) {
+                self.to_error_region_vid(upper_bound)
+            } else {
+                None
+            }
+        }
+    }
+
     /// Tries to find the best constraint to blame for the fact that
     /// `R: from_region`, where `R` is some region that meets
     /// `target_test`. This works by following the constraint graph,
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index 58fac5512d9..d5b9aaf9511 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -3,7 +3,7 @@ use rustc::mir::visit::Visitor;
 use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::TerminatorKind;
-use rustc::mir::{Operand, BorrowKind};
+use rustc::mir::{Operand, BorrowKind, Mutability};
 use rustc_data_structures::graph::dominators::Dominators;
 
 use crate::dataflow::indexes::BorrowIndex;
@@ -337,6 +337,22 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
                 );
             }
 
+            Rvalue::AddressOf(mutability, ref place) => {
+                let access_kind = match mutability {
+                    Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
+                        allow_two_phase_borrow: false,
+                    }))),
+                    Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+                };
+
+                self.access_place(
+                    location,
+                    place,
+                    access_kind,
+                    LocalMutationIsAllowed::No,
+                );
+            }
+
             Rvalue::Use(ref operand)
             | Rvalue::Repeat(ref operand, _)
             | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 11012ef2fc7..cd1e72e9d17 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -160,7 +160,7 @@ fn do_mir_borrowck<'a, 'tcx>(
             };
             let bm = *tables.pat_binding_modes().get(var_hir_id)
                 .expect("missing binding mode");
-            if bm == ty::BindByValue(hir::Mutability::Mutable) {
+            if bm == ty::BindByValue(hir::Mutability::Mut) {
                 upvar.mutability = Mutability::Mut;
             }
             upvar
@@ -1233,6 +1233,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 );
             }
 
+
+            Rvalue::AddressOf(mutability, ref place) => {
+                let access_kind = match mutability {
+                    Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
+                        allow_two_phase_borrow: false,
+                    }))),
+                    Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+                };
+
+                self.access_place(
+                    location,
+                    (place, span),
+                    access_kind,
+                    LocalMutationIsAllowed::No,
+                    flow_state,
+                );
+
+                self.check_if_path_or_subpath_is_moved(
+                    location,
+                    InitializationRequiringAction::Borrow,
+                    (place.as_ref(), span),
+                    flow_state,
+                );
+            }
+
             Rvalue::Use(ref operand)
             | Rvalue::Repeat(ref operand, _)
             | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
@@ -2200,10 +2225,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             ty::Ref(_, _, mutbl) => {
                                 match mutbl {
                                     // Shared borrowed data is never mutable
-                                    hir::Mutability::Immutable => Err(place),
+                                    hir::Mutability::Not => Err(place),
                                     // Mutably borrowed data is mutable, but only if we have a
                                     // unique path to the `&mut`
-                                    hir::Mutability::Mutable => {
+                                    hir::Mutability::Mut => {
                                         let mode = match self.is_upvar_field_projection(place) {
                                             Some(field)
                                                 if self.upvars[field.index()].by_ref =>
@@ -2223,10 +2248,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             ty::RawPtr(tnm) => {
                                 match tnm.mutbl {
                                     // `*const` raw pointers are not mutable
-                                    hir::Mutability::Immutable => Err(place),
+                                    hir::Mutability::Not => Err(place),
                                     // `*mut` raw pointers are always mutable, regardless of
                                     // context. The users have to check by themselves.
-                                    hir::Mutability::Mutable => {
+                                    hir::Mutability::Mut => {
                                         Ok(RootPlace {
                                             place_base: place.base,
                                             place_projection: place.projection,
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index c62de2af55f..e11db4ad5bb 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -58,7 +58,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
             if *elem == ProjectionElem::Deref {
                 let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty;
                 match ty.kind {
-                    ty::Ref(_, _, hir::Mutability::Immutable) if i == 0 => {
+                    ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
                         // For references to thread-local statics, we do need
                         // to track the borrow.
                         if body.local_decls[local].is_ref_to_thread_local() {
@@ -66,7 +66,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                         }
                         return true;
                     }
-                    ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Immutable) => {
+                    ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Not) => {
                         // For both derefs of raw pointers and `&T`
                         // references, the original path is `Copy` and
                         // therefore not significant.  In particular,
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 9245064f875..0cc7af330ca 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -246,13 +246,11 @@ fn place_components_conflict<'tcx>(
                     debug!("borrow_conflicts_with_place: shallow access behind ptr");
                     return false;
                 }
-                (ProjectionElem::Deref, ty::Ref(_, _, hir::Mutability::Immutable), _) => {
+                (ProjectionElem::Deref, ty::Ref(_, _, hir::Mutability::Not), _) => {
                     // Shouldn't be tracked
                     bug!("Tracking borrow behind shared reference.");
                 }
-                (ProjectionElem::Deref,
-                 ty::Ref(_, _, hir::Mutability::Mutable),
-                 AccessDepth::Drop) => {
+                (ProjectionElem::Deref, ty::Ref(_, _, hir::Mutability::Mut), AccessDepth::Drop) => {
                     // Values behind a mutable reference are not access either by dropping a
                     // value, or by StorageDead
                     debug!("borrow_conflicts_with_place: drop access behind ptr");
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 248faa56777..5b9ce7cb5fd 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -149,7 +149,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                         ty::Ref(
                             _, /*rgn*/
                             _, /*ty*/
-                            hir::Mutability::Immutable
+                            hir::Mutability::Not
                             ) => {
                             // don't continue traversing over derefs of raw pointers or shared
                             // borrows.
@@ -160,7 +160,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                         ty::Ref(
                             _, /*rgn*/
                             _, /*ty*/
-                            hir::Mutability::Mutable,
+                            hir::Mutability::Mut,
                             ) => {
                             self.next = Some(PlaceRef {
                                 base: cursor.base,
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index b6946e2f73f..dedc6b9b09a 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -928,32 +928,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
-    /// Converts a region inference variable into a `ty::Region` that
-    /// we can use for error reporting. If `r` is universally bound,
-    /// then we use the name that we have on record for it. If `r` is
-    /// existentially bound, then we check its inferred value and try
-    /// to find a good name from that. Returns `None` if we can't find
-    /// one (e.g., this is just some random part of the CFG).
-    pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
-        self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
-    }
-
-    /// Returns the [RegionVid] corresponding to the region returned by
-    /// `to_error_region`.
-    pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
-        if self.universal_regions.is_universal_region(r) {
-            Some(r)
-        } else {
-            let r_scc = self.constraint_sccs.scc(r);
-            let upper_bound = self.universal_upper_bound(r);
-            if self.scc_values.contains(r_scc, upper_bound) {
-                self.to_error_region_vid(upper_bound)
-            } else {
-                None
-            }
-        }
-    }
-
     /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot
     /// prove to be satisfied. If this is a closure, we will attempt to
     /// "promote" this type-test into our `ClosureRegionRequirements` and
@@ -1164,7 +1138,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///   include the CFG anyhow.
     /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
     ///   a result `'y`.
-    fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
+    pub (in crate::borrow_check) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
         debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
 
         // Find the smallest universal region that contains all other
@@ -1458,19 +1432,34 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             debug!("check_polonius_subset_errors: subset_error longer_fr={:?},\
                 shorter_fr={:?}", longer_fr, shorter_fr);
 
-            self.report_or_propagate_universal_region_error(
+            let propagated = self.try_propagate_universal_region_error(
                 *longer_fr,
                 *shorter_fr,
-                infcx,
                 body,
-                local_names,
-                upvars,
-                mir_def_id,
                 &mut propagated_outlives_requirements,
-                &mut outlives_suggestion,
-                errors_buffer,
-                region_naming,
             );
+            if !propagated {
+                // If we are not in a context where we can't propagate errors, or we
+                // could not shrink `fr` to something smaller, then just report an
+                // error.
+                //
+                // Note: in this case, we use the unapproximated regions to report the
+                // error. This gives better error messages in some cases.
+                let db = self.report_error(
+                    body,
+                    local_names,
+                    upvars,
+                    infcx,
+                    mir_def_id,
+                    *longer_fr,
+                    NLLRegionVariableOrigin::FreeRegion,
+                    *shorter_fr,
+                    &mut outlives_suggestion,
+                    region_naming,
+                );
+
+                db.buffer(errors_buffer);
+            }
         }
 
         // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has
@@ -1594,48 +1583,59 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             return None;
         }
 
-        self.report_or_propagate_universal_region_error(
+        let propagated = self.try_propagate_universal_region_error(
             longer_fr,
             shorter_fr,
-            infcx,
             body,
-            local_names,
-            upvars,
-            mir_def_id,
             propagated_outlives_requirements,
-            outlives_suggestion,
-            errors_buffer,
-            region_naming,
-        )
+        );
+
+        if propagated {
+            None
+        } else {
+            // If we are not in a context where we can't propagate errors, or we
+            // could not shrink `fr` to something smaller, then just report an
+            // error.
+            //
+            // Note: in this case, we use the unapproximated regions to report the
+            // error. This gives better error messages in some cases.
+            let db = self.report_error(
+                body,
+                local_names,
+                upvars,
+                infcx,
+                mir_def_id,
+                longer_fr,
+                NLLRegionVariableOrigin::FreeRegion,
+                shorter_fr,
+                outlives_suggestion,
+                region_naming,
+            );
+
+            db.buffer(errors_buffer);
+
+            Some(ErrorReported)
+        }
     }
 
-    fn report_or_propagate_universal_region_error(
+    /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's
+    /// creator. If we cannot, then the caller should report an error to the user.
+    ///
+    /// Returns `true` if the error was propagated, and `false` otherwise.
+    fn try_propagate_universal_region_error(
         &self,
         longer_fr: RegionVid,
         shorter_fr: RegionVid,
-        infcx: &InferCtxt<'_, 'tcx>,
         body: &Body<'tcx>,
-        local_names: &IndexVec<Local, Option<Symbol>>,
-        upvars: &[Upvar],
-        mir_def_id: DefId,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
-        outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
-        errors_buffer: &mut Vec<Diagnostic>,
-        region_naming: &mut RegionErrorNamingCtx,
-    ) -> Option<ErrorReported> {
-        debug!(
-            "report_or_propagate_universal_region_error: fr={:?} does not outlive shorter_fr={:?}",
-            longer_fr, shorter_fr,
-        );
-
+    ) -> bool {
         if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
             // Shrink `longer_fr` until we find a non-local region (if we do).
             // We'll call it `fr-` -- it's ever so slightly smaller than
             // `longer_fr`.
-
             if let Some(fr_minus) =
                 self.universal_region_relations.non_local_lower_bound(longer_fr) {
-                debug!("report_or_propagate_universal_region_error: fr_minus={:?}", fr_minus);
+                debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
 
                 let blame_span_category =
                     self.find_outlives_blame_span(body, longer_fr,
@@ -1648,7 +1648,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     .universal_region_relations
                     .non_local_upper_bounds(&shorter_fr);
                 debug!(
-                    "report_or_propagate_universal_region_error: shorter_fr_plus={:?}",
+                    "try_propagate_universal_region_error: shorter_fr_plus={:?}",
                     shorter_fr_plus
                 );
                 for &&fr in &shorter_fr_plus {
@@ -1660,32 +1660,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         category: blame_span_category.0,
                     });
                 }
-                return None;
+                return true;
             }
         }
 
-        // If we are not in a context where we can't propagate errors, or we
-        // could not shrink `fr` to something smaller, then just report an
-        // error.
-        //
-        // Note: in this case, we use the unapproximated regions to report the
-        // error. This gives better error messages in some cases.
-        let db = self.report_error(
-            body,
-            local_names,
-            upvars,
-            infcx,
-            mir_def_id,
-            longer_fr,
-            NLLRegionVariableOrigin::FreeRegion,
-            shorter_fr,
-            outlives_suggestion,
-            region_naming,
-        );
-
-        db.buffer(errors_buffer);
-
-        Some(ErrorReported)
+        false
     }
 
     fn check_bound_universal_region(
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 663536bc2b4..5613fd045ea 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -2162,7 +2162,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         let ty_from = match op.ty(*body, tcx).kind {
                             ty::RawPtr(ty::TypeAndMut {
                                 ty: ty_from,
-                                mutbl: hir::Mutability::Mutable,
+                                mutbl: hir::Mutability::Mut,
                             }) => ty_from,
                             _ => {
                                 span_mirbug!(
@@ -2177,7 +2177,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         let ty_to = match ty.kind {
                             ty::RawPtr(ty::TypeAndMut {
                                 ty: ty_to,
-                                mutbl: hir::Mutability::Immutable,
+                                mutbl: hir::Mutability::Not,
                             }) => ty_to,
                             _ => {
                                 span_mirbug!(
@@ -2211,7 +2211,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                         let opt_ty_elem = match ty_from.kind {
                             ty::RawPtr(
-                                ty::TypeAndMut { mutbl: hir::Mutability::Immutable, ty: array_ty }
+                                ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: array_ty }
                             ) => {
                                 match array_ty.kind {
                                     ty::Array(ty_elem, _) => Some(ty_elem),
@@ -2236,7 +2236,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                         let ty_to = match ty.kind {
                             ty::RawPtr(
-                                ty::TypeAndMut { mutbl: hir::Mutability::Immutable, ty: ty_to }
+                                ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: ty_to }
                             ) => {
                                 ty_to
                             }
@@ -2273,41 +2273,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(ty);
                         match (cast_ty_from, cast_ty_to) {
-                            (Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => {
-                                if let hir::Mutability::Mutable = ptr_tm.mutbl {
-                                    if let Err(terr) = self.eq_types(
-                                        ref_tm.ty,
-                                        ptr_tm.ty,
-                                        location.to_locations(),
-                                        ConstraintCategory::Cast,
-                                    ) {
-                                        span_mirbug!(
-                                            self,
-                                            rvalue,
-                                            "equating {:?} with {:?} yields {:?}",
-                                            ref_tm.ty,
-                                            ptr_tm.ty,
-                                            terr
-                                        )
-                                    }
-                                } else {
-                                    if let Err(terr) = self.sub_types(
-                                        ref_tm.ty,
-                                        ptr_tm.ty,
-                                        location.to_locations(),
-                                        ConstraintCategory::Cast,
-                                    ) {
-                                        span_mirbug!(
-                                            self,
-                                            rvalue,
-                                            "relating {:?} with {:?} yields {:?}",
-                                            ref_tm.ty,
-                                            ptr_tm.ty,
-                                            terr
-                                        )
-                                    }
-                                }
-                            },
                             (None, _)
                             | (_, None)
                             | (_, Some(CastTy::FnPtr))
@@ -2320,7 +2285,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 ty_from,
                                 ty,
                             ),
-                            _ => (),
+                            (Some(CastTy::Int(_)), Some(CastTy::Int(_)))
+                            | (Some(CastTy::Float), Some(CastTy::Int(_)))
+                            | (Some(CastTy::Int(_)), Some(CastTy::Float))
+                            | (Some(CastTy::Float), Some(CastTy::Float))
+                            | (Some(CastTy::Ptr(_)), Some(CastTy::Int(_)))
+                            | (Some(CastTy::FnPtr), Some(CastTy::Int(_)))
+                            | (Some(CastTy::Int(_)), Some(CastTy::Ptr(_)))
+                            | (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_)))
+                            | (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
                         }
                     }
                 }
@@ -2371,7 +2344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
 
-            Rvalue::Use(..)
+            Rvalue::AddressOf(..)
+            | Rvalue::Use(..)
             | Rvalue::Len(..)
             | Rvalue::BinaryOp(..)
             | Rvalue::CheckedBinaryOp(..)
@@ -2388,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Rvalue::Use(_)
             | Rvalue::Repeat(..)
             | Rvalue::Ref(..)
+            | Rvalue::AddressOf(..)
             | Rvalue::Len(..)
             | Rvalue::Cast(..)
             | Rvalue::BinaryOp(..)
@@ -2529,13 +2504,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             });
 
                             match mutbl {
-                                hir::Mutability::Immutable => {
+                                hir::Mutability::Not => {
                                     // Immutable reference. We don't need the base
                                     // to be valid for the entire lifetime of
                                     // the borrow.
                                     break;
                                 }
-                                hir::Mutability::Mutable => {
+                                hir::Mutability::Mut => {
                                     // Mutable reference. We *do* need the base
                                     // to be valid, because after the base becomes
                                     // invalid, someone else can use our mutable deref.
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index ddacda72e1e..15c7c92d7db 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::Pointer { .. }
             | ExprKind::Repeat { .. }
             | ExprKind::Borrow { .. }
+            | ExprKind::AddressOf { .. }
             | ExprKind::Match { .. }
             | ExprKind::Loop { .. }
             | ExprKind::Block { .. }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 37eb0cc9d96..24282a6617a 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::NeverToAny { .. }
             | ExprKind::Use { .. }
             | ExprKind::Borrow { .. }
+            | ExprKind::AddressOf { .. }
             | ExprKind::Adt { .. }
             | ExprKind::Loop { .. }
             | ExprKind::LogicalOp { .. }
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index 270a1a64474..4d0039b2e8c 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -49,6 +49,7 @@ impl Category {
             | ExprKind::Use { .. }
             | ExprKind::Adt { .. }
             | ExprKind::Borrow { .. }
+            | ExprKind::AddressOf { .. }
             | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
 
             ExprKind::Array { .. }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 07a44b190b2..608415408e3 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -3,6 +3,7 @@
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::hair::*;
+use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation};
 use rustc_data_structures::fx::FxHashMap;
@@ -295,6 +296,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.push_assign(block, source_info, destination, borrow);
                 block.unit()
             }
+            ExprKind::AddressOf {
+                mutability,
+                arg,
+            } => {
+                let place = match mutability {
+                    hir::Mutability::Not => this.as_read_only_place(block, arg),
+                    hir::Mutability::Mut => this.as_place(block, arg),
+                };
+                let address_of = Rvalue::AddressOf(mutability, unpack!(block = place));
+                this.cfg.push_assign(block, source_info, destination, address_of);
+                block.unit()
+            }
             ExprKind::Adt {
                 adt_def,
                 variant_index,
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 0009eb45cc0..6b6a58102fa 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -552,7 +552,7 @@ fn construct_fn<'a, 'tcx, A>(
     abi: Abi,
     return_ty: Ty<'tcx>,
     return_ty_span: Span,
-    body: &'tcx hir::Body,
+    body: &'tcx hir::Body<'tcx>,
 ) -> Body<'tcx>
 where
     A: Iterator<Item=ArgInfo<'tcx>>
@@ -821,7 +821,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         name = ident.name;
 
                         if let Some(&bm) = hir_tables.pat_binding_modes().get(pat.hir_id) {
-                            if bm == ty::BindByValue(hir::Mutability::Mutable) {
+                            if bm == ty::BindByValue(hir::Mutability::Mut) {
                                 mutability = Mutability::Mut;
                             } else {
                                 mutability = Mutability::Not;
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index fa0864e0de7..0b8f41f51a1 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -103,6 +103,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             }
         };
 
+        // The move path index of the first union that we find. Once this is
+        // some we stop creating child move paths, since moves from unions
+        // move the whole thing.
+        // We continue looking for other move errors though so that moving
+        // from `*(u.f: &_)` isn't allowed.
+        let mut union_path = None;
+
         for (i, elem) in place.projection.iter().enumerate() {
             let proj_base = &place.projection[..i];
             let body = self.builder.body;
@@ -127,9 +134,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                         InteriorOfTypeWithDestructor { container_ty: place_ty },
                     ));
                 }
-                // move out of union - always move the entire union
                 ty::Adt(adt, _) if adt.is_union() => {
-                    return Err(MoveError::UnionMove { path: base });
+                    union_path.get_or_insert(base);
                 }
                 ty::Slice(_) => {
                     return Err(MoveError::cannot_move_out_of(
@@ -155,15 +161,22 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 _ => {}
             };
 
-            base = self.add_move_path(base, elem, |tcx| {
-                Place {
-                    base: place.base.clone(),
-                    projection: tcx.intern_place_elems(&place.projection[..i+1]),
-                }
-            });
+            if union_path.is_none() {
+                base = self.add_move_path(base, elem, |tcx| {
+                    Place {
+                        base: place.base.clone(),
+                        projection: tcx.intern_place_elems(&place.projection[..i+1]),
+                    }
+                });
+            }
         }
 
-        Ok(base)
+        if let Some(base) = union_path {
+            // Move out of union - always move the entire union.
+            Err(MoveError::UnionMove { path: base })
+        } else {
+            Ok(base)
+        }
     }
 
     fn add_move_path(
@@ -335,6 +348,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 }
             }
             Rvalue::Ref(..)
+            | Rvalue::AddressOf(..)
             | Rvalue::Discriminant(..)
             | Rvalue::Len(..)
             | Rvalue::NullaryOp(NullOp::SizeOf, _)
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index f116f7d14da..589016a2ca2 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>(
                 arg: expr.to_ref(),
             }
         }
-        Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => {
-            raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime)
+        Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
+            ExprKind::AddressOf {
+                mutability,
+                arg: expr.to_ref(),
+            }
         }
     };
 
@@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
             }
         }
 
-        hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => {
-            cx.tcx.sess
-                .struct_span_err(
-                    expr.span,
-                    "raw borrows are not yet implemented"
-                )
-                .note("for more information, see https://github.com/rust-lang/rust/issues/64490")
-                .emit();
-
-            // Lower to an approximation to avoid further errors.
-            raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime)
+        hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
+            ExprKind::AddressOf {
+                mutability,
+                arg: arg.to_ref(),
+            }
         }
 
         hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
@@ -809,13 +806,12 @@ impl ToBorrowKind for AutoBorrowMutability {
     fn to_borrow_kind(&self) -> BorrowKind {
         use rustc::ty::adjustment::AllowTwoPhase;
         match *self {
-            AutoBorrowMutability::Mutable { allow_two_phase_borrow } =>
+            AutoBorrowMutability::Mut { allow_two_phase_borrow } =>
                 BorrowKind::Mut { allow_two_phase_borrow: match allow_two_phase_borrow {
                     AllowTwoPhase::Yes => true,
                     AllowTwoPhase::No => false
                 }},
-            AutoBorrowMutability::Immutable =>
-                BorrowKind::Shared,
+            AutoBorrowMutability::Not => BorrowKind::Shared,
         }
     }
 }
@@ -823,8 +819,8 @@ impl ToBorrowKind for AutoBorrowMutability {
 impl ToBorrowKind for hir::Mutability {
     fn to_borrow_kind(&self) -> BorrowKind {
         match *self {
-            hir::Mutability::Mutable => BorrowKind::Mut { allow_two_phase_borrow: false },
-            hir::Mutability::Immutable => BorrowKind::Shared,
+            hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
+            hir::Mutability::Not => BorrowKind::Shared,
         }
     }
 }
@@ -991,7 +987,7 @@ fn convert_var(
                         let ref_closure_ty = cx.tcx.mk_ref(region,
                                                            ty::TypeAndMut {
                                                                ty: closure_ty,
-                                                               mutbl: hir::Mutability::Immutable,
+                                                               mutbl: hir::Mutability::Not,
                                                            });
                         Expr {
                             ty: closure_ty,
@@ -1012,7 +1008,7 @@ fn convert_var(
                         let ref_closure_ty = cx.tcx.mk_ref(region,
                                                            ty::TypeAndMut {
                                                                ty: closure_ty,
-                                                               mutbl: hir::Mutability::Mutable,
+                                                               mutbl: hir::Mutability::Mut,
                                                            });
                         Expr {
                             ty: closure_ty,
@@ -1076,67 +1072,6 @@ fn convert_var(
 }
 
 
-/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf`
-/// exists in MIR.
-fn raw_ref_shim<'tcx>(
-    cx: &mut Cx<'_, 'tcx>,
-    arg: ExprRef<'tcx>,
-    ty: Ty<'tcx>,
-    mutbl: hir::Mutability,
-    span: Span,
-    temp_lifetime: Option<region::Scope>,
-) -> ExprKind<'tcx> {
-    let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind {
-        type_mutbl
-    } else {
-        bug!("raw_ref_shim called with non-raw pointer type");
-    };
-    // Convert this to a suitable `&foo` and
-    // then an unsafe coercion.
-    let borrow_expr = Expr {
-        temp_lifetime,
-        ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm),
-        span,
-        kind: ExprKind::Borrow {
-            borrow_kind: mutbl.to_borrow_kind(),
-            arg,
-        },
-    };
-    let cast_expr = Expr {
-        temp_lifetime,
-        ty,
-        span,
-        kind: ExprKind::Cast { source: borrow_expr.to_ref() }
-    };
-
-    // To ensure that both implicit and explicit coercions are
-    // handled the same way, we insert an extra layer of indirection here.
-    // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
-    // will be an ExprKind::Hair with the appropriate cast expression. Here,
-    // we make our Use source the generated Cast from the original coercion.
-    //
-    // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
-    // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
-    // Ordinary, this is identical to using the cast directly as an rvalue. However, if the
-    // source of the cast was previously borrowed as mutable, storing the cast in a
-    // temporary gives the source a chance to expire before the cast is used. For
-    // structs with a self-referential *mut ptr, this allows assignment to work as
-    // expected.
-    //
-    // For example, consider the type 'struct Foo { field: *mut Foo }',
-    // The method 'fn bar(&mut self) { self.field = self }'
-    // triggers a coercion from '&mut self' to '*mut self'. In order
-    // for the assignment to be valid, the implicit borrow
-    // of 'self' involved in the coercion needs to end before the local
-    // containing the '*mut T' is assigned to 'self.field' - otherwise,
-    // we end up trying to assign to 'self.field' while we have another mutable borrow
-    // active.
-    //
-    // We only need to worry about this kind of thing for coercions from refs to ptrs,
-    // since they get rid of a borrow implicitly.
-    ExprKind::Use { source: cast_expr.to_ref() }
-}
-
 fn bin_op(op: hir::BinOpKind) -> BinOp {
     match op {
         hir::BinOpKind::Add => BinOp::Add,
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 47644d9ba83..46e0d2a17b3 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> {
         borrow_kind: BorrowKind,
         arg: ExprRef<'tcx>,
     },
+    /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
+    AddressOf {
+        mutability: hir::Mutability,
+        arg: ExprRef<'tcx>,
+    },
     Break {
         label: region::Scope,
         value: Option<ExprRef<'tcx>>,
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index c3720328506..f267be812c3 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -620,10 +620,11 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
 enum SliceKind {
     /// Patterns of length `n` (`[x, y]`).
     FixedLen(u64),
-    /// Patterns using the `..` notation (`[x, .., y]`). Captures any array constructor of `length
-    /// >= i + j`. In the case where `array_len` is `Some(_)`, this indicates that we only care
-    /// about the first `i` and the last `j` values of the array, and everything in between is a
-    /// wildcard `_`.
+    /// Patterns using the `..` notation (`[x, .., y]`).
+    /// Captures any array constructor of `length >= i + j`.
+    /// In the case where `array_len` is `Some(_)`,
+    /// this indicates that we only care about the first `i` and the last `j` values of the array,
+    /// and everything in between is a wildcard `_`.
     VarLen(u64, u64),
 }
 
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 8156cfe7ab5..4ebf41fb9d2 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -76,10 +76,10 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
         self.check_patterns(false, &loc.pat);
     }
 
-    fn visit_body(&mut self, body: &'tcx hir::Body) {
+    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
         intravisit::walk_body(self, body);
 
-        for param in &body.params {
+        for param in body.params {
             self.check_irrefutable(&param.pat, "function argument", None);
             self.check_patterns(false, &param.pat);
         }
@@ -269,7 +269,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
     pat.walk(|p| {
         if let hir::PatKind::Binding(_, _, ident, None) = p.kind {
             if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) {
-                if bm != ty::BindByValue(hir::Mutability::Immutable) {
+                if bm != ty::BindByValue(hir::Mutability::Not) {
                     // Nothing to check.
                     return true;
                 }
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index e12f0322564..fdef6633925 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -445,6 +445,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pat<'tcx> {
         let mut ty = self.tables.node_type(pat.hir_id);
 
+        if let ty::Error = ty.kind {
+            // Avoid ICEs (e.g., #50577 and #50585).
+            return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
+        }
+
         let kind = match pat.kind {
             hir::PatKind::Wild => PatKind::Wild,
 
@@ -544,81 +549,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
 
             hir::PatKind::Slice(ref prefix, ref slice, ref suffix) => {
-                match ty.kind {
-                    ty::Ref(_, ty, _) =>
-                        PatKind::Deref {
-                            subpattern: Pat {
-                                ty,
-                                span: pat.span,
-                                kind: Box::new(self.slice_or_array_pattern(
-                                    pat.span, ty, prefix, slice, suffix))
-                            },
-                        },
-                    ty::Slice(..) |
-                    ty::Array(..) =>
-                        self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
-                    ty::Error => { // Avoid ICE
-                        return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
-                    }
-                    _ =>
-                        span_bug!(
-                            pat.span,
-                            "unexpanded type for vector pattern: {:?}",
-                            ty),
-                }
+                self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
             }
 
-            hir::PatKind::Tuple(ref subpatterns, ddpos) => {
-                match ty.kind {
-                    ty::Tuple(ref tys) => {
-                        let subpatterns =
-                            subpatterns.iter()
-                                       .enumerate_and_adjust(tys.len(), ddpos)
-                                       .map(|(i, subpattern)| FieldPat {
-                                            field: Field::new(i),
-                                            pattern: self.lower_pattern(subpattern)
-                                       })
-                                       .collect();
-
-                        PatKind::Leaf { subpatterns }
-                    }
-                    ty::Error => { // Avoid ICE (#50577)
-                        return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
-                    }
+            hir::PatKind::Tuple(ref pats, ddpos) => {
+                let tys = match ty.kind {
+                    ty::Tuple(ref tys) => tys,
                     _ => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty),
-                }
+                };
+                let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
+                PatKind::Leaf { subpatterns }
             }
 
             hir::PatKind::Binding(_, id, ident, ref sub) => {
-                let var_ty = self.tables.node_type(pat.hir_id);
-                if let ty::Error = var_ty.kind {
-                    // Avoid ICE
-                    return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
-                };
                 let bm = *self.tables.pat_binding_modes().get(pat.hir_id)
                                                          .expect("missing binding mode");
                 let (mutability, mode) = match bm {
-                    ty::BindByValue(hir::Mutability::Mutable) =>
-                        (Mutability::Mut, BindingMode::ByValue),
-                    ty::BindByValue(hir::Mutability::Immutable) =>
-                        (Mutability::Not, BindingMode::ByValue),
-                    ty::BindByReference(hir::Mutability::Mutable) =>
+                    ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
+                    ty::BindByReference(hir::Mutability::Mut) =>
                         (Mutability::Not, BindingMode::ByRef(
                             BorrowKind::Mut { allow_two_phase_borrow: false })),
-                    ty::BindByReference(hir::Mutability::Immutable) =>
+                    ty::BindByReference(hir::Mutability::Not) =>
                         (Mutability::Not, BindingMode::ByRef(
                             BorrowKind::Shared)),
                 };
 
                 // A ref x pattern is the same node used for x, and as such it has
                 // x's type, which is &T, where we want T (the type being matched).
+                let var_ty = ty;
                 if let ty::BindByReference(_) = bm {
                     if let ty::Ref(_, rty, _) = ty.kind {
                         ty = rty;
                     } else {
                         bug!("`ref {}` has wrong type {}", ident, ty);
                     }
-                }
+                };
 
                 PatKind::Binding {
                     mutability,
@@ -630,28 +595,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 }
             }
 
-            hir::PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => {
+            hir::PatKind::TupleStruct(ref qpath, ref pats, ddpos) => {
                 let res = self.tables.qpath_res(qpath, pat.hir_id);
                 let adt_def = match ty.kind {
                     ty::Adt(adt_def, _) => adt_def,
-                    ty::Error => { // Avoid ICE (#50585)
-                        return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
-                    }
-                    _ => span_bug!(pat.span,
-                                   "tuple struct pattern not applied to an ADT {:?}",
-                                   ty),
+                    _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty),
                 };
                 let variant_def = adt_def.variant_of_res(res);
-
-                let subpatterns =
-                        subpatterns.iter()
-                                   .enumerate_and_adjust(variant_def.fields.len(), ddpos)
-                                   .map(|(i, field)| FieldPat {
-                                       field: Field::new(i),
-                                       pattern: self.lower_pattern(field),
-                                   })
-                    .collect();
-
+                let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
                 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
             }
 
@@ -671,11 +622,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
             }
 
-            hir::PatKind::Or(ref pats) => {
-                PatKind::Or {
-                    pats: pats.iter().map(|p| self.lower_pattern(p)).collect(),
-                }
-            }
+            hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) },
         };
 
         Pat {
@@ -685,80 +632,50 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         }
     }
 
+    fn lower_tuple_subpats(
+        &mut self,
+        pats: &'tcx [P<hir::Pat>],
+        expected_len: usize,
+        gap_pos: Option<usize>,
+    ) -> Vec<FieldPat<'tcx>> {
+        pats.iter()
+            .enumerate_and_adjust(expected_len, gap_pos)
+            .map(|(i, subpattern)| FieldPat {
+                field: Field::new(i),
+                pattern: self.lower_pattern(subpattern)
+            })
+            .collect()
+    }
+
     fn lower_patterns(&mut self, pats: &'tcx [P<hir::Pat>]) -> Vec<Pat<'tcx>> {
         pats.iter().map(|p| self.lower_pattern(p)).collect()
     }
 
-    fn lower_opt_pattern(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pat<'tcx>>
-    {
+    fn lower_opt_pattern(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pat<'tcx>> {
         pat.as_ref().map(|p| self.lower_pattern(p))
     }
 
-    fn flatten_nested_slice_patterns(
-        &mut self,
-        prefix: Vec<Pat<'tcx>>,
-        slice: Option<Pat<'tcx>>,
-        suffix: Vec<Pat<'tcx>>)
-        -> (Vec<Pat<'tcx>>, Option<Pat<'tcx>>, Vec<Pat<'tcx>>)
-    {
-        let orig_slice = match slice {
-            Some(orig_slice) => orig_slice,
-            None => return (prefix, slice, suffix)
-        };
-        let orig_prefix = prefix;
-        let orig_suffix = suffix;
-
-        // dance because of intentional borrow-checker stupidity.
-        let kind = *orig_slice.kind;
-        match kind {
-            PatKind::Slice { prefix, slice, mut suffix } |
-            PatKind::Array { prefix, slice, mut suffix } => {
-                let mut orig_prefix = orig_prefix;
-
-                orig_prefix.extend(prefix);
-                suffix.extend(orig_suffix);
-
-                (orig_prefix, slice, suffix)
-            }
-            _ => {
-                (orig_prefix, Some(Pat {
-                    kind: box kind, ..orig_slice
-                }), orig_suffix)
-            }
-        }
-    }
-
     fn slice_or_array_pattern(
         &mut self,
         span: Span,
         ty: Ty<'tcx>,
         prefix: &'tcx [P<hir::Pat>],
         slice: &'tcx Option<P<hir::Pat>>,
-        suffix: &'tcx [P<hir::Pat>])
-        -> PatKind<'tcx>
-    {
+        suffix: &'tcx [P<hir::Pat>],
+    ) -> PatKind<'tcx> {
         let prefix = self.lower_patterns(prefix);
         let slice = self.lower_opt_pattern(slice);
         let suffix = self.lower_patterns(suffix);
-        let (prefix, slice, suffix) =
-            self.flatten_nested_slice_patterns(prefix, slice, suffix);
-
         match ty.kind {
-            ty::Slice(..) => {
-                // matching a slice or fixed-length array
-                PatKind::Slice { prefix: prefix, slice: slice, suffix: suffix }
-            }
-
+            // Matching a slice, `[T]`.
+            ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
+            // Fixed-length array, `[T; len]`.
             ty::Array(_, len) => {
-                // fixed-length array
                 let len = len.eval_usize(self.tcx, self.param_env);
                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
-                PatKind::Array { prefix: prefix, slice: slice, suffix: suffix }
-            }
-
-            _ => {
-                span_bug!(span, "bad slice pattern type {:?}", ty);
+                PatKind::Array { prefix, slice, suffix }
             }
+            _ => span_bug!(span, "bad slice pattern type {:?}", ty),
         }
     }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index f9cb40ffe94..e4698303afe 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -115,11 +115,11 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
         // For statics, allocation mutability is the combination of the place mutability and
         // the type mutability.
         // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
-        if mutability == Mutability::Immutable && frozen {
-            alloc.mutability = Mutability::Immutable;
+        if mutability == Mutability::Not && frozen {
+            alloc.mutability = Mutability::Not;
         } else {
             // Just making sure we are not "upgrading" an immutable allocation to mutable.
-            assert_eq!(alloc.mutability, Mutability::Mutable);
+            assert_eq!(alloc.mutability, Mutability::Mut);
         }
     } else {
         // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`.
@@ -127,10 +127,10 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
         // initial value was computed.
         // Constants are never mutable.
         assert_eq!(
-            mutability, Mutability::Immutable,
+            mutability, Mutability::Not,
             "Something went very wrong: mutability requested for a constant"
         );
-        alloc.mutability = Mutability::Immutable;
+        alloc.mutability = Mutability::Not;
     };
     // link the alloc id to the actual allocation
     let alloc = tcx.intern_const_alloc(alloc);
@@ -179,7 +179,7 @@ for
                 // We are crossing over an `UnsafeCell`, we can mutate again. This means that
                 // References we encounter inside here are interned as pointing to mutable
                 // allocations.
-                let old = std::mem::replace(&mut self.mutability, Mutability::Mutable);
+                let old = std::mem::replace(&mut self.mutability, Mutability::Mut);
                 assert_ne!(
                     self.mode, InternMode::Const,
                     "UnsafeCells are not allowed behind references in constants. This should have \
@@ -210,7 +210,7 @@ for
                 if let Ok(vtable) = mplace.meta.unwrap().to_ptr() {
                     // explitly choose `Immutable` here, since vtables are immutable, even
                     // if the reference of the fat pointer is mutable
-                    self.intern_shallow(vtable.alloc_id, Mutability::Immutable, None)?;
+                    self.intern_shallow(vtable.alloc_id, Mutability::Not, None)?;
                 }
             }
             // Check if we have encountered this pointer+layout combination before.
@@ -223,16 +223,16 @@ for
                 // const qualification enforces it. We can lift it in the future.
                 match (self.mode, mutability) {
                     // immutable references are fine everywhere
-                    (_, hir::Mutability::Immutable) => {},
+                    (_, hir::Mutability::Not) => {},
                     // all is "good and well" in the unsoundness of `static mut`
 
                     // mutable references are ok in `static`. Either they are treated as immutable
                     // because they are behind an immutable one, or they are behind an `UnsafeCell`
                     // and thus ok.
-                    (InternMode::Static, hir::Mutability::Mutable) => {},
+                    (InternMode::Static, hir::Mutability::Mut) => {},
                     // we statically prevent `&mut T` via `const_qualif` and double check this here
-                    (InternMode::ConstBase, hir::Mutability::Mutable) |
-                    (InternMode::Const, hir::Mutability::Mutable) => {
+                    (InternMode::ConstBase, hir::Mutability::Mut) |
+                    (InternMode::Const, hir::Mutability::Mut) => {
                         match referenced_ty.kind {
                             ty::Array(_, n)
                                 if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
@@ -243,16 +243,14 @@ for
                     },
                 }
                 // Compute the mutability with which we'll start visiting the allocation. This is
-                // what gets changed when we encounter an `UnsafeCell`
-                let mutability = match (self.mutability, mutability) {
-                    // The only way a mutable reference actually works as a mutable reference is
-                    // by being in a `static mut` directly or behind another mutable reference.
-                    // If there's an immutable reference or we are inside a static, then our
-                    // mutable reference is equivalent to an immutable one. As an example:
-                    // `&&mut Foo` is semantically equivalent to `&&Foo`
-                    (Mutability::Mutable, hir::Mutability::Mutable) => Mutability::Mutable,
-                    _ => Mutability::Immutable,
-                };
+                // what gets changed when we encounter an `UnsafeCell`.
+                //
+                // The only way a mutable reference actually works as a mutable reference is
+                // by being in a `static mut` directly or behind another mutable reference.
+                // If there's an immutable reference or we are inside a static, then our
+                // mutable reference is equivalent to an immutable one. As an example:
+                // `&&mut Foo` is semantically equivalent to `&&Foo`
+                let mutability = self.mutability.and(mutability);
                 // Recursing behind references changes the intern mode for constants in order to
                 // cause assertions to trigger if we encounter any `UnsafeCell`s.
                 let mode = match self.mode {
@@ -282,11 +280,10 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
 ) -> InterpResult<'tcx> {
     let tcx = ecx.tcx;
     let (base_mutability, base_intern_mode) = match place_mut {
-        Some(hir::Mutability::Immutable) => (Mutability::Immutable, InternMode::Static),
         // `static mut` doesn't care about interior mutability, it's mutable anyway
-        Some(hir::Mutability::Mutable) => (Mutability::Mutable, InternMode::Static),
+        Some(mutbl) => (mutbl, InternMode::Static),
         // consts, promoteds. FIXME: what about array lengths, array initializers?
-        None => (Mutability::Immutable, InternMode::ConstBase),
+        None => (Mutability::Not, InternMode::ConstBase),
     };
 
     // Type based interning.
@@ -346,7 +343,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
                 // We cannot have mutable memory inside a constant.
                 // FIXME: ideally we would assert that they already are immutable, to double-
                 // check our static checks.
-                alloc.mutability = Mutability::Immutable;
+                alloc.mutability = Mutability::Not;
             }
             let alloc = tcx.intern_const_alloc(alloc);
             tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 8f177ad1225..ba571043d38 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -539,7 +539,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             // Need to make a copy, even if `get_static_alloc` is able
             // to give us a cheap reference.
             let alloc = Self::get_static_alloc(memory_extra, tcx, id)?;
-            if alloc.mutability == Mutability::Immutable {
+            if alloc.mutability == Mutability::Not {
                 throw_unsup!(ModifiedConstantMemory)
             }
             match M::STATIC_KIND {
@@ -553,7 +553,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             Err(e) => Err(e),
             Ok(a) => {
                 let a = &mut a.1;
-                if a.mutability == Mutability::Immutable {
+                if a.mutability == Mutability::Not {
                     throw_unsup!(ModifiedConstantMemory)
                 }
                 Ok(a)
@@ -643,7 +643,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
-        self.get_raw_mut(id)?.mutability = Mutability::Immutable;
+        self.get_raw_mut(id)?.mutability = Mutability::Not;
         Ok(())
     }
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 48e7193ec39..93ab7b9aab7 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -444,13 +444,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Field(field, _) => self.operand_field(base, field.index() as u64)?,
             Downcast(_, variant) => self.operand_downcast(base, variant)?,
             Deref => self.deref_operand(base)?.into(),
-            Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() {
+            ConstantIndex { .. } | Index(_) if base.layout.is_zst() => {
                 OpTy {
                     op: Operand::Immediate(Scalar::zst().into()),
                     // the actual index doesn't matter, so we just pick a convenient one like 0
                     layout: base.layout.field(self, 0)?,
                 }
-            } else {
+            }
+            Subslice { from, to, from_end } if base.layout.is_zst() => {
+                let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind {
+                    elem_ty
+                } else {
+                    bug!("slices shouldn't be zero-sized");
+                };
+                assert!(!from_end, "arrays shouldn't be subsliced from the end");
+
+                OpTy {
+                    op: Operand::Immediate(Scalar::zst().into()),
+                    layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?,
+                }
+            }
+            Subslice { .. } | ConstantIndex { .. }  | Index(_) => {
                 // The rest should only occur as mplace, we do not use Immediates for types
                 // allowing such operations.  This matches place_projection forcing an allocation.
                 let mplace = base.assert_mem_place();
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 70ea3745b4d..a1e6eb69b9d 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -455,7 +455,10 @@ where
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let actual_to = if from_end {
-            assert!(from <= len - to);
+            if from + to > len {
+                // This can only be reached in ConstProp and non-rustc-MIR.
+                throw_ub!(BoundsCheckFailed { len: len as u64, index: from as u64 + to as u64 });
+            }
             len - to
         } else {
             to
@@ -523,7 +526,11 @@ where
                 from_end,
             } => {
                 let n = base.len(self)?;
-                assert!(n >= min_length as u64);
+                if n < min_length as u64 {
+                    // This can only be reached in ConstProp and non-rustc-MIR.
+                    throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 });
+                }
+                assert!(offset < min_length);
 
                 let index = if from_end {
                     n - u64::from(offset)
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 33ed69af6ba..33cdf1b27f8 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 )?;
             }
 
-            Ref(_, _, ref place) => {
+            AddressOf(_, ref place) | Ref(_, _, ref place) => {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(src)?;
                 if place.layout.size.bytes() > 0 {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index ab95c795c43..ac627d32392 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -977,7 +977,7 @@ struct RootCollector<'a, 'tcx> {
 }
 
 impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
-    fn visit_item(&mut self, item: &'v hir::Item) {
+    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
         match item.kind {
             hir::ItemKind::ExternCrate(..) |
             hir::ItemKind::Use(..) |
@@ -1042,12 +1042,12 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
         }
     }
 
-    fn visit_trait_item(&mut self, _: &'v hir::TraitItem) {
+    fn visit_trait_item(&mut self, _: &'v hir::TraitItem<'v>) {
         // Even if there's a default body with no explicit generics,
         // it's still generic over some `Self: Trait`, so not a root.
     }
 
-    fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
         match ii.kind {
             hir::ImplItemKind::Method(hir::FnSig { .. }, _) => {
                 let def_id = self.tcx.hir().local_def_id(ii.hir_id);
@@ -1128,7 +1128,7 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 
 fn create_mono_items_for_default_impls<'tcx>(
     tcx: TyCtxt<'tcx>,
-    item: &'tcx hir::Item,
+    item: &'tcx hir::Item<'tcx>,
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
     match item.kind {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 47b08048f83..a2974896218 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -471,7 +471,7 @@ impl CloneShimBuilder<'tcx> {
             Mutability::Not,
             tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
                 ty,
-                mutbl: hir::Mutability::Immutable,
+                mutbl: hir::Mutability::Not,
             })
         );
 
@@ -757,7 +757,7 @@ fn build_call_shim<'tcx>(
                 Mutability::Not,
                 tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
                     ty: sig.inputs()[0],
-                    mutbl: hir::Mutability::Mutable
+                    mutbl: hir::Mutability::Mut
                 }),
                 span
             ));
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index dc21c674eea..0e4fe3f7f40 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -136,21 +136,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
             // iterate backwards using indices.
             for i in (0..block_data.statements.len()).rev() {
                 let (retag_kind, place) = match block_data.statements[i].kind {
-                    // If we are casting *from* a reference, we may have to retag-as-raw.
-                    StatementKind::Assign(box(ref place, Rvalue::Cast(
-                        CastKind::Misc,
-                        ref src,
-                        dest_ty,
-                    ))) => {
-                        let src_ty = src.ty(&*local_decls, tcx);
-                        if src_ty.is_region_ptr() {
-                            // The only `Misc` casts on references are those creating raw pointers.
-                            assert!(dest_ty.is_unsafe_ptr());
-                            (RetagKind::Raw, place.clone())
-                        } else {
-                            // Some other cast, no retag
-                            continue
-                        }
+                    // Retag-as-raw after escaping to a raw pointer.
+                    StatementKind::Assign(box (ref place, Rvalue::AddressOf(..))) => {
+                        (RetagKind::Raw, place.clone())
                     }
                     // Assignments of reference or ptr type are the ones where we may have
                     // to update tags.  This includes `x = &[mut] ...` and hence
diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs
index 89672e81c7c..e8365a9ee1c 100644
--- a/src/librustc_mir/transform/check_consts/mod.rs
+++ b/src/librustc_mir/transform/check_consts/mod.rs
@@ -87,8 +87,8 @@ impl ConstKind {
 
             HirKind::Const => ConstKind::Const,
 
-            HirKind::Static(hir::Mutability::Immutable) => ConstKind::Static,
-            HirKind::Static(hir::Mutability::Mutable) => ConstKind::StaticMut,
+            HirKind::Static(hir::Mutability::Not) => ConstKind::Static,
+            HirKind::Static(hir::Mutability::Mut) => ConstKind::StaticMut,
         };
 
         Some(mode)
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index 3df60993d9a..e5f3003cd71 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -225,6 +225,23 @@ impl NonConstOp for MutBorrow {
 }
 
 #[derive(Debug)]
+pub struct MutAddressOf;
+impl NonConstOp for MutAddressOf {
+    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+        Some(tcx.features().const_mut_refs)
+    }
+
+    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
+        feature_err(
+            &item.tcx.sess.parse_sess,
+            sym::const_mut_refs,
+            span,
+            &format!("`&raw mut` is not allowed in {}s", item.const_kind())
+        ).emit();
+    }
+}
+
+#[derive(Debug)]
 pub struct MutDeref;
 impl NonConstOp for MutDeref {
     fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 223a5f8d605..28243bd71a2 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -151,17 +151,15 @@ pub trait Qualif {
                 Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs)
             }
 
-            Rvalue::Ref(_, _, ref place) => {
+            Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
                 // Special-case reborrows to be more like a copy of the reference.
-                if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
-                    if ProjectionElem::Deref == elem {
-                        let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
-                        if let ty::Ref(..) = base_ty.kind {
-                            return Self::in_place(cx, per_local, PlaceRef {
-                                base: &place.base,
-                                projection: proj_base,
-                            });
-                        }
+                if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
+                    let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
+                    if let ty::Ref(..) = base_ty.kind {
+                        return Self::in_place(cx, per_local, PlaceRef {
+                            base: &place.base,
+                            projection: proj_base,
+                        });
                     }
                 }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 6261315c711..0904264586c 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -276,6 +276,27 @@ impl Validator<'a, 'mir, 'tcx> {
             self.check_op_spanned(ops::StaticAccess, span)
         }
     }
+
+    fn check_immutable_borrow_like(
+        &mut self,
+        location: Location,
+        place: &Place<'tcx>,
+    ) {
+        // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually
+        // seek the cursors beforehand.
+        self.qualifs.has_mut_interior.cursor.seek_before(location);
+        self.qualifs.indirectly_mutable.seek(location);
+
+        let borrowed_place_has_mut_interior = HasMutInterior::in_place(
+            &self.item,
+            &|local| self.qualifs.has_mut_interior_eager_seek(local),
+            place.as_ref(),
+        );
+
+        if borrowed_place_has_mut_interior {
+            self.check_op(ops::CellBorrow);
+        }
+    }
 }
 
 impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
@@ -302,26 +323,44 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
         trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
 
         // Special-case reborrows to be more like a copy of a reference.
-        if let Rvalue::Ref(_, kind, ref place) = *rvalue {
-            if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
-                let ctx = match kind {
-                    BorrowKind::Shared => PlaceContext::NonMutatingUse(
-                        NonMutatingUseContext::SharedBorrow,
-                    ),
-                    BorrowKind::Shallow => PlaceContext::NonMutatingUse(
-                        NonMutatingUseContext::ShallowBorrow,
-                    ),
-                    BorrowKind::Unique => PlaceContext::NonMutatingUse(
-                        NonMutatingUseContext::UniqueBorrow,
-                    ),
-                    BorrowKind::Mut { .. } => PlaceContext::MutatingUse(
-                        MutatingUseContext::Borrow,
-                    ),
-                };
-                self.visit_place_base(&place.base, ctx, location);
-                self.visit_projection(&place.base, reborrowed_proj, ctx, location);
-                return;
+        match *rvalue {
+            Rvalue::Ref(_, kind, ref place) => {
+                if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
+                    let ctx = match kind {
+                        BorrowKind::Shared => PlaceContext::NonMutatingUse(
+                            NonMutatingUseContext::SharedBorrow,
+                        ),
+                        BorrowKind::Shallow => PlaceContext::NonMutatingUse(
+                            NonMutatingUseContext::ShallowBorrow,
+                        ),
+                        BorrowKind::Unique => PlaceContext::NonMutatingUse(
+                            NonMutatingUseContext::UniqueBorrow,
+                        ),
+                        BorrowKind::Mut { .. } => PlaceContext::MutatingUse(
+                            MutatingUseContext::Borrow,
+                        ),
+                    };
+                    self.visit_place_base(&place.base, ctx, location);
+                    self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+                    return;
+                }
             }
+            Rvalue::AddressOf(mutbl, ref place) => {
+                if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) {
+                    let ctx = match mutbl {
+                        Mutability::Not => PlaceContext::NonMutatingUse(
+                            NonMutatingUseContext::AddressOf,
+                        ),
+                        Mutability::Mut => PlaceContext::MutatingUse(
+                            MutatingUseContext::AddressOf,
+                        ),
+                    };
+                    self.visit_place_base(&place.base, ctx, location);
+                    self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+                    return;
+                }
+            }
+            _ => {}
         }
 
         self.super_rvalue(rvalue, location);
@@ -367,34 +406,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
                 }
             }
 
+            Rvalue::AddressOf(Mutability::Mut, _) => {
+                self.check_op(ops::MutAddressOf)
+            }
+
             // At the moment, `PlaceBase::Static` is only used for promoted MIR.
             | Rvalue::Ref(_, BorrowKind::Shared, ref place)
             | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
+            | Rvalue::AddressOf(Mutability::Not, ref place)
             if matches!(place.base, PlaceBase::Static(_))
             => bug!("Saw a promoted during const-checking, which must run before promotion"),
 
-            | Rvalue::Ref(_, kind @ BorrowKind::Shared, ref place)
-            | Rvalue::Ref(_, kind @ BorrowKind::Shallow, ref place)
-            => {
-                // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually
-                // seek the cursors beforehand.
-                self.qualifs.has_mut_interior.cursor.seek_before(location);
-                self.qualifs.indirectly_mutable.seek(location);
-
-                let borrowed_place_has_mut_interior = HasMutInterior::in_place(
-                    &self.item,
-                    &|local| self.qualifs.has_mut_interior_eager_seek(local),
-                    place.as_ref(),
-                );
-
-                if borrowed_place_has_mut_interior {
-                    if let BorrowKind::Mut{ .. } = kind {
-                        self.check_op(ops::MutBorrow);
-                    } else {
-                        self.check_op(ops::CellBorrow);
-                    }
-                }
-            }
+            | Rvalue::Ref(_, BorrowKind::Shared, ref place)
+            | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => {
+                self.check_immutable_borrow_like(location, place)
+            },
+
+            Rvalue::AddressOf(Mutability::Not, ref place) => {
+                self.check_immutable_borrow_like(location, place)
+            },
 
             Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
                 let operand_ty = operand.ty(*self.body, self.tcx);
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index c4d89b1494d..1a24a8b371d 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -238,7 +238,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
     ) -> InterpResult<'tcx> {
         // if the static allocation is mutable or if it has relocations (it may be legal to mutate
         // the memory behind that in the future), then we can't const prop it
-        if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 {
+        if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 {
             throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp"));
         }
 
@@ -262,7 +262,7 @@ struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
     tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
-    can_const_prop: IndexVec<Local, bool>,
+    can_const_prop: IndexVec<Local, ConstPropMode>,
     param_env: ParamEnv<'tcx>,
     // FIXME(eddyb) avoid cloning these two fields more than once,
     // by accessing them through `ecx` instead.
@@ -708,17 +708,28 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     }
 }
 
+/// The mode that `ConstProp` is allowed to run in for a given `Local`.
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum ConstPropMode {
+    /// The `Local` can be propagated into and reads of this `Local` can also be propagated.
+    FullConstProp,
+    /// The `Local` can be propagated into but reads cannot be propagated.
+    OnlyPropagateInto,
+    /// No propagation is allowed at all.
+    NoPropagation,
+}
+
 struct CanConstProp {
-    can_const_prop: IndexVec<Local, bool>,
+    can_const_prop: IndexVec<Local, ConstPropMode>,
     // false at the beginning, once set, there are not allowed to be any more assignments
     found_assignment: IndexVec<Local, bool>,
 }
 
 impl CanConstProp {
     /// returns true if `local` can be propagated
-    fn check(body: ReadOnlyBodyAndCache<'_, '_>) -> IndexVec<Local, bool> {
+    fn check(body: ReadOnlyBodyAndCache<'_, '_>) -> IndexVec<Local, ConstPropMode> {
         let mut cpv = CanConstProp {
-            can_const_prop: IndexVec::from_elem(true, &body.local_decls),
+            can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp, &body.local_decls),
             found_assignment: IndexVec::from_elem(false, &body.local_decls),
         };
         for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
@@ -728,10 +739,10 @@ impl CanConstProp {
             // FIXME(oli-obk): lint variables until they are used in a condition
             // FIXME(oli-obk): lint if return value is constant
             let local_kind = body.local_kind(local);
-            *val = local_kind == LocalKind::Temp || local_kind == LocalKind::ReturnPointer;
 
-            if !*val {
-                trace!("local {:?} can't be propagated because it's not a temporary", local);
+            if local_kind == LocalKind::Arg || local_kind == LocalKind::Var {
+                *val = ConstPropMode::OnlyPropagateInto;
+                trace!("local {:?} can't be const propagated because it's not a temporary", local);
             }
         }
         cpv.visit_body(body);
@@ -753,7 +764,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
             // only occur in independent execution paths
             MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] {
                 trace!("local {:?} can't be propagated because of multiple assignments", local);
-                self.can_const_prop[local] = false;
+                self.can_const_prop[local] = ConstPropMode::NoPropagation;
             } else {
                 self.found_assignment[local] = true
             },
@@ -766,7 +777,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
             NonUse(_) => {},
             _ => {
                 trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
-                self.can_const_prop[local] = false;
+                self.can_const_prop[local] = ConstPropMode::NoPropagation;
             },
         }
     }
@@ -800,10 +811,10 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
                 if let Some(local) = place.as_local() {
                     let source = statement.source_info;
+                    let can_const_prop = self.can_const_prop[local];
                     if let Some(()) = self.const_prop(rval, place_layout, source, place) {
-                        if self.can_const_prop[local] {
-                            trace!("propagated into {:?}", local);
-
+                        if can_const_prop == ConstPropMode::FullConstProp ||
+                           can_const_prop == ConstPropMode::OnlyPropagateInto {
                             if let Some(value) = self.get_const(local) {
                                 if self.should_const_prop(value) {
                                     trace!("replacing {:?} with {:?}", rval, value);
@@ -812,13 +823,18 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                                         value,
                                         statement.source_info,
                                     );
+
+                                    if can_const_prop == ConstPropMode::FullConstProp {
+                                        trace!("propagated into {:?}", local);
+                                    }
                                 }
                             }
-                        } else {
-                            trace!("can't propagate into {:?}", local);
-                            if local != RETURN_PLACE {
-                                self.remove_const(local);
-                            }
+                        }
+                    }
+                    if self.can_const_prop[local] != ConstPropMode::FullConstProp {
+                        trace!("can't propagate into {:?}", local);
+                        if local != RETURN_PLACE {
+                            self.remove_const(local);
                         }
                     }
                 }
@@ -826,7 +842,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
         } else {
             match statement.kind {
                 StatementKind::StorageLive(local) |
-                StatementKind::StorageDead(local) if self.can_const_prop[local] => {
+                StatementKind::StorageDead(local) => {
                     let frame = self.ecx.frame_mut();
                     frame.locals[local].value =
                         if let StatementKind::StorageLive(_) = statement.kind {
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 3d15d047172..b314ff83abe 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -391,7 +391,7 @@ fn make_generator_state_argument_indirect<'tcx>(
 
     let ref_gen_ty = tcx.mk_ref(region, ty::TypeAndMut {
         ty: gen_ty,
-        mutbl: hir::Mutability::Mutable
+        mutbl: hir::Mutability::Mut
     });
 
     // Replace the by value generator argument
@@ -969,7 +969,7 @@ fn create_generator_drop_shim<'tcx>(
         mutability: Mutability::Mut,
         ty: tcx.mk_ptr(ty::TypeAndMut {
             ty: gen_ty,
-            mutbl: hir::Mutability::Mutable,
+            mutbl: hir::Mutability::Mut,
         }),
         user_ty: UserTypeProjections::none(),
         source_info,
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 9763913082d..dca14227946 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -663,9 +663,9 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
 
     fn make_integrate_local(&self, local: &Local) -> Local {
         if *local == RETURN_PLACE {
-            match self.destination.as_local() {
-                Some(l) => return l,
-                ref place => bug!("Return place is {:?}, not local", place),
+            match self.destination.base {
+                PlaceBase::Local(l) => return l,
+                PlaceBase::Static(ref s) => bug!("Return place is {:?}, not local", s),
             }
         }
 
@@ -695,14 +695,24 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
     fn visit_place(
         &mut self,
         place: &mut Place<'tcx>,
-        context: PlaceContext,
-        location: Location,
+        _context: PlaceContext,
+        _location: Location,
     ) {
-        if let Some(RETURN_PLACE) = place.as_local() {
-            // Return pointer; update the place itself
-            *place = self.destination.clone();
-        } else {
-            self.super_place(place, context, location);
+        match &mut place.base {
+            PlaceBase::Static(_) => {},
+            PlaceBase::Local(l) => {
+                // If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
+                let dest_proj_len = self.destination.projection.len();
+                if *l == RETURN_PLACE && dest_proj_len > 0 {
+                    let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
+                    projs.extend(self.destination.projection);
+                    projs.extend(place.projection);
+
+                    place.projection = self.tcx.intern_place_elems(&*projs);
+                }
+
+                *l = self.make_integrate_local(l);
+            }
         }
     }
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 2e1a08a0224..350df575047 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -74,7 +74,7 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
     }
     impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
         fn visit_variant_data(&mut self,
-                              v: &'tcx hir::VariantData,
+                              v: &'tcx hir::VariantData<'tcx>,
                               _: ast::Name,
                               _: &'tcx hir::Generics,
                               _: hir::HirId,
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 4c723199102..4e5d8ae08fe 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -196,7 +196,12 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
         } else if let TempState::Defined { ref mut uses, .. } = *temp {
             // We always allow borrows, even mutable ones, as we need
             // to promote mutable borrows of some ZSTs e.g., `&mut []`.
-            let allowed_use = context.is_borrow() || context.is_nonmutating_use();
+            let allowed_use = match context {
+                PlaceContext::MutatingUse(MutatingUseContext::Borrow)
+                | PlaceContext::NonMutatingUse(_) => true,
+                PlaceContext::MutatingUse(_)
+                | PlaceContext::NonUse(_) => false,
+            };
             debug!("visit_local: allowed_use={:?}", allowed_use);
             if allowed_use {
                 *uses += 1;
@@ -618,6 +623,21 @@ impl<'tcx> Validator<'_, 'tcx> {
                 self.validate_operand(rhs)
             }
 
+            Rvalue::AddressOf(_, place) => {
+                // Raw reborrows can come from reference to pointer coercions,
+                // so are allowed.
+                if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
+                    let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
+                    if let ty::Ref(..) = base_ty.kind {
+                        return self.validate_place(PlaceRef {
+                            base: &place.base,
+                            projection: proj_base,
+                        });
+                    }
+                }
+                Err(Unpromotable)
+            }
+
             Rvalue::Ref(_, kind, place) => {
                 if let BorrowKind::Mut { .. } = kind {
                     let ty = place.ty(*self.body, self.tcx).ty;
@@ -950,7 +970,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 Candidate::Ref(loc) => {
                     let ref mut statement = blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
-                        StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => {
+                        StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => {
                             // Use the underlying local for this (necessarily interior) borrow.
                             let ty = place.base.ty(local_decls).ty;
                             let span = statement.source_info.span;
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index e2530795749..0d2e0bb8281 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -79,7 +79,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
 fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
     for ty in ty.walk() {
         match ty.kind {
-            ty::Ref(_, _, hir::Mutability::Mutable) => {
+            ty::Ref(_, _, hir::Mutability::Mut) => {
                 if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
                     return Err((
                         span,
@@ -135,7 +135,10 @@ fn check_rvalue(
         Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
             check_operand(tcx, operand, span, def_id, body)
         }
-        Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
+        Rvalue::Len(place)
+        | Rvalue::Discriminant(place)
+        | Rvalue::Ref(_, _, place)
+        | Rvalue::AddressOf(_, place) => {
             check_place(tcx, place, span, def_id, body)
         }
         Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
@@ -147,9 +150,6 @@ fn check_rvalue(
                     span,
                     "casting pointers to ints is unstable in const fn".into(),
                 )),
-                (CastTy::RPtr(_), CastTy::Float) => bug!(),
-                (CastTy::RPtr(_), CastTy::Int(_)) => bug!(),
-                (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(),
                 _ => check_operand(tcx, operand, span, def_id, body),
             }
         }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 67e5bfafafd..6ff84996bd3 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -521,7 +521,7 @@ where
 
         let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
             ty,
-            mutbl: hir::Mutability::Mutable
+            mutbl: hir::Mutability::Mut
         });
         let ref_place = self.new_temp(ref_ty);
         let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
@@ -557,10 +557,10 @@ where
     ///    if can_go then succ else drop-block
     /// drop-block:
     ///    if ptr_based {
-    ///        ptr = &mut *cur
+    ///        ptr = cur
     ///        cur = cur.offset(1)
     ///    } else {
-    ///        ptr = &mut P[cur]
+    ///        ptr = &raw mut P[cur]
     ///        cur = cur + 1
     ///    }
     ///    drop(ptr)
@@ -574,34 +574,28 @@ where
         unwind: Unwind,
         ptr_based: bool,
     ) -> BasicBlock {
-        let copy = |place: &Place<'tcx>| Operand::Copy(place.clone());
-        let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
+        let copy = |place: Place<'tcx>| Operand::Copy(place);
+        let move_ = |place: Place<'tcx>| Operand::Move(place);
         let tcx = self.tcx();
 
-        let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
+        let ptr_ty = tcx.mk_ptr(ty::TypeAndMut {
             ty: ety,
-            mutbl: hir::Mutability::Mutable
+            mutbl: hir::Mutability::Mut
         });
-        let ptr = &Place::from(self.new_temp(ref_ty));
-        let can_go = &Place::from(self.new_temp(tcx.types.bool));
+        let ptr = &Place::from(self.new_temp(ptr_ty));
+        let can_go = Place::from(self.new_temp(tcx.types.bool));
 
         let one = self.constant_usize(1);
         let (ptr_next, cur_next) = if ptr_based {
-            (Rvalue::Ref(
-                tcx.lifetimes.re_erased,
-                BorrowKind::Mut { allow_two_phase_borrow: false },
-                Place {
-                    base: PlaceBase::Local(cur),
-                    projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]),
-                }
-             ),
-             Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one))
+            (
+                Rvalue::Use(copy(cur.into())),
+                Rvalue::BinaryOp(BinOp::Offset, move_(cur.into()), one),
+            )
         } else {
-            (Rvalue::Ref(
-                 tcx.lifetimes.re_erased,
-                 BorrowKind::Mut { allow_two_phase_borrow: false },
-                 tcx.mk_place_index(self.place.clone(), cur)),
-             Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one))
+            (
+                Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place.clone(), cur)),
+                Rvalue::BinaryOp(BinOp::Add, move_(cur.into()), one),
+            )
         };
 
         let drop_block = BasicBlockData {
@@ -620,9 +614,9 @@ where
 
         let loop_block = BasicBlockData {
             statements: vec![
-                self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
-                                                     copy(&Place::from(cur)),
-                                                     copy(length_or_end)))
+                self.assign(&can_go, Rvalue::BinaryOp(BinOp::Eq,
+                                                     copy(Place::from(cur)),
+                                                     copy(length_or_end.clone())))
             ],
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
@@ -725,8 +719,6 @@ where
 
         let cur = self.new_temp(iter_ty);
         let length_or_end = if ptr_based {
-            // FIXME check if we want to make it return a `Place` directly
-            // if all use sites want a `Place::Base` anyway.
             Place::from(self.new_temp(iter_ty))
         } else {
             length.clone()
@@ -753,23 +745,16 @@ where
         let drop_block_stmts = if ptr_based {
             let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
             let tmp = Place::from(self.new_temp(tmp_ty));
-            // tmp = &mut P;
+            // tmp = &raw mut P;
             // cur = tmp as *mut T;
             // end = Offset(cur, len);
             vec![
-                self.assign(&tmp, Rvalue::Ref(
-                    tcx.lifetimes.re_erased,
-                    BorrowKind::Mut { allow_two_phase_borrow: false },
-                    self.place.clone()
-                )),
-                self.assign(
-                    &cur,
-                    Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty),
-                ),
+                self.assign(&tmp, Rvalue::AddressOf(Mutability::Mut, self.place.clone())),
+                self.assign(&cur, Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty)),
                 self.assign(
                     &length_or_end,
-                    Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)
-                )),
+                    Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)),
+                ),
             ]
         } else {
             // cur = 0 (length already pushed)
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 68c2e16399a..01eebeb8c55 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -167,6 +167,8 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
 
+        PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
+        PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs
index d6c8e54c18d..4c8c9d15d56 100644
--- a/src/librustc_msan/lib.rs
+++ b/src/librustc_msan/lib.rs
@@ -5,4 +5,4 @@
 #![no_std]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
-            issue = "0")]
+            issue = "none")]
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index 1e9203f377f..38ae7050abe 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -344,12 +344,12 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
         noop_flat_map_item(configure!(self, item), self)
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
-        noop_flat_map_impl_item(configure!(self, item), self)
+    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+        noop_flat_map_assoc_item(configure!(self, item), self)
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
-        noop_flat_map_trait_item(configure!(self, item), self)
+    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+        noop_flat_map_assoc_item(configure!(self, item), self)
     }
 
     fn visit_mac(&mut self, _mac: &mut ast::Mac) {
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index faff386e923..3de7f888724 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -2,6 +2,7 @@
 
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
+#![feature(slice_patterns)]
 
 use syntax::ast;
 use syntax::print::pprust;
@@ -305,10 +306,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
         Nonterminal::NtItem(ref item) => {
             prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
         }
-        Nonterminal::NtTraitItem(ref item) => {
-            prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
-        }
-        Nonterminal::NtImplItem(ref item) => {
+        Nonterminal::NtTraitItem(ref item) | Nonterminal::NtImplItem(ref item) => {
             prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
         }
         Nonterminal::NtIdent(ident, is_raw) => {
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index 00fd6b8a25b..51310fb88f6 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -1,4 +1,4 @@
-use super::{SeqSep, Parser, TokenType, PathStyle};
+use super::{Parser, TokenType, PathStyle};
 use rustc_errors::PResult;
 use syntax::attr;
 use syntax::ast;
@@ -301,8 +301,10 @@ impl<'a> Parser<'a> {
     crate fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
         Ok(if self.eat(&token::Eq) {
             ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?)
-        } else if self.eat(&token::OpenDelim(token::Paren)) {
-            ast::MetaItemKind::List(self.parse_meta_seq()?)
+        } else if self.check(&token::OpenDelim(token::Paren)) {
+            // Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
+            let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
+            ast::MetaItemKind::List(list)
         } else {
             ast::MetaItemKind::Word
         })
@@ -311,16 +313,12 @@ impl<'a> Parser<'a> {
     /// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`.
     fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
         match self.parse_unsuffixed_lit() {
-            Ok(lit) => {
-                return Ok(ast::NestedMetaItem::Literal(lit))
-            }
+            Ok(lit) => return Ok(ast::NestedMetaItem::Literal(lit)),
             Err(ref mut err) => err.cancel(),
         }
 
         match self.parse_meta_item() {
-            Ok(mi) => {
-                return Ok(ast::NestedMetaItem::MetaItem(mi))
-            }
+            Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)),
             Err(ref mut err) => err.cancel(),
         }
 
@@ -328,11 +326,4 @@ impl<'a> Parser<'a> {
         let msg = format!("expected unsuffixed literal or identifier, found `{}`", found);
         Err(self.diagnostic().struct_span_err(self.token.span, &msg))
     }
-
-    /// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
-    fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
-        self.parse_seq_to_end(&token::CloseDelim(token::Paren),
-                              SeqSep::trailing_allowed(token::Comma),
-                              |p: &mut Parser<'a>| p.parse_meta_item_inner())
-    }
 }
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index ba125cacab4..353f6607c1d 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -4,14 +4,13 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{self, PResult, Applicability, DiagnosticBuilder, Handler, pluralize};
 use rustc_error_codes::*;
 use syntax::ast::{self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item};
-use syntax::ast::{ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
+use syntax::ast::{ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, AttrVec};
 use syntax::token::{self, TokenKind, token_can_begin_expr};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::ThinVec;
 use syntax::util::parser::AssocOp;
 use syntax::struct_span_err;
-use syntax_pos::symbol::{kw, sym};
+use syntax_pos::symbol::kw;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
 
 use log::{debug, trace};
@@ -23,7 +22,7 @@ const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify typ
 pub(super) fn dummy_arg(ident: Ident) -> Param {
     let pat = P(Pat {
         id: ast::DUMMY_NODE_ID,
-        kind: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
+        kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
         span: ident.span,
     });
     let ty = Ty {
@@ -32,7 +31,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
         id: ast::DUMMY_NODE_ID
     };
     Param {
-        attrs: ThinVec::default(),
+        attrs: AttrVec::default(),
         id: ast::DUMMY_NODE_ID,
         pat,
         span: ident.span,
@@ -164,7 +163,7 @@ impl RecoverQPath for Expr {
         Self {
             span: path.span,
             kind: ExprKind::Path(qself, path),
-            attrs: ThinVec::new(),
+            attrs: AttrVec::new(),
             id: ast::DUMMY_NODE_ID,
         }
     }
@@ -312,22 +311,6 @@ impl<'a> Parser<'a> {
         };
         self.last_unexpected_token_span = Some(self.token.span);
         let mut err = self.fatal(&msg_exp);
-        if self.token.is_ident_named(sym::and) {
-            err.span_suggestion_short(
-                self.token.span,
-                "use `&&` instead of `and` for the boolean operator",
-                "&&".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        }
-        if self.token.is_ident_named(sym::or) {
-            err.span_suggestion_short(
-                self.token.span,
-                "use `||` instead of `or` for the boolean operator",
-                "||".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        }
         let sp = if self.token == token::Eof {
             // This is EOF; don't want to point at the following char, but rather the last token.
             self.prev_span
@@ -567,7 +550,7 @@ impl<'a> Parser<'a> {
         );
 
         let mk_err_expr = |this: &Self, span| {
-            Ok(Some(this.mk_expr(span, ExprKind::Err, ThinVec::new())))
+            Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new())))
         };
 
         match lhs.kind {
@@ -986,21 +969,32 @@ impl<'a> Parser<'a> {
 
     /// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
     /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
-    pub(super) fn parse_incorrect_await_syntax(
+    pub(super) fn recover_incorrect_await_syntax(
         &mut self,
         lo: Span,
         await_sp: Span,
-    ) -> PResult<'a, (Span, ExprKind)> {
-        if self.token == token::Not {
+        attrs: AttrVec,
+    ) -> PResult<'a, P<Expr>> {
+        let (hi, expr, is_question) = if self.token == token::Not {
             // Handle `await!(<expr>)`.
-            self.expect(&token::Not)?;
-            self.expect(&token::OpenDelim(token::Paren))?;
-            let expr = self.parse_expr()?;
-            self.expect(&token::CloseDelim(token::Paren))?;
-            let sp = self.error_on_incorrect_await(lo, self.prev_span, &expr, false);
-            return Ok((sp, ExprKind::Await(expr)))
-        }
+            self.recover_await_macro()?
+        } else {
+            self.recover_await_prefix(await_sp)?
+        };
+        let sp = self.error_on_incorrect_await(lo, hi, &expr, is_question);
+        let expr = self.mk_expr(lo.to(sp), ExprKind::Await(expr), attrs);
+        self.maybe_recover_from_bad_qpath(expr, true)
+    }
+
+    fn recover_await_macro(&mut self) -> PResult<'a, (Span, P<Expr>, bool)> {
+        self.expect(&token::Not)?;
+        self.expect(&token::OpenDelim(token::Paren))?;
+        let expr = self.parse_expr()?;
+        self.expect(&token::CloseDelim(token::Paren))?;
+        Ok((self.prev_span, expr, false))
+    }
 
+    fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, P<Expr>, bool)> {
         let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
         let expr = if self.token == token::OpenDelim(token::Brace) {
             // Handle `await { <expr> }`.
@@ -1010,7 +1004,7 @@ impl<'a> Parser<'a> {
                 None,
                 self.token.span,
                 BlockCheckMode::Default,
-                ThinVec::new(),
+                AttrVec::new(),
             )
         } else {
             self.parse_expr()
@@ -1018,8 +1012,7 @@ impl<'a> Parser<'a> {
             err.span_label(await_sp, "while parsing this incorrect await expression");
             err
         })?;
-        let sp = self.error_on_incorrect_await(lo, expr.span, &expr, is_question);
-        Ok((sp, ExprKind::Await(expr)))
+        Ok((expr.span, expr, is_question))
     }
 
     fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: bool) -> Span {
@@ -1132,7 +1125,7 @@ impl<'a> Parser<'a> {
                 err.emit();
                 // Recover from parse error, callers expect the closing delim to be consumed.
                 self.consume_block(delim, ConsumeClosingDelim::Yes);
-                self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
+                self.mk_expr(lo.to(self.prev_span), ExprKind::Err, AttrVec::new())
             }
         }
     }
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 3cd4988ce0b..71c9e58f58f 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -4,11 +4,10 @@ use super::pat::{GateOr, PARAM_EXPECTED};
 use super::diagnostics::Error;
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::{PResult, Applicability};
-use syntax::ast::{self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode};
-use syntax::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind};
-use syntax::ast::{FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit};
+use syntax::ast::{self, DUMMY_NODE_ID, AttrVec, AttrStyle, Ident, CaptureBy, Field, Lit};
+use syntax::ast::{BlockCheckMode, Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm};
+use syntax::ast::{Ty, TyKind, FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst};
 use syntax::token::{self, Token, TokenKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
@@ -37,14 +36,14 @@ macro_rules! maybe_whole_expr {
                     let path = path.clone();
                     $p.bump();
                     return Ok($p.mk_expr(
-                        $p.token.span, ExprKind::Path(None, path), ThinVec::new()
+                        $p.token.span, ExprKind::Path(None, path), AttrVec::new()
                     ));
                 }
                 token::NtBlock(block) => {
                     let block = block.clone();
                     $p.bump();
                     return Ok($p.mk_expr(
-                        $p.token.span, ExprKind::Block(block, None), ThinVec::new()
+                        $p.token.span, ExprKind::Block(block, None), AttrVec::new()
                     ));
                 }
                 // N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
@@ -57,16 +56,16 @@ macro_rules! maybe_whole_expr {
 #[derive(Debug)]
 pub(super) enum LhsExpr {
     NotYetParsed,
-    AttributesParsed(ThinVec<Attribute>),
+    AttributesParsed(AttrVec),
     AlreadyParsed(P<Expr>),
 }
 
-impl From<Option<ThinVec<Attribute>>> for LhsExpr {
+impl From<Option<AttrVec>> for LhsExpr {
     /// Converts `Some(attrs)` into `LhsExpr::AttributesParsed(attrs)`
     /// and `None` into `LhsExpr::NotYetParsed`.
     ///
     /// This conversion does not allocate.
-    fn from(o: Option<ThinVec<Attribute>>) -> Self {
+    fn from(o: Option<AttrVec>) -> Self {
         if let Some(attrs) = o {
             LhsExpr::AttributesParsed(attrs)
         } else {
@@ -91,24 +90,33 @@ impl<'a> Parser<'a> {
         self.parse_expr_res(Restrictions::empty(), None)
     }
 
+    pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
+        self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
+    }
+
+    fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
+        match self.parse_expr() {
+            Ok(expr) => Ok(expr),
+            Err(mut err) => match self.token.kind {
+                token::Ident(name, false)
+                if name == kw::Underscore && self.look_ahead(1, |t| {
+                    t == &token::Comma
+                }) => {
+                    // Special-case handling of `foo(_, _, _)`
+                    err.emit();
+                    let sp = self.token.span;
+                    self.bump();
+                    Ok(self.mk_expr(sp, ExprKind::Err, AttrVec::new()))
+                }
+                _ => Err(err),
+            },
+        }
+    }
+
+    /// Parses a sequence of expressions delimited by parentheses.
     fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
         self.parse_paren_comma_seq(|p| {
-            match p.parse_expr() {
-                Ok(expr) => Ok(expr),
-                Err(mut err) => match p.token.kind {
-                    token::Ident(name, false)
-                    if name == kw::Underscore && p.look_ahead(1, |t| {
-                        t == &token::Comma
-                    }) => {
-                        // Special-case handling of `foo(_, _, _)`
-                        err.emit();
-                        let sp = p.token.span;
-                        p.bump();
-                        Ok(p.mk_expr(sp, ExprKind::Err, ThinVec::new()))
-                    }
-                    _ => Err(err),
-                },
-            }
+            p.parse_expr_catch_underscore()
         }).map(|(r, _)| r)
     }
 
@@ -117,7 +125,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_expr_res(
         &mut self,
         r: Restrictions,
-        already_parsed_attrs: Option<ThinVec<Attribute>>
+        already_parsed_attrs: Option<AttrVec>
     ) -> PResult<'a, P<Expr>> {
         self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
     }
@@ -129,7 +137,7 @@ impl<'a> Parser<'a> {
     #[inline]
     fn parse_assoc_expr(
         &mut self,
-        already_parsed_attrs: Option<ThinVec<Attribute>>,
+        already_parsed_attrs: Option<AttrVec>,
     ) -> PResult<'a, P<Expr>> {
         self.parse_assoc_expr_with(0, already_parsed_attrs.into())
     }
@@ -155,53 +163,13 @@ impl<'a> Parser<'a> {
         };
         let last_type_ascription_set = self.last_type_ascription.is_some();
 
-        match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) {
-            (true, None) => {
-                self.last_type_ascription = None;
-                // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
-                return Ok(lhs);
-            }
-            (false, _) => {} // continue parsing the expression
-            // An exhaustive check is done in the following block, but these are checked first
-            // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
-            // want to keep their span info to improve diagnostics in these cases in a later stage.
-            (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
-            (true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
-            (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
-            (true, Some(AssocOp::Add)) // `{ 42 } + 42
-            // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
-            // `if x { a } else { b } && if y { c } else { d }`
-            if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
-                self.last_type_ascription = None;
-                // These cases are ambiguous and can't be identified in the parser alone
-                let sp = self.sess.source_map().start_point(self.token.span);
-                self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
-                return Ok(lhs);
-            }
-            (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => {
-                self.last_type_ascription = None;
-                return Ok(lhs);
-            }
-            (true, Some(_)) => {
-                // We've found an expression that would be parsed as a statement, but the next
-                // token implies this should be parsed as an expression.
-                // For example: `if let Some(x) = x { x } else { 0 } / 2`
-                let mut err = self.struct_span_err(self.token.span, &format!(
-                    "expected expression, found `{}`",
-                    pprust::token_to_string(&self.token),
-                ));
-                err.span_label(self.token.span, "expected expression");
-                self.sess.expr_parentheses_needed(
-                    &mut err,
-                    lhs.span,
-                    Some(pprust::expr_to_string(&lhs),
-                ));
-                err.emit();
-            }
+        if !self.should_continue_as_assoc_expr(&lhs) {
+            self.last_type_ascription = None;
+            return Ok(lhs);
         }
-        self.expected_tokens.push(TokenType::Operator);
-        while let Some(op) = AssocOp::from_token(&self.token) {
 
+        self.expected_tokens.push(TokenType::Operator);
+        while let Some(op) = self.check_assoc_op() {
             // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what
             // it refers to. Interpolated identifiers are unwrapped early and never show up here
             // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process
@@ -272,7 +240,7 @@ impl<'a> Parser<'a> {
                 };
 
                 let r = self.mk_range(Some(lhs), rhs, limits)?;
-                lhs = self.mk_expr(lhs_span.to(rhs_span), r, ThinVec::new());
+                lhs = self.mk_expr(lhs_span.to(rhs_span), r, AttrVec::new());
                 break
             }
 
@@ -306,9 +274,9 @@ impl<'a> Parser<'a> {
                 AssocOp::Greater | AssocOp::GreaterEqual => {
                     let ast_op = op.to_ast_binop().unwrap();
                     let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
-                    self.mk_expr(span, binary, ThinVec::new())
+                    self.mk_expr(span, binary, AttrVec::new())
                 }
-                AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()),
+                AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs), AttrVec::new()),
                 AssocOp::AssignOp(k) => {
                     let aop = match k {
                         token::Plus =>    BinOpKind::Add,
@@ -323,7 +291,7 @@ impl<'a> Parser<'a> {
                         token::Shr =>     BinOpKind::Shr,
                     };
                     let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
-                    self.mk_expr(span, aopexpr, ThinVec::new())
+                    self.mk_expr(span, aopexpr, AttrVec::new())
                 }
                 AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
                     self.bug("AssocOp should have been handled by special case")
@@ -338,6 +306,80 @@ impl<'a> Parser<'a> {
         Ok(lhs)
     }
 
+    fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
+        match (self.expr_is_complete(lhs), self.check_assoc_op()) {
+            // Semi-statement forms are odd:
+            // See https://github.com/rust-lang/rust/issues/29071
+            (true, None) => false,
+            (false, _) => true, // Continue parsing the expression.
+            // An exhaustive check is done in the following block, but these are checked first
+            // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
+            // want to keep their span info to improve diagnostics in these cases in a later stage.
+            (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
+            (true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
+            (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
+            (true, Some(AssocOp::Add)) // `{ 42 } + 42
+            // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
+            // `if x { a } else { b } && if y { c } else { d }`
+            if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
+                // These cases are ambiguous and can't be identified in the parser alone.
+                let sp = self.sess.source_map().start_point(self.token.span);
+                self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
+                false
+            }
+            (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => false,
+            (true, Some(_)) => {
+                self.error_found_expr_would_be_stmt(lhs);
+                true
+            }
+        }
+    }
+
+    /// We've found an expression that would be parsed as a statement,
+    /// but the next token implies this should be parsed as an expression.
+    /// For example: `if let Some(x) = x { x } else { 0 } / 2`.
+    fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
+        let mut err = self.struct_span_err(self.token.span, &format!(
+            "expected expression, found `{}`",
+            pprust::token_to_string(&self.token),
+        ));
+        err.span_label(self.token.span, "expected expression");
+        self.sess.expr_parentheses_needed(&mut err, lhs.span, Some(pprust::expr_to_string(&lhs)));
+        err.emit();
+    }
+
+    /// Possibly translate the current token to an associative operator.
+    /// The method does not advance the current token.
+    ///
+    /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
+    fn check_assoc_op(&self) -> Option<AssocOp> {
+        match (AssocOp::from_token(&self.token), &self.token.kind) {
+            (op @ Some(_), _) => op,
+            (None, token::Ident(sym::and, false)) => {
+                self.error_bad_logical_op("and", "&&", "conjunction");
+                Some(AssocOp::LAnd)
+            }
+            (None, token::Ident(sym::or, false)) => {
+                self.error_bad_logical_op("or", "||", "disjunction");
+                Some(AssocOp::LOr)
+            }
+            _ => None,
+        }
+    }
+
+    /// Error on `and` and `or` suggesting `&&` and `||` respectively.
+    fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
+        self.struct_span_err(self.token.span, &format!("`{}` is not a logical operator", bad))
+            .span_suggestion_short(
+                self.token.span,
+                &format!("use `{}` to perform logical {}", good, english),
+                good.to_string(),
+                Applicability::MachineApplicable,
+            )
+            .note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
+            .emit();
+    }
+
     /// Checks if this expression is a successfully parsed statement.
     fn expr_is_complete(&self, e: &Expr) -> bool {
         self.restrictions.contains(Restrictions::STMT_EXPR) &&
@@ -359,7 +401,7 @@ impl<'a> Parser<'a> {
     /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
     fn parse_prefix_range_expr(
         &mut self,
-        already_parsed_attrs: Option<ThinVec<Attribute>>
+        already_parsed_attrs: Option<AttrVec>
     ) -> PResult<'a, P<Expr>> {
         // Check for deprecated `...` syntax.
         if self.token == token::DotDotDot {
@@ -396,10 +438,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a prefix-unary-operator expr.
-    fn parse_prefix_expr(
-        &mut self,
-        already_parsed_attrs: Option<ThinVec<Attribute>>
-    ) -> PResult<'a, P<Expr>> {
+    fn parse_prefix_expr(&mut self, already_parsed_attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> {
         let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
         let lo = self.token.span;
         // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
@@ -510,7 +549,7 @@ impl<'a> Parser<'a> {
                            expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind)
                            -> PResult<'a, P<Expr>> {
         let mk_expr = |this: &mut Self, rhs: P<Ty>| {
-            this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), ThinVec::new())
+            this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), AttrVec::new())
         };
 
         // Save the state of the parser before parsing type normally, in case there is a
@@ -611,7 +650,7 @@ impl<'a> Parser<'a> {
     /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
     fn parse_dot_or_call_expr(
         &mut self,
-        already_parsed_attrs: Option<ThinVec<Attribute>>,
+        already_parsed_attrs: Option<AttrVec>,
     ) -> PResult<'a, P<Expr>> {
         let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
 
@@ -624,7 +663,7 @@ impl<'a> Parser<'a> {
         &mut self,
         e0: P<Expr>,
         lo: Span,
-        mut attrs: ThinVec<Attribute>,
+        mut attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
         // Stitch the list of outer attributes onto the return value.
         // A little bit ugly, but the best way given the current code
@@ -633,19 +672,20 @@ impl<'a> Parser<'a> {
             expr.map(|mut expr| {
                 attrs.extend::<Vec<_>>(expr.attrs.into());
                 expr.attrs = attrs;
-                match expr.kind {
-                    ExprKind::If(..) if !expr.attrs.is_empty() => {
-                        // Just point to the first attribute in there...
-                        let span = expr.attrs[0].span;
-                        self.span_err(span, "attributes are not yet allowed on `if` expressions");
-                    }
-                    _ => {}
-                }
+                self.error_attr_on_if_expr(&expr);
                 expr
             })
         )
     }
 
+    fn error_attr_on_if_expr(&self, expr: &Expr) {
+        if let (ExprKind::If(..), [a0, ..]) = (&expr.kind, &*expr.attrs) {
+            // Just point to the first attribute in there...
+            self.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions")
+                .emit();
+        }
+    }
+
     fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         let mut e = e0;
         let mut hi;
@@ -653,7 +693,7 @@ impl<'a> Parser<'a> {
             // expr?
             while self.eat(&token::Question) {
                 let hi = self.prev_span;
-                e = self.mk_expr(lo.to(hi), ExprKind::Try(e), ThinVec::new());
+                e = self.mk_expr(lo.to(hi), ExprKind::Try(e), AttrVec::new());
             }
 
             // expr.f
@@ -666,7 +706,7 @@ impl<'a> Parser<'a> {
                         let span = self.token.span;
                         self.bump();
                         let field = ExprKind::Field(e, Ident::new(symbol, span));
-                        e = self.mk_expr(lo.to(span), field, ThinVec::new());
+                        e = self.mk_expr(lo.to(span), field, AttrVec::new());
 
                         self.expect_no_suffix(span, "a tuple index", suffix);
                     }
@@ -715,7 +755,7 @@ impl<'a> Parser<'a> {
                     let seq = self.parse_paren_expr_seq().map(|es| {
                         let nd = self.mk_call(e, es);
                         let hi = self.prev_span;
-                        self.mk_expr(lo.to(hi), nd, ThinVec::new())
+                        self.mk_expr(lo.to(hi), nd, AttrVec::new())
                     });
                     e = self.recover_seq_parse_error(token::Paren, lo, seq);
                 }
@@ -728,7 +768,7 @@ impl<'a> Parser<'a> {
                     hi = self.token.span;
                     self.expect(&token::CloseDelim(token::Bracket))?;
                     let index = self.mk_index(e, ix);
-                    e = self.mk_expr(lo.to(hi), index, ThinVec::new())
+                    e = self.mk_expr(lo.to(hi), index, AttrVec::new())
                 }
                 _ => return Ok(e)
             }
@@ -752,7 +792,7 @@ impl<'a> Parser<'a> {
                 args.insert(0, self_arg);
 
                 let span = lo.to(self.prev_span);
-                self.mk_expr(span, ExprKind::MethodCall(segment, args), ThinVec::new())
+                self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new())
             }
             _ => {
                 // Field access `expr.f`
@@ -762,7 +802,7 @@ impl<'a> Parser<'a> {
                 }
 
                 let span = lo.to(self.prev_span);
-                self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), ThinVec::new())
+                self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), AttrVec::new())
             }
         })
     }
@@ -781,305 +821,275 @@ impl<'a> Parser<'a> {
         //
         // Therefore, prevent sub-parser from parsing
         // attributes by giving them a empty "already-parsed" list.
-        let mut attrs = ThinVec::new();
+        let attrs = AttrVec::new();
 
+        // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
         let lo = self.token.span;
-        let mut hi = self.token.span;
-
-        let ex: ExprKind;
-
-        macro_rules! parse_lit {
-            () => {
-                match self.parse_opt_lit() {
-                    Some(literal) => {
-                        hi = self.prev_span;
-                        ex = ExprKind::Lit(literal);
-                    }
-                    None => {
-                        return Err(self.expected_expression_found());
-                    }
+        if let token::Literal(_) = self.token.kind {
+            // This match arm is a special-case of the `_` match arm below and
+            // could be removed without changing functionality, but it's faster
+            // to have it here, especially for programs with large constants.
+            self.parse_lit_expr(attrs)
+        } else if self.check(&token::OpenDelim(token::Paren)) {
+            self.parse_tuple_parens_expr(attrs)
+        } else if self.check(&token::OpenDelim(token::Brace)) {
+            self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs)
+        } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
+            self.parse_closure_expr(attrs)
+        } else if self.check(&token::OpenDelim(token::Bracket)) {
+            self.parse_array_or_repeat_expr(attrs)
+        } else if self.eat_lt() {
+            let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+            Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
+        } else if self.token.is_path_start() {
+            self.parse_path_start_expr(attrs)
+        } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
+            self.parse_closure_expr(attrs)
+        } else if self.eat_keyword(kw::If) {
+            self.parse_if_expr(attrs)
+        } else if self.eat_keyword(kw::For) {
+            self.parse_for_expr(None, self.prev_span, attrs)
+        } else if self.eat_keyword(kw::While) {
+            self.parse_while_expr(None, self.prev_span, attrs)
+        } else if let Some(label) = self.eat_label() {
+            self.parse_labeled_expr(label, attrs)
+        } else if self.eat_keyword(kw::Loop) {
+            self.parse_loop_expr(None, self.prev_span, attrs)
+        } else if self.eat_keyword(kw::Continue) {
+            let kind = ExprKind::Continue(self.eat_label());
+            Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs))
+        } else if self.eat_keyword(kw::Match) {
+            let match_sp = self.prev_span;
+            self.parse_match_expr(attrs).map_err(|mut err| {
+                err.span_label(match_sp, "while parsing this match expression");
+                err
+            })
+        } else if self.eat_keyword(kw::Unsafe) {
+            self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
+        } else if self.is_do_catch_block() {
+            self.recover_do_catch(attrs)
+        } else if self.is_try_block() {
+            self.expect_keyword(kw::Try)?;
+            self.parse_try_block(lo, attrs)
+        } else if self.eat_keyword(kw::Return) {
+            self.parse_return_expr(attrs)
+        } else if self.eat_keyword(kw::Break) {
+            self.parse_break_expr(attrs)
+        } else if self.eat_keyword(kw::Yield) {
+            self.parse_yield_expr(attrs)
+        } else if self.eat_keyword(kw::Let) {
+            self.parse_let_expr(attrs)
+        } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
+            // Don't complain about bare semicolons after unclosed braces
+            // recovery in order to keep the error count down. Fixing the
+            // delimiters will possibly also fix the bare semicolon found in
+            // expression context. For example, silence the following error:
+            //
+            //     error: expected expression, found `;`
+            //      --> file.rs:2:13
+            //       |
+            //     2 |     foo(bar(;
+            //       |             ^ expected expression
+            self.bump();
+            Ok(self.mk_expr_err(self.token.span))
+        } else if self.token.span.rust_2018() {
+            // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
+            if self.check_keyword(kw::Async) {
+                if self.is_async_block() { // Check for `async {` and `async move {`.
+                    self.parse_async_block(attrs)
+                } else {
+                    self.parse_closure_expr(attrs)
                 }
+            } else if self.eat_keyword(kw::Await) {
+                self.recover_incorrect_await_syntax(lo, self.prev_span, attrs)
+            } else {
+                self.parse_lit_expr(attrs)
             }
+        } else {
+            self.parse_lit_expr(attrs)
         }
+    }
 
-        // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
-        match self.token.kind {
-            // This match arm is a special-case of the `_` match arm below and
-            // could be removed without changing functionality, but it's faster
-            // to have it here, especially for programs with large constants.
-            token::Literal(_) => {
-                parse_lit!()
+    fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.token.span;
+        match self.parse_opt_lit() {
+            Some(literal) => {
+                let expr = self.mk_expr(lo.to(self.prev_span), ExprKind::Lit(literal), attrs);
+                self.maybe_recover_from_bad_qpath(expr, true)
             }
-            token::OpenDelim(token::Paren) => {
-                self.bump();
+            None => return Err(self.expected_expression_found()),
+        }
+    }
 
-                attrs.extend(self.parse_inner_attributes()?);
-
-                // `(e)` is parenthesized `e`.
-                // `(e,)` is a tuple with only one field, `e`.
-                let mut es = vec![];
-                let mut trailing_comma = false;
-                let mut recovered = false;
-                while self.token != token::CloseDelim(token::Paren) {
-                    es.push(match self.parse_expr() {
-                        Ok(es) => es,
-                        Err(mut err) => {
-                            // Recover from parse error in tuple list.
-                            match self.token.kind {
-                                token::Ident(name, false)
-                                if name == kw::Underscore && self.look_ahead(1, |t| {
-                                    t == &token::Comma
-                                }) => {
-                                    // Special-case handling of `Foo<(_, _, _)>`
-                                    err.emit();
-                                    let sp = self.token.span;
-                                    self.bump();
-                                    self.mk_expr(sp, ExprKind::Err, ThinVec::new())
-                                }
-                                _ => return Ok(
-                                    self.recover_seq_parse_error(token::Paren, lo, Err(err)),
-                                ),
-                            }
-                        }
-                    });
-                    recovered = self.expect_one_of(
-                        &[],
-                        &[token::Comma, token::CloseDelim(token::Paren)],
-                    )?;
-                    if self.eat(&token::Comma) {
-                        trailing_comma = true;
-                    } else {
-                        trailing_comma = false;
-                        break;
-                    }
-                }
-                if !recovered {
-                    self.bump();
-                }
+    fn parse_tuple_parens_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.token.span;
+        self.expect(&token::OpenDelim(token::Paren))?;
+        attrs.extend(self.parse_inner_attributes()?); // `(#![foo] a, b, ...)` is OK.
+        let (es, trailing_comma) = match self.parse_seq_to_end(
+            &token::CloseDelim(token::Paren),
+            SeqSep::trailing_allowed(token::Comma),
+            |p| p.parse_expr_catch_underscore(),
+        ) {
+            Ok(x) => x,
+            Err(err) => return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err))),
+        };
+        let kind = if es.len() == 1 && !trailing_comma {
+            // `(e)` is parenthesized `e`.
+            ExprKind::Paren(es.into_iter().nth(0).unwrap())
+        } else {
+            // `(e,)` is a tuple with only one field, `e`.
+            ExprKind::Tup(es)
+        };
+        let expr = self.mk_expr(lo.to(self.prev_span), kind, attrs);
+        self.maybe_recover_from_bad_qpath(expr, true)
+    }
 
-                hi = self.prev_span;
-                ex = if es.len() == 1 && !trailing_comma {
-                    ExprKind::Paren(es.into_iter().nth(0).unwrap())
-                } else {
-                    ExprKind::Tup(es)
-                };
-            }
-            token::OpenDelim(token::Brace) => {
-                return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs);
-            }
-            token::BinOp(token::Or) | token::OrOr => {
-                return self.parse_closure_expr(attrs);
-            }
-            token::OpenDelim(token::Bracket) => {
-                self.bump();
+    fn parse_array_or_repeat_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.token.span;
+        self.bump(); // `[`
 
-                attrs.extend(self.parse_inner_attributes()?);
+        attrs.extend(self.parse_inner_attributes()?);
 
-                if self.eat(&token::CloseDelim(token::Bracket)) {
-                    // Empty vector
-                    ex = ExprKind::Array(Vec::new());
-                } else {
-                    // Non-empty vector
-                    let first_expr = self.parse_expr()?;
-                    if self.eat(&token::Semi) {
-                        // Repeating array syntax: `[ 0; 512 ]`
-                        let count = AnonConst {
-                            id: DUMMY_NODE_ID,
-                            value: self.parse_expr()?,
-                        };
-                        self.expect(&token::CloseDelim(token::Bracket))?;
-                        ex = ExprKind::Repeat(first_expr, count);
-                    } else if self.eat(&token::Comma) {
-                        // Vector with two or more elements
-                        let remaining_exprs = self.parse_seq_to_end(
-                            &token::CloseDelim(token::Bracket),
-                            SeqSep::trailing_allowed(token::Comma),
-                            |p| Ok(p.parse_expr()?)
-                        )?;
-                        let mut exprs = vec![first_expr];
-                        exprs.extend(remaining_exprs);
-                        ex = ExprKind::Array(exprs);
-                    } else {
-                        // Vector with one element
-                        self.expect(&token::CloseDelim(token::Bracket))?;
-                        ex = ExprKind::Array(vec![first_expr]);
-                    }
-                }
-                hi = self.prev_span;
+        let close = &token::CloseDelim(token::Bracket);
+        let kind = if self.eat(close) {
+            // Empty vector
+            ExprKind::Array(Vec::new())
+        } else {
+            // Non-empty vector
+            let first_expr = self.parse_expr()?;
+            if self.eat(&token::Semi) {
+                // Repeating array syntax: `[ 0; 512 ]`
+                let count = self.parse_anon_const_expr()?;
+                self.expect(close)?;
+                ExprKind::Repeat(first_expr, count)
+            } else if self.eat(&token::Comma) {
+                // Vector with two or more elements.
+                let sep = SeqSep::trailing_allowed(token::Comma);
+                let (remaining_exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?;
+                let mut exprs = vec![first_expr];
+                exprs.extend(remaining_exprs);
+                ExprKind::Array(exprs)
+            } else {
+                // Vector with one element
+                self.expect(close)?;
+                ExprKind::Array(vec![first_expr])
             }
-            _ => {
-                if self.eat_lt() {
-                    let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
-                    hi = path.span;
-                    return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
-                }
-                if self.token.is_path_start() {
-                    let path = self.parse_path(PathStyle::Expr)?;
-
-                    // `!`, as an operator, is prefix, so we know this isn't that.
-                    if self.eat(&token::Not) {
-                        // MACRO INVOCATION expression
-                        let args = self.parse_mac_args()?;
-                        hi = self.prev_span;
-                        ex = ExprKind::Mac(Mac {
-                            path,
-                            args,
-                            prior_type_ascription: self.last_type_ascription,
-                        });
-                    } else if self.check(&token::OpenDelim(token::Brace)) {
-                        if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
-                            return expr;
-                        } else {
-                            hi = path.span;
-                            ex = ExprKind::Path(None, path);
-                        }
-                    } else {
-                        hi = path.span;
-                        ex = ExprKind::Path(None, path);
-                    }
+        };
+        let expr = self.mk_expr(lo.to(self.prev_span), kind, attrs);
+        self.maybe_recover_from_bad_qpath(expr, true)
+    }
 
-                    let expr = self.mk_expr(lo.to(hi), ex, attrs);
-                    return self.maybe_recover_from_bad_qpath(expr, true);
-                }
-                if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
-                    return self.parse_closure_expr(attrs);
-                }
-                if self.eat_keyword(kw::If) {
-                    return self.parse_if_expr(attrs);
-                }
-                if self.eat_keyword(kw::For) {
-                    let lo = self.prev_span;
-                    return self.parse_for_expr(None, lo, attrs);
-                }
-                if self.eat_keyword(kw::While) {
-                    let lo = self.prev_span;
-                    return self.parse_while_expr(None, lo, attrs);
-                }
-                if let Some(label) = self.eat_label() {
-                    let lo = label.ident.span;
-                    self.expect(&token::Colon)?;
-                    if self.eat_keyword(kw::While) {
-                        return self.parse_while_expr(Some(label), lo, attrs)
-                    }
-                    if self.eat_keyword(kw::For) {
-                        return self.parse_for_expr(Some(label), lo, attrs)
-                    }
-                    if self.eat_keyword(kw::Loop) {
-                        return self.parse_loop_expr(Some(label), lo, attrs)
-                    }
-                    if self.token == token::OpenDelim(token::Brace) {
-                        return self.parse_block_expr(Some(label),
-                                                     lo,
-                                                     BlockCheckMode::Default,
-                                                     attrs);
-                    }
-                    let msg = "expected `while`, `for`, `loop` or `{` after a label";
-                    let mut err = self.fatal(msg);
-                    err.span_label(self.token.span, msg);
-                    return Err(err);
-                }
-                if self.eat_keyword(kw::Loop) {
-                    let lo = self.prev_span;
-                    return self.parse_loop_expr(None, lo, attrs);
-                }
-                if self.eat_keyword(kw::Continue) {
-                    let label = self.eat_label();
-                    let ex = ExprKind::Continue(label);
-                    let hi = self.prev_span;
-                    return Ok(self.mk_expr(lo.to(hi), ex, attrs));
-                }
-                if self.eat_keyword(kw::Match) {
-                    let match_sp = self.prev_span;
-                    return self.parse_match_expr(attrs).map_err(|mut err| {
-                        err.span_label(match_sp, "while parsing this match expression");
-                        err
-                    });
-                }
-                if self.eat_keyword(kw::Unsafe) {
-                    return self.parse_block_expr(
-                        None,
-                        lo,
-                        BlockCheckMode::Unsafe(ast::UserProvided),
-                        attrs);
-                }
-                if self.is_do_catch_block() {
-                    let mut db = self.fatal("found removed `do catch` syntax");
-                    db.help("following RFC #2388, the new non-placeholder syntax is `try`");
-                    return Err(db);
-                }
-                if self.is_try_block() {
-                    let lo = self.token.span;
-                    assert!(self.eat_keyword(kw::Try));
-                    return self.parse_try_block(lo, attrs);
-                }
+    fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.token.span;
+        let path = self.parse_path(PathStyle::Expr)?;
+
+        // `!`, as an operator, is prefix, so we know this isn't that.
+        let (hi, kind) = if self.eat(&token::Not) {
+            // MACRO INVOCATION expression
+            let mac = Mac {
+                path,
+                args: self.parse_mac_args()?,
+                prior_type_ascription: self.last_type_ascription,
+            };
+            (self.prev_span, ExprKind::Mac(mac))
+        } else if self.check(&token::OpenDelim(token::Brace)) {
+            if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
+                return expr;
+            } else {
+                (path.span, ExprKind::Path(None, path))
+            }
+        } else {
+            (path.span, ExprKind::Path(None, path))
+        };
 
-                // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
-                let is_span_rust_2018 = self.token.span.rust_2018();
-                if is_span_rust_2018 && self.check_keyword(kw::Async) {
-                    return if self.is_async_block() { // Check for `async {` and `async move {`.
-                        self.parse_async_block(attrs)
-                    } else {
-                        self.parse_closure_expr(attrs)
-                    };
-                }
-                if self.eat_keyword(kw::Return) {
-                    if self.token.can_begin_expr() {
-                        let e = self.parse_expr()?;
-                        hi = e.span;
-                        ex = ExprKind::Ret(Some(e));
-                    } else {
-                        ex = ExprKind::Ret(None);
-                    }
-                } else if self.eat_keyword(kw::Break) {
-                    let label = self.eat_label();
-                    let e = if self.token.can_begin_expr()
-                               && !(self.token == token::OpenDelim(token::Brace)
-                                    && self.restrictions.contains(
-                                           Restrictions::NO_STRUCT_LITERAL)) {
-                        Some(self.parse_expr()?)
-                    } else {
-                        None
-                    };
-                    ex = ExprKind::Break(label, e);
-                    hi = self.prev_span;
-                } else if self.eat_keyword(kw::Yield) {
-                    if self.token.can_begin_expr() {
-                        let e = self.parse_expr()?;
-                        hi = e.span;
-                        ex = ExprKind::Yield(Some(e));
-                    } else {
-                        ex = ExprKind::Yield(None);
-                    }
+        let expr = self.mk_expr(lo.to(hi), kind, attrs);
+        self.maybe_recover_from_bad_qpath(expr, true)
+    }
 
-                    let span = lo.to(hi);
-                    self.sess.gated_spans.gate(sym::generators, span);
-                } else if self.eat_keyword(kw::Let) {
-                    return self.parse_let_expr(attrs);
-                } else if is_span_rust_2018 && self.eat_keyword(kw::Await) {
-                    let (await_hi, e_kind) = self.parse_incorrect_await_syntax(lo, self.prev_span)?;
-                    hi = await_hi;
-                    ex = e_kind;
-                } else {
-                    if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
-                        // Don't complain about bare semicolons after unclosed braces
-                        // recovery in order to keep the error count down. Fixing the
-                        // delimiters will possibly also fix the bare semicolon found in
-                        // expression context. For example, silence the following error:
-                        //
-                        //     error: expected expression, found `;`
-                        //      --> file.rs:2:13
-                        //       |
-                        //     2 |     foo(bar(;
-                        //       |             ^ expected expression
-                        self.bump();
-                        return Ok(self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()));
-                    }
-                    parse_lit!()
-                }
-            }
+    fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = label.ident.span;
+        self.expect(&token::Colon)?;
+        if self.eat_keyword(kw::While) {
+            return self.parse_while_expr(Some(label), lo, attrs)
         }
+        if self.eat_keyword(kw::For) {
+            return self.parse_for_expr(Some(label), lo, attrs)
+        }
+        if self.eat_keyword(kw::Loop) {
+            return self.parse_loop_expr(Some(label), lo, attrs)
+        }
+        if self.token == token::OpenDelim(token::Brace) {
+            return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs);
+        }
+
+        let msg = "expected `while`, `for`, `loop` or `{` after a label";
+        self.struct_span_err(self.token.span, msg)
+            .span_label(self.token.span, msg)
+            .emit();
+        // Continue as an expression in an effort to recover on `'label: non_block_expr`.
+        self.parse_expr()
+    }
+
+    /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
+    fn recover_do_catch(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.token.span;
+
+        self.bump(); // `do`
+        self.bump(); // `catch`
+
+        let span_dc = lo.to(self.prev_span);
+        self.struct_span_err(span_dc, "found removed `do catch` syntax")
+            .span_suggestion(
+                span_dc,
+                "replace with the new syntax",
+                "try".to_string(),
+                Applicability::MachineApplicable,
+            )
+            .note("following RFC #2388, the new non-placeholder syntax is `try`")
+            .emit();
 
-        let expr = self.mk_expr(lo.to(hi), ex, attrs);
+        self.parse_try_block(lo, attrs)
+    }
+
+    /// Parse an expression if the token can begin one.
+    fn parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>> {
+        Ok(if self.token.can_begin_expr() {
+            Some(self.parse_expr()?)
+        } else {
+            None
+        })
+    }
+
+    /// Parse `"return" expr?`.
+    fn parse_return_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.prev_span;
+        let kind = ExprKind::Ret(self.parse_expr_opt()?);
+        let expr = self.mk_expr(lo.to(self.prev_span), kind, attrs);
+        self.maybe_recover_from_bad_qpath(expr, true)
+    }
+
+    /// Parse `"('label ":")? break expr?`.
+    fn parse_break_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.prev_span;
+        let label = self.eat_label();
+        let kind = if self.token != token::OpenDelim(token::Brace)
+            || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
+        {
+            self.parse_expr_opt()?
+        } else {
+            None
+        };
+        let expr = self.mk_expr(lo.to(self.prev_span), ExprKind::Break(label, kind), attrs);
+        self.maybe_recover_from_bad_qpath(expr, true)
+    }
+
+    /// Parse `"yield" expr?`.
+    fn parse_yield_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        let lo = self.prev_span;
+        let kind = ExprKind::Yield(self.parse_expr_opt()?);
+        let span = lo.to(self.prev_span);
+        self.sess.gated_spans.gate(sym::generators, span);
+        let expr = self.mk_expr(span, kind, attrs);
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
@@ -1282,12 +1292,12 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let literal = self.parse_lit()?;
         let hi = self.prev_span;
-        let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new());
+        let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), AttrVec::new());
 
         if minus_present {
             let minus_hi = self.prev_span;
             let unary = self.mk_unary(UnOp::Neg, expr);
-            Ok(self.mk_expr(minus_lo.to(minus_hi), unary, ThinVec::new()))
+            Ok(self.mk_expr(minus_lo.to(minus_hi), unary, AttrVec::new()))
         } else {
             Ok(expr)
         }
@@ -1299,7 +1309,7 @@ impl<'a> Parser<'a> {
         opt_label: Option<Label>,
         lo: Span,
         blk_mode: BlockCheckMode,
-        outer_attrs: ThinVec<Attribute>,
+        outer_attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
         if let Some(label) = opt_label {
             self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
@@ -1315,7 +1325,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a closure expression (e.g., `move |args| expr`).
-    fn parse_closure_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
 
         let movability = if self.eat_keyword(kw::Static) {
@@ -1345,7 +1355,7 @@ impl<'a> Parser<'a> {
             _ => {
                 // If an explicit return type is given, require a block to appear (RFC 968).
                 let body_lo = self.token.span;
-                self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())?
+                self.parse_block_expr(None, body_lo, BlockCheckMode::Default, AttrVec::new())?
             }
         };
 
@@ -1381,7 +1391,7 @@ impl<'a> Parser<'a> {
                 args
             }
         };
-        let output = self.parse_ret_ty(true)?;
+        let output = self.parse_ret_ty(true, true)?;
 
         Ok(P(FnDecl {
             inputs: inputs_captures,
@@ -1415,7 +1425,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an `if` expression (`if` token already eaten).
-    fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_span;
         let cond = self.parse_cond_expr()?;
 
@@ -1461,7 +1471,7 @@ impl<'a> Parser<'a> {
 
     /// Parses a `let $pat = $expr` pseudo-expression.
     /// The `let` token has already been eaten.
-    fn parse_let_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_span;
         let pat = self.parse_top_pat(GateOr::No)?;
         self.expect(&token::Eq)?;
@@ -1477,10 +1487,10 @@ impl<'a> Parser<'a> {
     /// Parses an `else { ... }` expression (`else` token already eaten).
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
         if self.eat_keyword(kw::If) {
-            return self.parse_if_expr(ThinVec::new());
+            return self.parse_if_expr(AttrVec::new());
         } else {
             let blk = self.parse_block()?;
-            return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), ThinVec::new()));
+            return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()));
         }
     }
 
@@ -1489,7 +1499,7 @@ impl<'a> Parser<'a> {
         &mut self,
         opt_label: Option<Label>,
         span_lo: Span,
-        mut attrs: ThinVec<Attribute>
+        mut attrs: AttrVec
     ) -> PResult<'a, P<Expr>> {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
@@ -1531,7 +1541,7 @@ impl<'a> Parser<'a> {
         &mut self,
         opt_label: Option<Label>,
         span_lo: Span,
-        mut attrs: ThinVec<Attribute>
+        mut attrs: AttrVec
     ) -> PResult<'a, P<Expr>> {
         let cond = self.parse_cond_expr()?;
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1545,7 +1555,7 @@ impl<'a> Parser<'a> {
         &mut self,
         opt_label: Option<Label>,
         span_lo: Span,
-        mut attrs: ThinVec<Attribute>
+        mut attrs: AttrVec
     ) -> PResult<'a, P<Expr>> {
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
@@ -1564,7 +1574,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `match ... { ... }` expression (`match` token already eaten).
-    fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    fn parse_match_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let match_span = self.prev_span;
         let lo = self.prev_span;
         let discriminant = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@@ -1676,11 +1686,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `try {...}` expression (`try` token already eaten).
-    fn parse_try_block(
-        &mut self,
-        span_lo: Span,
-        mut attrs: ThinVec<Attribute>
-    ) -> PResult<'a, P<Expr>> {
+    fn parse_try_block(&mut self, span_lo: Span, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         if self.eat_keyword(kw::Catch) {
@@ -1712,7 +1718,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an `async move? {...}` expression.
-    fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    fn parse_async_block(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let span_lo = self.token.span;
         self.expect_keyword(kw::Async)?;
         let capture_clause = self.parse_capture_clause();
@@ -1739,7 +1745,7 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         path: &ast::Path,
-        attrs: &ThinVec<Attribute>,
+        attrs: &AttrVec,
     ) -> Option<PResult<'a, P<Expr>>> {
         let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
         let certainly_not_a_block = || self.look_ahead(1, |t| t.is_ident()) && (
@@ -1780,7 +1786,7 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         pth: ast::Path,
-        mut attrs: ThinVec<Attribute>
+        mut attrs: AttrVec
     ) -> PResult<'a, P<Expr>> {
         let struct_sp = lo.to(self.prev_span);
         self.bump();
@@ -1826,9 +1832,9 @@ impl<'a> Parser<'a> {
                     recovery_field = Some(ast::Field {
                         ident: Ident::new(name, self.token.span),
                         span: self.token.span,
-                        expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()),
+                        expr: self.mk_expr(self.token.span, ExprKind::Err, AttrVec::new()),
                         is_shorthand: false,
-                        attrs: ThinVec::new(),
+                        attrs: AttrVec::new(),
                         id: DUMMY_NODE_ID,
                         is_placeholder: false,
                     });
@@ -1907,7 +1913,7 @@ impl<'a> Parser<'a> {
 
             // Mimic `x: x` for the `x` field shorthand.
             let path = ast::Path::from_ident(fieldname);
-            let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), ThinVec::new());
+            let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), AttrVec::new());
             (fieldname, expr, true)
         };
         Ok(ast::Field {
@@ -1984,16 +1990,16 @@ impl<'a> Parser<'a> {
 
     fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         let span = lo.to(self.prev_span);
-        let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), ThinVec::new());
+        let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new());
         self.recover_from_await_method_call();
         Ok(await_expr)
     }
 
-    crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
+    crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
         P(Expr { kind, span, attrs, id: DUMMY_NODE_ID })
     }
 
     pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
-        self.mk_expr(span, ExprKind::Err, ThinVec::new())
+        self.mk_expr(span, ExprKind::Err, AttrVec::new())
     }
 }
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 34ef12e818c..ea9047d2d77 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -5,15 +5,14 @@ use crate::maybe_whole;
 
 use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
 use rustc_error_codes::*;
-use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
-use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
+use syntax::ast::{self, DUMMY_NODE_ID, Ident, AttrVec, Attribute, AttrKind, AttrStyle};
+use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind};
 use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
 use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
 use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
 use syntax::ast::{Mac, MacArgs, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::ThinVec;
 use syntax::token;
 use syntax::tokenstream::{DelimSpan, TokenTree, TokenStream};
 use syntax::struct_span_err;
@@ -648,7 +647,7 @@ impl<'a> Parser<'a> {
         Ok((Ident::invalid(), item_kind, Some(attrs)))
     }
 
-    fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
+    fn parse_impl_body(&mut self) -> PResult<'a, (Vec<AssocItem>, Vec<Attribute>)> {
         self.expect(&token::OpenDelim(token::Brace))?;
         let attrs = self.parse_inner_attributes()?;
 
@@ -669,60 +668,6 @@ impl<'a> Parser<'a> {
         Ok((impl_items, attrs))
     }
 
-    /// Parses an impl item.
-    pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
-        maybe_whole!(self, NtImplItem, |x| x);
-        let attrs = self.parse_outer_attributes()?;
-        let mut unclosed_delims = vec![];
-        let (mut item, tokens) = self.collect_tokens(|this| {
-            let item = this.parse_impl_item_(at_end, attrs);
-            unclosed_delims.append(&mut this.unclosed_delims);
-            item
-        })?;
-        self.unclosed_delims.append(&mut unclosed_delims);
-
-        // See `parse_item` for why this clause is here.
-        if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
-            item.tokens = Some(tokens);
-        }
-        Ok(item)
-    }
-
-    fn parse_impl_item_(
-        &mut self,
-        at_end: &mut bool,
-        mut attrs: Vec<Attribute>,
-    ) -> PResult<'a, ImplItem> {
-        let lo = self.token.span;
-        let vis = self.parse_visibility(FollowedByType::No)?;
-        let defaultness = self.parse_defaultness();
-        let (name, kind, generics) = if self.eat_keyword(kw::Type) {
-            let (name, ty, generics) = self.parse_type_alias()?;
-            (name, ast::ImplItemKind::TyAlias(ty), generics)
-        } else if self.is_const_item() {
-            self.parse_impl_const()?
-        } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? {
-            // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
-            (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default())
-        } else {
-            let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?;
-            attrs.extend(inner_attrs);
-            (name, kind, generics)
-        };
-
-        Ok(ImplItem {
-            id: DUMMY_NODE_ID,
-            span: lo.to(self.prev_span),
-            ident: name,
-            vis,
-            defaultness,
-            attrs,
-            generics,
-            kind,
-            tokens: None,
-        })
-    }
-
     /// Parses defaultness (i.e., `default` or nothing).
     fn parse_defaultness(&mut self) -> Defaultness {
         // `pub` is included for better error messages
@@ -745,26 +690,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Returns `true` if we are looking at `const ID`
-    /// (returns `false` for things like `const fn`, etc.).
-    fn is_const_item(&self) -> bool {
-        self.token.is_keyword(kw::Const) &&
-            !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
-    }
-
-    /// This parses the grammar:
-    ///     ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
-    fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
-        self.expect_keyword(kw::Const)?;
-        let name = self.parse_ident()?;
-        self.expect(&token::Colon)?;
-        let typ = self.parse_ty()?;
-        self.expect(&token::Eq)?;
-        let expr = self.parse_expr()?;
-        self.expect_semi()?;
-        Ok((name, ImplItemKind::Const(typ, expr), Generics::default()))
-    }
-
     /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
     fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
         // Parse optional `auto` prefix.
@@ -857,13 +782,30 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parses the items in a trait declaration.
-    pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> {
+    pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
+        maybe_whole!(self, NtImplItem, |x| x);
+        self.parse_assoc_item(at_end, |_| true)
+    }
+
+    pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
         maybe_whole!(self, NtTraitItem, |x| x);
+        // This is somewhat dubious; We don't want to allow
+        // param names to be left off if there is a definition...
+        //
+        // We don't allow param names to be left off in edition 2018.
+        self.parse_assoc_item(at_end, |t| t.span.rust_2018())
+    }
+
+    /// Parses associated items.
+    fn parse_assoc_item(
+        &mut self,
+        at_end: &mut bool,
+        is_name_required: fn(&token::Token) -> bool,
+    ) -> PResult<'a, AssocItem> {
         let attrs = self.parse_outer_attributes()?;
         let mut unclosed_delims = vec![];
         let (mut item, tokens) = self.collect_tokens(|this| {
-            let item = this.parse_trait_item_(at_end, attrs);
+            let item = this.parse_assoc_item_(at_end, attrs, is_name_required);
             unclosed_delims.append(&mut this.unclosed_delims);
             item
         })?;
@@ -875,54 +817,66 @@ impl<'a> Parser<'a> {
         Ok(item)
     }
 
-    fn parse_trait_item_(
+    fn parse_assoc_item_(
         &mut self,
         at_end: &mut bool,
         mut attrs: Vec<Attribute>,
-    ) -> PResult<'a, TraitItem> {
+        is_name_required: fn(&token::Token) -> bool,
+    ) -> PResult<'a, AssocItem> {
         let lo = self.token.span;
         let vis = self.parse_visibility(FollowedByType::No)?;
+        let defaultness = self.parse_defaultness();
         let (name, kind, generics) = if self.eat_keyword(kw::Type) {
-            self.parse_trait_item_assoc_ty()?
+            self.parse_assoc_ty()?
         } else if self.is_const_item() {
-            self.parse_trait_item_const()?
-        } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
-            // trait item macro.
-            (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
+            self.parse_assoc_const()?
+        } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? {
+            (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default())
         } else {
-            self.parse_trait_item_method(at_end, &mut attrs)?
+            self.parse_assoc_fn(at_end, &mut attrs, is_name_required)?
         };
 
-        Ok(TraitItem {
+        Ok(AssocItem {
             id: DUMMY_NODE_ID,
+            span: lo.to(self.prev_span),
             ident: name,
             attrs,
             vis,
+            defaultness,
             generics,
             kind,
-            span: lo.to(self.prev_span),
             tokens: None,
         })
     }
 
-    fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
+    /// Returns `true` if we are looking at `const ID`
+    /// (returns `false` for things like `const fn`, etc.).
+    fn is_const_item(&self) -> bool {
+        self.token.is_keyword(kw::Const) &&
+            !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
+    }
+
+    /// This parses the grammar:
+    ///
+    ///     AssocConst = "const" Ident ":" Ty "=" Expr ";"
+    fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
         self.expect_keyword(kw::Const)?;
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
-        let default = if self.eat(&token::Eq) {
+        let expr = if self.eat(&token::Eq) {
             Some(self.parse_expr()?)
         } else {
             None
         };
         self.expect_semi()?;
-        Ok((ident, TraitItemKind::Const(ty, default), Generics::default()))
+        Ok((ident, AssocItemKind::Const(ty, expr), Generics::default()))
     }
 
     /// Parses the following grammar:
     ///
-    ///     TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
-    fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
+    ///     AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
+    fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -941,7 +895,7 @@ impl<'a> Parser<'a> {
         };
         self.expect_semi()?;
 
-        Ok((ident, TraitItemKind::Type(bounds, default), generics))
+        Ok((ident, AssocItemKind::TyAlias(bounds, default), generics))
     }
 
     /// Parses a `UseTree`.
@@ -1285,8 +1239,8 @@ impl<'a> Parser<'a> {
         // Construct the error and stash it away with the hope
         // that typeck will later enrich the error with a type.
         let kind = match m {
-            Some(Mutability::Mutable) => "static mut",
-            Some(Mutability::Immutable) => "static",
+            Some(Mutability::Mut) => "static mut",
+            Some(Mutability::Not) => "static",
             None => "const",
         };
         let mut err = self.struct_span_err(id.span, &format!("missing type for `{}` item", kind));
@@ -1363,10 +1317,7 @@ impl<'a> Parser<'a> {
         };
 
         let disr_expr = if self.eat(&token::Eq) {
-            Some(AnonConst {
-                id: DUMMY_NODE_ID,
-                value: self.parse_expr()?,
-            })
+            Some(self.parse_anon_const_expr()?)
         } else {
             None
         };
@@ -1772,8 +1723,6 @@ impl<'a> Parser<'a> {
 pub(super) struct ParamCfg {
     /// Is `self` is allowed as the first parameter?
     pub is_self_allowed: bool,
-    /// Is `...` allowed as the tail of the parameter list?
-    pub allow_c_variadic: bool,
     /// `is_name_required` decides if, per-parameter,
     /// the parameter must have a pattern or just a type.
     pub is_name_required: fn(&token::Token) -> bool,
@@ -1789,16 +1738,8 @@ impl<'a> Parser<'a> {
         attrs: Vec<Attribute>,
         header: FnHeader,
     ) -> PResult<'a, Option<P<Item>>> {
-        let is_c_abi = match header.ext {
-            ast::Extern::None => false,
-            ast::Extern::Implicit => true,
-            ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
-        };
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
-            // FIXME: Parsing should not depend on ABI or unsafety and
-            // the variadic parameter should always be parsed.
-            allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe,
             is_name_required: |_| true,
         })?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1817,7 +1758,6 @@ impl<'a> Parser<'a> {
         self.expect_keyword(kw::Fn)?;
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
-            allow_c_variadic: true,
             is_name_required: |_| true,
         })?;
         let span = lo.to(self.token.span);
@@ -1833,48 +1773,39 @@ impl<'a> Parser<'a> {
         })
     }
 
-    /// Parses a method or a macro invocation in a trait impl.
-    fn parse_impl_method(
-        &mut self,
-        at_end: &mut bool,
-    ) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ImplItemKind)> {
-        let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
-        *at_end = true;
-        let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-        Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
-    }
-
-    fn parse_trait_item_method(
+    fn parse_assoc_fn(
         &mut self,
         at_end: &mut bool,
         attrs: &mut Vec<Attribute>,
-    ) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
-        // This is somewhat dubious; We don't want to allow
-        // argument names to be left off if there is a definition...
-        //
-        // We don't allow argument names to be left off in edition 2018.
-        let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
-        let body = self.parse_trait_method_body(at_end, attrs)?;
-        Ok((ident, TraitItemKind::Method(sig, body), generics))
+        is_name_required: fn(&token::Token) -> bool,
+    ) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
+        let header = self.parse_fn_front_matter()?;
+        let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
+            is_self_allowed: true,
+            is_name_required,
+        })?;
+        let sig = FnSig { header, decl };
+        let body = self.parse_assoc_fn_body(at_end, attrs)?;
+        Ok((ident, AssocItemKind::Fn(sig, body), generics))
     }
 
-    /// Parse the "body" of a method in a trait item definition.
+    /// Parse the "body" of a method in an associated item definition.
     /// This can either be `;` when there's no body,
     /// or e.g. a block when the method is a provided one.
-    fn parse_trait_method_body(
+    fn parse_assoc_fn_body(
         &mut self,
         at_end: &mut bool,
         attrs: &mut Vec<Attribute>,
     ) -> PResult<'a, Option<P<Block>>> {
         Ok(match self.token.kind {
             token::Semi => {
-                debug!("parse_trait_method_body(): parsing required method");
+                debug!("parse_assoc_fn_body(): parsing required method");
                 self.bump();
                 *at_end = true;
                 None
             }
             token::OpenDelim(token::Brace) => {
-                debug!("parse_trait_method_body(): parsing provided method");
+                debug!("parse_assoc_fn_body(): parsing provided method");
                 *at_end = true;
                 let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
                 attrs.extend(inner_attrs.iter().cloned());
@@ -1895,21 +1826,6 @@ impl<'a> Parser<'a> {
         })
     }
 
-    /// Parse the "signature", including the identifier, parameters, and generics
-    /// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
-    fn parse_method_sig(
-        &mut self,
-        is_name_required: fn(&token::Token) -> bool,
-    ) -> PResult<'a, (Ident, FnSig, Generics)> {
-        let header = self.parse_fn_front_matter()?;
-        let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
-            is_self_allowed: true,
-            allow_c_variadic: false,
-            is_name_required,
-        })?;
-        Ok((ident, FnSig { header, decl }, generics))
-    }
-
     /// Parses all the "front matter" for a `fn` declaration, up to
     /// and including the `fn` keyword:
     ///
@@ -1959,64 +1875,29 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, P<FnDecl>> {
         Ok(P(FnDecl {
             inputs: self.parse_fn_params(cfg)?,
-            output: self.parse_ret_ty(ret_allow_plus)?,
+            output: self.parse_ret_ty(ret_allow_plus, true)?,
         }))
     }
 
     /// Parses the parameter list of a function, including the `(` and `)` delimiters.
     fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
-        let sp = self.token.span;
         let is_trait_item = cfg.is_self_allowed;
-        let mut c_variadic = false;
         // Parse the arguments, starting out with `self` being possibly allowed...
-        let (params, _) = self.parse_paren_comma_seq(|p| {
-            let param = p.parse_param_general(&cfg, is_trait_item);
+        let (mut params, _) = self.parse_paren_comma_seq(|p| {
+            let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| {
+                e.emit();
+                let lo = p.prev_span;
+                // Skip every token until next possible arg or end.
+                p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
+                // Create a placeholder argument for proper arg count (issue #34264).
+                Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span))))
+            });
             // ...now that we've parsed the first argument, `self` is no longer allowed.
             cfg.is_self_allowed = false;
-
-            match param {
-                Ok(param) => Ok(
-                    if let TyKind::CVarArgs = param.ty.kind {
-                        c_variadic = true;
-                        if p.token != token::CloseDelim(token::Paren) {
-                            p.span_err(
-                                p.token.span,
-                                "`...` must be the last argument of a C-variadic function",
-                            );
-                            // FIXME(eddyb) this should probably still push `CVarArgs`.
-                            // Maybe AST validation/HIR lowering should emit the above error?
-                            None
-                        } else {
-                            Some(param)
-                        }
-                    } else {
-                        Some(param)
-                    }
-                ),
-                Err(mut e) => {
-                    e.emit();
-                    let lo = p.prev_span;
-                    // Skip every token until next possible arg or end.
-                    p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
-                    // Create a placeholder argument for proper arg count (issue #34264).
-                    let span = lo.to(p.prev_span);
-                    Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
-                }
-            }
+            param
         })?;
-
-        let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
-
         // Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
         self.deduplicate_recovered_params_names(&mut params);
-
-        if c_variadic && params.len() <= 1 {
-            self.span_err(
-                sp,
-                "C-variadic function must be declared with at least one named argument",
-            );
-        }
-
         Ok(params)
     }
 
@@ -2061,12 +1942,12 @@ impl<'a> Parser<'a> {
             }
 
             self.eat_incorrect_doc_comment_for_param_type();
-            (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?)
+            (pat, self.parse_ty_for_param()?)
         } else {
             debug!("parse_param_general ident_to_pat");
             let parser_snapshot_before_ty = self.clone();
             self.eat_incorrect_doc_comment_for_param_type();
-            let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic);
+            let mut ty = self.parse_ty_for_param();
             if ty.is_ok() && self.token != token::Comma &&
                self.token != token::CloseDelim(token::Paren) {
                 // This wasn't actually a type, but a pattern looking like a type,
@@ -2076,7 +1957,7 @@ impl<'a> Parser<'a> {
             match ty {
                 Ok(ty) => {
                     let ident = Ident::new(kw::Invalid, self.prev_span);
-                    let bm = BindingMode::ByValue(Mutability::Immutable);
+                    let bm = BindingMode::ByValue(Mutability::Not);
                     let pat = self.mk_pat_ident(ty.span, bm, ident);
                     (pat, ty)
                 }
@@ -2148,7 +2029,7 @@ impl<'a> Parser<'a> {
                 .span_label(span, msg)
                 .emit();
 
-            Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span))
+            Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_span))
         };
 
         // Parse optional `self` parameter of a method.
@@ -2160,23 +2041,23 @@ impl<'a> Parser<'a> {
                 let eself = if is_isolated_self(self, 1) {
                     // `&self`
                     self.bump();
-                    SelfKind::Region(None, Mutability::Immutable)
+                    SelfKind::Region(None, Mutability::Not)
                 } else if is_isolated_mut_self(self, 1) {
                     // `&mut self`
                     self.bump();
                     self.bump();
-                    SelfKind::Region(None, Mutability::Mutable)
+                    SelfKind::Region(None, Mutability::Mut)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
                     // `&'lt self`
                     self.bump();
                     let lt = self.expect_lifetime();
-                    SelfKind::Region(Some(lt), Mutability::Immutable)
+                    SelfKind::Region(Some(lt), Mutability::Not)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) {
                     // `&'lt mut self`
                     self.bump();
                     let lt = self.expect_lifetime();
                     self.bump();
-                    SelfKind::Region(Some(lt), Mutability::Mutable)
+                    SelfKind::Region(Some(lt), Mutability::Mut)
                 } else {
                     // `&not_self`
                     return Ok(None);
@@ -2199,18 +2080,18 @@ impl<'a> Parser<'a> {
             }
             // `self` and `self: TYPE`
             token::Ident(..) if is_isolated_self(self, 0) => {
-                parse_self_possibly_typed(self, Mutability::Immutable)?
+                parse_self_possibly_typed(self, Mutability::Not)?
             }
             // `mut self` and `mut self: TYPE`
             token::Ident(..) if is_isolated_mut_self(self, 0) => {
                 self.bump();
-                parse_self_possibly_typed(self, Mutability::Mutable)?
+                parse_self_possibly_typed(self, Mutability::Mut)?
             }
             _ => return Ok(None),
         };
 
         let eself = source_map::respan(eself_lo.to(eself_hi), eself);
-        Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
+        Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
     }
 
     fn is_named_param(&self) -> bool {
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 07e99cfe012..16bc2e1a8d6 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -15,9 +15,8 @@ use crate::{Directory, DirectoryOwnership};
 use crate::lexer::UnmatchedBrace;
 
 use rustc_errors::{PResult, Applicability, DiagnosticBuilder, FatalError};
-use rustc_data_structures::thin_vec::ThinVec;
-use syntax::ast::{self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit};
-use syntax::ast::{IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety};
+use syntax::ast::{self, DUMMY_NODE_ID, AttrVec, AttrStyle, CrateSugar, Extern, Ident, Unsafety};
+use syntax::ast::{StrLit, IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::token::{self, Token, TokenKind, DelimToken};
@@ -740,34 +739,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parses a sequence, including the closing delimiter. The function
-    /// `f` must consume tokens until reaching the next separator or
-    /// closing bracket.
-    fn parse_seq_to_end<T>(
-        &mut self,
-        ket: &TokenKind,
-        sep: SeqSep,
-        f: impl FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
-    ) -> PResult<'a, Vec<T>> {
-        let (val, _, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
-        if !recovered {
-            self.bump();
-        }
-        Ok(val)
-    }
-
-    /// Parses a sequence, not including the closing delimiter. The function
-    /// `f` must consume tokens until reaching the next separator or
-    /// closing bracket.
-    fn parse_seq_to_before_end<T>(
-        &mut self,
-        ket: &TokenKind,
-        sep: SeqSep,
-        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
-    ) -> PResult<'a, (Vec<T>, bool, bool)> {
-        self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
-    }
-
     fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool {
         kets.iter().any(|k| {
             match expect {
@@ -855,6 +826,34 @@ impl<'a> Parser<'a> {
         Ok((v, trailing, recovered))
     }
 
+    /// Parses a sequence, not including the closing delimiter. The function
+    /// `f` must consume tokens until reaching the next separator or
+    /// closing bracket.
+    fn parse_seq_to_before_end<T>(
+        &mut self,
+        ket: &TokenKind,
+        sep: SeqSep,
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+    ) -> PResult<'a, (Vec<T>, bool, bool)> {
+        self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
+    }
+
+    /// Parses a sequence, including the closing delimiter. The function
+    /// `f` must consume tokens until reaching the next separator or
+    /// closing bracket.
+    fn parse_seq_to_end<T>(
+        &mut self,
+        ket: &TokenKind,
+        sep: SeqSep,
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
+    ) -> PResult<'a, (Vec<T>, bool /* trailing */)> {
+        let (val, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
+        if !recovered {
+            self.eat(ket);
+        }
+        Ok((val, trailing))
+    }
+
     /// Parses a sequence, including the closing delimiter. The function
     /// `f` must consume tokens until reaching the next separator or
     /// closing bracket.
@@ -866,11 +865,7 @@ impl<'a> Parser<'a> {
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (Vec<T>, bool)> {
         self.expect(bra)?;
-        let (result, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
-        if !recovered {
-            self.eat(ket);
-        }
-        Ok((result, trailing))
+        self.parse_seq_to_end(ket, sep, f)
     }
 
     fn parse_delim_comma_seq<T>(
@@ -979,18 +974,18 @@ impl<'a> Parser<'a> {
     /// Parses mutability (`mut` or nothing).
     fn parse_mutability(&mut self) -> Mutability {
         if self.eat_keyword(kw::Mut) {
-            Mutability::Mutable
+            Mutability::Mut
         } else {
-            Mutability::Immutable
+            Mutability::Not
         }
     }
 
     /// Possibly parses mutability (`const` or `mut`).
     fn parse_const_or_mut(&mut self) -> Option<Mutability> {
         if self.eat_keyword(kw::Mut) {
-            Some(Mutability::Mutable)
+            Some(Mutability::Mut)
         } else if self.eat_keyword(kw::Const) {
-            Some(Mutability::Immutable)
+            Some(Mutability::Not)
         } else {
             None
         }
@@ -1054,8 +1049,8 @@ impl<'a> Parser<'a> {
 
     fn parse_or_use_outer_attributes(
         &mut self,
-        already_parsed_attrs: Option<ThinVec<Attribute>>,
-    ) -> PResult<'a, ThinVec<Attribute>> {
+        already_parsed_attrs: Option<AttrVec>,
+    ) -> PResult<'a, AttrVec> {
         if let Some(attrs) = already_parsed_attrs {
             Ok(attrs)
         } else {
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index 117b92dc9a5..33cac1aacee 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,12 +1,11 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 use rustc_errors::{PResult, Applicability, DiagnosticBuilder};
-use syntax::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
+use syntax::ast::{self, AttrVec, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
 use syntax::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind};
 use syntax::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor};
 use syntax::ptr::P;
 use syntax::print::pprust;
-use syntax::ThinVec;
 use syntax::token;
 use syntax_pos::source_map::{respan, Span, Spanned};
 use syntax_pos::symbol::{kw, sym};
@@ -326,7 +325,7 @@ impl<'a> Parser<'a> {
                 // Parse `ident @ pat`
                 // This can give false positives and parse nullary enums,
                 // they are dealt with later in resolve.
-                self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))?
+                self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
             } else if self.is_start_of_pat_with_path() {
                 // Parse pattern starting with a path
                 let (qself, path) = if self.eat_lt() {
@@ -540,7 +539,7 @@ impl<'a> Parser<'a> {
             )
             .emit();
 
-        self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable))
+        self.parse_pat_ident(BindingMode::ByRef(Mutability::Mut))
     }
 
     /// Turn all by-value immutable bindings in a pattern into mutable bindings.
@@ -553,10 +552,10 @@ impl<'a> Parser<'a> {
             }
 
             fn visit_pat(&mut self, pat: &mut P<Pat>) {
-                if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..)
+                if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Not), ..)
                     = pat.kind
                 {
-                    *m = Mutability::Mutable;
+                    *m = Mutability::Mut;
                     self.0 = true;
                 }
                 noop_visit_pat(pat, self);
@@ -636,7 +635,7 @@ impl<'a> Parser<'a> {
         let op_span = self.token.span;
         // Parse range
         let span = lo.to(self.prev_span);
-        let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
+        let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
         self.bump();
         let end = self.parse_pat_range_end_opt(&begin, form)?;
         Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
@@ -693,7 +692,7 @@ impl<'a> Parser<'a> {
         let lo = self.prev_span;
         let end = self.parse_pat_range_end()?;
         let range_span = lo.to(end.span);
-        let begin = self.mk_expr(range_span, ExprKind::Err, ThinVec::new());
+        let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new());
 
         self.diagnostic()
             .struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
@@ -731,7 +730,7 @@ impl<'a> Parser<'a> {
                 )
                 .emit();
 
-            Ok(self.mk_expr(range_span, ExprKind::Err, ThinVec::new()))
+            Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new()))
         }
     }
 
@@ -747,7 +746,7 @@ impl<'a> Parser<'a> {
                 (None, self.parse_path(PathStyle::Expr)?)
             };
             let hi = self.prev_span;
-            Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), ThinVec::new()))
+            Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), AttrVec::new()))
         } else {
             self.parse_literal_maybe_minus()
         }
@@ -987,10 +986,10 @@ impl<'a> Parser<'a> {
             hi = self.prev_span;
 
             let bind_type = match (is_ref, is_mut) {
-                (true, true) => BindingMode::ByRef(Mutability::Mutable),
-                (true, false) => BindingMode::ByRef(Mutability::Immutable),
-                (false, true) => BindingMode::ByValue(Mutability::Mutable),
-                (false, false) => BindingMode::ByValue(Mutability::Immutable),
+                (true, true) => BindingMode::ByRef(Mutability::Mut),
+                (true, false) => BindingMode::ByRef(Mutability::Not),
+                (false, true) => BindingMode::ByValue(Mutability::Mut),
+                (false, false) => BindingMode::ByValue(Mutability::Not),
             };
 
             let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname);
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 5334fc485e7..802d38e2997 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -3,7 +3,6 @@ use crate::maybe_whole;
 use rustc_errors::{PResult, Applicability, pluralize};
 use syntax::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
 use syntax::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
-use syntax::ThinVec;
 use syntax::token::{self, Token};
 use syntax_pos::source_map::{Span, BytePos};
 use syntax_pos::symbol::{kw, sym};
@@ -182,11 +181,7 @@ impl<'a> Parser<'a> {
                 // `(T, U) -> R`
                 let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
                 let span = ident.span.to(self.prev_span);
-                let output = if self.eat(&token::RArrow) {
-                    Some(self.parse_ty_common(false, false, false)?)
-                } else {
-                    None
-                };
+                let output = self.parse_ret_ty(false, false)?;
                 ParenthesizedArgs { inputs, output, span }.into()
             };
 
@@ -404,7 +399,7 @@ impl<'a> Parser<'a> {
                 // Parse const argument.
                 let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
                     self.parse_block_expr(
-                        None, self.token.span, BlockCheckMode::Default, ThinVec::new()
+                        None, self.token.span, BlockCheckMode::Default, ast::AttrVec::new()
                     )?
                 } else if self.token.is_ident() {
                     // FIXME(const_generics): to distinguish between idents for types and consts,
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 943b6ecc825..42d85e96aef 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -7,15 +7,14 @@ use crate::maybe_whole;
 use crate::DirectoryOwnership;
 
 use rustc_errors::{PResult, Applicability};
-use syntax::ThinVec;
 use syntax::ptr::P;
 use syntax::ast;
 use syntax::ast::{DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
-use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
+use syntax::ast::{AttrVec, Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
 use syntax::util::classify;
 use syntax::token;
 use syntax_pos::source_map::{respan, Span};
-use syntax_pos::symbol::{kw, sym};
+use syntax_pos::symbol::{kw, sym, Symbol};
 
 use std::mem;
 
@@ -23,15 +22,11 @@ impl<'a> Parser<'a> {
     /// Parses a statement. This stops just before trailing semicolons on everything but items.
     /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
     pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
-        Ok(self.parse_stmt_(true))
-    }
-
-    fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> {
-        self.parse_stmt_without_recovery(macro_legacy_warnings).unwrap_or_else(|mut e| {
+        Ok(self.parse_stmt_without_recovery(true).unwrap_or_else(|mut e| {
             e.emit();
             self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
             None
-        })
+        }))
     }
 
     fn parse_stmt_without_recovery(
@@ -43,171 +38,195 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
 
-        Ok(Some(if self.eat_keyword(kw::Let) {
-            Stmt {
-                id: DUMMY_NODE_ID,
-                kind: StmtKind::Local(self.parse_local(attrs.into())?),
-                span: lo.to(self.prev_span),
-            }
-        } else if let Some(macro_def) = self.eat_macro_def(
-            &attrs,
-            &respan(lo, VisibilityKind::Inherited),
-            lo,
-        )? {
-            Stmt {
-                id: DUMMY_NODE_ID,
-                kind: StmtKind::Item(macro_def),
-                span: lo.to(self.prev_span),
-            }
+        if self.eat_keyword(kw::Let) {
+            return self.parse_local_mk(lo, attrs.into()).map(Some)
+        }
+        if self.is_kw_followed_by_ident(kw::Mut) {
+            return self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut");
+        }
+        if self.is_kw_followed_by_ident(kw::Auto) {
+            self.bump(); // `auto`
+            let msg = "write `let` instead of `auto` to introduce a new variable";
+            return self.recover_stmt_local(lo, attrs.into(), msg, "let");
+        }
+        if self.is_kw_followed_by_ident(sym::var) {
+            self.bump(); // `var`
+            let msg = "write `let` instead of `var` to introduce a new variable";
+            return self.recover_stmt_local(lo, attrs.into(), msg, "let");
+        }
+
+        let mac_vis = respan(lo, VisibilityKind::Inherited);
+        if let Some(macro_def) = self.eat_macro_def(&attrs, &mac_vis, lo)? {
+            return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Item(macro_def))));
+        }
+
         // Starts like a simple path, being careful to avoid contextual keywords
         // such as a union items, item with `crate` visibility or auto trait items.
         // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
         // like a path (1 token), but it fact not a path.
-        // `union::b::c` - path, `union U { ... }` - not a path.
-        // `crate::b::c` - path, `crate struct S;` - not a path.
-        } else if self.token.is_path_start() &&
-                  !self.token.is_qpath_start() &&
-                  !self.is_union_item() &&
-                  !self.is_crate_vis() &&
-                  !self.is_auto_trait_item() &&
-                  !self.is_async_fn() {
+        if self.token.is_path_start()
+            && !self.token.is_qpath_start()
+            && !self.is_union_item() // `union::b::c` - path, `union U { ... }` - not a path.
+            && !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path.
+            && !self.is_auto_trait_item()
+            && !self.is_async_fn()
+        {
             let path = self.parse_path(PathStyle::Expr)?;
 
-            if !self.eat(&token::Not) {
-                let expr = if self.check(&token::OpenDelim(token::Brace)) {
-                    self.parse_struct_expr(lo, path, ThinVec::new())?
-                } else {
-                    let hi = self.prev_span;
-                    self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new())
-                };
-
-                let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
-                    let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
-                    this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
-                })?;
-
-                return Ok(Some(Stmt {
-                    id: DUMMY_NODE_ID,
-                    kind: StmtKind::Expr(expr),
-                    span: lo.to(self.prev_span),
-                }));
+            if self.eat(&token::Not) {
+                return self.parse_stmt_mac(lo, attrs.into(), path, macro_legacy_warnings);
             }
 
-            let args = self.parse_mac_args()?;
-            let delim = args.delim();
-            let hi = self.prev_span;
-
-            let style = if delim == token::Brace {
-                MacStmtStyle::Braces
+            let expr = if self.check(&token::OpenDelim(token::Brace)) {
+                self.parse_struct_expr(lo, path, AttrVec::new())?
             } else {
-                MacStmtStyle::NoBraces
+                let hi = self.prev_span;
+                self.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())
             };
 
-            let mac = Mac {
-                path,
-                args,
-                prior_type_ascription: self.last_type_ascription,
-            };
-            let kind = if delim == token::Brace ||
-                          self.token == token::Semi || self.token == token::Eof {
-                StmtKind::Mac(P((mac, style, attrs.into())))
-            }
-            // We used to incorrectly stop parsing macro-expanded statements here.
-            // If the next token will be an error anyway but could have parsed with the
-            // earlier behavior, stop parsing here and emit a warning to avoid breakage.
-            else if macro_legacy_warnings && self.token.can_begin_expr() &&
-                match self.token.kind {
-                    // These can continue an expression, so we can't stop parsing and warn.
-                    token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
-                    token::BinOp(token::Minus) | token::BinOp(token::Star) |
-                    token::BinOp(token::And) | token::BinOp(token::Or) |
-                    token::AndAnd | token::OrOr |
-                    token::DotDot | token::DotDotDot | token::DotDotEq => false,
-                    _ => true,
-                }
-            {
-                self.warn_missing_semicolon();
-                StmtKind::Mac(P((mac, style, attrs.into())))
-            } else {
-                let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), ThinVec::new());
-                let e = self.maybe_recover_from_bad_qpath(e, true)?;
-                let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
-                let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
-                StmtKind::Expr(e)
-            };
-            Stmt {
-                id: DUMMY_NODE_ID,
-                span: lo.to(hi),
-                kind,
+            let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
+                let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
+                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+            })?;
+            return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr))));
+        }
+
+        // FIXME: Bad copy of attrs
+        let old_directory_ownership =
+            mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
+        let item = self.parse_item_(attrs.clone(), false, true)?;
+        self.directory.ownership = old_directory_ownership;
+
+        if let Some(item) = item {
+            return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(item))));
+        }
+
+        // Do not attempt to parse an expression if we're done here.
+        if self.token == token::Semi {
+            self.error_outer_attrs(&attrs);
+            self.bump();
+            let mut last_semi = lo;
+            while self.token == token::Semi {
+                last_semi = self.token.span;
+                self.bump();
             }
+            // We are encoding a string of semicolons as an an empty tuple that spans
+            // the excess semicolons to preserve this info until the lint stage.
+            let kind = StmtKind::Semi(self.mk_expr(
+                lo.to(last_semi),
+                ExprKind::Tup(Vec::new()),
+                AttrVec::new()
+            ));
+            return Ok(Some(self.mk_stmt(lo.to(last_semi), kind)));
+        }
+
+        if self.token == token::CloseDelim(token::Brace) {
+            self.error_outer_attrs(&attrs);
+            return Ok(None);
+        }
+
+        // Remainder are line-expr stmts.
+        let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?;
+        Ok(Some(self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))))
+    }
+
+    /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`.
+    /// At this point, the `!` token after the path has already been eaten.
+    fn parse_stmt_mac(
+        &mut self,
+        lo: Span,
+        attrs: AttrVec,
+        path: ast::Path,
+        legacy_warnings: bool,
+    ) -> PResult<'a, Option<Stmt>> {
+        let args = self.parse_mac_args()?;
+        let delim = args.delim();
+        let hi = self.prev_span;
+
+        let style = if delim == token::Brace {
+            MacStmtStyle::Braces
         } else {
-            // FIXME: Bad copy of attrs
-            let old_directory_ownership =
-                mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
-            let item = self.parse_item_(attrs.clone(), false, true)?;
-            self.directory.ownership = old_directory_ownership;
-
-            match item {
-                Some(i) => Stmt {
-                    id: DUMMY_NODE_ID,
-                    span: lo.to(i.span),
-                    kind: StmtKind::Item(i),
-                },
-                None => {
-                    let unused_attrs = |attrs: &[Attribute], s: &mut Self| {
-                        if !attrs.is_empty() {
-                            if s.prev_token_kind == PrevTokenKind::DocComment {
-                                s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit();
-                            } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
-                                s.span_err(
-                                    s.token.span, "expected statement after outer attribute"
-                                );
-                            }
-                        }
-                    };
-
-                    // Do not attempt to parse an expression if we're done here.
-                    if self.token == token::Semi {
-                        unused_attrs(&attrs, self);
-                        self.bump();
-                        let mut last_semi = lo;
-                        while self.token == token::Semi {
-                            last_semi = self.token.span;
-                            self.bump();
-                        }
-                        // We are encoding a string of semicolons as an
-                        // an empty tuple that spans the excess semicolons
-                        // to preserve this info until the lint stage
-                        return Ok(Some(Stmt {
-                            id: DUMMY_NODE_ID,
-                            span: lo.to(last_semi),
-                            kind: StmtKind::Semi(self.mk_expr(lo.to(last_semi),
-                                ExprKind::Tup(Vec::new()),
-                                ThinVec::new()
-                            )),
-                        }));
-                    }
+            MacStmtStyle::NoBraces
+        };
 
-                    if self.token == token::CloseDelim(token::Brace) {
-                        unused_attrs(&attrs, self);
-                        return Ok(None);
-                    }
+        let mac = Mac {
+            path,
+            args,
+            prior_type_ascription: self.last_type_ascription,
+        };
 
-                    // Remainder are line-expr stmts.
-                    let e = self.parse_expr_res(
-                        Restrictions::STMT_EXPR, Some(attrs.into()))?;
-                    Stmt {
-                        id: DUMMY_NODE_ID,
-                        span: lo.to(e.span),
-                        kind: StmtKind::Expr(e),
-                    }
-                }
+        let kind = if delim == token::Brace
+            || self.token == token::Semi
+            || self.token == token::Eof
+        {
+            StmtKind::Mac(P((mac, style, attrs.into())))
+        }
+        // We used to incorrectly stop parsing macro-expanded statements here.
+        // If the next token will be an error anyway but could have parsed with the
+        // earlier behavior, stop parsing here and emit a warning to avoid breakage.
+        else if legacy_warnings
+            && self.token.can_begin_expr()
+            && match self.token.kind {
+                // These can continue an expression, so we can't stop parsing and warn.
+                token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
+                token::BinOp(token::Minus) | token::BinOp(token::Star) |
+                token::BinOp(token::And) | token::BinOp(token::Or) |
+                token::AndAnd | token::OrOr |
+                token::DotDot | token::DotDotDot | token::DotDotEq => false,
+                _ => true,
             }
-        }))
+        {
+            self.warn_missing_semicolon();
+            StmtKind::Mac(P((mac, style, attrs)))
+        } else {
+            // Since none of the above applied, this is an expression statement macro.
+            let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), AttrVec::new());
+            let e = self.maybe_recover_from_bad_qpath(e, true)?;
+            let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
+            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+            StmtKind::Expr(e)
+        };
+        Ok(Some(self.mk_stmt(lo.to(hi), kind)))
+    }
+
+    /// Error on outer attributes in this context.
+    /// Also error if the previous token was a doc comment.
+    fn error_outer_attrs(&self, attrs: &[Attribute]) {
+        if !attrs.is_empty() {
+            if self.prev_token_kind == PrevTokenKind::DocComment {
+                self.span_fatal_err(self.prev_span, Error::UselessDocComment).emit();
+            } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
+                self.span_err(self.token.span, "expected statement after outer attribute");
+            }
+        }
+    }
+
+    fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
+        self.token.is_keyword(kw)
+            && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
+    }
+
+    fn recover_stmt_local(
+        &mut self,
+        lo: Span,
+        attrs: AttrVec,
+        msg: &str,
+        sugg: &str,
+    ) -> PResult<'a, Option<Stmt>> {
+        let stmt = self.parse_local_mk(lo, attrs)?;
+        self.struct_span_err(lo, "invalid variable declaration")
+            .span_suggestion(lo, msg, sugg.to_string(), Applicability::MachineApplicable)
+            .emit();
+        Ok(Some(stmt))
+    }
+
+    fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {
+        let local = self.parse_local(attrs.into())?;
+        Ok(self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local)))
     }
 
     /// Parses a local variable declaration.
-    fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
+    fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
         let lo = self.prev_span;
         let pat = self.parse_top_pat(GateOr::Yes)?;
 
@@ -307,70 +326,58 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
 
         if !self.eat(&token::OpenDelim(token::Brace)) {
-            let sp = self.token.span;
-            let tok = self.this_token_descr();
-            let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
-            let do_not_suggest_help =
-                self.token.is_keyword(kw::In) || self.token == token::Colon;
-
-            if self.token.is_ident_named(sym::and) {
-                e.span_suggestion_short(
-                    self.token.span,
-                    "use `&&` instead of `and` for the boolean operator",
-                    "&&".to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            if self.token.is_ident_named(sym::or) {
-                e.span_suggestion_short(
-                    self.token.span,
-                    "use `||` instead of `or` for the boolean operator",
-                    "||".to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            }
+            return self.error_block_no_opening_brace();
+        }
 
-            // Check to see if the user has written something like
-            //
-            //    if (cond)
-            //      bar;
-            //
-            // which is valid in other languages, but not Rust.
-            match self.parse_stmt_without_recovery(false) {
-                Ok(Some(stmt)) => {
-                    if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
-                        || do_not_suggest_help {
-                        // If the next token is an open brace (e.g., `if a b {`), the place-
-                        // inside-a-block suggestion would be more likely wrong than right.
-                        e.span_label(sp, "expected `{`");
-                        return Err(e);
-                    }
-                    let mut stmt_span = stmt.span;
-                    // Expand the span to include the semicolon, if it exists.
-                    if self.eat(&token::Semi) {
-                        stmt_span = stmt_span.with_hi(self.prev_span.hi());
-                    }
-                    if let Ok(snippet) = self.span_to_snippet(stmt_span) {
-                        e.span_suggestion(
-                            stmt_span,
-                            "try placing this code inside a block",
-                            format!("{{ {} }}", snippet),
-                            // Speculative; has been misleading in the past (#46836).
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
+        self.parse_block_tail(lo, BlockCheckMode::Default)
+    }
+
+    fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
+        let sp = self.token.span;
+        let tok = self.this_token_descr();
+        let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
+        let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
+
+        // Check to see if the user has written something like
+        //
+        //    if (cond)
+        //      bar;
+        //
+        // which is valid in other languages, but not Rust.
+        match self.parse_stmt_without_recovery(false) {
+            Ok(Some(stmt)) => {
+                if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
+                    || do_not_suggest_help
+                {
+                    // If the next token is an open brace (e.g., `if a b {`), the place-
+                    // inside-a-block suggestion would be more likely wrong than right.
+                    e.span_label(sp, "expected `{`");
+                    return Err(e);
                 }
-                Err(mut e) => {
-                    self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
-                    e.cancel();
+                let stmt_span = if self.eat(&token::Semi) {
+                    // Expand the span to include the semicolon.
+                    stmt.span.with_hi(self.prev_span.hi())
+                } else {
+                    stmt.span
+                };
+                if let Ok(snippet) = self.span_to_snippet(stmt_span) {
+                    e.span_suggestion(
+                        stmt_span,
+                        "try placing this code inside a block",
+                        format!("{{ {} }}", snippet),
+                        // Speculative; has been misleading in the past (#46836).
+                        Applicability::MaybeIncorrect,
+                    );
                 }
-                _ => ()
             }
-            e.span_label(sp, "expected `{`");
-            return Err(e);
+            Err(mut e) => {
+                self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
+                e.cancel();
+            }
+            _ => {}
         }
-
-        self.parse_block_tail(lo, BlockCheckMode::Default)
+        e.span_label(sp, "expected `{`");
+        return Err(e);
     }
 
     /// Parses a block. Inner attributes are allowed.
@@ -402,11 +409,10 @@ impl<'a> Parser<'a> {
                     self.maybe_annotate_with_ascription(&mut err, false);
                     err.emit();
                     self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
-                    Some(Stmt {
-                        id: DUMMY_NODE_ID,
-                        kind: StmtKind::Expr(self.mk_expr_err(self.token.span)),
-                        span: self.token.span,
-                    })
+                    Some(self.mk_stmt(
+                        self.token.span,
+                        StmtKind::Expr(self.mk_expr_err(self.token.span)),
+                    ))
                 }
                 Ok(stmt) => stmt,
             };
@@ -478,4 +484,8 @@ impl<'a> Parser<'a> {
             "this was erroneously allowed and will become a hard error in a future release"
         }).emit();
     }
+
+    fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
+        Stmt { id: DUMMY_NODE_ID, kind, span }
+    }
 }
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 84ffef68e9a..58f3a5b3d60 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -8,9 +8,9 @@ use rustc_error_codes::*;
 use syntax::ptr::P;
 use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
 use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
-use syntax::ast::{Mutability, AnonConst, Mac};
+use syntax::ast::{Mutability, Mac};
 use syntax::token::{self, Token};
-use syntax::struct_span_fatal;
+use syntax::struct_span_err;
 use syntax_pos::source_map::Span;
 use syntax_pos::symbol::kw;
 
@@ -30,6 +30,13 @@ impl<'a> Parser<'a> {
         self.parse_ty_common(true, true, false)
     }
 
+    /// Parse a type suitable for a function or function pointer parameter.
+    /// The difference from `parse_ty` is that this version allows `...`
+    /// (`CVarArgs`) at the top level of the the type.
+    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(true, true, true)
+    }
+
     /// Parses a type in restricted contexts where `+` is not permitted.
     ///
     /// Example 1: `&'a TYPE`
@@ -41,93 +48,46 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an optional return type `[ -> TY ]` in a function declaration.
-    pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
-        if self.eat(&token::RArrow) {
-            Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?))
+    pub(super) fn parse_ret_ty(
+        &mut self,
+        allow_plus: bool,
+        allow_qpath_recovery: bool,
+    ) -> PResult<'a, FunctionRetTy> {
+        Ok(if self.eat(&token::RArrow) {
+            // FIXME(Centril): Can we unconditionally `allow_plus`?
+            FunctionRetTy::Ty(self.parse_ty_common(allow_plus, allow_qpath_recovery, false)?)
         } else {
-            Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo()))
-        }
+            FunctionRetTy::Default(self.token.span.shrink_to_lo())
+        })
     }
 
-    pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
-                       allow_c_variadic: bool) -> PResult<'a, P<Ty>> {
+    fn parse_ty_common(
+        &mut self,
+        allow_plus: bool,
+        allow_qpath_recovery: bool,
+        // Is `...` (`CVarArgs`) legal in the immediate top level call?
+        allow_c_variadic: bool,
+    ) -> PResult<'a, P<Ty>> {
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
         maybe_whole!(self, NtTy, |x| x);
 
         let lo = self.token.span;
         let mut impl_dyn_multi = false;
-        let kind = if self.eat(&token::OpenDelim(token::Paren)) {
-            // `(TYPE)` is a parenthesized type.
-            // `(TYPE,)` is a tuple with a single field of type TYPE.
-            let mut ts = vec![];
-            let mut last_comma = false;
-            while self.token != token::CloseDelim(token::Paren) {
-                ts.push(self.parse_ty()?);
-                if self.eat(&token::Comma) {
-                    last_comma = true;
-                } else {
-                    last_comma = false;
-                    break;
-                }
-            }
-            let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus;
-            self.expect(&token::CloseDelim(token::Paren))?;
-
-            if ts.len() == 1 && !last_comma {
-                let ty = ts.into_iter().nth(0).unwrap().into_inner();
-                let maybe_bounds = allow_plus && self.token.is_like_plus();
-                match ty.kind {
-                    // `(TY_BOUND_NOPAREN) + BOUND + ...`.
-                    TyKind::Path(None, ref path) if maybe_bounds => {
-                        self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)?
-                    }
-                    TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
-                            if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
-                        let path = match bounds[0] {
-                            GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
-                            GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
-                        };
-                        self.parse_remaining_bounds(Vec::new(), path, lo, true)?
-                    }
-                    // `(TYPE)`
-                    _ => TyKind::Paren(P(ty))
-                }
-            } else {
-                TyKind::Tup(ts)
-            }
+        let kind = if self.check(&token::OpenDelim(token::Paren)) {
+            self.parse_ty_tuple_or_parens(lo, allow_plus)?
         } else if self.eat(&token::Not) {
             // Never type `!`
             TyKind::Never
         } else if self.eat(&token::BinOp(token::Star)) {
-            // Raw pointer
-            TyKind::Ptr(self.parse_ptr()?)
+            self.parse_ty_ptr()?
         } else if self.eat(&token::OpenDelim(token::Bracket)) {
-            // Array or slice
-            let t = self.parse_ty()?;
-            // Parse optional `; EXPR` in `[TYPE; EXPR]`
-            let t = match self.maybe_parse_fixed_length_of_vec()? {
-                None => TyKind::Slice(t),
-                Some(length) => TyKind::Array(t, AnonConst {
-                    id: ast::DUMMY_NODE_ID,
-                    value: length,
-                }),
-            };
-            self.expect(&token::CloseDelim(token::Bracket))?;
-            t
+            self.parse_array_or_slice_ty()?
         } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
             // Reference
             self.expect_and()?;
             self.parse_borrowed_pointee()?
         } else if self.eat_keyword_noexpect(kw::Typeof) {
-            // `typeof(EXPR)`
-            // In order to not be ambiguous, the type must be surrounded by parens.
-            self.expect(&token::OpenDelim(token::Paren))?;
-            let e = AnonConst {
-                id: ast::DUMMY_NODE_ID,
-                value: self.parse_expr()?,
-            };
-            self.expect(&token::CloseDelim(token::Paren))?;
-            TyKind::Typeof(e)
+            self.parse_typeof_ty()?
         } else if self.eat_keyword(kw::Underscore) {
             // A type to be inferred `_`
             TyKind::Infer
@@ -138,7 +98,6 @@ impl<'a> Parser<'a> {
             // Function pointer type or bound list (trait object type) starting with a poly-trait.
             //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
             //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
-            let lo = self.token.span;
             let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
             if self.token_is_bare_fn_keyword() {
                 self.parse_ty_bare_fn(lifetime_defs)?
@@ -148,65 +107,33 @@ impl<'a> Parser<'a> {
                 self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
             }
         } else if self.eat_keyword(kw::Impl) {
-            // Always parse bounds greedily for better error recovery.
-            let bounds = self.parse_generic_bounds(None)?;
-            impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
-            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
-        } else if self.check_keyword(kw::Dyn) &&
-                  (self.token.span.rust_2018() ||
-                   self.look_ahead(1, |t| t.can_begin_bound() &&
-                                          !can_continue_type_after_non_fn_ident(t))) {
-            self.bump(); // `dyn`
-            // Always parse bounds greedily for better error recovery.
-            let bounds = self.parse_generic_bounds(None)?;
-            impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
-            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
-        } else if self.check(&token::Question) ||
-                  self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) {
+            self.parse_impl_ty(&mut impl_dyn_multi)?
+        } else if self.is_explicit_dyn_type() {
+            self.parse_dyn_ty(&mut impl_dyn_multi)?
+        } else if self.check(&token::Question)
+            || self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus())
+        {
             // Bound list (trait object type)
-            TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?,
-                                TraitObjectSyntax::None)
+            let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
+            TyKind::TraitObject(bounds, TraitObjectSyntax::None)
         } else if self.eat_lt() {
             // Qualified path
             let (qself, path) = self.parse_qpath(PathStyle::Type)?;
             TyKind::Path(Some(qself), path)
         } else if self.token.is_path_start() {
-            // Simple path
-            let path = self.parse_path(PathStyle::Type)?;
-            if self.eat(&token::Not) {
-                // Macro invocation in type position
-                let args = self.parse_mac_args()?;
-                let mac = Mac {
-                    path,
-                    args,
-                    prior_type_ascription: self.last_type_ascription,
-                };
-                TyKind::Mac(mac)
-            } else {
-                // Just a type path or bound list (trait object type) starting with a trait.
-                //   `Type`
-                //   `Trait1 + Trait2 + 'a`
-                if allow_plus && self.check_plus() {
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)?
-                } else {
-                    TyKind::Path(None, path)
-                }
-            }
-        } else if self.check(&token::DotDotDot) {
+            self.parse_path_start_ty(lo, allow_plus)?
+        } else if self.eat(&token::DotDotDot) {
             if allow_c_variadic {
-                self.eat(&token::DotDotDot);
                 TyKind::CVarArgs
             } else {
-                return Err(struct_span_fatal!(
-                    self.sess.span_diagnostic,
-                    self.token.span,
-                    E0743,
-                    "only foreign functions are allowed to be C-variadic",
-                ));
+                // FIXME(Centril): Should we just allow `...` syntactically
+                // anywhere in a type and use semantic restrictions instead?
+                self.error_illegal_c_varadic_ty(lo);
+                TyKind::Err
             }
         } else {
             let msg = format!("expected type, found {}", self.this_token_descr());
-            let mut err = self.fatal(&msg);
+            let mut err = self.struct_span_err(self.token.span, &msg);
             err.span_label(self.token.span, "expected type");
             self.maybe_annotate_with_ascription(&mut err, true);
             return Err(err);
@@ -221,8 +148,48 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
     }
 
-    fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
-                              lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
+    /// Parses either:
+    /// - `(TYPE)`, a parenthesized type.
+    /// - `(TYPE,)`, a tuple with a single field of type TYPE.
+    fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: bool) -> PResult<'a, TyKind> {
+        let mut trailing_plus = false;
+        let (ts, trailing) = self.parse_paren_comma_seq(|p| {
+            let ty = p.parse_ty()?;
+            trailing_plus = p.prev_token_kind == PrevTokenKind::Plus;
+            Ok(ty)
+        })?;
+
+        if ts.len() == 1 && !trailing {
+            let ty = ts.into_iter().nth(0).unwrap().into_inner();
+            let maybe_bounds = allow_plus && self.token.is_like_plus();
+            match ty.kind {
+                // `(TY_BOUND_NOPAREN) + BOUND + ...`.
+                TyKind::Path(None, path) if maybe_bounds => {
+                    self.parse_remaining_bounds(Vec::new(), path, lo, true)
+                }
+                TyKind::TraitObject(mut bounds, TraitObjectSyntax::None)
+                if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
+                    let path = match bounds.remove(0) {
+                        GenericBound::Trait(pt, ..) => pt.trait_ref.path,
+                        GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
+                    };
+                    self.parse_remaining_bounds(Vec::new(), path, lo, true)
+                }
+                // `(TYPE)`
+                _ => Ok(TyKind::Paren(P(ty)))
+            }
+        } else {
+            Ok(TyKind::Tup(ts))
+        }
+    }
+
+    fn parse_remaining_bounds(
+        &mut self,
+        generic_params: Vec<GenericParam>,
+        path: ast::Path,
+        lo: Span,
+        parse_plus: bool,
+    ) -> PResult<'a, TyKind> {
         let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
         let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
         if parse_plus {
@@ -232,7 +199,8 @@ impl<'a> Parser<'a> {
         Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
     }
 
-    fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
+    /// Parses a raw pointer type: `*[const | mut] $type`.
+    fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
         let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
             let span = self.prev_span;
             let msg = "expected mut or const in raw pointer type";
@@ -240,25 +208,39 @@ impl<'a> Parser<'a> {
                 .span_label(span, msg)
                 .help("use `*mut T` or `*const T` as appropriate")
                 .emit();
-            Mutability::Immutable
+            Mutability::Not
         });
-        let t = self.parse_ty_no_plus()?;
-        Ok(MutTy { ty: t, mutbl })
+        let ty = self.parse_ty_no_plus()?;
+        Ok(TyKind::Ptr(MutTy { ty, mutbl }))
     }
 
-    fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> {
-        if self.eat(&token::Semi) {
-            Ok(Some(self.parse_expr()?))
+    /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
+    /// The opening `[` bracket is already eaten.
+    fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
+        let elt_ty = self.parse_ty()?;
+        let ty = if self.eat(&token::Semi) {
+            TyKind::Array(elt_ty, self.parse_anon_const_expr()?)
         } else {
-            Ok(None)
-        }
+            TyKind::Slice(elt_ty)
+        };
+        self.expect(&token::CloseDelim(token::Bracket))?;
+        Ok(ty)
     }
 
     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
         let mutbl = self.parse_mutability();
         let ty = self.parse_ty_no_plus()?;
-        return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }));
+        Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
+    }
+
+    // Parses the `typeof(EXPR)`.
+    // To avoid ambiguity, the type is surrounded by parenthesis.
+    fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
+        self.expect(&token::OpenDelim(token::Paren))?;
+        let expr = self.parse_anon_const_expr()?;
+        self.expect(&token::CloseDelim(token::Paren))?;
+        Ok(TyKind::Typeof(expr))
     }
 
     /// Is the current token one of the keywords that signals a bare function type?
@@ -268,26 +250,20 @@ impl<'a> Parser<'a> {
             self.check_keyword(kw::Extern)
     }
 
-    /// Parses a `TyKind::BareFn` type.
+    /// Parses a function pointer type (`TyKind::BareFn`).
+    /// ```
+    /// [unsafe] [extern "ABI"] fn (S) -> T
+    ///  ^~~~~^          ^~~~^     ^~^    ^
+    ///    |               |        |     |
+    ///    |               |        |   Return type
+    /// Function Style    ABI  Parameter types
+    /// ```
     fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
-        /*
-
-        [unsafe] [extern "ABI"] fn (S) -> T
-         ^~~~^           ^~~~^     ^~^    ^
-           |               |        |     |
-           |               |        |   Return type
-           |               |      Argument types
-           |               |
-           |              ABI
-        Function Style
-        */
-
         let unsafety = self.parse_unsafety();
         let ext = self.parse_extern()?;
         self.expect_keyword(kw::Fn)?;
         let cfg = ParamCfg {
             is_self_allowed: false,
-            allow_c_variadic: true,
             is_name_required: |_| false,
         };
         let decl = self.parse_fn_decl(cfg, false)?;
@@ -299,130 +275,241 @@ impl<'a> Parser<'a> {
         })))
     }
 
-    pub(super) fn parse_generic_bounds(&mut self,
-                                  colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
+    /// Parses an `impl B0 + ... + Bn` type.
+    fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
+        // Always parse bounds greedily for better error recovery.
+        let bounds = self.parse_generic_bounds(None)?;
+        *impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
+        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
+    }
+
+    /// Is a `dyn B0 + ... + Bn` type allowed here?
+    fn is_explicit_dyn_type(&mut self) -> bool {
+        self.check_keyword(kw::Dyn)
+            && (self.token.span.rust_2018()
+                || self.look_ahead(1, |t| {
+                    t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)
+                }))
+    }
+
+    /// Parses a `dyn B0 + ... + Bn` type.
+    ///
+    /// Note that this does *not* parse bare trait objects.
+    fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
+        self.bump(); // `dyn`
+        // Always parse bounds greedily for better error recovery.
+        let bounds = self.parse_generic_bounds(None)?;
+        *impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
+        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn))
+    }
+
+    /// Parses a type starting with a path.
+    ///
+    /// This can be:
+    /// 1. a type macro, `mac!(...)`,
+    /// 2. a bare trait object, `B0 + ... + Bn`,
+    /// 3. or a path, `path::to::MyType`.
+    fn parse_path_start_ty(&mut self, lo: Span, allow_plus: bool) -> PResult<'a, TyKind> {
+        // Simple path
+        let path = self.parse_path(PathStyle::Type)?;
+        if self.eat(&token::Not) {
+            // Macro invocation in type position
+            Ok(TyKind::Mac(Mac {
+                path,
+                args: self.parse_mac_args()?,
+                prior_type_ascription: self.last_type_ascription,
+            }))
+        } else if allow_plus && self.check_plus() {
+            // `Trait1 + Trait2 + 'a`
+            self.parse_remaining_bounds(Vec::new(), path, lo, true)
+        } else {
+            // Just a type path.
+            Ok(TyKind::Path(None, path))
+        }
+    }
+
+    fn error_illegal_c_varadic_ty(&self, lo: Span) {
+        struct_span_err!(
+            self.sess.span_diagnostic,
+            lo.to(self.prev_span),
+            E0743,
+            "C-variadic type `...` may not be nested inside another type",
+        )
+        .emit();
+    }
+
+    pub(super) fn parse_generic_bounds(
+        &mut self,
+        colon_span: Option<Span>,
+    ) -> PResult<'a, GenericBounds> {
         self.parse_generic_bounds_common(true, colon_span)
     }
 
     /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
     ///
-    /// ```
-    /// BOUND = TY_BOUND | LT_BOUND
-    /// LT_BOUND = LIFETIME (e.g., `'a`)
-    /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
-    /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
-    /// ```
-    fn parse_generic_bounds_common(&mut self,
-                                   allow_plus: bool,
-                                   colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
+    /// See `parse_generic_bound` for the `BOUND` grammar.
+    fn parse_generic_bounds_common(
+        &mut self,
+        allow_plus: bool,
+        colon_span: Option<Span>,
+    ) -> PResult<'a, GenericBounds> {
         let mut bounds = Vec::new();
         let mut negative_bounds = Vec::new();
-        let mut last_plus_span = None;
-        let mut was_negative = false;
-        loop {
-            // This needs to be synchronized with `TokenKind::can_begin_bound`.
-            let is_bound_start = self.check_path() || self.check_lifetime() ||
-                                 self.check(&token::Not) || // used for error reporting only
-                                 self.check(&token::Question) ||
-                                 self.check_keyword(kw::For) ||
-                                 self.check(&token::OpenDelim(token::Paren));
-            if is_bound_start {
-                let lo = self.token.span;
-                let has_parens = self.eat(&token::OpenDelim(token::Paren));
-                let inner_lo = self.token.span;
-                let is_negative = self.eat(&token::Not);
-                let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
-                if self.token.is_lifetime() {
-                    if let Some(question_span) = question {
-                        self.span_err(question_span,
-                                      "`?` may only modify trait bounds, not lifetime bounds");
-                    }
-                    bounds.push(GenericBound::Outlives(self.expect_lifetime()));
-                    if has_parens {
-                        let inner_span = inner_lo.to(self.prev_span);
-                        self.expect(&token::CloseDelim(token::Paren))?;
-                        let mut err = self.struct_span_err(
-                            lo.to(self.prev_span),
-                            "parenthesized lifetime bounds are not supported"
-                        );
-                        if let Ok(snippet) = self.span_to_snippet(inner_span) {
-                            err.span_suggestion_short(
-                                lo.to(self.prev_span),
-                                "remove the parentheses",
-                                snippet.to_owned(),
-                                Applicability::MachineApplicable
-                            );
-                        }
-                        err.emit();
-                    }
-                } else {
-                    let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-                    let path = self.parse_path(PathStyle::Type)?;
-                    if has_parens {
-                        self.expect(&token::CloseDelim(token::Paren))?;
-                    }
-                    let poly_span = lo.to(self.prev_span);
-                    if is_negative {
-                        was_negative = true;
-                        if let Some(sp) = last_plus_span.or(colon_span) {
-                            negative_bounds.push(sp.to(poly_span));
-                        }
-                    } else {
-                        let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
-                        let modifier = if question.is_some() {
-                            TraitBoundModifier::Maybe
-                        } else {
-                            TraitBoundModifier::None
-                        };
-                        bounds.push(GenericBound::Trait(poly_trait, modifier));
-                    }
-                }
-            } else {
-                break
+        while self.can_begin_bound() {
+            match self.parse_generic_bound()? {
+                Ok(bound) => bounds.push(bound),
+                Err(neg_sp) => negative_bounds.push(neg_sp),
             }
-
             if !allow_plus || !self.eat_plus() {
                 break
-            } else {
-                last_plus_span = Some(self.prev_span);
             }
         }
 
-        if !negative_bounds.is_empty() || was_negative {
-            let negative_bounds_len = negative_bounds.len();
-            let last_span = negative_bounds.last().map(|sp| *sp);
-            let mut err = self.struct_span_err(
-                negative_bounds,
-                "negative trait bounds are not supported",
-            );
-            if let Some(sp) = last_span {
-                err.span_label(sp, "negative trait bounds are not supported");
-            }
-            if let Some(bound_list) = colon_span {
-                let bound_list = bound_list.to(self.prev_span);
-                let mut new_bound_list = String::new();
-                if !bounds.is_empty() {
-                    let mut snippets = bounds.iter().map(|bound| bound.span())
-                        .map(|span| self.span_to_snippet(span));
-                    while let Some(Ok(snippet)) = snippets.next() {
-                        new_bound_list.push_str(" + ");
-                        new_bound_list.push_str(&snippet);
-                    }
-                    new_bound_list = new_bound_list.replacen(" +", ":", 1);
+        if !negative_bounds.is_empty() {
+            self.error_negative_bounds(colon_span, &bounds, negative_bounds);
+        }
+
+        Ok(bounds)
+    }
+
+    /// Can the current token begin a bound?
+    fn can_begin_bound(&mut self) -> bool {
+        // This needs to be synchronized with `TokenKind::can_begin_bound`.
+        self.check_path()
+        || self.check_lifetime()
+        || self.check(&token::Not) // Used for error reporting only.
+        || self.check(&token::Question)
+        || self.check_keyword(kw::For)
+        || self.check(&token::OpenDelim(token::Paren))
+    }
+
+    fn error_negative_bounds(
+        &self,
+        colon_span: Option<Span>,
+        bounds: &[GenericBound],
+        negative_bounds: Vec<Span>,
+    ) {
+        let negative_bounds_len = negative_bounds.len();
+        let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
+        let mut err = self.struct_span_err(
+            negative_bounds,
+            "negative bounds are not supported",
+        );
+        err.span_label(last_span, "negative bounds are not supported");
+        if let Some(bound_list) = colon_span {
+            let bound_list = bound_list.to(self.prev_span);
+            let mut new_bound_list = String::new();
+            if !bounds.is_empty() {
+                let mut snippets = bounds.iter().map(|bound| self.span_to_snippet(bound.span()));
+                while let Some(Ok(snippet)) = snippets.next() {
+                    new_bound_list.push_str(" + ");
+                    new_bound_list.push_str(&snippet);
                 }
-                err.span_suggestion_hidden(
-                    bound_list,
-                    &format!("remove the trait bound{}", pluralize!(negative_bounds_len)),
-                    new_bound_list,
-                    Applicability::MachineApplicable,
-                );
+                new_bound_list = new_bound_list.replacen(" +", ":", 1);
             }
-            err.emit();
+            err.tool_only_span_suggestion(
+                bound_list,
+                &format!("remove the bound{}", pluralize!(negative_bounds_len)),
+                new_bound_list,
+                Applicability::MachineApplicable,
+            );
+        }
+        err.emit();
+    }
+
+    /// Parses a bound according to the grammar:
+    /// ```
+    /// BOUND = TY_BOUND | LT_BOUND
+    /// ```
+    fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
+        let anchor_lo = self.prev_span;
+        let lo = self.token.span;
+        let has_parens = self.eat(&token::OpenDelim(token::Paren));
+        let inner_lo = self.token.span;
+        let is_negative = self.eat(&token::Not);
+        let question = self.eat(&token::Question).then_some(self.prev_span);
+        let bound = if self.token.is_lifetime() {
+            self.parse_generic_lt_bound(lo, inner_lo, has_parens, question)?
+        } else {
+            self.parse_generic_ty_bound(lo, has_parens, question)?
+        };
+        Ok(if is_negative {
+            Err(anchor_lo.to(self.prev_span))
+        } else {
+            Ok(bound)
+        })
+    }
+
+    /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
+    /// ```
+    /// LT_BOUND = LIFETIME
+    /// ```
+    fn parse_generic_lt_bound(
+        &mut self,
+        lo: Span,
+        inner_lo: Span,
+        has_parens: bool,
+        question: Option<Span>,
+    ) -> PResult<'a, GenericBound> {
+        self.error_opt_out_lifetime(question);
+        let bound = GenericBound::Outlives(self.expect_lifetime());
+        if has_parens {
+            // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
+            // possibly introducing `GenericBound::Paren(P<GenericBound>)`?
+            self.recover_paren_lifetime(lo, inner_lo)?;
         }
+        Ok(bound)
+    }
 
-        return Ok(bounds);
+    fn error_opt_out_lifetime(&self, question: Option<Span>) {
+        if let Some(span) = question {
+            self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
+                .emit();
+        }
+    }
+
+    /// Recover on `('lifetime)` with `(` already eaten.
+    fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
+        let inner_span = inner_lo.to(self.prev_span);
+        self.expect(&token::CloseDelim(token::Paren))?;
+        let mut err = self.struct_span_err(
+            lo.to(self.prev_span),
+            "parenthesized lifetime bounds are not supported"
+        );
+        if let Ok(snippet) = self.span_to_snippet(inner_span) {
+            err.span_suggestion_short(
+                lo.to(self.prev_span),
+                "remove the parentheses",
+                snippet.to_owned(),
+                Applicability::MachineApplicable
+            );
+        }
+        err.emit();
+        Ok(())
+    }
+
+    /// Parses a type bound according to:
+    /// ```
+    /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
+    /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
+    /// ```
+    fn parse_generic_ty_bound(
+        &mut self,
+        lo: Span,
+        has_parens: bool,
+        question: Option<Span>,
+    ) -> PResult<'a, GenericBound> {
+        let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+        let path = self.parse_path(PathStyle::Type)?;
+        if has_parens {
+            self.expect(&token::CloseDelim(token::Paren))?;
+        }
+        let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
+        let modifier = question.map_or(TraitBoundModifier::None, |_| TraitBoundModifier::Maybe);
+        Ok(GenericBound::Trait(poly_trait, modifier))
     }
 
+    /// Optionally parses `for<$generic_params>`.
     pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
         if self.eat_keyword(kw::For) {
             self.expect_lt()?;
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 202b6ae2f94..ee6a67802ad 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -161,9 +161,9 @@ impl<'a> AstValidator<'a> {
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
-                PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
+                PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) |
                 PatKind::Wild => {}
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) =>
                     report_err(pat.span, true),
                 _ => report_err(pat.span, false),
             }
@@ -250,6 +250,26 @@ impl<'a> AstValidator<'a> {
     }
 
     fn check_fn_decl(&self, fn_decl: &FnDecl) {
+        match &*fn_decl.inputs {
+            [Param { ty, span, .. }] => if let TyKind::CVarArgs = ty.kind {
+                self.err_handler()
+                    .span_err(
+                        *span,
+                        "C-variadic function must be declared with at least one named argument",
+                    );
+            },
+            [ps @ .., _] => for Param { ty, span, .. } in ps {
+                if let TyKind::CVarArgs = ty.kind {
+                    self.err_handler()
+                        .span_err(
+                            *span,
+                            "`...` must be the last argument of a C-variadic function",
+                        );
+                }
+            }
+            _ => {}
+        }
+
         fn_decl
             .inputs
             .iter()
@@ -259,18 +279,65 @@ impl<'a> AstValidator<'a> {
                 !arr.contains(&attr.name_or_empty()) && attr::is_builtin_attr(attr)
             })
             .for_each(|attr| if attr.is_doc_comment() {
-                let mut err = self.err_handler().struct_span_err(
+                self.err_handler().struct_span_err(
                     attr.span,
                     "documentation comments cannot be applied to function parameters"
-                );
-                err.span_label(attr.span, "doc comments are not allowed here");
-                err.emit();
-            }
-            else {
+                )
+                .span_label(attr.span, "doc comments are not allowed here")
+                .emit();
+            } else {
                 self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \
                 forbid, and warn are the only allowed built-in attributes in function parameters")
             });
     }
+
+    fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
+        if let Defaultness::Default = defaultness {
+            self.err_handler()
+                .struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
+                .emit();
+        }
+    }
+
+    fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
+        if body.is_some() {
+            return;
+        }
+
+        self.err_handler()
+            .struct_span_err(sp, &format!("associated {} in `impl` without body", ctx))
+            .span_suggestion(
+                self.session.source_map().end_point(sp),
+                &format!("provide a definition for the {}", ctx),
+                sugg.to_string(),
+                Applicability::HasPlaceholders,
+            )
+            .emit();
+    }
+
+    fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
+        let span = match bounds {
+            [] => return,
+            [b0] => b0.span(),
+            [b0, .., bl] => b0.span().to(bl.span()),
+        };
+        self.err_handler()
+            .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect")
+            .emit();
+    }
+
+    fn check_c_varadic_type(&self, decl: &FnDecl) {
+        for Param { ty, span, .. } in &decl.inputs {
+            if let TyKind::CVarArgs = ty.kind {
+                self.err_handler()
+                    .struct_span_err(
+                        *span,
+                        "only foreign or `unsafe extern \"C\" functions may be C-variadic",
+                    )
+                    .emit();
+            }
+        }
+    }
 }
 
 enum GenericPosition {
@@ -477,7 +544,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
                 for impl_item in impl_items {
                     self.invalid_visibility(&impl_item.vis, None);
-                    if let ImplItemKind::Method(ref sig, _) = impl_item.kind {
+                    if let AssocItemKind::Fn(ref sig, _) = impl_item.kind {
                         self.check_trait_fn_not_const(sig.header.constness);
                         self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
                     }
@@ -519,6 +586,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         }
                     }
                 }
+                // Reject C-varadic type unless the function is `unsafe extern "C"` semantically.
+                match sig.header.ext {
+                    Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) |
+                    Extern::Implicit if sig.header.unsafety == Unsafety::Unsafe => {}
+                    _ => self.check_c_varadic_type(&sig.decl),
+                }
             }
             ItemKind::ForeignMod(..) => {
                 self.invalid_visibility(
@@ -554,26 +627,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     }
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
-                for trait_item in trait_items {
-                    if let TraitItemKind::Method(ref sig, ref block) = trait_item.kind {
-                        self.check_fn_decl(&sig.decl);
-                        self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
-                        self.check_trait_fn_not_const(sig.header.constness);
-                        if block.is_none() {
-                            Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
-                                if mut_ident {
-                                    self.lint_buffer.buffer_lint(
-                                        lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
-                                        trait_item.id, span,
-                                        "patterns aren't allowed in methods without bodies");
-                                } else {
-                                    struct_span_err!(self.session, span, E0642,
-                                        "patterns aren't allowed in methods without bodies").emit();
-                                }
-                            });
-                        }
-                    }
-                }
             }
             ItemKind::Mod(_) => {
                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
@@ -639,10 +692,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             GenericArgs::Parenthesized(ref data) => {
                 walk_list!(self, visit_ty, &data.inputs);
-                if let Some(ref type_) = data.output {
+                if let FunctionRetTy::Ty(ty) = &data.output {
                     // `-> Foo` syntax is essentially an associated type binding,
                     // so it is also allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(None, |this| this.visit_ty(type_));
+                    self.with_impl_trait(None, |this| this.visit_ty(ty));
                 }
             }
         }
@@ -737,17 +790,59 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             |this| visit::walk_enum_def(this, enum_definition, generics, item_id))
     }
 
-    fn visit_impl_item(&mut self, ii: &'a ImplItem) {
-        if let ImplItemKind::Method(ref sig, _) = ii.kind {
-            self.check_fn_decl(&sig.decl);
+    fn visit_impl_item(&mut self, ii: &'a AssocItem) {
+        match &ii.kind {
+            AssocItemKind::Const(_, body) => {
+                self.check_impl_item_provided(ii.span, body, "constant", " = <expr>;");
+            }
+            AssocItemKind::Fn(sig, body) => {
+                self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
+                self.check_fn_decl(&sig.decl);
+            }
+            AssocItemKind::TyAlias(bounds, body) => {
+                self.check_impl_item_provided(ii.span, body, "type", " = <type>;");
+                self.check_impl_assoc_type_no_bounds(bounds);
+            }
+            _ => {}
         }
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_trait_item(&mut self, ti: &'a TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'a AssocItem) {
         self.invalid_visibility(&ti.vis, None);
+        self.check_defaultness(ti.span, ti.defaultness);
+
+        if let AssocItemKind::Fn(sig, block) = &ti.kind {
+            self.check_fn_decl(&sig.decl);
+            self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node);
+            self.check_trait_fn_not_const(sig.header.constness);
+            if block.is_none() {
+                Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
+                    if mut_ident {
+                        self.lint_buffer.buffer_lint(
+                            lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                            ti.id, span,
+                            "patterns aren't allowed in methods without bodies"
+                        );
+                    } else {
+                        struct_span_err!(
+                            self.session, span, E0642,
+                            "patterns aren't allowed in methods without bodies"
+                        ).emit();
+                    }
+                });
+            }
+        }
+
         visit::walk_trait_item(self, ti);
     }
+
+    fn visit_assoc_item(&mut self, item: &'a AssocItem) {
+        if let AssocItemKind::Fn(sig, _) = &item.kind {
+            self.check_c_varadic_type(&sig.decl);
+        }
+        visit::walk_assoc_item(self, item);
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs
index 725a742382e..6b5b5c823e8 100644
--- a/src/librustc_passes/check_const.rs
+++ b/src/librustc_passes/check_const.rs
@@ -75,14 +75,14 @@ enum ConstKind {
 }
 
 impl ConstKind {
-    fn for_body(body: &hir::Body, hir_map: &Map<'_>) -> Option<Self> {
+    fn for_body(body: &hir::Body<'_>, hir_map: &Map<'_>) -> Option<Self> {
         let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();
 
         let owner = hir_map.body_owner(body.id());
         let const_kind = match hir_map.body_owner_kind(owner) {
             hir::BodyOwnerKind::Const => Self::Const,
-            hir::BodyOwnerKind::Static(Mutability::Mutable) => Self::StaticMut,
-            hir::BodyOwnerKind::Static(Mutability::Immutable) => Self::Static,
+            hir::BodyOwnerKind::Static(Mutability::Mut) => Self::StaticMut,
+            hir::BodyOwnerKind::Static(Mutability::Not) => Self::Static,
 
             hir::BodyOwnerKind::Fn if is_const_fn(owner) => Self::ConstFn,
             hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None,
@@ -215,7 +215,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
         self.recurse_into(kind, |this| hir::intravisit::walk_anon_const(this, anon));
     }
 
-    fn visit_body(&mut self, body: &'tcx hir::Body) {
+    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
         let kind = ConstKind::for_body(body, self.tcx.hir());
         self.recurse_into(kind, |this| hir::intravisit::walk_body(this, body));
     }
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index db661e7f4d2..3edd010f311 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -223,7 +223,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
         self.tables = old_tables;
     }
 
-    fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name,
+    fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>, _: ast::Name,
                           _: &hir::Generics, _: hir::HirId, _: syntax_pos::Span) {
         let has_repr_c = self.repr_has_repr_c;
         let inherited_pub_visibility = self.inherited_pub_visibility;
@@ -355,14 +355,14 @@ fn has_allow_dead_code_or_lang_attr(
 //     * Implementation of a trait method
 struct LifeSeeder<'k, 'tcx> {
     worklist: Vec<hir::HirId>,
-    krate: &'k hir::Crate,
+    krate: &'k hir::Crate<'k>,
     tcx: TyCtxt<'tcx>,
     // see `MarkSymbolVisitor::struct_constructors`
     struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
 }
 
 impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx,
                                                                item.hir_id,
                                                                &item.attrs);
@@ -375,13 +375,13 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
                     self.worklist.extend(enum_def.variants.iter().map(|variant| variant.id));
                 }
 
-                for variant in &enum_def.variants {
+                for variant in enum_def.variants {
                     if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
                         self.struct_constructors.insert(ctor_hir_id, variant.id);
                     }
                 }
             }
-            hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            hir::ItemKind::Trait(.., trait_item_refs) => {
                 for trait_item_ref in trait_item_refs {
                     let trait_item = self.krate.trait_item(trait_item_ref.id);
                     match trait_item.kind {
@@ -397,7 +397,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
                     }
                 }
             }
-            hir::ItemKind::Impl(.., ref opt_trait, _, ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., ref opt_trait, _, impl_item_refs) => {
                 for impl_item_ref in impl_item_refs {
                     let impl_item = self.krate.impl_item(impl_item_ref.id);
                     if opt_trait.is_some() ||
@@ -417,11 +417,11 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _item: &hir::TraitItem<'_>) {
         // ignore: we are handling this in `visit_item` above
     }
 
-    fn visit_impl_item(&mut self, _item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _item: &hir::ImplItem<'_>) {
         // ignore: we are handling this in `visit_item` above
     }
 }
@@ -429,7 +429,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
 fn create_and_seed_worklist<'tcx>(
     tcx: TyCtxt<'tcx>,
     access_levels: &privacy::AccessLevels,
-    krate: &hir::Crate,
+    krate: &hir::Crate<'_>,
 ) -> (Vec<hir::HirId>, FxHashMap<hir::HirId, hir::HirId>) {
     let worklist = access_levels.map.iter().filter_map(|(&id, level)| {
         if level >= &privacy::AccessLevel::Reachable {
@@ -457,7 +457,7 @@ fn create_and_seed_worklist<'tcx>(
 fn find_live<'tcx>(
     tcx: TyCtxt<'tcx>,
     access_levels: &privacy::AccessLevels,
-    krate: &hir::Crate,
+    krate: &hir::Crate<'_>,
 ) -> FxHashSet<hir::HirId> {
     let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate);
     let mut symbol_visitor = MarkSymbolVisitor {
@@ -481,7 +481,7 @@ struct DeadVisitor<'tcx> {
 }
 
 impl DeadVisitor<'tcx> {
-    fn should_warn_about_item(&mut self, item: &hir::Item) -> bool {
+    fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool {
         let should_warn = match item.kind {
             hir::ItemKind::Static(..)
             | hir::ItemKind::Const(..)
@@ -495,7 +495,7 @@ impl DeadVisitor<'tcx> {
         should_warn && !self.symbol_is_live(item.hir_id)
     }
 
-    fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
+    fn should_warn_about_field(&mut self, field: &hir::StructField<'_>) -> bool {
         let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id));
         !field.is_positional()
             && !self.symbol_is_live(field.hir_id)
@@ -503,14 +503,14 @@ impl DeadVisitor<'tcx> {
             && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs)
     }
 
-    fn should_warn_about_variant(&mut self, variant: &hir::Variant) -> bool {
+    fn should_warn_about_variant(&mut self, variant: &hir::Variant<'_>) -> bool {
         !self.symbol_is_live(variant.id)
             && !has_allow_dead_code_or_lang_attr(self.tcx,
                                                  variant.id,
                                                  &variant.attrs)
     }
 
-    fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool {
+    fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool {
         !self.symbol_is_live(fi.hir_id)
             && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id, &fi.attrs)
     }
@@ -567,7 +567,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         if self.should_warn_about_item(item) {
             // For most items, we want to highlight its identifier
             let span = match item.kind {
@@ -610,7 +610,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     }
 
     fn visit_variant(&mut self,
-                     variant: &'tcx hir::Variant,
+                     variant: &'tcx hir::Variant<'tcx>,
                      g: &'tcx hir::Generics,
                      id: hir::HirId) {
         if self.should_warn_about_variant(&variant) {
@@ -621,7 +621,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
         }
     }
 
-    fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) {
         if self.should_warn_about_foreign_item(fi) {
             self.warn_dead_code(fi.hir_id, fi.span, fi.ident.name,
                                 fi.kind.descriptive_variant(), "used");
@@ -629,14 +629,14 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
         intravisit::walk_foreign_item(self, fi);
     }
 
-    fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
+    fn visit_struct_field(&mut self, field: &'tcx hir::StructField<'tcx>) {
         if self.should_warn_about_field(&field) {
             self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "read");
         }
         intravisit::walk_struct_field(self, field);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         match impl_item.kind {
             hir::ImplItemKind::Const(_, body_id) => {
                 if !self.symbol_is_live(impl_item.hir_id) {
@@ -662,7 +662,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     }
 
     // Overwrite so that we don't warn the trait item itself.
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         match trait_item.kind {
             hir::TraitItemKind::Const(_, Some(body_id)) |
             hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index d0cedc08162..77ee6ce8513 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -33,18 +33,18 @@ struct EntryContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &'tcx Item) {
+    fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         let def_id = self.map.local_def_id(item.hir_id);
         let def_key = self.map.def_key(def_id);
         let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
         find_item(item, self, at_root);
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem<'tcx>) {
         // Entry fn is never a trait item.
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem<'tcx>) {
         // Entry fn is never a trait item.
     }
 }
@@ -81,7 +81,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
 
 // Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
 // them in sync.
-fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
+fn entry_point_type(item: &Item<'_>, at_root: bool) -> EntryPointType {
     match item.kind {
         ItemKind::Fn(..) => {
             if attr::contains_name(&item.attrs, sym::start) {
@@ -104,7 +104,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
 }
 
 
-fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
+fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
     match entry_point_type(item, at_root) {
         EntryPointType::MainNamed => {
             if ctxt.main_fn.is_none() {
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index a5924efefc2..776c1aff111 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -23,12 +23,12 @@ struct NodeData {
 }
 
 struct StatCollector<'k> {
-    krate: Option<&'k hir::Crate>,
+    krate: Option<&'k hir::Crate<'k>>,
     data: FxHashMap<&'static str, NodeData>,
     seen: FxHashSet<Id>,
 }
 
-pub fn print_hir_stats(krate: &hir::Crate) {
+pub fn print_hir_stats(krate: &hir::Crate<'_>) {
     let mut collector = StatCollector {
         krate: Some(krate),
         data: FxHashMap::default(),
@@ -123,17 +123,17 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         self.visit_body(nested_body)
     }
 
-    fn visit_item(&mut self, i: &'v hir::Item) {
+    fn visit_item(&mut self, i: &'v hir::Item<'v>) {
         self.record("Item", Id::Node(i.hir_id), i);
         hir_visit::walk_item(self, i)
     }
 
-    fn visit_mod(&mut self, m: &'v hir::Mod, _s: Span, n: hir::HirId) {
+    fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: hir::HirId) {
         self.record("Mod", Id::None, m);
         hir_visit::walk_mod(self, m, n)
     }
 
-    fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) {
         self.record("ForeignItem", Id::Node(i.hir_id), i);
         hir_visit::walk_foreign_item(self, i)
     }
@@ -188,12 +188,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         hir_visit::walk_where_predicate(self, predicate)
     }
 
-    fn visit_trait_item(&mut self, ti: &'v hir::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) {
         self.record("TraitItem", Id::Node(ti.hir_id), ti);
         hir_visit::walk_trait_item(self, ti)
     }
 
-    fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
         self.record("ImplItem", Id::Node(ii.hir_id), ii);
         hir_visit::walk_impl_item(self, ii)
     }
@@ -203,13 +203,13 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         hir_visit::walk_param_bound(self, bounds)
     }
 
-    fn visit_struct_field(&mut self, s: &'v hir::StructField) {
+    fn visit_struct_field(&mut self, s: &'v hir::StructField<'v>) {
         self.record("StructField", Id::Node(s.hir_id), s);
         hir_visit::walk_struct_field(self, s)
     }
 
     fn visit_variant(&mut self,
-                     v: &'v hir::Variant,
+                     v: &'v hir::Variant<'v>,
                      g: &'v hir::Generics,
                      item_id: hir::HirId) {
         self.record("Variant", Id::None, v);
@@ -247,7 +247,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         self.record("Attribute", Id::Attr(attr.id), attr);
     }
 
-    fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) {
+    fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef<'v>) {
         self.record("MacroDef", Id::Node(macro_def.hir_id), macro_def);
         hir_visit::walk_macro_def(self, macro_def)
     }
@@ -314,12 +314,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
         ast_visit::walk_fn(self, fk, fd, s)
     }
 
-    fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'v ast::AssocItem) {
         self.record("TraitItem", Id::None, ti);
         ast_visit::walk_trait_item(self, ti)
     }
 
-    fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'v ast::AssocItem) {
         self.record("ImplItem", Id::None, ii);
         ast_visit::walk_impl_item(self, ii)
     }
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index 06683c16e4a..d7872f80d26 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -28,7 +28,7 @@ struct VarianceTest<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
 
         if let ItemKind::TyAlias(..) = item.kind {
@@ -40,12 +40,12 @@ impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
 }
 
 impl VarianceTest<'tcx> {
-    fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item, attr: &Attribute) {
+    fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item<'tcx>, attr: &Attribute) {
         let tcx = self.tcx;
         let param_env = self.tcx.param_env(item_def_id);
         let ty = self.tcx.type_of(item_def_id);
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 81a39edf215..f18ecb90fc1 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -371,7 +371,7 @@ fn visit_fn<'tcx>(
 
     let body = ir.tcx.hir().body(body_id);
 
-    for param in &body.params {
+    for param in body.params {
         let is_shorthand = match param.pat.kind {
             rustc::hir::PatKind::Struct(..) => true,
             _ => false,
@@ -1463,8 +1463,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
         }
     }
 
-    fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
-        for p in &body.params {
+    fn warn_about_unused_args(&self, body: &hir::Body<'_>, entry_ln: LiveNode) {
+        for p in body.params {
             self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| {
                 if self.live_on_entry(ln, var).is_none() {
                     self.report_dead_assign(hir_id, spans, var, true);
diff --git a/src/librustc_plugin_impl/build.rs b/src/librustc_plugin_impl/build.rs
index 01559a95c9c..8ceef5a4b76 100644
--- a/src/librustc_plugin_impl/build.rs
+++ b/src/librustc_plugin_impl/build.rs
@@ -14,7 +14,7 @@ struct RegistrarFinder {
 }
 
 impl<'v> ItemLikeVisitor<'v> for RegistrarFinder {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let hir::ItemKind::Fn(..) = item.kind {
             if attr::contains_name(&item.attrs, sym::plugin_registrar) {
                 self.registrars.push((item.hir_id, item.span));
@@ -22,10 +22,10 @@ impl<'v> ItemLikeVisitor<'v> for RegistrarFinder {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
 
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index fcbc2a3301a..83f2fe7e023 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -510,7 +510,7 @@ impl EmbargoVisitor<'tcx> {
     fn update_macro_reachable_mod(&mut self, reachable_mod: hir::HirId, defining_mod: DefId) {
         let module_def_id = self.tcx.hir().local_def_id(reachable_mod);
         let module = self.tcx.hir().get_module(module_def_id).0;
-        for item_id in &module.item_ids {
+        for item_id in module.item_ids {
             let hir_id = item_id.id;
             let item_def_id = self.tcx.hir().local_def_id(hir_id);
             if let Some(def_kind) = self.tcx.def_kind(item_def_id) {
@@ -652,7 +652,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let inherited_item_level = match item.kind {
             hir::ItemKind::Impl(..) =>
                 Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels),
@@ -675,7 +675,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
         // Update levels of nested things.
         match item.kind {
             hir::ItemKind::Enum(ref def, _) => {
-                for variant in &def.variants {
+                for variant in def.variants {
                     let variant_level = self.update(variant.id, item_level);
                     if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
                         self.update(ctor_hir_id, item_level);
@@ -685,14 +685,14 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     }
                 }
             }
-            hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => {
                 for impl_item_ref in impl_item_refs {
                     if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() {
                         self.update(impl_item_ref.id.hir_id, item_level);
                     }
                 }
             }
-            hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            hir::ItemKind::Trait(.., trait_item_refs) => {
                 for trait_item_ref in trait_item_refs {
                     self.update(trait_item_ref.id.hir_id, item_level);
                 }
@@ -708,7 +708,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 }
             }
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
+                for foreign_item in foreign_mod.items {
                     if foreign_item.vis.node.is_pub() {
                         self.update(foreign_item.hir_id, item_level);
                     }
@@ -756,7 +756,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     self.reach(item.hir_id, item_level).generics().predicates().ty();
                 }
             }
-            hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            hir::ItemKind::Trait(.., trait_item_refs) => {
                 if item_level.is_some() {
                     self.reach(item.hir_id, item_level).generics().predicates();
 
@@ -779,7 +779,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 }
             }
             // Visit everything except for private impl items.
-            hir::ItemKind::Impl(.., ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., impl_item_refs) => {
                 if item_level.is_some() {
                     self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
 
@@ -798,7 +798,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 if item_level.is_some() {
                     self.reach(item.hir_id, item_level).generics().predicates();
                 }
-                for variant in &def.variants {
+                for variant in def.variants {
                     let variant_level = self.get(variant.id);
                     if variant_level.is_some() {
                         for field in variant.data.fields() {
@@ -812,7 +812,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             }
             // Visit everything, but foreign items have their own levels.
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
+                for foreign_item in foreign_mod.items {
                     let foreign_item_level = self.get(foreign_item.hir_id);
                     if foreign_item_level.is_some() {
                         self.reach(foreign_item.hir_id, foreign_item_level)
@@ -849,7 +849,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
         self.prev_level = orig_level;
     }
 
-    fn visit_mod(&mut self, m: &'tcx hir::Mod, _sp: Span, id: hir::HirId) {
+    fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _sp: Span, id: hir::HirId) {
         // This code is here instead of in visit_item so that the
         // crate module gets processed as well.
         if self.prev_level.is_some() {
@@ -870,7 +870,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
         intravisit::walk_mod(self, m, id);
     }
 
-    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
+    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
         if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque {
             self.update(md.hir_id, Some(AccessLevel::Public));
             return
@@ -992,7 +992,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
-    fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: hir::HirId) {
+    fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
         // Don't visit nested modules, since we run a separate visitor walk
         // for each module in `privacy_access_levels`
     }
@@ -1004,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
         self.tables = orig_tables;
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let orig_current_item = mem::replace(&mut self.current_item, item.hir_id);
         let orig_tables =
             mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
@@ -1013,14 +1013,14 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
         self.tables = orig_tables;
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
         let orig_tables =
             mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
         intravisit::walk_trait_item(self, ti);
         self.tables = orig_tables;
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
         let orig_tables =
             mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
         intravisit::walk_impl_item(self, ii);
@@ -1132,7 +1132,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
-    fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: hir::HirId) {
+    fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
         // Don't visit nested modules, since we run a separate visitor walk
         // for each module in `privacy_access_levels`
     }
@@ -1283,7 +1283,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
     }
 
     // Check types in item interfaces.
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let orig_current_item = mem::replace(&mut self.current_item,
             self.tcx.hir().local_def_id(item.hir_id));
         let orig_in_body = mem::replace(&mut self.in_body, false);
@@ -1295,14 +1295,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
         self.current_item = orig_current_item;
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
         let orig_tables =
             mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
         intravisit::walk_trait_item(self, ti);
         self.tables = orig_tables;
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
         let orig_tables =
             mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
         intravisit::walk_impl_item(self, ii);
@@ -1416,7 +1416,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         match item.kind {
             // Contents of a private mod can be re-exported, so we need
             // to check internals.
@@ -1441,7 +1441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
             // (i.e., we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible).
-            hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, impl_item_refs) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // `impl [... for] Public<...>`, but not `impl [... for]
@@ -1621,7 +1621,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         if self.access_levels.is_reachable(item.hir_id) {
             intravisit::walk_foreign_item(self, item)
         }
@@ -1637,7 +1637,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     }
 
     fn visit_variant(&mut self,
-                     v: &'tcx hir::Variant,
+                     v: &'tcx hir::Variant<'tcx>,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
         if self.access_levels.is_reachable(v.id) {
@@ -1647,7 +1647,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
         if s.vis.node.is_pub() || self.in_variant {
             intravisit::walk_struct_field(self, s);
         }
@@ -1849,7 +1849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let tcx = self.tcx;
         let item_visibility = ty::Visibility::from_hir(&item.vis, item.hir_id, tcx);
 
@@ -1872,7 +1872,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                 // it's not a part of interface, so we skip it.
                 self.check(item.hir_id, item_visibility).generics().predicates();
             }
-            hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            hir::ItemKind::Trait(.., trait_item_refs) => {
                 self.check(item.hir_id, item_visibility).generics().predicates();
 
                 for trait_item_ref in trait_item_refs {
@@ -1890,7 +1890,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             hir::ItemKind::Enum(ref def, _) => {
                 self.check(item.hir_id, item_visibility).generics().predicates();
 
-                for variant in &def.variants {
+                for variant in def.variants {
                     for field in variant.data.fields() {
                         self.check(field.hir_id, item_visibility).ty();
                     }
@@ -1898,7 +1898,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             }
             // Subitems of foreign modules have their own publicity.
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
+                for foreign_item in foreign_mod.items {
                     let vis = ty::Visibility::from_hir(&foreign_item.vis, item.hir_id, tcx);
                     self.check(foreign_item.hir_id, vis).generics().predicates().ty();
                 }
@@ -1917,7 +1917,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             // Subitems of inherent impls have their own publicity.
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity.
-            hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
+            hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => {
                 let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default());
                 self.check(item.hir_id, impl_vis).generics().predicates();
                 for impl_item_ref in impl_item_refs {
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index e2578d67e73..e94e0dc695c 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -30,7 +30,7 @@ use errors::Applicability;
 use syntax::ast::{Name, Ident};
 use syntax::attr;
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
-use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind};
+use syntax::ast::{MetaItemKind, StmtKind, AssocItem, AssocItemKind};
 use syntax::token::{self, Token};
 use syntax::span_err;
 use syntax::source_map::{respan, Spanned};
@@ -1164,10 +1164,10 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         self.parent_scope.legacy = orig_current_legacy_scope;
     }
 
-    fn visit_trait_item(&mut self, item: &'b TraitItem) {
+    fn visit_trait_item(&mut self, item: &'b AssocItem) {
         let parent = self.parent_scope.module;
 
-        if let TraitItemKind::Macro(_) = item.kind {
+        if let AssocItemKind::Macro(_) = item.kind {
             self.visit_invoc(item.id);
             return
         }
@@ -1175,15 +1175,15 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         // Add the item to the trait info.
         let item_def_id = self.r.definitions.local_def_id(item.id);
         let (res, ns) = match item.kind {
-            TraitItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
-            TraitItemKind::Method(ref sig, _) => {
+            AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
+            AssocItemKind::Fn(ref sig, _) => {
                 if sig.decl.has_self() {
                     self.r.has_self.insert(item_def_id);
                 }
                 (Res::Def(DefKind::Method, item_def_id), ValueNS)
             }
-            TraitItemKind::Type(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS),
-            TraitItemKind::Macro(_) => bug!(),  // handled above
+            AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS),
+            AssocItemKind::Macro(_) => bug!(),  // handled above
         };
 
         let vis = ty::Visibility::Public;
@@ -1193,8 +1193,8 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         visit::walk_trait_item(self, item);
     }
 
-    fn visit_impl_item(&mut self, item: &'b ast::ImplItem) {
-        if let ast::ImplItemKind::Macro(..) = item.kind {
+    fn visit_impl_item(&mut self, item: &'b ast::AssocItem) {
+        if let ast::AssocItemKind::Macro(..) = item.kind {
             self.visit_invoc(item.id);
         } else {
             self.resolve_visibility(&item.vis);
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index dd6b1d2119e..9bae339f80e 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -50,7 +50,7 @@ impl<'a> DefCollector<'a> {
         header: &FnHeader,
         generics: &'a Generics,
         decl: &'a FnDecl,
-        body: &'a Block,
+        body: Option<&'a Block>,
     ) {
         let (closure_id, return_impl_trait_id) = match header.asyncness.node {
             IsAsync::Async {
@@ -74,7 +74,9 @@ impl<'a> DefCollector<'a> {
                 closure_id, DefPathData::ClosureExpr, span,
             );
             this.with_parent(closure_def, |this| {
-                visit::walk_block(this, body);
+                if let Some(body) = body {
+                    visit::walk_block(this, body);
+                }
             })
         })
     }
@@ -123,7 +125,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     &sig.header,
                     generics,
                     &sig.decl,
-                    body,
+                    Some(body),
                 )
             }
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
@@ -210,23 +212,20 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         visit::walk_generic_param(self, param);
     }
 
-    fn visit_trait_item(&mut self, ti: &'a TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'a AssocItem) {
         let def_data = match ti.kind {
-            TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name),
-            TraitItemKind::Type(..) => {
-                DefPathData::TypeNs(ti.ident.name)
-            },
-            TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
+            AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name),
+            AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ti.ident.name),
+            AssocItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
         };
 
         let def = self.create_def(ti.id, def_data, ti.span);
         self.with_parent(def, |this| visit::walk_trait_item(this, ti));
     }
 
-    fn visit_impl_item(&mut self, ii: &'a ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'a AssocItem) {
         let def_data = match ii.kind {
-            ImplItemKind::Method(FnSig {
+            AssocItemKind::Fn(FnSig {
                 ref header,
                 ref decl,
             }, ref body) if header.asyncness.node.is_async() => {
@@ -237,13 +236,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     header,
                     &ii.generics,
                     decl,
-                    body,
+                    body.as_deref(),
                 )
             }
-            ImplItemKind::Method(..) |
-            ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
-            ImplItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name),
-            ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
+            AssocItemKind::Fn(..) |
+            AssocItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
+            AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name),
+            AssocItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
         };
 
         let def = self.create_def(ii.id, def_data, ii.span);
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 4f95d6fe70f..df81231cf98 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -806,7 +806,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                                 this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind,
                                     |this| {
                                         match trait_item.kind {
-                                            TraitItemKind::Const(ref ty, ref default) => {
+                                            AssocItemKind::Const(ref ty, ref default) => {
                                                 this.visit_ty(ty);
 
                                                 // Only impose the restrictions of
@@ -818,13 +818,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                                                     });
                                                 }
                                             }
-                                            TraitItemKind::Method(_, _) => {
+                                            AssocItemKind::Fn(_, _) => {
                                                 visit::walk_trait_item(this, trait_item)
                                             }
-                                            TraitItemKind::Type(..) => {
+                                            AssocItemKind::TyAlias(..) => {
                                                 visit::walk_trait_item(this, trait_item)
                                             }
-                                            TraitItemKind::Macro(_) => {
+                                            AssocItemKind::Macro(_) => {
                                                 panic!("unexpanded macro in resolve!")
                                             }
                                         };
@@ -989,13 +989,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
     /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412.
     fn with_trait_items<T>(
         &mut self,
-        trait_items: &Vec<TraitItem>,
+        trait_items: &Vec<AssocItem>,
         f: impl FnOnce(&mut Self) -> T,
     ) -> T {
         let trait_assoc_types = replace(
             &mut self.diagnostic_metadata.current_trait_assoc_types,
             trait_items.iter().filter_map(|item| match &item.kind {
-                TraitItemKind::Type(bounds, _) if bounds.len() == 0 => Some(item.ident),
+                AssocItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident),
                 _ => None,
             }).collect(),
         );
@@ -1063,7 +1063,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                               opt_trait_reference: &Option<TraitRef>,
                               self_type: &Ty,
                               item_id: NodeId,
-                              impl_items: &[ImplItem]) {
+                              impl_items: &[AssocItem]) {
         debug!("resolve_implementation");
         // If applicable, create a rib for the type parameters.
         self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
@@ -1092,9 +1092,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                                                                 |this| {
                                         use crate::ResolutionError::*;
                                         match impl_item.kind {
-                                            ImplItemKind::Const(..) => {
+                                            AssocItemKind::Const(..) => {
                                                 debug!(
-                                                    "resolve_implementation ImplItemKind::Const",
+                                                    "resolve_implementation AssocItemKind::Const",
                                                 );
                                                 // If this is a trait impl, ensure the const
                                                 // exists in trait
@@ -1109,7 +1109,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                                                     visit::walk_impl_item(this, impl_item)
                                                 });
                                             }
-                                            ImplItemKind::Method(..) => {
+                                            AssocItemKind::Fn(..) => {
                                                 // If this is a trait impl, ensure the method
                                                 // exists in trait
                                                 this.check_trait_item(impl_item.ident,
@@ -1119,7 +1119,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
 
                                                 visit::walk_impl_item(this, impl_item);
                                             }
-                                            ImplItemKind::TyAlias(ref ty) => {
+                                            AssocItemKind::TyAlias(_, _) => {
                                                 // If this is a trait impl, ensure the type
                                                 // exists in trait
                                                 this.check_trait_item(impl_item.ident,
@@ -1127,9 +1127,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                                                                       impl_item.span,
                                                     |n, s| TypeNotMemberOfTrait(n, s));
 
-                                                this.visit_ty(ty);
+                                                visit::walk_impl_item(this, impl_item);
                                             }
-                                            ImplItemKind::Macro(_) =>
+                                            AssocItemKind::Macro(_) =>
                                                 panic!("unexpanded macro in resolve!"),
                                         }
                                     });
@@ -1471,7 +1471,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
         // An immutable (no `mut`) by-value (no `ref`) binding pattern without
         // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
         // also be interpreted as a path to e.g. a constant, variant, etc.
-        let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Immutable);
+        let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
 
         match res {
             Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 396d9484339..df6ad51d104 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -676,7 +676,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         generics: &'l ast::Generics,
         trait_ref: &'l Option<ast::TraitRef>,
         typ: &'l ast::Ty,
-        impl_items: &'l [ast::ImplItem],
+        impl_items: &'l [ast::AssocItem],
     ) {
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
             if !self.span.filter_generated(item.span) {
@@ -707,7 +707,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         item: &'l ast::Item,
         generics: &'l ast::Generics,
         trait_refs: &'l ast::GenericBounds,
-        methods: &'l [ast::TraitItem],
+        methods: &'l [ast::AssocItem],
     ) {
         let name = item.ident.to_string();
         let qualname = format!("::{}",
@@ -811,9 +811,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                 match **generic_args {
                     ast::GenericArgs::AngleBracketed(ref data) => {
                         for arg in &data.args {
-                            match arg {
-                                ast::GenericArg::Type(ty) => self.visit_ty(ty),
-                                _ => {}
+                            if let ast::GenericArg::Type(ty) = arg {
+                                self.visit_ty(ty);
                             }
                         }
                     }
@@ -821,8 +820,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                         for t in &data.inputs {
                             self.visit_ty(t);
                         }
-                        if let Some(ref t) = data.output {
-                            self.visit_ty(t);
+                        if let ast::FunctionRetTy::Ty(ty) = &data.output {
+                            self.visit_ty(ty);
                         }
                     }
                 }
@@ -1030,11 +1029,11 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         // }
     }
 
-    fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
+    fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId) {
         self.process_macro_use(trait_item.span);
         let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.kind {
-            ast::TraitItemKind::Const(ref ty, ref expr) => {
+            ast::AssocItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(
                     trait_item.id,
                     trait_item.ident,
@@ -1045,7 +1044,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     &trait_item.attrs,
                 );
             }
-            ast::TraitItemKind::Method(ref sig, ref body) => {
+            ast::AssocItemKind::Fn(ref sig, ref body) => {
                 self.process_method(
                     sig,
                     body.as_ref().map(|x| &**x),
@@ -1056,7 +1055,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     trait_item.span,
                 );
             }
-            ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
+            ast::AssocItemKind::TyAlias(ref bounds, ref default_ty) => {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
                 let qualname = format!("::{}",
@@ -1098,28 +1097,28 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     self.visit_ty(default_ty)
                 }
             }
-            ast::TraitItemKind::Macro(_) => {}
+            ast::AssocItemKind::Macro(_) => {}
         }
     }
 
-    fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) {
+    fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) {
         self.process_macro_use(impl_item.span);
         match impl_item.kind {
-            ast::ImplItemKind::Const(ref ty, ref expr) => {
+            ast::AssocItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(
                     impl_item.id,
                     impl_item.ident,
                     &ty,
-                    Some(expr),
+                    expr.as_deref(),
                     impl_id,
                     impl_item.vis.clone(),
                     &impl_item.attrs,
                 );
             }
-            ast::ImplItemKind::Method(ref sig, ref body) => {
+            ast::AssocItemKind::Fn(ref sig, ref body) => {
                 self.process_method(
                     sig,
-                    Some(body),
+                    body.as_deref(),
                     impl_item.id,
                     impl_item.ident,
                     &impl_item.generics,
@@ -1127,13 +1126,14 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     impl_item.span,
                 );
             }
-            ast::ImplItemKind::TyAlias(ref ty) => {
+            ast::AssocItemKind::TyAlias(_, None) => {}
+            ast::AssocItemKind::TyAlias(_, Some(ref ty)) => {
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
                 // trait.
                 self.visit_ty(ty)
             }
-            ast::ImplItemKind::Macro(_) => {}
+            ast::AssocItemKind::Macro(_) => {}
         }
     }
 
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 424d57c8fe7..0e839d35b99 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -614,9 +614,9 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             Node::TraitRef(tr) => tr.path.res,
 
             Node::Item(&hir::Item {
-                kind: hir::ItemKind::Use(ref path, _),
+                kind: hir::ItemKind::Use(path, _),
                 ..
-            }) |
+            }) => path.res,
             Node::Visibility(&Spanned {
                 node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.res,
 
@@ -985,7 +985,7 @@ impl<'l> Visitor<'l> for PathCollector<'l> {
                     // Even if the ref is mut, you can't change the ref, only
                     // the data pointed at, so showing the initialising expression
                     // is still worthwhile.
-                    ast::BindingMode::ByRef(_) => ast::Mutability::Immutable,
+                    ast::BindingMode::ByRef(_) => ast::Mutability::Not,
                     ast::BindingMode::ByValue(mt) => mt,
                 };
                 self.collected_idents
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 255938a193c..d1ac0ac210e 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -175,8 +175,8 @@ impl Sig for ast::Ty {
             }
             ast::TyKind::Ptr(ref mt) => {
                 let prefix = match mt.mutbl {
-                    ast::Mutability::Mutable => "*mut ",
-                    ast::Mutability::Immutable => "*const ",
+                    ast::Mutability::Mut => "*mut ",
+                    ast::Mutability::Not => "*const ",
                 };
                 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
                 let text = format!("{}{}", prefix, nested.text);
@@ -188,7 +188,7 @@ impl Sig for ast::Ty {
                     prefix.push_str(&l.ident.to_string());
                     prefix.push(' ');
                 }
-                if let ast::Mutability::Mutable = mt.mutbl {
+                if let ast::Mutability::Mut = mt.mutbl {
                     prefix.push_str("mut ");
                 };
 
@@ -330,7 +330,7 @@ impl Sig for ast::Item {
         match self.kind {
             ast::ItemKind::Static(ref ty, m, ref expr) => {
                 let mut text = "static ".to_owned();
-                if m == ast::Mutability::Mutable {
+                if m == ast::Mutability::Mut {
                     text.push_str("mut ");
                 }
                 let name = self.ident.to_string();
@@ -787,7 +787,7 @@ impl Sig for ast::ForeignItem {
             }
             ast::ForeignItemKind::Static(ref ty, m) => {
                 let mut text = "static ".to_owned();
-                if m == ast::Mutability::Mutable {
+                if m == ast::Mutability::Mut {
                     text.push_str("mut ");
                 }
                 let name = self.ident.to_string();
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 9ddc9c0d602..2f2d03fc596 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -866,8 +866,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "extra arguments to prepend to the linker invocation (space separated)"),
     profile: bool = (false, parse_bool, [TRACKED],
                      "insert profiling code"),
-    disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED],
-        "Disable the instrumentation pre-inliner, useful for profiling / PGO."),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
         "choose which RELRO level to use"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
index 3ad68d4a9df..f281ac17620 100644
--- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
@@ -243,7 +243,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>(
         ty::Float(..) |
         ty::RawPtr(..) |
         ty::Never |
-        ty::Ref(_, _, hir::Mutability::Immutable) => (),
+        ty::Ref(_, _, hir::Mutability::Not) => (),
 
         // Non parametric primitive types.
         ty::Infer(ty::IntVar(_)) |
@@ -319,7 +319,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>(
         ty::Generator(..) |
         ty::Str |
         ty::Slice(..) |
-        ty::Ref(_, _, hir::Mutability::Mutable) => (),
+        ty::Ref(_, _, hir::Mutability::Mut) => (),
 
         ty::Bound(..) |
         ty::GeneratorWitness(..) |
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 0df367fcca8..9e286094642 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -669,22 +669,22 @@ impl Visitor<'tcx> for ClauseDumper<'tcx> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         self.process_attrs(item.hir_id, &item.attrs);
         intravisit::walk_item(self, item);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         self.process_attrs(trait_item.hir_id, &trait_item.attrs);
         intravisit::walk_trait_item(self, trait_item);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         self.process_attrs(impl_item.hir_id, &impl_item.attrs);
         intravisit::walk_impl_item(self, impl_item);
     }
 
-    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
         self.process_attrs(s.hir_id, &s.attrs);
         intravisit::walk_struct_field(self, s);
     }
diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs
index d6c8e54c18d..4c8c9d15d56 100644
--- a/src/librustc_tsan/lib.rs
+++ b/src/librustc_tsan/lib.rs
@@ -5,4 +5,4 @@
 #![no_std]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
-            issue = "0")]
+            issue = "none")]
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 290f86d626e..9b737428d5a 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -88,6 +88,7 @@ pub trait AstConv<'tcx> {
     fn projected_ty_from_poly_trait_ref(&self,
                                         span: Span,
                                         item_def_id: DefId,
+                                        item_segment: &hir::PathSegment,
                                         poly_trait_ref: ty::PolyTraitRef<'tcx>)
                                         -> Ty<'tcx>;
 
@@ -205,6 +206,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
             span,
             def_id,
+            &[],
             item_segment.generic_args(),
             item_segment.infer_args,
             None,
@@ -615,9 +617,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     ///    `Output = u32` are returned in the `Vec<ConvertedBinding...>` result.
     ///
     /// Note that the type listing given here is *exactly* what the user provided.
+    ///
+    /// For (generic) associated types
+    ///
+    /// ```
+    /// <Vec<u8> as Iterable<u8>>::Iter::<'a>
+    /// ```
+    ///
+    /// We have the parent substs are the substs for the parent trait:
+    /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
+    /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
+    /// lists: `[Vec<u8>, u8, 'a]`.
     fn create_substs_for_ast_path<'a>(&self,
         span: Span,
         def_id: DefId,
+        parent_substs: &[subst::GenericArg<'tcx>],
         generic_args: &'a hir::GenericArgs,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>)
@@ -633,17 +647,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let tcx = self.tcx();
         let generic_params = tcx.generics_of(def_id);
 
-        // If a self-type was declared, one should be provided.
-        assert_eq!(generic_params.has_self, self_ty.is_some());
+        if generic_params.has_self {
+            if generic_params.parent.is_some() {
+                // The parent is a trait so it should have at least one subst
+                // for the `Self` type.
+                assert!(!parent_substs.is_empty())
+            } else {
+                // This item (presumably a trait) needs a self-type.
+                assert!(self_ty.is_some());
+            }
+        } else {
+            assert!(self_ty.is_none() && parent_substs.is_empty());
+        }
 
-        let has_self = generic_params.has_self;
         let (_, potential_assoc_types) = Self::check_generic_arg_count(
             tcx,
             span,
             &generic_params,
             &generic_args,
             GenericArgPosition::Type,
-            has_self,
+            self_ty.is_some(),
             infer_args,
         );
 
@@ -652,7 +675,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         });
         let default_needs_object_self = |param: &ty::GenericParamDef| {
             if let GenericParamDefKind::Type { has_default, .. } = param.kind {
-                if is_object && has_default && has_self {
+                if is_object && has_default {
                     let self_param = tcx.types.self_param;
                     if tcx.at(span).type_of(param.def_id).walk().any(|ty| ty == self_param) {
                         // There is no suitable inference default for a type parameter
@@ -668,7 +691,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let substs = Self::create_substs_for_generic_args(
             tcx,
             def_id,
-            &[][..],
+            parent_substs,
             self_ty.is_some(),
             self_ty,
             // Provide the generic args, and whether types should be inferred.
@@ -780,6 +803,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         (substs, assoc_bindings, potential_assoc_types)
     }
 
+    crate fn create_substs_for_associated_item(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+        item_def_id: DefId,
+        item_segment: &hir::PathSegment,
+        parent_substs: SubstsRef<'tcx>,
+    ) -> SubstsRef<'tcx> {
+        if tcx.generics_of(item_def_id).params.is_empty() {
+            self.prohibit_generics(slice::from_ref(item_segment));
+
+            parent_substs
+        } else {
+            self.create_substs_for_ast_path(
+                span,
+                item_def_id,
+                parent_substs,
+                item_segment.generic_args(),
+                item_segment.infer_args,
+                None,
+            ).0
+        }
+    }
+
     /// Instantiates the path for the given trait reference, assuming that it's
     /// bound to a valid trait type. Returns the `DefId` of the defining trait.
     /// The type _cannot_ be a type other than a trait type.
@@ -919,6 +966,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         self.create_substs_for_ast_path(span,
                                         trait_def_id,
+                                        &[],
                                         trait_segment.generic_args(),
                                         trait_segment.infer_args,
                                         Some(self_ty))
@@ -1665,8 +1713,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
 
-        self.prohibit_generics(slice::from_ref(assoc_segment));
-
         // Check if we have an enum variant.
         let mut variant_resolution = None;
         if let ty::Adt(adt_def, _) = qself_ty.kind {
@@ -1677,6 +1723,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 if let Some(variant_def) = variant_def {
                     if permit_variants {
                         tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
+                        self.prohibit_generics(slice::from_ref(assoc_segment));
                         return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
                     } else {
                         variant_resolution = Some(variant_def.def_id);
@@ -1767,7 +1814,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 i.ident.modern() == assoc_ident
         }).expect("missing associated type");
 
-        let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound);
+        let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
         let ty = self.normalize_ty(span, ty);
 
         let kind = DefKind::AssocTy;
@@ -1818,8 +1865,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
 
-        self.prohibit_generics(slice::from_ref(item_segment));
-
         let self_ty = if let Some(ty) = opt_self_ty {
             ty
         } else {
@@ -1861,9 +1906,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                                         self_ty,
                                                         trait_segment);
 
+        let item_substs = self.create_substs_for_associated_item(
+            tcx,
+            span,
+            item_def_id,
+            item_segment,
+            trait_ref.substs,
+        );
+
         debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
 
-        self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs))
+        self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
     }
 
     pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment>>(
@@ -2518,10 +2571,10 @@ impl<'tcx> Bounds<'tcx> {
         // If it could be sized, and is, add the `Sized` predicate.
         let sized_predicate = self.implicitly_sized.and_then(|span| {
             tcx.lang_items().sized_trait().map(|sized| {
-                let trait_ref = ty::TraitRef {
+                let trait_ref = ty::Binder::bind(ty::TraitRef {
                     def_id: sized,
                     substs: tcx.mk_substs_trait(param_ty, &[])
-                };
+                });
                 (trait_ref.to_predicate(), span)
             })
         });
@@ -2529,10 +2582,11 @@ impl<'tcx> Bounds<'tcx> {
         sized_predicate.into_iter().chain(
             self.region_bounds.iter().map(|&(region_bound, span)| {
                 // Account for the binder being introduced below; no need to shift `param_ty`
-                // because, at present at least, it can only refer to early-bound regions.
+                // because, at present at least, it either only refers to early-bound regions,
+                // or it's a generic associated type that deliberately has escaping bound vars.
                 let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
                 let outlives = ty::OutlivesPredicate(param_ty, region_bound);
-                (ty::Binder::dummy(outlives).to_predicate(), span)
+                (ty::Binder::bind(outlives).to_predicate(), span)
             }).chain(
                 self.trait_bounds.iter().map(|&(bound_trait_ref, span)| {
                     (bound_trait_ref.to_predicate(), span)
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 6b34159066a..182c64e9069 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -430,8 +430,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let contains_ref_bindings = arms.iter()
             .filter_map(|a| a.pat.contains_explicit_ref_binding())
             .max_by_key(|m| match *m {
-                hir::Mutability::Mutable => 1,
-                hir::Mutability::Immutable => 0,
+                hir::Mutability::Mut => 1,
+                hir::Mutability::Not => 0,
             });
 
         if let Some(m) = contains_ref_bindings {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 1b3af48ea83..db969486b8d 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -217,8 +217,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if borrow {
                     if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind {
                         let mutbl = match mutbl {
-                            hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                            hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                            hir::Mutability::Not => AutoBorrowMutability::Not,
+                            hir::Mutability::Mut => AutoBorrowMutability::Mut {
                                 // For initial two-phase borrow
                                 // deployment, conservatively omit
                                 // overloaded function call ops.
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 035ece23810..05236439695 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -469,22 +469,48 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             (Some(t_from), Some(t_cast)) => (t_from, t_cast),
             // Function item types may need to be reified before casts.
             (None, Some(t_cast)) => {
-                if let ty::FnDef(..) = self.expr_ty.kind {
-                    // Attempt a coercion to a fn pointer type.
-                    let f = self.expr_ty.fn_sig(fcx.tcx);
-                    let res = fcx.try_coerce(self.expr,
-                                             self.expr_ty,
-                                             fcx.tcx.mk_fn_ptr(f),
-                                             AllowTwoPhase::No);
-                    if let Err(TypeError::IntrinsicCast) = res {
-                        return Err(CastError::IllegalCast);
+                match self.expr_ty.kind {
+                    ty::FnDef(..) => {
+                        // Attempt a coercion to a fn pointer type.
+                        let f = self.expr_ty.fn_sig(fcx.tcx);
+                        let res = fcx.try_coerce(self.expr,
+                                                 self.expr_ty,
+                                                 fcx.tcx.mk_fn_ptr(f),
+                                                 AllowTwoPhase::No);
+                        if let Err(TypeError::IntrinsicCast) = res {
+                            return Err(CastError::IllegalCast);
+                        }
+                        if res.is_err() {
+                            return Err(CastError::NonScalar);
+                        }
+                        (FnPtr, t_cast)
                     }
-                    if res.is_err() {
-                        return Err(CastError::NonScalar);
+                    // Special case some errors for references, and check for
+                    // array-ptr-casts. `Ref` is not a CastTy because the cast
+                    // is split into a coercion to a pointer type, followed by
+                    // a cast.
+                    ty::Ref(_, inner_ty, mutbl) => {
+                        return match t_cast {
+                            Int(_) | Float => match inner_ty.kind {
+                                ty::Int(_) |
+                                ty::Uint(_) |
+                                ty::Float(_) |
+                                ty::Infer(ty::InferTy::IntVar(_)) |
+                                ty::Infer(ty::InferTy::FloatVar(_)) => {
+                                    Err(CastError::NeedDeref)
+                                }
+                                _ => Err(CastError::NeedViaPtr),
+                            }
+                            // array-ptr-cast
+                            Ptr(mt) => self.check_ref_cast(
+                                fcx,
+                                TypeAndMut { mutbl, ty: inner_ty },
+                                mt,
+                            ),
+                            _ => Err(CastError::NonScalar),
+                        };
                     }
-                    (FnPtr, t_cast)
-                } else {
-                    return Err(CastError::NonScalar);
+                    _ => return Err(CastError::NonScalar),
                 }
             }
             _ => return Err(CastError::NonScalar),
@@ -492,7 +518,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
         match (t_from, t_cast) {
             // These types have invariants! can't cast into them.
-            (_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar),
+            (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar),
 
             // * -> Bool
             (_, Int(Bool)) => Err(CastError::CastToBool),
@@ -517,28 +543,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
             (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
             (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
-            (RPtr(p), Int(_)) |
-            (RPtr(p), Float) => {
-                match p.ty.kind {
-                    ty::Int(_) |
-                    ty::Uint(_) |
-                    ty::Float(_) => {
-                        Err(CastError::NeedDeref)
-                    }
-                    ty::Infer(t) => {
-                        match t {
-                            ty::InferTy::IntVar(_) |
-                            ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref),
-                            _ => Err(CastError::NeedViaPtr),
-                        }
-                    }
-                    _ => Err(CastError::NeedViaPtr),
-                }
-            }
+
             // * -> ptr
             (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
             (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
-            (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast
 
             // prim -> prim
             (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast),
@@ -629,8 +637,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     ) -> Result<CastKind, CastError> {
         // array-ptr-cast.
 
-        if m_expr.mutbl == hir::Mutability::Immutable &&
-            m_cast.mutbl == hir::Mutability::Immutable {
+        if m_expr.mutbl == hir::Mutability::Not &&
+            m_cast.mutbl == hir::Mutability::Not {
             if let ty::Array(ety, _) = m_expr.ty.kind {
                 // Due to the limitations of LLVM global constants,
                 // region pointers end up pointing at copies of
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 30cb0d4f967..46b9a8d7f91 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr,
         opt_kind: Option<ty::ClosureKind>,
         decl: &'tcx hir::FnDecl,
-        body: &'tcx hir::Body,
+        body: &'tcx hir::Body<'tcx>,
         gen: Option<hir::Movability>,
         expected_sig: Option<ExpectedSig<'tcx>>,
     ) -> Ty<'tcx> {
@@ -316,7 +316,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr_def_id: DefId,
         decl: &hir::FnDecl,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
         expected_sig: Option<ExpectedSig<'tcx>>,
     ) -> ClosureSignatures<'tcx> {
         if let Some(e) = expected_sig {
@@ -332,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr_def_id: DefId,
         decl: &hir::FnDecl,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
     ) -> ClosureSignatures<'tcx> {
         debug!("sig_of_closure_no_expectation()");
 
@@ -392,7 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr_def_id: DefId,
         decl: &hir::FnDecl,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
         expected_sig: ExpectedSig<'tcx>,
     ) -> ClosureSignatures<'tcx> {
         debug!(
@@ -450,7 +450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr_def_id: DefId,
         decl: &hir::FnDecl,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
         expected_sig: ExpectedSig<'tcx>,
     ) -> ClosureSignatures<'tcx> {
         let expr_map_node = self.tcx.hir().get_if_local(expr_def_id).unwrap();
@@ -482,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr_def_id: DefId,
         decl: &hir::FnDecl,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
         expected_sigs: &ClosureSignatures<'tcx>,
     ) -> InferResult<'tcx, ()> {
         // Get the signature S that the user gave.
@@ -590,7 +590,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr_def_id: DefId,
         decl: &hir::FnDecl,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
     ) -> ty::PolyFnSig<'tcx> {
         let astconv: &dyn AstConv<'_> = self;
 
@@ -788,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn closure_sigs(
         &self,
         expr_def_id: DefId,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
         bound_sig: ty::PolyFnSig<'tcx>,
     ) -> ClosureSignatures<'tcx> {
         let liberated_sig = self.tcx()
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 726b3ba9857..e44b00d74bf 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -101,10 +101,10 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
                        to_mutbl: hir::Mutability)
                        -> RelateResult<'tcx, ()> {
     match (from_mutbl, to_mutbl) {
-        (hir::Mutability::Mutable, hir::Mutability::Mutable) |
-        (hir::Mutability::Immutable, hir::Mutability::Immutable) |
-        (hir::Mutability::Mutable, hir::Mutability::Immutable) => Ok(()),
-        (hir::Mutability::Immutable, hir::Mutability::Mutable) => Err(TypeError::Mutability),
+        (hir::Mutability::Mut, hir::Mutability::Mut) |
+        (hir::Mutability::Not, hir::Mutability::Not) |
+        (hir::Mutability::Mut, hir::Mutability::Not) => Ok(()),
+        (hir::Mutability::Not, hir::Mutability::Mut) => Err(TypeError::Mutability),
     }
 }
 
@@ -412,7 +412,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             }
         };
 
-        if ty == a && mt_a.mutbl == hir::Mutability::Immutable && autoderef.step_count() == 1 {
+        if ty == a && mt_a.mutbl == hir::Mutability::Not && autoderef.step_count() == 1 {
             // As a special case, if we would produce `&'a *x`, that's
             // a total no-op. We end up with the type `&'a T` just as
             // we started with.  In that case, just skip it
@@ -424,7 +424,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             // `self.x` both have `&mut `type would be a move of
             // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
             // which is a borrow.
-            assert_eq!(mt_b.mutbl, hir::Mutability::Immutable); // can only coerce &T -> &U
+            assert_eq!(mt_b.mutbl, hir::Mutability::Not); // can only coerce &T -> &U
             return success(vec![], ty, obligations);
         }
 
@@ -441,8 +441,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             _ => span_bug!(span, "expected a ref type, got {:?}", ty),
         };
         let mutbl = match mt_b.mutbl {
-            hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-            hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+            hir::Mutability::Not => AutoBorrowMutability::Not,
+            hir::Mutability::Mut => AutoBorrowMutability::Mut {
                 allow_two_phase_borrow: self.allow_two_phase,
             }
         };
@@ -487,8 +487,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 let coercion = Coercion(self.cause.span);
                 let r_borrow = self.next_region_var(coercion);
                 let mutbl = match mutbl_b {
-                    hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                    hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                    hir::Mutability::Not => AutoBorrowMutability::Not,
+                    hir::Mutability::Mut => AutoBorrowMutability::Mut {
                         // We don't allow two-phase borrows here, at least for initial
                         // implementation. If it happens that this coercion is a function argument,
                         // the reborrow in coerce_borrowed_ptr will pick it up.
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 42414228522..4dba2fb96eb 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -5,7 +5,7 @@ use rustc::ty::{self, TyCtxt, GenericParamDefKind};
 use rustc::ty::util::ExplicitSelf;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
-use rustc::ty::subst::{Subst, InternalSubsts, SubstsRef};
+use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::util::common::ErrorReported;
 use errors::{Applicability, DiagnosticId};
 
@@ -26,7 +26,7 @@ use rustc_error_codes::*;
 /// - `trait_m`: the method in the trait
 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
 
-pub fn compare_impl_method<'tcx>(
+crate fn compare_impl_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
     impl_m_span: Span,
@@ -181,13 +181,14 @@ fn compare_predicate_entailment<'tcx>(
     let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
 
     // Check region bounds.
-    check_region_bounds_on_impl_method(tcx,
-                                       impl_m_span,
-                                       impl_m,
-                                       trait_m,
-                                       &trait_m_generics,
-                                       &impl_m_generics,
-                                       trait_to_skol_substs)?;
+    check_region_bounds_on_impl_item(
+        tcx,
+        impl_m_span,
+        impl_m,
+        trait_m,
+        &trait_m_generics,
+        &impl_m_generics,
+    )?;
 
     // Create obligations for each predicate declared by the impl
     // definition in the context of the trait's parameter
@@ -361,25 +362,22 @@ fn compare_predicate_entailment<'tcx>(
     })
 }
 
-fn check_region_bounds_on_impl_method<'tcx>(
+fn check_region_bounds_on_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     span: Span,
     impl_m: &ty::AssocItem,
     trait_m: &ty::AssocItem,
     trait_generics: &ty::Generics,
     impl_generics: &ty::Generics,
-    trait_to_skol_substs: SubstsRef<'tcx>,
 ) -> Result<(), ErrorReported> {
     let trait_params = trait_generics.own_counts().lifetimes;
     let impl_params = impl_generics.own_counts().lifetimes;
 
-    debug!("check_region_bounds_on_impl_method: \
+    debug!("check_region_bounds_on_impl_item: \
             trait_generics={:?} \
-            impl_generics={:?} \
-            trait_to_skol_substs={:?}",
+            impl_generics={:?}",
            trait_generics,
-           impl_generics,
-           trait_to_skol_substs);
+           impl_generics);
 
     // Must have same number of early-bound lifetime parameters.
     // Unfortunately, if the user screws up the bounds, then this
@@ -391,20 +389,25 @@ fn check_region_bounds_on_impl_method<'tcx>(
     // are zero. Since I don't quite know how to phrase things at
     // the moment, give a kind of vague error message.
     if trait_params != impl_params {
+        let item_kind = assoc_item_kind_str(impl_m);
         let def_span = tcx.sess.source_map().def_span(span);
         let span = tcx.hir().get_generics(impl_m.def_id).map(|g| g.span).unwrap_or(def_span);
         let mut err = struct_span_err!(
             tcx.sess,
             span,
             E0195,
-            "lifetime parameters or bounds on method `{}` do not match the trait declaration",
+            "lifetime parameters or bounds on {} `{}` do not match the trait declaration",
+            item_kind,
             impl_m.ident,
         );
-        err.span_label(span, "lifetimes do not match method in trait");
+        err.span_label(span, &format!("lifetimes do not match {} in trait", item_kind));
         if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) {
             let def_sp = tcx.sess.source_map().def_span(sp);
             let sp = tcx.hir().get_generics(trait_m.def_id).map(|g| g.span).unwrap_or(def_sp);
-            err.span_label(sp, "lifetimes in impl do not match this method in trait");
+            err.span_label(
+                sp,
+                &format!("lifetimes in impl do not match this {} in trait", item_kind),
+            );
         }
         err.emit();
         return Err(ErrorReported);
@@ -534,8 +537,8 @@ fn compare_self_type<'tcx>(
             let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
             match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
                 ExplicitSelf::ByValue => "self".to_owned(),
-                ExplicitSelf::ByReference(_, hir::Mutability::Immutable) => "&self".to_owned(),
-                ExplicitSelf::ByReference(_, hir::Mutability::Mutable) => "&mut self".to_owned(),
+                ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
+                ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
                 _ => format!("self: {}", self_arg_ty)
             }
         })
@@ -603,6 +606,8 @@ fn compare_number_of_generics<'tcx>(
         ("const", trait_own_counts.consts, impl_own_counts.consts),
     ];
 
+    let item_kind = assoc_item_kind_str(impl_);
+
     let mut err_occurred = false;
     for &(kind, trait_count, impl_count) in &matchings {
         if impl_count != trait_count {
@@ -647,8 +652,9 @@ fn compare_number_of_generics<'tcx>(
             let mut err = tcx.sess.struct_span_err_with_code(
                 spans,
                 &format!(
-                    "method `{}` has {} {kind} parameter{} but its trait \
+                    "{} `{}` has {} {kind} parameter{} but its trait \
                      declaration has {} {kind} parameter{}",
+                    item_kind,
                     trait_.ident,
                     impl_count,
                     pluralize!(impl_count),
@@ -961,7 +967,7 @@ fn compare_synthetic_generics<'tcx>(
     }
 }
 
-pub fn compare_const_impl<'tcx>(
+crate fn compare_const_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_c: &ty::AssocItem,
     impl_c_span: Span,
@@ -1059,3 +1065,131 @@ pub fn compare_const_impl<'tcx>(
         fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]);
     });
 }
+
+crate fn compare_ty_impl<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_ty: &ty::AssocItem,
+    impl_ty_span: Span,
+    trait_ty: &ty::AssocItem,
+    impl_trait_ref: ty::TraitRef<'tcx>,
+    trait_item_span: Option<Span>,
+) {
+    debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
+
+    let _: Result<(), ErrorReported> = (|| {
+        compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
+
+        compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
+    })();
+}
+
+/// The equivalent of [compare_predicate_entailment], but for associated types
+/// instead of associated functions.
+fn compare_type_predicate_entailment(
+    tcx: TyCtxt<'tcx>,
+    impl_ty: &ty::AssocItem,
+    impl_ty_span: Span,
+    trait_ty: &ty::AssocItem,
+    impl_trait_ref: ty::TraitRef<'tcx>,
+) -> Result<(), ErrorReported> {
+    let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
+    let trait_to_impl_substs = impl_substs.rebase_onto(tcx,
+                                                       impl_ty.container.id(),
+                                                       impl_trait_ref.substs);
+
+    let impl_ty_generics = tcx.generics_of(impl_ty.def_id);
+    let trait_ty_generics = tcx.generics_of(trait_ty.def_id);
+    let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
+    let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
+
+    check_region_bounds_on_impl_item(
+        tcx,
+        impl_ty_span,
+        impl_ty,
+        trait_ty,
+        &trait_ty_generics,
+        &impl_ty_generics,
+    )?;
+
+    let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);
+
+    if impl_ty_own_bounds.is_empty() {
+        // Nothing to check.
+        return Ok(());
+    }
+
+    // This `HirId` should be used for the `body_id` field on each
+    // `ObligationCause` (and the `FnCtxt`). This is what
+    // `regionck_item` expects.
+    let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id).unwrap();
+    let cause = ObligationCause {
+        span: impl_ty_span,
+        body_id: impl_ty_hir_id,
+        code: ObligationCauseCode::CompareImplTypeObligation {
+            item_name: impl_ty.ident.name,
+            impl_item_def_id: impl_ty.def_id,
+            trait_item_def_id: trait_ty.def_id,
+        },
+    };
+
+    debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
+
+    // The predicates declared by the impl definition, the trait and the
+    // associated type in the trait are assumed.
+    let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap());
+    let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
+    hybrid_preds.predicates.extend(
+        trait_ty_predicates.instantiate_own(tcx, trait_to_impl_substs).predicates);
+
+    debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
+
+    let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
+    let param_env = ty::ParamEnv::new(
+        tcx.intern_predicates(&hybrid_preds.predicates),
+        Reveal::UserFacing,
+        None
+    );
+    let param_env = traits::normalize_param_env_or_error(tcx,
+                                                         impl_ty.def_id,
+                                                         param_env,
+                                                         normalize_cause.clone());
+    tcx.infer_ctxt().enter(|infcx| {
+        let inh = Inherited::new(infcx, impl_ty.def_id);
+        let infcx = &inh.infcx;
+
+        debug!("compare_type_predicate_entailment: caller_bounds={:?}",
+               param_env.caller_bounds);
+
+        let mut selcx = traits::SelectionContext::new(&infcx);
+
+        for predicate in impl_ty_own_bounds.predicates {
+            let traits::Normalized { value: predicate, obligations } =
+                traits::normalize(&mut selcx, param_env, normalize_cause.clone(), &predicate);
+
+            inh.register_predicates(obligations);
+            inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
+        }
+
+        // Check that all obligations are satisfied by the implementation's
+        // version.
+        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
+            infcx.report_fulfillment_errors(errors, None, false);
+            return Err(ErrorReported);
+        }
+
+        // Finally, resolve all regions. This catches wily misuses of
+        // lifetime parameters.
+        let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+
+        Ok(())
+    })
+}
+
+fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
+    match impl_item.kind {
+        ty::AssocKind::Const => "const",
+        ty::AssocKind::Method => "method",
+        ty::AssocKind::Type | ty::AssocKind::OpaqueTy => "type",
+    }
+}
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 16a55d2a4d3..1e3ede4c182 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -436,10 +436,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // bar(&x); // error, expected &mut
                 // ```
                 let ref_ty = match mutability {
-                    hir::Mutability::Mutable => {
+                    hir::Mutability::Mut => {
                         self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
                     }
-                    hir::Mutability::Immutable => {
+                    hir::Mutability::Not => {
                         self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
                     }
                 };
@@ -489,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         })) = self.tcx.hir().find(
                             self.tcx.hir().get_parent_node(expr.hir_id),
                         ) {
-                            if mutability == hir::Mutability::Mutable {
+                            if mutability == hir::Mutability::Mut {
                                 // Found the following case:
                                 // fn foo(opt: &mut Option<String>){ opt = None }
                                 //                                   ---   ^^^^
@@ -508,12 +508,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
 
                         return Some(match mutability {
-                            hir::Mutability::Mutable => (
+                            hir::Mutability::Mut => (
                                 sp,
                                 "consider mutably borrowing here",
                                 format!("{}&mut {}", field_name, sugg_expr),
                             ),
-                            hir::Mutability::Immutable => (
+                            hir::Mutability::Not => (
                                 sp,
                                 "consider borrowing here",
                                 format!("{}&{}", field_name, sugg_expr),
@@ -551,15 +551,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Check for `Deref` implementations by constructing a predicate to
                 // prove: `<T as Deref>::Output == U`
                 let deref_trait = self.tcx.lang_items().deref_trait().unwrap();
-                let item_def_id = self.tcx.associated_items(deref_trait).next().unwrap().def_id;
+                let item_def_id = self.tcx.associated_items(deref_trait)
+                    .find(|item| item.kind == ty::AssocKind::Type)
+                    .unwrap()
+                    .def_id;
                 let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
                     // `<T as Deref>::Output`
                     projection_ty: ty::ProjectionTy {
                         // `T`
-                        substs: self.tcx.mk_substs_trait(
-                            checked_ty,
-                            self.fresh_substs_for_item(sp, item_def_id),
-                        ),
+                        substs: self.tcx.intern_substs(&[checked_ty.into()]),
                         // `Deref::Output`
                         item_def_id,
                     },
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index fba933ab0ce..025bb05f63a 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -2,13 +2,15 @@ use crate::check::regionck::RegionCtxt;
 
 use crate::hir;
 use crate::hir::def_id::DefId;
+use crate::util::common::ErrorReported;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::{InferOk, SuppressRegionErrors};
 use rustc::middle::region;
 use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt};
+use rustc::ty::error::TypeError;
+use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc::ty::subst::{Subst, SubstsRef};
-use rustc::ty::{self, Ty, TyCtxt};
-use crate::util::common::ErrorReported;
+use rustc::ty::{self, Predicate, Ty, TyCtxt};
 
 use syntax_pos::Span;
 
@@ -56,8 +58,10 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
             // already checked by coherence, but compilation may
             // not have been terminated.
             let span = tcx.def_span(drop_impl_did);
-            tcx.sess.delay_span_bug(span,
-                &format!("should have been rejected by coherence check: {}", dtor_self_type));
+            tcx.sess.delay_span_bug(
+                span,
+                &format!("should have been rejected by coherence check: {}", dtor_self_type),
+            );
             Err(ErrorReported)
         }
     }
@@ -85,10 +89,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
         let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
 
         let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
-        match infcx
-            .at(cause, impl_param_env)
-            .eq(named_type, fresh_impl_self_ty)
-        {
+        match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) {
             Ok(InferOk { obligations, .. }) => {
                 fulfillment_cx.register_predicate_obligations(infcx, obligations);
             }
@@ -99,12 +100,13 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
                     drop_impl_span,
                     E0366,
                     "Implementations of Drop cannot be specialized"
-                ).span_note(
+                )
+                .span_note(
                     item_span,
                     "Use same sequence of generic type and region \
                      parameters that is on the struct/enum definition",
                 )
-                    .emit();
+                .emit();
                 return Err(ErrorReported);
             }
         }
@@ -194,6 +196,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
     let assumptions_in_impl_context = assumptions_in_impl_context.predicates;
 
+    let self_param_env = tcx.param_env(self_type_did);
+
     // An earlier version of this code attempted to do this checking
     // via the traits::fulfill machinery. However, it ran into trouble
     // since the fulfill machinery merely turns outlives-predicates
@@ -207,14 +211,35 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         // to take on a structure that is roughly an alpha-renaming of
         // the generic parameters of the item definition.)
 
-        // This path now just checks *all* predicates via the direct
-        // lookup, rather than using fulfill machinery.
+        // This path now just checks *all* predicates via an instantiation of
+        // the `SimpleEqRelation`, which simply forwards to the `relate` machinery
+        // after taking care of anonymizing late bound regions.
         //
         // However, it may be more efficient in the future to batch
-        // the analysis together via the fulfill , rather than the
-        // repeated `contains` calls.
+        // the analysis together via the fulfill (see comment above regarding
+        // the usage of the fulfill machinery), rather than the
+        // repeated `.iter().any(..)` calls.
 
-        if !assumptions_in_impl_context.contains(&predicate) {
+        // This closure is a more robust way to check `Predicate` equality
+        // than simple `==` checks (which were the previous implementation).
+        // It relies on `ty::relate` for `TraitPredicate` and `ProjectionPredicate`
+        // (which implement the Relate trait), while delegating on simple equality
+        // for the other `Predicate`.
+        // This implementation solves (Issue #59497) and (Issue #58311).
+        // It is unclear to me at the moment whether the approach based on `relate`
+        // could be extended easily also to the other `Predicate`.
+        let predicate_matches_closure = |p: &'_ Predicate<'tcx>| {
+            let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
+            match (predicate, p) {
+                (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(),
+                (Predicate::Projection(a), Predicate::Projection(b)) => {
+                    relator.relate(a, b).is_ok()
+                }
+                _ => predicate == p,
+            }
+        };
+
+        if !assumptions_in_impl_context.iter().any(predicate_matches_closure) {
             let item_span = tcx.hir().span(self_type_hir_id);
             struct_span_err!(
                 tcx.sess,
@@ -222,12 +247,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
                 E0367,
                 "The requirement `{}` is added only by the Drop impl.",
                 predicate
-            ).span_note(
+            )
+            .span_note(
                 item_span,
                 "The same requirement must be part of \
                  the struct/enum definition",
             )
-                .emit();
+            .emit();
             result = Err(ErrorReported);
         }
     }
@@ -253,3 +279,99 @@ crate fn check_drop_obligations<'a, 'tcx>(
 
     Ok(())
 }
+
+// This is an implementation of the TypeRelation trait with the
+// aim of simply comparing for equality (without side-effects).
+// It is not intended to be used anywhere else other than here.
+crate struct SimpleEqRelation<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+}
+
+impl<'tcx> SimpleEqRelation<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> SimpleEqRelation<'tcx> {
+        SimpleEqRelation { tcx, param_env }
+    }
+}
+
+impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+
+    fn tag(&self) -> &'static str {
+        "dropck::SimpleEqRelation"
+    }
+
+    fn a_is_expected(&self) -> bool {
+        true
+    }
+
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        _: ty::Variance,
+        a: &T,
+        b: &T,
+    ) -> RelateResult<'tcx, T> {
+        // Here we ignore variance because we require drop impl's types
+        // to be *exactly* the same as to the ones in the struct definition.
+        self.relate(a, b)
+    }
+
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        debug!("SimpleEqRelation::tys(a={:?}, b={:?})", a, b);
+        ty::relate::super_relate_tys(self, a, b)
+    }
+
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        debug!("SimpleEqRelation::regions(a={:?}, b={:?})", a, b);
+
+        // We can just equate the regions because LBRs have been
+        // already anonymized.
+        if a == b {
+            Ok(a)
+        } else {
+            // I'm not sure is this `TypeError` is the right one, but
+            // it should not matter as it won't be checked (the dropck
+            // will emit its own, more informative and higher-level errors
+            // in case anything goes wrong).
+            Err(TypeError::RegionsPlaceholderMismatch)
+        }
+    }
+
+    fn consts(
+        &mut self,
+        a: &'tcx ty::Const<'tcx>,
+        b: &'tcx ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
+        debug!("SimpleEqRelation::consts(a={:?}, b={:?})", a, b);
+        ty::relate::super_relate_consts(self, a, b)
+    }
+
+    fn binders<T>(
+        &mut self,
+        a: &ty::Binder<T>,
+        b: &ty::Binder<T>,
+    ) -> RelateResult<'tcx, ty::Binder<T>>
+    where
+        T: Relate<'tcx>,
+    {
+        debug!("SimpleEqRelation::binders({:?}: {:?}", a, b);
+
+        // Anonymizing the LBRs is necessary to solve (Issue #59497).
+        // After we do so, it should be totally fine to skip the binders.
+        let anon_a = self.tcx.anonymize_late_bound_regions(a);
+        let anon_b = self.tcx.anonymize_late_bound_regions(b);
+        self.relate(anon_a.skip_binder(), anon_b.skip_binder())?;
+
+        Ok(a.clone())
+    }
+}
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index b287b39cb99..a6ae10b3dea 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -363,8 +363,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let method = self.register_infer_ok_obligations(ok);
                         if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind {
                             let mutbl = match mutbl {
-                                hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                                hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                                hir::Mutability::Not => AutoBorrowMutability::Not,
+                                hir::Mutability::Mut => AutoBorrowMutability::Mut {
                                     // (It shouldn't actually matter for unary ops whether
                                     // we enable two-phase borrows or not, since a unary
                                     // op has no additional operands.)
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index fcf6b22f74f..607efca88dd 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -19,6 +19,7 @@ struct InteriorVisitor<'a, 'tcx> {
     region_scope_tree: &'tcx region::ScopeTree,
     expr_count: usize,
     kind: hir::GeneratorKind,
+    prev_unresolved_span: Option<Span>,
 }
 
 impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
@@ -32,7 +33,6 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
         debug!("generator_interior: attempting to record type {:?} {:?} {:?} {:?}",
                ty, scope, expr, source_span);
 
-
         let live_across_yield = scope.map(|s| {
             self.region_scope_tree.yield_in_scope(s).and_then(|yield_data| {
                 // If we are recording an expression that is the last yield
@@ -54,15 +54,11 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
         }).unwrap_or_else(|| Some(YieldData {
             span: DUMMY_SP,
             expr_and_pat_count: 0,
-            source: match self.kind { // Guess based on the kind of the current generator.
-                hir::GeneratorKind::Gen => hir::YieldSource::Yield,
-                hir::GeneratorKind::Async(_) => hir::YieldSource::Await,
-            },
+            source: self.kind.into(),
         }));
 
         if let Some(yield_data) = live_across_yield {
             let ty = self.fcx.resolve_vars_if_possible(&ty);
-
             debug!("type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
                    expr, scope, ty, self.expr_count, yield_data.span);
 
@@ -74,9 +70,12 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                                    yield_data.source);
 
                 // If unresolved type isn't a ty_var then unresolved_type_span is None
+                let span = self.prev_unresolved_span.unwrap_or_else(
+                    || unresolved_type_span.unwrap_or(source_span)
+                );
                 self.fcx.need_type_info_err_in_generator(
                     self.kind,
-                    unresolved_type_span.unwrap_or(source_span),
+                    span,
                     unresolved_type,
                 )
                     .span_note(yield_data.span, &*note)
@@ -94,6 +93,13 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
         } else {
             debug!("no type in expr = {:?}, count = {:?}, span = {:?}",
                    expr, self.expr_count, expr.map(|e| e.span));
+            let ty = self.fcx.resolve_vars_if_possible(&ty);
+            if let Some((unresolved_type, unresolved_type_span))
+                = self.fcx.unresolved_type_vars(&ty) {
+                debug!("remained unresolved_type = {:?}, unresolved_type_span: {:?}",
+                    unresolved_type, unresolved_type_span);
+                self.prev_unresolved_span = unresolved_type_span;
+            }
         }
     }
 }
@@ -112,6 +118,7 @@ pub fn resolve_interior<'a, 'tcx>(
         region_scope_tree: fcx.tcx.region_scope_tree(def_id),
         expr_count: 0,
         kind,
+        prev_unresolved_span: None,
     };
     intravisit::walk_body(&mut visitor, body);
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index cec831147c4..d6661a7ec6a 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -17,7 +17,7 @@ use std::iter;
 
 fn equate_intrinsic_type<'tcx>(
     tcx: TyCtxt<'tcx>,
-    it: &hir::ForeignItem,
+    it: &hir::ForeignItem<'_>,
     n_tps: usize,
     abi: Abi,
     safety: hir::Unsafety,
@@ -83,7 +83,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
 
 /// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
 /// and in libcore/intrinsics.rs
-pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
+pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
     let name = it.ident.as_str();
 
@@ -165,7 +165,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
             "prefetch_read_instruction" | "prefetch_write_instruction" => {
                 (1, vec![tcx.mk_ptr(ty::TypeAndMut {
                           ty: param(0),
-                          mutbl: hir::Mutability::Immutable
+                          mutbl: hir::Mutability::Not
                          }), tcx.types.i32],
                     tcx.mk_unit())
             }
@@ -181,13 +181,13 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
                vec![
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(0),
-                      mutbl: hir::Mutability::Immutable
+                      mutbl: hir::Mutability::Not
                   }),
                   tcx.types.isize
                ],
                tcx.mk_ptr(ty::TypeAndMut {
                    ty: param(0),
-                   mutbl: hir::Mutability::Immutable
+                   mutbl: hir::Mutability::Not
                }))
             }
             "copy" | "copy_nonoverlapping" => {
@@ -195,11 +195,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
                vec![
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(0),
-                      mutbl: hir::Mutability::Immutable
+                      mutbl: hir::Mutability::Not
                   }),
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(0),
-                      mutbl: hir::Mutability::Mutable
+                      mutbl: hir::Mutability::Mut
                   }),
                   tcx.types.usize,
                ],
@@ -210,11 +210,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
                vec![
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(0),
-                      mutbl: hir::Mutability::Mutable
+                      mutbl: hir::Mutability::Mut
                   }),
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(0),
-                      mutbl: hir::Mutability::Immutable
+                      mutbl: hir::Mutability::Not
                   }),
                   tcx.types.usize,
                ],
@@ -225,7 +225,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
                vec![
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(0),
-                      mutbl: hir::Mutability::Mutable
+                      mutbl: hir::Mutability::Mut
                   }),
                   tcx.types.u8,
                   tcx.types.usize,
@@ -351,14 +351,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
             }
 
             "va_start" | "va_end" => {
-                match mk_va_list_ty(hir::Mutability::Mutable) {
+                match mk_va_list_ty(hir::Mutability::Mut) {
                     Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()),
                     None => bug!("`va_list` language item needed for C-variadic intrinsics")
                 }
             }
 
             "va_copy" => {
-                match mk_va_list_ty(hir::Mutability::Immutable) {
+                match mk_va_list_ty(hir::Mutability::Not) {
                     Some((va_list_ref_ty, va_list_ty)) => {
                         let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty);
                         (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit())
@@ -368,7 +368,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
             }
 
             "va_arg" => {
-                match mk_va_list_ty(hir::Mutability::Mutable) {
+                match mk_va_list_ty(hir::Mutability::Mut) {
                     Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)),
                     None => bug!("`va_list` language item needed for C-variadic intrinsics")
                 }
@@ -399,7 +399,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
-pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
+pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let param = |n| {
         let name = Symbol::intern(&format!("P{}", n));
         tcx.mk_ty_param(n, name)
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 4bdab84faf1..d04baf7dd07 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -131,7 +131,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             sig: method_sig,
         };
 
-        if let Some(hir::Mutability::Mutable) = pick.autoref {
+        if let Some(hir::Mutability::Mut) = pick.autoref {
             self.convert_place_derefs_to_mutable();
         }
 
@@ -172,8 +172,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 ty: target
             });
             let mutbl = match mutbl {
-                hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                hir::Mutability::Not => AutoBorrowMutability::Not,
+                hir::Mutability::Mut => AutoBorrowMutability::Mut {
                     // Method call receivers are the primary use case
                     // for two-phase borrows.
                     allow_two_phase_borrow: AllowTwoPhase::Yes,
@@ -554,8 +554,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind {
                     debug!("convert_place_op_to_mutable: converting autoref {:?}", adjustment);
                     let mutbl = match mutbl {
-                        hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                        hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                        hir::Mutability::Not => AutoBorrowMutability::Not,
+                        hir::Mutability::Mut => AutoBorrowMutability::Mut {
                             // For initial two-phase borrow
                             // deployment, conservatively omit
                             // overloaded operators.
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 880ead0e301..f797eec911b 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -608,11 +608,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 let lang_def_id = lang_items.slice_u8_alloc_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Immutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
                 let lang_def_id = lang_items.const_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
                 let lang_def_id = lang_items.mut_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
@@ -1047,8 +1047,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty)
                     });
                 self.pick_by_value_method(step, self_ty).or_else(|| {
-                self.pick_autorefd_method(step, self_ty, hir::Mutability::Immutable).or_else(|| {
-                self.pick_autorefd_method(step, self_ty, hir::Mutability::Mutable)
+                self.pick_autorefd_method(step, self_ty, hir::Mutability::Not).or_else(|| {
+                self.pick_autorefd_method(step, self_ty, hir::Mutability::Mut)
             })})})
             .next()
     }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 9cd8c9abfd7..e2b77c01e24 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -1002,7 +1002,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
     }
 
     impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
-        fn visit_item(&mut self, i: &'v hir::Item) {
+        fn visit_item(&mut self, i: &'v hir::Item<'v>) {
             match i.kind {
                 hir::ItemKind::Trait(..) |
                 hir::ItemKind::TraitAlias(..) => {
@@ -1013,9 +1013,9 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
             }
         }
 
-        fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
+        fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
-        fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {}
+        fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
     }
 
     tcx.hir().krate().visit_all_item_likes(&mut Visitor {
@@ -1076,7 +1076,7 @@ struct UsePlacementFinder<'tcx> {
 impl UsePlacementFinder<'tcx> {
     fn check(
         tcx: TyCtxt<'tcx>,
-        krate: &'tcx hir::Crate,
+        krate: &'tcx hir::Crate<'tcx>,
         target_module: hir::HirId,
     ) -> (Option<Span>, bool) {
         let mut finder = UsePlacementFinder {
@@ -1093,7 +1093,7 @@ impl UsePlacementFinder<'tcx> {
 impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
     fn visit_mod(
         &mut self,
-        module: &'tcx hir::Mod,
+        module: &'tcx hir::Mod<'tcx>,
         _: Span,
         hir_id: hir::HirId,
     ) {
@@ -1105,7 +1105,7 @@ impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
             return;
         }
         // Find a `use` statement.
-        for item_id in &module.item_ids {
+        for item_id in module.item_ids {
             let item = self.tcx.hir().expect_item(item_id.id);
             match item.kind {
                 hir::ItemKind::Use(..) => {
@@ -1127,7 +1127,7 @@ impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
                             self.span = Some(item.span.shrink_to_lo());
                         } else {
                             // Find the first attribute on the item.
-                            for attr in &item.attrs {
+                            for attr in item.attrs {
                                 if self.span.map_or(true, |span| attr.span < span) {
                                     self.span = Some(attr.span.shrink_to_lo());
                                 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 84f5847ddd3..ea295103982 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -154,7 +154,7 @@ pub use self::Expectation::*;
 use self::autoderef::Autoderef;
 use self::callee::DeferredCallResolution;
 use self::coercion::{CoerceMany, DynamicCoerceMany};
-pub use self::compare_method::{compare_impl_method, compare_const_impl};
+use self::compare_method::{compare_impl_method, compare_const_impl, compare_ty_impl};
 use self::method::{MethodCallee, SelfSource};
 use self::TupleArgumentsFlag::*;
 
@@ -397,8 +397,8 @@ pub enum Needs {
 impl Needs {
     fn maybe_mut_place(m: hir::Mutability) -> Self {
         match m {
-            hir::Mutability::Mutable => Needs::MutPlace,
-            hir::Mutability::Immutable => Needs::None,
+            hir::Mutability::Mut => Needs::MutPlace,
+            hir::Mutability::Not => Needs::None,
         }
     }
 }
@@ -751,11 +751,11 @@ struct CheckItemTypesVisitor<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
-    fn visit_item(&mut self, i: &'tcx hir::Item) {
+    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
         check_item_type(self.tcx, i);
     }
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { }
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) { }
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) { }
 }
 
 pub fn check_wf_new(tcx: TyCtxt<'_>) {
@@ -1260,7 +1260,7 @@ fn check_fn<'a, 'tcx>(
     fn_sig: ty::FnSig<'tcx>,
     decl: &'tcx hir::FnDecl,
     fn_id: hir::HirId,
-    body: &'tcx hir::Body,
+    body: &'tcx hir::Body<'tcx>,
     can_be_generator: Option<hir::Movability>,
 ) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
     let mut fn_sig = fn_sig.clone();
@@ -1327,7 +1327,7 @@ fn check_fn<'a, 'tcx>(
     for (param_ty, param) in
         fn_sig.inputs().iter().copied()
             .chain(maybe_va_list)
-            .zip(&body.params)
+            .zip(body.params)
     {
         // Check the pattern.
         fcx.check_pat_top(&param.pat, param_ty, None);
@@ -1436,7 +1436,7 @@ fn check_fn<'a, 'tcx>(
                         ty::Ref(region, ty, mutbl) => match ty.kind {
                             ty::Adt(ref adt, _) => {
                                 adt.did == panic_info_did &&
-                                    mutbl == hir::Mutability::Immutable &&
+                                    mutbl == hir::Mutability::Not &&
                                     *region != RegionKind::ReStatic
                             },
                             _ => false,
@@ -1696,7 +1696,7 @@ fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
     }
 }
 
-pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
+pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
     debug!(
         "check_item_type(it.hir_id={}, it.name={})",
         it.hir_id,
@@ -1766,15 +1766,15 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
             check_abi(tcx, it.span, m.abi);
 
             if m.abi == Abi::RustIntrinsic {
-                for item in &m.items {
+                for item in m.items {
                     intrinsic::check_intrinsic_type(tcx, item);
                 }
             } else if m.abi == Abi::PlatformIntrinsic {
-                for item in &m.items {
+                for item in m.items {
                     intrinsic::check_platform_intrinsic_type(tcx, item);
                 }
             } else {
-                for item in &m.items {
+                for item in m.items {
                     let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
                     let own_counts = generics.own_counts();
                     if generics.params.len() - own_counts.lifetimes != 0 {
@@ -1851,7 +1851,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
     }
 }
 
-fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item) {
+fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) {
     let item_def_id = tcx.hir().local_def_id(item.hir_id);
     // an error would be reported if this fails.
     let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id);
@@ -1859,7 +1859,7 @@ fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item
 
 fn report_forbidden_specialization(
     tcx: TyCtxt<'_>,
-    impl_item: &hir::ImplItem,
+    impl_item: &hir::ImplItem<'_>,
     parent_impl: DefId,
 ) {
     let mut err = struct_span_err!(
@@ -1889,7 +1889,7 @@ fn check_specialization_validity<'tcx>(
     trait_def: &ty::TraitDef,
     trait_item: &ty::AssocItem,
     impl_id: DefId,
-    impl_item: &hir::ImplItem,
+    impl_item: &hir::ImplItem<'_>,
 ) {
     let kind = match impl_item.kind {
         hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
@@ -2008,14 +2008,14 @@ fn check_impl_items_against_trait<'tcx>(
                     }
                 }
                 hir::ImplItemKind::Method(..) => {
-                    let trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
+                    let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Method {
                         compare_impl_method(tcx,
                                             &ty_impl_item,
                                             impl_item.span,
                                             &ty_trait_item,
                                             impl_trait_ref,
-                                            trait_span);
+                                            opt_trait_span);
                     } else {
                         let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324,
                             "item `{}` is an associated method, \
@@ -2023,7 +2023,7 @@ fn check_impl_items_against_trait<'tcx>(
                             ty_impl_item.ident,
                             impl_trait_ref.print_only_trait_path());
                          err.span_label(impl_item.span, "does not match trait");
-                         if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
+                         if let Some(trait_span) = opt_trait_span {
                             err.span_label(trait_span, "item in trait");
                          }
                          err.emit()
@@ -2031,10 +2031,19 @@ fn check_impl_items_against_trait<'tcx>(
                 }
                 hir::ImplItemKind::OpaqueTy(..) |
                 hir::ImplItemKind::TyAlias(_) => {
+                    let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Type {
                         if ty_trait_item.defaultness.has_value() {
                             overridden_associated_type = Some(impl_item);
                         }
+                        compare_ty_impl(
+                            tcx,
+                            &ty_impl_item,
+                            impl_item.span,
+                            &ty_trait_item,
+                            impl_trait_ref,
+                            opt_trait_span,
+                        )
                     } else {
                         let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325,
                             "item `{}` is an associated type, \
@@ -2042,7 +2051,7 @@ fn check_impl_items_against_trait<'tcx>(
                             ty_impl_item.ident,
                             impl_trait_ref.print_only_trait_path());
                          err.span_label(impl_item.span, "does not match trait");
-                         if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
+                         if let Some(trait_span) = opt_trait_span {
                             err.span_label(trait_span, "item in trait");
                          }
                          err.emit()
@@ -2429,7 +2438,12 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
 }
 
 #[allow(trivial_numeric_casts)]
-pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], id: hir::HirId) {
+pub fn check_enum<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sp: Span,
+    vs: &'tcx [hir::Variant<'tcx>],
+    id: hir::HirId,
+) {
     let def_id = tcx.hir().local_def_id(id);
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
@@ -2466,12 +2480,12 @@ pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], i
 
     if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
         let is_unit =
-            |var: &hir::Variant| match var.data {
+            |var: &hir::Variant<'_>| match var.data {
                 hir::VariantData::Unit(..) => true,
                 _ => false
             };
 
-        let has_disr = |var: &hir::Variant| var.disr_expr.is_some();
+        let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
         let has_non_units = vs.iter().any(|var| !is_unit(var));
         let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
         let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
@@ -2598,6 +2612,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn projected_ty_from_poly_trait_ref(&self,
                                         span: Span,
                                         item_def_id: DefId,
+                                        item_segment: &hir::PathSegment,
                                         poly_trait_ref: ty::PolyTraitRef<'tcx>)
                                         -> Ty<'tcx>
     {
@@ -2607,7 +2622,16 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
             &poly_trait_ref
         );
 
-        self.tcx().mk_projection(item_def_id, trait_ref.substs)
+        let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
+            self,
+            self.tcx,
+            span,
+            item_def_id,
+            item_segment,
+            trait_ref.substs,
+        );
+
+        self.tcx().mk_projection(item_def_id, item_substs)
     }
 
     fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -3413,8 +3437,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let mut adjustments = autoderef.adjust_steps(self, needs);
                 if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].kind {
                     let mutbl = match r_mutbl {
-                        hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                        hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                        hir::Mutability::Not => AutoBorrowMutability::Not,
+                        hir::Mutability::Mut => AutoBorrowMutability::Mut {
                             // Indexing can be desugared to a method call,
                             // so maybe we could use two-phase here.
                             // See the documentation of AllowTwoPhase for why that's
@@ -3874,36 +3898,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_sp: Span,
         args: &'tcx [hir::Expr],
     ) {
-        if !call_sp.desugaring_kind().is_some() {
-            // We *do not* do this for desugared call spans to keep good diagnostics when involving
-            // the `?` operator.
-            for error in errors {
-                if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
-                    // Collect the argument position for all arguments that could have caused this
-                    // `FulfillmentError`.
-                    let mut referenced_in = final_arg_types.iter()
-                        .map(|(i, checked_ty, _)| (i, checked_ty))
-                        .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
-                        .flat_map(|(i, ty)| {
-                            let ty = self.resolve_vars_if_possible(ty);
-                            // We walk the argument type because the argument's type could have
-                            // been `Option<T>`, but the `FulfillmentError` references `T`.
-                            ty.walk()
-                                .filter(|&ty| ty == predicate.skip_binder().self_ty())
-                                .map(move |_| *i)
-                        })
-                        .collect::<Vec<_>>();
+        // We *do not* do this for desugared call spans to keep good diagnostics when involving
+        // the `?` operator.
+        if call_sp.desugaring_kind().is_some() {
+            return
+        }
 
-                    // Both checked and coerced types could have matched, thus we need to remove
-                    // duplicates.
-                    referenced_in.dedup();
+        for error in errors {
+            // Only if the cause is somewhere inside the expression we want try to point at arg.
+            // Otherwise, it means that the cause is somewhere else and we should not change
+            // anything because we can break the correct span.
+            if !call_sp.contains(error.obligation.cause.span) {
+                continue
+            }
 
-                    if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
-                        // We make sure that only *one* argument matches the obligation failure
-                        // and we assign the obligation's span to its expression's.
-                        error.obligation.cause.span = args[ref_in].span;
-                        error.points_at_arg_span = true;
-                    }
+            if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
+                // Collect the argument position for all arguments that could have caused this
+                // `FulfillmentError`.
+                let mut referenced_in = final_arg_types.iter()
+                    .map(|(i, checked_ty, _)| (i, checked_ty))
+                    .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
+                    .flat_map(|(i, ty)| {
+                        let ty = self.resolve_vars_if_possible(ty);
+                        // We walk the argument type because the argument's type could have
+                        // been `Option<T>`, but the `FulfillmentError` references `T`.
+                        ty.walk()
+                            .filter(|&ty| ty == predicate.skip_binder().self_ty())
+                            .map(move |_| *i)
+                    })
+                    .collect::<Vec<_>>();
+
+                // Both checked and coerced types could have matched, thus we need to remove
+                // duplicates.
+                referenced_in.dedup();
+
+                if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
+                    // We make sure that only *one* argument matches the obligation failure
+                    // and we assign the obligation's span to its expression's.
+                    error.obligation.cause.span = args[ref_in].span;
+                    error.points_at_arg_span = true;
                 }
             }
         }
@@ -4674,7 +4707,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(Node::ForeignItem(hir::ForeignItem {
                     kind: hir::ForeignItemKind::Fn(_, idents, _),
                     ..
-                })) |
+                })) => sugg_call = idents.iter()
+                        .map(|ident| if ident.name != kw::SelfLower {
+                            ident.to_string()
+                        } else {
+                            "_".to_string()
+                        }).collect::<Vec<_>>()
+                        .join(", "),
                 Some(Node::TraitItem(hir::TraitItem {
                     kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)),
                     ..
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 4f20a91e4b0..041a6c6f44c 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -206,8 +206,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if is_assign == IsAssign::Yes || by_ref_binop {
                     if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind {
                         let mutbl = match mutbl {
-                            hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                            hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                            hir::Mutability::Not => AutoBorrowMutability::Not,
+                            hir::Mutability::Mut => AutoBorrowMutability::Mut {
                                 // Allow two-phase borrows for binops in initial deployment
                                 // since they desugar to methods
                                 allow_two_phase_borrow: AllowTwoPhase::Yes,
@@ -223,8 +223,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if by_ref_binop {
                     if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].kind {
                         let mutbl = match mutbl {
-                            hir::Mutability::Immutable => AutoBorrowMutability::Immutable,
-                            hir::Mutability::Mutable => AutoBorrowMutability::Mutable {
+                            hir::Mutability::Not => AutoBorrowMutability::Not,
+                            hir::Mutability::Mut => AutoBorrowMutability::Mut {
                                 // Allow two-phase borrows for binops in initial deployment
                                 // since they desugar to methods
                                 allow_two_phase_borrow: AllowTwoPhase::Yes,
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 4fb57a65625..ec6439c6d77 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -32,7 +32,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn check_pat_top(&self, pat: &'tcx Pat, expected: Ty<'tcx>, discrim_span: Option<Span>) {
-        let def_bm = BindingMode::BindByValue(hir::Mutability::Immutable);
+        let def_bm = BindingMode::BindByValue(hir::Mutability::Not);
         self.check_pat(pat, expected, def_bm, discrim_span);
     }
 
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             //
             // See issue #46688.
             let def_bm = match pat.kind {
-                PatKind::Ref(..) => ty::BindByValue(hir::Mutability::Immutable),
+                PatKind::Ref(..) => ty::BindByValue(hir::Mutability::Not),
                 _ => def_bm,
             };
             (expected, def_bm)
@@ -277,10 +277,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // (depending on whether we observe `&` or `&mut`).
                 ty::BindByValue(_) |
                 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
-                ty::BindByReference(hir::Mutability::Mutable) => inner_mutability,
+                ty::BindByReference(hir::Mutability::Mut) => inner_mutability,
                 // Once a `ref`, always a `ref`.
                 // This is because a `& &mut` cannot mutate the underlying value.
-                ty::BindByReference(m @ hir::Mutability::Immutable) => m,
+                ty::BindByReference(m @ hir::Mutability::Not) => m,
             });
         }
 
@@ -1174,47 +1174,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         def_bm: BindingMode,
         discrim_span: Option<Span>,
     ) -> Ty<'tcx> {
-        let tcx = self.tcx;
-        let expected_ty = self.structurally_resolved_type(span, expected);
-        let (inner_ty, slice_ty) = match expected_ty.kind {
+        let err = self.tcx.types.err;
+        let expected = self.structurally_resolved_type(span, expected);
+        let (inner_ty, slice_ty, expected) = match expected.kind {
             // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
-            ty::Array(inner_ty, size) => {
-                let slice_ty = if let Some(size) = size.try_eval_usize(tcx, self.param_env) {
-                    // Now we know the length...
-                    let min_len = before.len() as u64 + after.len() as u64;
-                    if slice.is_none() {
-                        // ...and since there is no variable-length pattern,
-                        // we require an exact match between the number of elements
-                        // in the array pattern and as provided by the matched type.
-                        if min_len != size {
-                            self.error_scrutinee_inconsistent_length(span, min_len, size)
-                        }
-                        tcx.types.err
-                    } else if let Some(rest) = size.checked_sub(min_len) {
-                        // The variable-length pattern was there,
-                        // so it has an array type with the remaining elements left as its size...
-                        tcx.mk_array(inner_ty, rest)
-                    } else {
-                        // ...however, in this case, there were no remaining elements.
-                        // That is, the slice pattern requires more than the array type offers.
-                        self.error_scrutinee_with_rest_inconsistent_length(span, min_len, size);
-                        tcx.types.err
-                    }
-                } else {
-                    // No idea what the length is, which happens if we have e.g.,
-                    // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
-                    self.error_scrutinee_unfixed_length(span);
-                    tcx.types.err
-                };
-                (inner_ty, slice_ty)
+            ty::Array(inner_ty, len) => {
+                let min = before.len() as u64 + after.len() as u64;
+                let slice_ty = self.check_array_pat_len(span, slice, len, min)
+                    .map_or(err, |len| self.tcx.mk_array(inner_ty, len));
+                (inner_ty, slice_ty, expected)
             }
-            ty::Slice(inner_ty) => (inner_ty, expected_ty),
+            ty::Slice(inner_ty) => (inner_ty, expected, expected),
             // The expected type must be an array or slice, but was neither, so error.
             _ => {
-                if !expected_ty.references_error() {
-                    self.error_expected_array_or_slice(span, expected_ty);
+                if !expected.references_error() {
+                    self.error_expected_array_or_slice(span, expected);
                 }
-                (tcx.types.err, tcx.types.err)
+                (err, err, err)
             }
         };
 
@@ -1230,7 +1206,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         for elt in after {
             self.check_pat(&elt, inner_ty, def_bm, discrim_span);
         }
-        expected_ty
+        expected
+    }
+
+    /// Type check the length of an array pattern.
+    ///
+    /// Return the length of the variable length pattern,
+    /// if it exists and there are no errors.
+    fn check_array_pat_len(
+        &self,
+        span: Span,
+        slice: Option<&'tcx Pat>,
+        len: &ty::Const<'tcx>,
+        min_len: u64,
+    ) -> Option<u64> {
+        if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
+            // Now we know the length...
+            if slice.is_none() {
+                // ...and since there is no variable-length pattern,
+                // we require an exact match between the number of elements
+                // in the array pattern and as provided by the matched type.
+                if min_len != len {
+                    self.error_scrutinee_inconsistent_length(span, min_len, len);
+                }
+            } else if let r @ Some(_) = len.checked_sub(min_len) {
+                // The variable-length pattern was there,
+                // so it has an array type with the remaining elements left as its size...
+                return r;
+            } else {
+                // ...however, in this case, there were no remaining elements.
+                // That is, the slice pattern requires more than the array type offers.
+                self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len);
+            }
+        } else {
+            // No idea what the length is, which happens if we have e.g.,
+            // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
+            self.error_scrutinee_unfixed_length(span);
+        }
+        None
     }
 
     fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 8ceb2174852..396ff5ce518 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -106,7 +106,7 @@ macro_rules! ignore_err {
 // PUBLIC ENTRY POINTS
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    pub fn regionck_expr(&self, body: &'tcx hir::Body) {
+    pub fn regionck_expr(&self, body: &'tcx hir::Body<'tcx>) {
         let subject = self.tcx.hir().body_owner_def_id(body.id());
         let id = body.value.hir_id;
         let mut rcx = RegionCtxt::new(
@@ -159,7 +159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// rest of type check and because sometimes we need type
     /// inference to have completed before we can determine which
     /// constraints to add.
-    pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'tcx hir::Body) {
+    pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>) {
         debug!("regionck_fn(id={})", fn_id);
         let subject = self.tcx.hir().body_owner_def_id(body.id());
         let hir_id = body.value.hir_id;
@@ -300,7 +300,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
     fn visit_fn_body(
         &mut self,
         id: hir::HirId, // the id of the fn itself
-        body: &'tcx hir::Body,
+        body: &'tcx hir::Body<'tcx>,
         span: Span,
     ) {
         // When we enter a function, we can derive
@@ -1255,7 +1255,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         // know whether this scenario has occurred; but I wanted to show
         // how all the types get adjusted.)
         match ref_mutability {
-            hir::Mutability::Immutable => {
+            hir::Mutability::Not => {
                 // The reference being reborrowed is a shareable ref of
                 // type `&'a T`. In this case, it doesn't matter where we
                 // *found* the `&T` pointer, the memory it references will
@@ -1263,7 +1263,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
                 true
             }
 
-            hir::Mutability::Mutable => {
+            hir::Mutability::Mut => {
                 // The reference being reborrowed is either an `&mut T`. This is
                 // the case where recursion is needed.
                 false
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index c5a6c072979..2788aa6b83e 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -46,7 +46,7 @@ use syntax::ast;
 use syntax_pos::Span;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    pub fn closure_analyze(&self, body: &'tcx hir::Body) {
+    pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
         InferBorrowKindVisitor { fcx: self }.visit_body(body);
 
         // it's our job to process these.
@@ -81,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         closure_hir_id: hir::HirId,
         span: Span,
-        body: &hir::Body,
+        body: &hir::Body<'_>,
         capture_clause: hir::CaptureBy,
     ) {
 
@@ -353,7 +353,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
                     // borrowed pointer implies that the
                     // pointer itself must be unique, but not
                     // necessarily *mutable*
-                    ty::Ref(.., hir::Mutability::Mutable) => borrow_kind = ty::UniqueImmBorrow,
+                    ty::Ref(.., hir::Mutability::Mut) => borrow_kind = ty::UniqueImmBorrow,
                     _ => (),
                 }
             }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 20b6b01de57..e974b070dbd 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -235,7 +235,7 @@ fn check_associated_item(
     })
 }
 
-fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) -> CheckWfFcxBuilder<'tcx> {
+fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
     for_id(tcx, item.hir_id, item.span)
 }
 
@@ -252,7 +252,7 @@ fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_>
 /// In a type definition, we check that to ensure that the types of the fields are well-formed.
 fn check_type_defn<'tcx, F>(
     tcx: TyCtxt<'tcx>,
-    item: &hir::Item,
+    item: &hir::Item<'tcx>,
     all_sized: bool,
     mut lookup_fields: F,
 ) where
@@ -325,7 +325,7 @@ fn check_type_defn<'tcx, F>(
     });
 }
 
-fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item) {
+fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     debug!("check_trait: {:?}", item.hir_id);
 
     let trait_def_id = tcx.hir().local_def_id(item.hir_id);
@@ -348,7 +348,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item) {
     });
 }
 
-fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item) {
+fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     for_item(tcx, item).with_fcx(|fcx, tcx| {
         let def_id = fcx.tcx.hir().local_def_id(item.hir_id);
         let sig = fcx.tcx.fn_sig(def_id);
@@ -396,7 +396,7 @@ fn check_item_type(
 
 fn check_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
-    item: &'tcx hir::Item,
+    item: &'tcx hir::Item<'tcx>,
     ast_self_ty: &hir::Ty,
     ast_trait_ref: &Option<hir::TraitRef>,
 ) {
@@ -977,7 +977,7 @@ fn receiver_is_implemented(
 
 fn check_variances_for_type_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
-    item: &hir::Item,
+    item: &hir::Item<'tcx>,
     hir_generics: &hir::Generics,
 ) {
     let item_def_id = tcx.hir().local_def_id(item.hir_id);
@@ -1081,19 +1081,19 @@ impl CheckTypeWellFormedVisitor<'tcx> {
 }
 
 impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
-    fn visit_item(&self, i: &'tcx hir::Item) {
+    fn visit_item(&self, i: &'tcx hir::Item<'tcx>) {
         debug!("visit_item: {:?}", i);
         let def_id = self.tcx.hir().local_def_id(i.hir_id);
         self.tcx.ensure().check_item_well_formed(def_id);
     }
 
-    fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         debug!("visit_trait_item: {:?}", trait_item);
         let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
         self.tcx.ensure().check_trait_item_well_formed(def_id);
     }
 
-    fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         debug!("visit_impl_item: {:?}", impl_item);
         let def_id = self.tcx.hir().local_def_id(impl_item.hir_id);
         self.tcx.ensure().check_impl_item_well_formed(def_id);
@@ -1113,7 +1113,7 @@ struct AdtField<'tcx> {
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
+    fn non_enum_variant(&self, struct_def: &hir::VariantData<'_>) -> AdtVariant<'tcx> {
         let fields = struct_def.fields().iter().map(|field| {
             let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id));
             let field_ty = self.normalize_associated_types_in(field.span,
@@ -1126,7 +1126,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         AdtVariant { fields }
     }
 
-    fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> {
+    fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec<AdtVariant<'tcx>> {
         enum_def.variants.iter()
             .map(|variant| self.non_enum_variant(&variant.data))
             .collect()
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 35f25b322e0..a32c98068da 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -32,7 +32,9 @@ use std::mem;
 // resolve_type_vars_in_body, which creates a new TypeTables which
 // doesn't contain any inference types.
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    pub fn resolve_type_vars_in_body(&self, body: &'tcx hir::Body) -> &'tcx ty::TypeckTables<'tcx> {
+    pub fn resolve_type_vars_in_body(&self, body: &'tcx hir::Body<'tcx>)
+        -> &'tcx ty::TypeckTables<'tcx>
+    {
         let item_id = self.tcx.hir().body_owner(body.id());
         let item_def_id = self.tcx.hir().local_def_id(item_id);
 
@@ -41,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);
 
         let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
-        for param in &body.params {
+        for param in body.params {
             wbcx.visit_node_id(param.pat.span, param.hir_id);
         }
         // Type only exists for constants and statics, not functions.
@@ -102,7 +104,7 @@ struct WritebackCx<'cx, 'tcx> {
 
     tables: ty::TypeckTables<'tcx>,
 
-    body: &'tcx hir::Body,
+    body: &'tcx hir::Body<'tcx>,
 
     rustc_dump_user_substs: bool,
 }
@@ -110,7 +112,7 @@ struct WritebackCx<'cx, 'tcx> {
 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn new(
         fcx: &'cx FnCtxt<'cx, 'tcx>,
-        body: &'tcx hir::Body,
+        body: &'tcx hir::Body<'tcx>,
         rustc_dump_user_substs: bool,
     ) -> WritebackCx<'cx, 'tcx> {
         let owner = body.id().hir_id;
@@ -265,7 +267,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
         match e.kind {
             hir::ExprKind::Closure(_, _, body, _, _) => {
                 let body = self.fcx.tcx.hir().body(body);
-                for param in &body.params {
+                for param in body.params {
                     self.visit_node_id(e.span, param.hir_id);
                 }
 
@@ -698,14 +700,14 @@ struct Resolver<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     span: &'cx dyn Locatable,
-    body: &'tcx hir::Body,
+    body: &'tcx hir::Body<'tcx>,
 }
 
 impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
     fn new(
         fcx: &'cx FnCtxt<'cx, 'tcx>,
         span: &'cx dyn Locatable,
-        body: &'tcx hir::Body,
+        body: &'tcx hir::Body<'tcx>,
     ) -> Resolver<'cx, 'tcx> {
         Resolver {
             tcx: fcx.tcx,
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 7af1a342ff3..7377c4df979 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -29,7 +29,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
 }
 
 impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         if item.vis.node.is_pub() || item.span.is_dummy() {
             return;
         }
@@ -38,10 +38,10 @@ impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
 
@@ -217,7 +217,7 @@ struct ExternCrateToLint {
 }
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
             let extern_crate_def_id = self.tcx.hir().local_def_id(item.hir_id);
             self.crates_to_lint.push(
@@ -231,9 +231,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index d126a96014b..3797fcb1a6b 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -360,7 +360,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
         let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                            mt_b: ty::TypeAndMut<'tcx>,
                            mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
-            if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Immutable, hir::Mutability::Mutable) {
+            if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) {
                 infcx.report_mismatched_types(&cause,
                                               mk_ptr(mt_b.ty),
                                               target,
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 1c228396b8c..16fe6d529a4 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -50,7 +50,7 @@ struct InherentCollect<'tcx> {
 }
 
 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         let ty = match item.kind {
             hir::ItemKind::Impl(.., None, ref ty, _) => ty,
             _ => return
@@ -109,7 +109,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
                                           "[T]",
                                           item.span);
             }
-            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Immutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.const_ptr_impl(),
                                           None,
@@ -117,7 +117,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
                                           "*const T",
                                           item.span);
             }
-            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mutable }) => {
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.mut_ptr_impl(),
                                           None,
@@ -254,15 +254,15 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
 
 impl InherentCollect<'tcx> {
-    fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
+    fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) {
         if def_id.is_local() {
             // Add the implementation to the mapping from implementation to base
             // type def ID, if there is a base type for this implementation and
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 39ecfad89bc..1acbf0795a6 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -85,7 +85,7 @@ impl InherentOverlapChecker<'tcx> {
 }
 
 impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
-    fn visit_item(&mut self, item: &'v hir::Item) {
+    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
         match item.kind {
             hir::ItemKind::Enum(..) |
             hir::ItemKind::Struct(..) |
@@ -98,9 +98,9 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {
     }
 }
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index c5d9ef2030c..109609f5d49 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -23,7 +23,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
     /// apply to a specific impl, so just return after reporting one
     /// to prevent inundating the user with a bunch of similar error
     /// reports.
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         let def_id = self.tcx.hir().local_def_id(item.hir_id);
         // "Trait" impl
         if let hir::ItemKind::Impl(.., generics, Some(tr), impl_ty, _) = &item.kind {
@@ -218,9 +218,9 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 650e15ea8a7..324ac0a0f35 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -18,7 +18,7 @@ struct UnsafetyChecker<'tcx> {
 
 impl UnsafetyChecker<'tcx> {
     fn check_unsafety_coherence(&mut self,
-                                item: &'v hir::Item,
+                                item: &'v hir::Item<'v>,
                                 impl_generics: Option<&hir::Generics>,
                                 unsafety: hir::Unsafety,
                                 polarity: hir::ImplPolarity)
@@ -72,15 +72,15 @@ impl UnsafetyChecker<'tcx> {
 }
 
 impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> {
-    fn visit_item(&mut self, item: &'v hir::Item) {
+    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
         if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.kind {
             self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index b9829793cbe..8d93d0b4c70 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -111,7 +111,7 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         convert_item(self.tcx, item.hir_id);
         intravisit::walk_item(self, item);
     }
@@ -145,12 +145,12 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
         intravisit::walk_expr(self, expr);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         convert_trait_item(self.tcx, trait_item.hir_id);
         intravisit::walk_trait_item(self, trait_item);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         convert_impl_item(self.tcx, impl_item.hir_id);
         intravisit::walk_impl_item(self, impl_item);
     }
@@ -224,10 +224,19 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
         &self,
         span: Span,
         item_def_id: DefId,
+        item_segment: &hir::PathSegment,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
         if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
-            self.tcx().mk_projection(item_def_id, trait_ref.substs)
+            let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
+                self,
+                self.tcx,
+                span,
+                item_def_id,
+                item_segment,
+                trait_ref.substs,
+            );
+            self.tcx().mk_projection(item_def_id, item_substs)
         } else {
             // There are no late-bound regions; we can just ignore the binder.
             span_err!(
@@ -417,7 +426,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
         | hir::ItemKind::Mod(_)
         | hir::ItemKind::GlobalAsm(_) => {}
         hir::ItemKind::ForeignMod(ref foreign_mod) => {
-            for item in &foreign_mod.items {
+            for item in foreign_mod.items {
                 let def_id = tcx.hir().local_def_id(item.hir_id);
                 tcx.generics_of(def_id);
                 tcx.type_of(def_id);
@@ -529,7 +538,7 @@ fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) {
 fn convert_enum_variant_types(
     tcx: TyCtxt<'_>,
     def_id: DefId,
-    variants: &[hir::Variant]
+    variants: &[hir::Variant<'_>]
 ) {
     let def = tcx.adt_def(def_id);
     let repr_type = def.repr.discr_type();
@@ -584,7 +593,7 @@ fn convert_variant(
     ctor_did: Option<DefId>,
     ident: Ident,
     discr: ty::VariantDiscr,
-    def: &hir::VariantData,
+    def: &hir::VariantData<'_>,
     adt_kind: ty::AdtKind,
     parent_did: DefId,
 ) -> ty::VariantDef {
@@ -1693,7 +1702,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
             intravisit::NestedVisitorMap::All(&self.tcx.hir())
         }
-        fn visit_item(&mut self, it: &'tcx Item) {
+        fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
             debug!("find_existential_constraints: visiting {:?}", it);
             let def_id = self.tcx.hir().local_def_id(it.hir_id);
             // The opaque type itself or its children are not within its reveal scope.
@@ -1702,7 +1711,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 intravisit::walk_item(self, it);
             }
         }
-        fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
+        fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
             debug!("find_existential_constraints: visiting {:?}", it);
             let def_id = self.tcx.hir().local_def_id(it.hir_id);
             // The opaque type itself or its children are not within its reveal scope.
@@ -1711,7 +1720,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 intravisit::walk_impl_item(self, it);
             }
         }
-        fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
+        fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
             debug!("find_existential_constraints: visiting {:?}", it);
             let def_id = self.tcx.hir().local_def_id(it.hir_id);
             self.check(def_id);
@@ -2052,8 +2061,6 @@ fn explicit_predicates_of(
 
     const NO_GENERICS: &hir::Generics = &hir::Generics::empty();
 
-    let empty_trait_items = HirVec::new();
-
     let mut predicates = UniquePredicates::new();
 
     let ast_generics = match node {
@@ -2098,12 +2105,12 @@ fn explicit_predicates_of(
                 | ItemKind::Struct(_, ref generics)
                 | ItemKind::Union(_, ref generics) => generics,
 
-                ItemKind::Trait(_, _, ref generics, .., ref items) => {
+                ItemKind::Trait(_, _, ref generics, .., items) => {
                     is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
                     generics
                 }
                 ItemKind::TraitAlias(ref generics, _) => {
-                    is_trait = Some((ty::TraitRef::identity(tcx, def_id), &empty_trait_items));
+                    is_trait = Some((ty::TraitRef::identity(tcx, def_id), &[]));
                     generics
                 }
                 ItemKind::OpaqueTy(OpaqueTy {
@@ -2291,25 +2298,7 @@ fn explicit_predicates_of(
     // Add predicates from associated type bounds.
     if let Some((self_trait_ref, trait_items)) = is_trait {
         predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
-            let trait_item = tcx.hir().trait_item(trait_item_ref.id);
-            let bounds = match trait_item.kind {
-                hir::TraitItemKind::Type(ref bounds, _) => bounds,
-                _ => return Vec::new().into_iter()
-            };
-
-            let assoc_ty =
-                tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id),
-                    self_trait_ref.substs);
-
-            let bounds = AstConv::compute_bounds(
-                &ItemCtxt::new(tcx, def_id),
-                assoc_ty,
-                bounds,
-                SizedByDefault::Yes,
-                trait_item.span,
-            );
-
-            bounds.predicates(tcx, assoc_ty).into_iter()
+            associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
         }))
     }
 
@@ -2343,6 +2332,105 @@ fn explicit_predicates_of(
     result
 }
 
+fn associated_item_predicates(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    self_trait_ref: ty::TraitRef<'tcx>,
+    trait_item_ref: &hir::TraitItemRef,
+) -> Vec<(ty::Predicate<'tcx>, Span)> {
+    let trait_item = tcx.hir().trait_item(trait_item_ref.id);
+    let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
+    let bounds = match trait_item.kind {
+        hir::TraitItemKind::Type(ref bounds, _) => bounds,
+        _ => return Vec::new()
+    };
+
+    let is_gat = !tcx.generics_of(item_def_id).params.is_empty();
+
+    let mut had_error = false;
+
+    let mut unimplemented_error = |arg_kind: &str| {
+        if !had_error {
+            tcx.sess.struct_span_err(
+                trait_item.span,
+                &format!("{}-generic associated types are not yet implemented", arg_kind),
+            )
+                .note("for more information, see https://github.com/rust-lang/rust/issues/44265")
+                .emit();
+            had_error = true;
+        }
+    };
+
+    let mk_bound_param = |param: &ty::GenericParamDef, _: &_| {
+        match param.kind {
+            ty::GenericParamDefKind::Lifetime => {
+                tcx.mk_region(ty::RegionKind::ReLateBound(
+                    ty::INNERMOST,
+                    ty::BoundRegion::BrNamed(param.def_id, param.name)
+                )).into()
+            }
+            // FIXME(generic_associated_types): Use bound types and constants
+            // once they are handled by the trait system.
+            ty::GenericParamDefKind::Type { .. } => {
+                unimplemented_error("type");
+                tcx.types.err.into()
+            }
+            ty::GenericParamDefKind::Const => {
+                unimplemented_error("const");
+                tcx.consts.err.into()
+            }
+        }
+    };
+
+    let bound_substs = if is_gat {
+        // Given:
+        //
+        // trait X<'a, B, const C: usize> {
+        //     type T<'d, E, const F: usize>: Default;
+        // }
+        //
+        // We need to create predicates on the trait:
+        //
+        // for<'d, E, const F: usize>
+        // <Self as X<'a, B, const C: usize>>::T<'d, E, const F: usize>: Sized + Default
+        //
+        // We substitute escaping bound parameters for the generic
+        // arguments to the associated type which are then bound by
+        // the `Binder` around the the predicate.
+        //
+        // FIXME(generic_associated_types): Currently only lifetimes are handled.
+        self_trait_ref.substs.extend_to(tcx, item_def_id, mk_bound_param)
+    } else {
+        self_trait_ref.substs
+    };
+
+    let assoc_ty = tcx.mk_projection(
+        tcx.hir().local_def_id(trait_item.hir_id),
+        bound_substs,
+    );
+
+    let bounds = AstConv::compute_bounds(
+        &ItemCtxt::new(tcx, def_id),
+        assoc_ty,
+        bounds,
+        SizedByDefault::Yes,
+        trait_item.span,
+    );
+
+    let predicates = bounds.predicates(tcx, assoc_ty);
+
+    if is_gat {
+        // We use shifts to get the regions that we're substituting to
+        // be bound by the binders in the `Predicate`s rather that
+        // escaping.
+        let shifted_in = ty::fold::shift_vars(tcx, &predicates, 1);
+        let substituted = shifted_in.subst(tcx, bound_substs);
+        ty::fold::shift_out_vars(tcx, &substituted, 1)
+    } else {
+        predicates
+    }
+}
+
 /// Converts a specific `GenericBound` from the AST into a set of
 /// predicates that apply to the self type. A vector is returned
 /// because this can be anywhere from zero predicates (`T: ?Sized` adds no
diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs
index 0523de56512..a3a703cf50e 100644
--- a/src/librustc_typeck/constrained_generic_params.rs
+++ b/src/librustc_typeck/constrained_generic_params.rs
@@ -135,7 +135,7 @@ pub fn identify_constrained_generic_params<'tcx>(
 /// by 0. I should probably pick a less tangled example, but I can't
 /// think of any.
 pub fn setup_constraining_predicates<'tcx>(
-    tcx: TyCtxt<'_>,
+    tcx: TyCtxt<'tcx>,
     predicates: &mut [(ty::Predicate<'tcx>, Span)],
     impl_trait_ref: Option<ty::TraitRef<'tcx>>,
     input_parameters: &mut FxHashSet<Parameter>,
diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs
index 03d7ab2d633..7e67d30db18 100644
--- a/src/librustc_typeck/expr_use_visitor.rs
+++ b/src/librustc_typeck/expr_use_visitor.rs
@@ -131,10 +131,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn consume_body(&mut self, body: &hir::Body) {
+    pub fn consume_body(&mut self, body: &hir::Body<'_>) {
         debug!("consume_body(body={:?})", body);
 
-        for param in &body.params {
+        for param in body.params {
             let param_ty = return_if_err!(self.mc.pat_ty_adjusted(&param.pat));
             debug!("consume_body: param_ty = {:?}", param_ty);
 
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index 28fc44dfad5..7bcc5386445 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -79,7 +79,7 @@ struct ImplWfCheck<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.kind {
             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
             enforce_impl_params_are_constrained(self.tcx,
@@ -89,9 +89,9 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) { }
+    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) { }
 
-    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
+    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) { }
 }
 
 fn enforce_impl_params_are_constrained(
diff --git a/src/librustc_typeck/namespace.rs b/src/librustc_typeck/namespace.rs
index 1e1d3e7865c..553c93e0958 100644
--- a/src/librustc_typeck/namespace.rs
+++ b/src/librustc_typeck/namespace.rs
@@ -19,8 +19,8 @@ impl From<ty::AssocKind> for Namespace {
     }
 }
 
-impl<'a> From <&'a hir::ImplItemKind> for Namespace {
-    fn from(impl_kind: &'a hir::ImplItemKind) -> Self {
+impl<'a> From <&'a hir::ImplItemKind<'_>> for Namespace {
+    fn from(impl_kind: &'a hir::ImplItemKind<'_>) -> Self {
         match *impl_kind {
             hir::ImplItemKind::OpaqueTy(..) |
             hir::ImplItemKind::TyAlias(..) => Namespace::Type,
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
index 74048b8d20c..e3947a84989 100644
--- a/src/librustc_typeck/outlives/implicit_infer.rs
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -51,7 +51,7 @@ pub struct InferVisitor<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         let item_did = self.tcx.hir().local_def_id(item.hir_id);
 
         debug!("InferVisitor::visit_item(item={:?})", item_did);
@@ -113,9 +113,9 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) {}
+    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
 
-    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {}
+    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
 }
 
 fn insert_required_predicates_to_be_wf<'tcx>(
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index aa5272fd4e0..081d0ff1e16 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -16,7 +16,7 @@ struct OutlivesTest<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
 
         // For unit testing: check for a special "rustc_outlives"
@@ -33,6 +33,6 @@ impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
 }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 1e1be72221f..64357cb4a3d 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -67,7 +67,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
 }
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         match item.kind {
             hir::ItemKind::Struct(ref struct_def, _) |
             hir::ItemKind::Union(ref struct_def, _) => {
@@ -81,7 +81,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
             hir::ItemKind::Enum(ref enum_def, _) => {
                 self.visit_node_helper(item.hir_id);
 
-                for variant in &enum_def.variants {
+                for variant in enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.data {
                         self.visit_node_helper(variant.data.ctor_hir_id().unwrap());
                     }
@@ -93,7 +93,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
             }
 
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
+                for foreign_item in foreign_mod.items {
                     if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
                         self.visit_node_helper(foreign_item.hir_id);
                     }
@@ -104,13 +104,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         if let hir::TraitItemKind::Method(..) = trait_item.kind {
             self.visit_node_helper(trait_item.hir_id);
         }
     }
 
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         if let hir::ImplItemKind::Method(..) = impl_item.kind {
             self.visit_node_helper(impl_item.hir_id);
         }
@@ -454,12 +454,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                mt: &ty::TypeAndMut<'tcx>,
                                variance: VarianceTermPtr<'a>) {
         match mt.mutbl {
-            hir::Mutability::Mutable => {
+            hir::Mutability::Mut => {
                 let invar = self.invariant(variance);
                 self.add_constraints_from_ty(current, mt.ty, invar);
             }
 
-            hir::Mutability::Immutable => {
+            hir::Mutability::Not => {
                 self.add_constraints_from_ty(current, mt.ty, variance);
             }
         }
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 863a0b267fd..95f361763e8 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -127,7 +127,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
         debug!("add_inferreds for item {}",
                self.tcx.hir().node_to_string(item.hir_id));
 
@@ -144,7 +144,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
             hir::ItemKind::Enum(ref enum_def, _) => {
                 self.add_inferreds_for_item(item.hir_id);
 
-                for variant in &enum_def.variants {
+                for variant in enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.data {
                         self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap());
                     }
@@ -156,7 +156,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
             }
 
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
+                for foreign_item in foreign_mod.items {
                     if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
                         self.add_inferreds_for_item(foreign_item.hir_id);
                     }
@@ -167,13 +167,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         if let hir::TraitItemKind::Method(..) = trait_item.kind {
             self.add_inferreds_for_item(trait_item.hir_id);
         }
     }
 
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         if let hir::ImplItemKind::Method(..) = impl_item.kind {
             self.add_inferreds_for_item(impl_item.hir_id);
         }
diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs
index a7fadb5459e..1233be43e09 100644
--- a/src/librustc_typeck/variance/test.rs
+++ b/src/librustc_typeck/variance/test.rs
@@ -14,7 +14,7 @@ struct VarianceTest<'tcx> {
 }
 
 impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
 
         // For unit testing: check for a special "rustc_variance"
@@ -29,6 +29,6 @@ impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { }
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) { }
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) { }
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7eb1370c342..93a1d5845ad 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -20,7 +20,7 @@ use rustc::hir::def::{CtorKind, DefKind, Res};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc::hir::ptr::P;
 use rustc::ty::subst::InternalSubsts;
-use rustc::ty::{self, TyCtxt, Ty, AdtKind};
+use rustc::ty::{self, TyCtxt, Ty, AdtKind, Lift};
 use rustc::ty::fold::TypeFolder;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use syntax::ast::{self, Ident};
@@ -69,6 +69,12 @@ impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
     }
 }
 
+impl<T: Clean<U>, U> Clean<U> for &T {
+    fn clean(&self, cx: &DocContext<'_>) -> U {
+        (**self).clean(cx)
+    }
+}
+
 impl<T: Clean<U>, U> Clean<U> for P<T> {
     fn clean(&self, cx: &DocContext<'_>) -> U {
         (**self).clean(cx)
@@ -550,7 +556,8 @@ impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
 
 impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
     fn clean(&self, cx: &DocContext<'_>) -> Type {
-        let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
+        let lifted = self.lift_to_tcx(cx.tcx).unwrap();
+        let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) {
             GenericBound::TraitBound(t, _) => t.trait_,
             GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
         };
@@ -1079,7 +1086,7 @@ impl Clean<PolyTrait> for hir::PolyTraitRef {
     }
 }
 
-impl Clean<Item> for hir::TraitItem {
+impl Clean<Item> for hir::TraitItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let inner = match self.kind {
             hir::TraitItemKind::Const(ref ty, default) => {
@@ -1120,7 +1127,7 @@ impl Clean<Item> for hir::TraitItem {
     }
 }
 
-impl Clean<Item> for hir::ImplItem {
+impl Clean<Item> for hir::ImplItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let inner = match self.kind {
             hir::ImplItemKind::Const(ref ty, expr) => {
@@ -1721,7 +1728,7 @@ impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
     }
 }
 
-impl Clean<Item> for hir::StructField {
+impl Clean<Item> for hir::StructField<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let local_did = cx.tcx.hir().local_def_id(self.hir_id);
 
@@ -1814,7 +1821,7 @@ impl Clean<Item> for doctree::Union<'_> {
     }
 }
 
-impl Clean<VariantStruct> for ::rustc::hir::VariantData {
+impl Clean<VariantStruct> for ::rustc::hir::VariantData<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
         VariantStruct {
             struct_type: doctree::struct_type_from_def(self),
@@ -1901,7 +1908,7 @@ impl Clean<Item> for ty::VariantDef {
     }
 }
 
-impl Clean<VariantKind> for hir::VariantData {
+impl Clean<VariantKind> for hir::VariantData<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
         match self {
             hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
@@ -2085,8 +2092,8 @@ impl Clean<Item> for doctree::Constant<'_> {
 impl Clean<Mutability> for hir::Mutability {
     fn clean(&self, _: &DocContext<'_>) -> Mutability {
         match self {
-            &hir::Mutability::Mutable => Mutable,
-            &hir::Mutability::Immutable => Immutable,
+            &hir::Mutability::Mut => Mutable,
+            &hir::Mutability::Not => Immutable,
         }
     }
 }
@@ -2370,12 +2377,6 @@ impl Clean<Stability> for attr::Stability {
     }
 }
 
-impl<'a> Clean<Stability> for &'a attr::Stability {
-    fn clean(&self, dc: &DocContext<'_>) -> Stability {
-        (**self).clean(dc)
-    }
-}
-
 impl Clean<Deprecation> for attr::Deprecation {
     fn clean(&self, _: &DocContext<'_>) -> Deprecation {
         Deprecation {
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 002ca6fe983..ae62b743f9d 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -9,7 +9,6 @@ use syntax_pos::{self, Span};
 
 use rustc::hir;
 use rustc::hir::def_id::CrateNum;
-use rustc::hir::ptr::P;
 
 pub struct Module<'hir> {
     pub name: Option<Name>,
@@ -90,7 +89,7 @@ pub struct Struct<'hir> {
     pub name: Name,
     pub generics: &'hir hir::Generics,
     pub attrs: &'hir [ast::Attribute],
-    pub fields: &'hir [hir::StructField],
+    pub fields: &'hir [hir::StructField<'hir>],
     pub whence: Span,
 }
 
@@ -101,7 +100,7 @@ pub struct Union<'hir> {
     pub name: Name,
     pub generics: &'hir hir::Generics,
     pub attrs: &'hir [ast::Attribute],
-    pub fields: &'hir [hir::StructField],
+    pub fields: &'hir [hir::StructField<'hir>],
     pub whence: Span,
 }
 
@@ -119,7 +118,7 @@ pub struct Variant<'hir> {
     pub name: Name,
     pub id: hir::HirId,
     pub attrs: &'hir [ast::Attribute],
-    pub def: &'hir hir::VariantData,
+    pub def: &'hir hir::VariantData<'hir>,
     pub whence: Span,
 }
 
@@ -136,7 +135,7 @@ pub struct Function<'hir> {
 }
 
 pub struct Typedef<'hir> {
-    pub ty: &'hir P<hir::Ty>,
+    pub ty: &'hir hir::Ty,
     pub gen: &'hir hir::Generics,
     pub name: Name,
     pub id: hir::HirId,
@@ -156,7 +155,7 @@ pub struct OpaqueTy<'hir> {
 
 #[derive(Debug)]
 pub struct Static<'hir> {
-    pub type_: &'hir P<hir::Ty>,
+    pub type_: &'hir hir::Ty,
     pub mutability: hir::Mutability,
     pub expr: hir::BodyId,
     pub name: Name,
@@ -167,7 +166,7 @@ pub struct Static<'hir> {
 }
 
 pub struct Constant<'hir> {
-    pub type_: &'hir P<hir::Ty>,
+    pub type_: &'hir hir::Ty,
     pub expr: hir::BodyId,
     pub name: Name,
     pub attrs: &'hir [ast::Attribute],
@@ -180,7 +179,7 @@ pub struct Trait<'hir> {
     pub is_auto: hir::IsAuto,
     pub unsafety: hir::Unsafety,
     pub name: Name,
-    pub items: Vec<&'hir hir::TraitItem>,
+    pub items: Vec<&'hir hir::TraitItem<'hir>>,
     pub generics: &'hir hir::Generics,
     pub bounds: &'hir [hir::GenericBound],
     pub attrs: &'hir [ast::Attribute],
@@ -206,8 +205,8 @@ pub struct Impl<'hir> {
     pub defaultness: hir::Defaultness,
     pub generics: &'hir hir::Generics,
     pub trait_: &'hir Option<hir::TraitRef>,
-    pub for_: &'hir P<hir::Ty>,
-    pub items: Vec<&'hir hir::ImplItem>,
+    pub for_: &'hir hir::Ty,
+    pub items: Vec<&'hir hir::ImplItem<'hir>>,
     pub attrs: &'hir [ast::Attribute],
     pub whence: Span,
     pub vis: &'hir hir::Visibility,
@@ -218,7 +217,7 @@ pub struct ForeignItem<'hir> {
     pub vis: &'hir hir::Visibility,
     pub id: hir::HirId,
     pub name: Name,
-    pub kind: &'hir hir::ForeignItemKind,
+    pub kind: &'hir hir::ForeignItemKind<'hir>,
     pub attrs: &'hir [ast::Attribute],
     pub whence: Span,
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index aea9b7c38ef..897c00f276e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> {
         let mut module = self.visit_mod_contents(krate.span,
-                                              &krate.attrs,
+                                              krate.attrs,
                                               &Spanned { span: syntax_pos::DUMMY_SP,
                                                         node: hir::VisibilityKind::Public },
                                               hir::CRATE_HIR_ID,
@@ -213,9 +213,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_mod_contents(&mut self, span: Span, attrs: &'tcx hir::HirVec<ast::Attribute>,
+    fn visit_mod_contents(&mut self, span: Span, attrs: &'tcx [ast::Attribute],
                               vis: &'tcx hir::Visibility, id: hir::HirId,
-                              m: &'tcx hir::Mod,
+                              m: &'tcx hir::Mod<'tcx>,
                               name: Option<ast::Name>) -> Module<'tcx> {
         let mut om = Module::new(name, attrs, vis);
         om.where_outer = span;
@@ -224,7 +224,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
         self.inside_public_path &= vis.node.is_pub();
-        for i in &m.item_ids {
+        for i in m.item_ids {
             let item = self.cx.tcx.hir().expect_item(i.id);
             self.visit_item(item, None, &mut om);
         }
@@ -322,7 +322,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let ret = match tcx.hir().get(res_hir_id) {
             Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                for i in &m.item_ids {
+                for i in m.item_ids {
                     let i = self.cx.tcx.hir().expect_item(i.id);
                     self.visit_item(i, None, om);
                 }
@@ -363,7 +363,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
         match item.kind {
             hir::ItemKind::ForeignMod(ref fm) => {
-                for item in &fm.items {
+                for item in fm.items {
                     self.visit_foreign_item(item, None, om);
                 }
             }
@@ -440,7 +440,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 om.unions.push(self.visit_union_data(item, ident.name, sd, gen)),
             hir::ItemKind::Fn(ref sig, ref gen, body) =>
                 self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body),
-            hir::ItemKind::TyAlias(ref ty, ref gen) => {
+            hir::ItemKind::TyAlias(ty, ref gen) => {
                 let t = Typedef {
                     ty,
                     gen,
@@ -463,7 +463,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.opaque_tys.push(t);
             },
-            hir::ItemKind::Static(ref type_, mutability, expr) => {
+            hir::ItemKind::Static(type_, mutability, expr) => {
                 let s = Static {
                     type_,
                     mutability,
@@ -476,7 +476,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.statics.push(s);
             },
-            hir::ItemKind::Const(ref type_, expr) => {
+            hir::ItemKind::Const(type_, expr) => {
                 let s = Constant {
                     type_,
                     expr,
@@ -524,7 +524,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                           defaultness,
                           ref generics,
                           ref trait_,
-                          ref for_,
+                          for_,
                           ref item_ids) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index ff52974775b..eccf8cabf22 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -205,7 +205,7 @@ fn default_alloc_error_hook(layout: Layout) {
 #[cfg(not(test))]
 #[doc(hidden)]
 #[alloc_error_handler]
-#[unstable(feature = "alloc_internals", issue = "0")]
+#[unstable(feature = "alloc_internals", issue = "none")]
 pub fn rust_oom(layout: Layout) -> ! {
     let hook = HOOK.load(Ordering::SeqCst);
     let hook: fn(Layout) = if hook.is_null() {
@@ -220,7 +220,7 @@ pub fn rust_oom(layout: Layout) -> ! {
 #[cfg(not(test))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
-#[unstable(feature = "alloc_internals", issue = "0")]
+#[unstable(feature = "alloc_internals", issue = "none")]
 pub mod __default_lib_allocator {
     use super::{System, Layout, GlobalAlloc};
     // These magic symbol names are used as a fallback for implementing the
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 05008958ed2..48ebb77cfb3 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -1065,7 +1065,7 @@ impl CStr {
     /// ```
     #[inline]
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-    #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "0")]
+    #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
         &*(bytes as *const [u8] as *const CStr)
     }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index a1a33bade0d..587ac243267 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -280,7 +280,7 @@ pub use self::error::{Error, ErrorKind, Result};
 pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
-#[unstable(feature = "print_internals", issue = "0")]
+#[unstable(feature = "print_internals", issue = "none")]
 pub use self::stdio::{_eprint, _print};
 #[unstable(feature = "libstd_io_internals", issue = "42788")]
 #[doc(no_inline, hidden)]
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 6574ef13db9..4aa35884fb4 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -723,7 +723,7 @@ impl fmt::Debug for StderrLock<'_> {
 #[unstable(feature = "set_stdio",
            reason = "this function may disappear completely or be replaced \
                      with a more general mechanism",
-           issue = "0")]
+           issue = "none")]
 #[doc(hidden)]
 pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
     use crate::mem;
@@ -746,7 +746,7 @@ pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
 #[unstable(feature = "set_stdio",
            reason = "this function may disappear completely or be replaced \
                      with a more general mechanism",
-           issue = "0")]
+           issue = "none")]
 #[doc(hidden)]
 pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
     use crate::mem;
@@ -795,7 +795,7 @@ where
 
 #[unstable(feature = "print_internals",
            reason = "implementation detail which may disappear or be replaced at any time",
-           issue = "0")]
+           issue = "none")]
 #[doc(hidden)]
 #[cfg(not(test))]
 pub fn _print(args: fmt::Arguments<'_>) {
@@ -804,7 +804,7 @@ pub fn _print(args: fmt::Arguments<'_>) {
 
 #[unstable(feature = "print_internals",
            reason = "implementation detail which may disappear or be replaced at any time",
-           issue = "0")]
+           issue = "none")]
 #[doc(hidden)]
 #[cfg(not(test))]
 pub fn _eprint(args: fmt::Arguments<'_>) {
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index ac8e0daf766..6ad5519d34a 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -205,7 +205,7 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for &T {}
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
-#[unstable(feature = "ptr_internals", issue = "0")]
+#[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index c028ddcd676..886acf1f95d 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -214,7 +214,7 @@ fn default_hook(info: &PanicInfo<'_>) {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[unstable(feature = "update_panic_count", issue = "0")]
+#[unstable(feature = "update_panic_count", issue = "none")]
 pub fn update_panic_count(amt: isize) -> usize {
     use crate::cell::Cell;
     thread_local! { static PANIC_COUNT: Cell<usize> = Cell::new(0) }
@@ -307,7 +307,7 @@ pub fn panicking() -> bool {
 /// the actual formatting into this shared place.
 #[unstable(feature = "libstd_sys_internals",
            reason = "used by the panic! macro",
-           issue = "0")]
+           issue = "none")]
 #[cold]
 // If panic_immediate_abort, inline the abort call,
 // otherwise avoid inlining because of it is cold path.
@@ -383,7 +383,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
 /// arbitrary payloads, not just format strings.
 #[unstable(feature = "libstd_sys_internals",
            reason = "used by the panic! macro",
-           issue = "0")]
+           issue = "none")]
 #[cfg_attr(not(test), lang = "begin_panic")] // lang item for CTFE panic support
 // never inline unless panic_immediate_abort to avoid code
 // bloat at the call sites as much as possible
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 1ed984509d2..2426b2dead7 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -10,7 +10,7 @@
     feature = "rt",
     reason = "this public module should not exist and is highly likely \
               to disappear",
-    issue = "0"
+    issue = "none"
 )]
 #![doc(hidden)]
 
diff --git a/src/libstd/sys/hermit/fast_thread_local.rs b/src/libstd/sys/hermit/fast_thread_local.rs
index 05464787a05..1108e2545bd 100644
--- a/src/libstd/sys/hermit/fast_thread_local.rs
+++ b/src/libstd/sys/hermit/fast_thread_local.rs
@@ -1,4 +1,4 @@
 #![cfg(target_thread_local)]
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 
 pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
diff --git a/src/libstd/sys/hermit/fd.rs b/src/libstd/sys/hermit/fd.rs
index f2f61fdfb8c..97d1a38b41a 100644
--- a/src/libstd/sys/hermit/fd.rs
+++ b/src/libstd/sys/hermit/fd.rs
@@ -1,4 +1,4 @@
-#![unstable(reason = "not public", issue = "0", feature = "fd")]
+#![unstable(reason = "not public", issue = "none", feature = "fd")]
 
 use crate::io::{self, ErrorKind, Read};
 use crate::mem;
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index 9eeab34643f..875ff1af920 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -69,7 +69,7 @@ cfg_if::cfg_if! {
         // On CloudABI and wasm right now the module below doesn't compile
         // (missing things in `libc` which is empty) so just omit everything
         // with an empty module
-        #[unstable(issue = "0", feature = "std_internals")]
+        #[unstable(issue = "none", feature = "std_internals")]
         #[allow(missing_docs)]
         pub mod unix_ext {}
     } else {
@@ -92,7 +92,7 @@ cfg_if::cfg_if! {
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
         // On CloudABI and wasm right now the shim below doesn't compile, so
         // just omit it
-        #[unstable(issue = "0", feature = "std_internals")]
+        #[unstable(issue = "none", feature = "std_internals")]
         #[allow(missing_docs)]
         pub mod windows_ext {}
     } else {
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index 0861432f8a9..8730b4de8be 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -1,5 +1,5 @@
 #![cfg(target_thread_local)]
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 
 // Since what appears to be glibc 2.18 this symbol has been shipped which
 // GCC and clang both use to invoke destructors in thread_local globals, so
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 53b50763fbf..8a99836912a 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -1,4 +1,4 @@
-#![unstable(reason = "not public", issue = "0", feature = "fd")]
+#![unstable(reason = "not public", issue = "none", feature = "fd")]
 
 use crate::cmp;
 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs
index 387ebd0520a..098668cf521 100644
--- a/src/libstd/sys/vxworks/fast_thread_local.rs
+++ b/src/libstd/sys/vxworks/fast_thread_local.rs
@@ -1,5 +1,5 @@
 #![cfg(target_thread_local)]
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     use crate::sys_common::thread_local::register_dtor_fallback;
diff --git a/src/libstd/sys/vxworks/fd.rs b/src/libstd/sys/vxworks/fd.rs
index 9b649aa7ef4..65c67dabc1a 100644
--- a/src/libstd/sys/vxworks/fd.rs
+++ b/src/libstd/sys/vxworks/fd.rs
@@ -1,4 +1,4 @@
-#![unstable(reason = "not public", issue = "0", feature = "fd")]
+#![unstable(reason = "not public", issue = "none", feature = "fd")]
 
 use crate::cmp;
 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs
index 92d0e60c07e..6696efa8871 100644
--- a/src/libstd/sys/wasi/ext/fs.rs
+++ b/src/libstd/sys/wasi/ext/fs.rs
@@ -1,6 +1,6 @@
 //! WASI-specific extensions to primitives in the `std::fs` module.
 
-#![unstable(feature = "wasi_ext", issue = "0")]
+#![unstable(feature = "wasi_ext", issue = "none")]
 
 use crate::fs::{self, File, Metadata, OpenOptions};
 use crate::io::{self, IoSlice, IoSliceMut};
diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs
index f678b71a2b9..be3c2d97a24 100644
--- a/src/libstd/sys/wasi/ext/io.rs
+++ b/src/libstd/sys/wasi/ext/io.rs
@@ -1,6 +1,6 @@
 //! WASI-specific extensions to general I/O primitives
 
-#![unstable(feature = "wasi_ext", issue = "0")]
+#![unstable(feature = "wasi_ext", issue = "none")]
 
 use crate::fs;
 use crate::io;
diff --git a/src/libstd/sys/wasm/fast_thread_local.rs b/src/libstd/sys/wasm/fast_thread_local.rs
index 3b0993fdb58..9bdc26ae7d6 100644
--- a/src/libstd/sys/wasm/fast_thread_local.rs
+++ b/src/libstd/sys/wasm/fast_thread_local.rs
@@ -1,4 +1,4 @@
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 
 pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern fn(*mut u8)) {
     // FIXME: right now there is no concept of "thread exit", but this is likely
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index b1f9d9766f7..4cdac89a864 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -2,7 +2,7 @@
 
 #![allow(nonstandard_style)]
 #![cfg_attr(test, allow(dead_code))]
-#![unstable(issue = "0", feature = "windows_c")]
+#![unstable(issue = "none", feature = "windows_c")]
 
 use crate::os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort, c_char};
 use crate::ptr;
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index 7eaff226a76..0462f889a8e 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -504,17 +504,17 @@ impl MetadataExt for Metadata {
 /// On Windows, a symbolic link knows whether it is a file or directory.
 ///
 /// [`FileType`]: ../../../../std/fs/struct.FileType.html
-#[unstable(feature = "windows_file_type_ext", issue = "0")]
+#[unstable(feature = "windows_file_type_ext", issue = "none")]
 pub trait FileTypeExt {
     /// Returns `true` if this file type is a symbolic link that is also a directory.
-    #[unstable(feature = "windows_file_type_ext", issue = "0")]
+    #[unstable(feature = "windows_file_type_ext", issue = "none")]
     fn is_symlink_dir(&self) -> bool;
     /// Returns `true` if this file type is a symbolic link that is also a file.
-    #[unstable(feature = "windows_file_type_ext", issue = "0")]
+    #[unstable(feature = "windows_file_type_ext", issue = "none")]
     fn is_symlink_file(&self) -> bool;
 }
 
-#[unstable(feature = "windows_file_type_ext", issue = "0")]
+#[unstable(feature = "windows_file_type_ext", issue = "none")]
 impl FileTypeExt for fs::FileType {
     fn is_symlink_dir(&self) -> bool {
         self.as_inner().is_symlink_dir()
diff --git a/src/libstd/sys/windows/fast_thread_local.rs b/src/libstd/sys/windows/fast_thread_local.rs
index 31d0bd1e72e..191fa07f32a 100644
--- a/src/libstd/sys/windows/fast_thread_local.rs
+++ b/src/libstd/sys/windows/fast_thread_local.rs
@@ -1,4 +1,4 @@
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 #![cfg(target_thread_local)]
 
 pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index ebaa0783d60..fd0c2350cb3 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -1,4 +1,4 @@
-#![unstable(issue = "0", feature = "windows_handle")]
+#![unstable(issue = "none", feature = "windows_handle")]
 
 use crate::cmp;
 use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read};
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index 2f2f285edc1..53e08d50004 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -1,4 +1,4 @@
-#![unstable(issue = "0", feature = "windows_net")]
+#![unstable(issue = "none", feature = "windows_net")]
 
 use crate::cmp;
 use crate::io::{self, Read, IoSlice, IoSliceMut};
@@ -395,7 +395,7 @@ impl Socket {
     }
 }
 
-#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
+#[unstable(reason = "not public", issue = "none", feature = "fd_read")]
 impl<'a> Read for &'a Socket {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         (**self).read(buf)
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 096b7bea8a5..060997be97d 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -1,4 +1,4 @@
-#![unstable(feature = "process_internals", issue = "0")]
+#![unstable(feature = "process_internals", issue = "none")]
 
 use crate::collections::BTreeMap;
 use crate::env::split_paths;
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index f322c2b1d96..c84896296ec 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -1,4 +1,4 @@
-#![unstable(issue = "0", feature = "windows_stdio")]
+#![unstable(issue = "none", feature = "windows_stdio")]
 
 use crate::char::decode_utf16;
 use crate::cmp;
diff --git a/src/libstd/sys/windows/stdio_uwp.rs b/src/libstd/sys/windows/stdio_uwp.rs
index 0f2178f7353..5bdabf6d4b7 100644
--- a/src/libstd/sys/windows/stdio_uwp.rs
+++ b/src/libstd/sys/windows/stdio_uwp.rs
@@ -1,4 +1,4 @@
-#![unstable(issue = "0", feature = "windows_stdio")]
+#![unstable(issue = "none", feature = "windows_stdio")]
 
 use crate::io;
 use crate::mem::ManuallyDrop;
diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs
index 55b421794c4..042641852b3 100644
--- a/src/libstd/sys_common/process.rs
+++ b/src/libstd/sys_common/process.rs
@@ -1,5 +1,5 @@
 #![allow(dead_code)]
-#![unstable(feature = "process_internals", issue = "0")]
+#![unstable(feature = "process_internals", issue = "none")]
 
 use crate::collections::BTreeMap;
 use crate::env;
diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs
index bdf79002e90..9596911fd48 100644
--- a/src/libstd/sys_common/thread_local.rs
+++ b/src/libstd/sys_common/thread_local.rs
@@ -45,7 +45,7 @@
 //! ```
 
 #![allow(non_camel_case_types)]
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 #![allow(dead_code)] // sys isn't exported yet
 
 use crate::ptr;
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index 9c530e7b324..1dd942e252f 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -1,6 +1,6 @@
 //! Thread local storage
 
-#![unstable(feature = "thread_local_internals", issue = "0")]
+#![unstable(feature = "thread_local_internals", issue = "none")]
 
 use crate::error::Error;
 use crate::fmt;
@@ -142,7 +142,7 @@ macro_rules! thread_local {
 }
 
 #[doc(hidden)]
-#[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "0")]
+#[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]
 #[macro_export]
 #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
 #[allow_internal_unsafe]
@@ -215,7 +215,7 @@ impl<T: 'static> LocalKey<T> {
     #[unstable(
         feature = "thread_local_internals",
         reason = "recently added to create a key",
-        issue = "0"
+        issue = "none"
     )]
     pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> {
         LocalKey { inner }
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 0c632d2afbd..9df6af4c5d8 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -194,13 +194,13 @@ pub use self::local::{LocalKey, AccessError};
 // where fast TLS was not available; end-user code is compiled with fast TLS
 // where available, but both are needed.
 
-#[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[unstable(feature = "libstd_thread_internals", issue = "none")]
 #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
 #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner;
-#[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[unstable(feature = "libstd_thread_internals", issue = "none")]
 #[cfg(target_thread_local)]
 #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner;
-#[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[unstable(feature = "libstd_thread_internals", issue = "none")]
 #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 92ba071a03d..aa38a8135ce 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -254,7 +254,7 @@ pub struct ParenthesizedArgs {
     pub inputs: Vec<P<Ty>>,
 
     /// `C`
-    pub output: Option<P<Ty>>,
+    pub output: FunctionRetTy,
 }
 
 impl ParenthesizedArgs {
@@ -338,7 +338,7 @@ pub enum GenericParamKind {
 pub struct GenericParam {
     pub id: NodeId,
     pub ident: Ident,
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
     pub bounds: GenericBounds,
     pub is_placeholder: bool,
     pub kind: GenericParamKind,
@@ -509,7 +509,7 @@ impl Pat {
             // In a type expression `_` is an inference variable.
             PatKind::Wild => TyKind::Infer,
             // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
-            PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => {
+            PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
                 TyKind::Path(None, Path::from_ident(*ident))
             }
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@@ -599,7 +599,7 @@ pub struct FieldPat {
     /// The pattern the field is destructured to
     pub pat: P<Pat>,
     pub is_shorthand: bool,
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub is_placeholder: bool,
@@ -695,30 +695,30 @@ pub enum PatKind {
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
          RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum Mutability {
-    Mutable,
-    Immutable,
+    Mut,
+    Not,
 }
 
 impl Mutability {
     /// Returns `MutMutable` only if both `self` and `other` are mutable.
     pub fn and(self, other: Self) -> Self {
         match self {
-            Mutability::Mutable => other,
-            Mutability::Immutable => Mutability::Immutable,
+            Mutability::Mut => other,
+            Mutability::Not => Mutability::Not,
         }
     }
 
     pub fn invert(self) -> Self {
         match self {
-            Mutability::Mutable => Mutability::Immutable,
-            Mutability::Immutable => Mutability::Mutable,
+            Mutability::Mut => Mutability::Not,
+            Mutability::Not => Mutability::Mut,
         }
     }
 
     pub fn prefix_str(&self) -> &'static str {
         match self {
-            Mutability::Mutable => "mut ",
-            Mutability::Immutable => "",
+            Mutability::Mut => "mut ",
+            Mutability::Not => "",
         }
     }
 }
@@ -728,13 +728,13 @@ impl Mutability {
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum BorrowKind {
-    /// A raw borrow, `&raw const $expr` or `&raw mut $expr`.
-    /// The resulting type is either `*const T` or `*mut T`
-    /// where `T = typeof($expr)`.
-    Ref,
     /// A normal borrow, `&$expr` or `&mut $expr`.
     /// The resulting type is either `&'a T` or `&'a mut T`
     /// where `T = typeof($expr)` and `'a` is some lifetime.
+    Ref,
+    /// A raw borrow, `&raw const $expr` or `&raw mut $expr`.
+    /// The resulting type is either `*const T` or `*mut T`
+    /// where `T = typeof($expr)`.
     Raw,
 }
 
@@ -911,7 +911,7 @@ pub enum StmtKind {
     /// Expr with a trailing semi-colon.
     Semi(P<Expr>),
     /// Macro.
-    Mac(P<(Mac, MacStmtStyle, ThinVec<Attribute>)>),
+    Mac(P<(Mac, MacStmtStyle, AttrVec)>),
 }
 
 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
@@ -936,7 +936,7 @@ pub struct Local {
     /// Initializer expression to set the value, if any.
     pub init: Option<P<Expr>>,
     pub span: Span,
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
 }
 
 /// An arm of a 'match'.
@@ -966,7 +966,7 @@ pub struct Arm {
 /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Field {
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub ident: Ident,
@@ -1004,7 +1004,7 @@ pub struct Expr {
     pub id: NodeId,
     pub kind: ExprKind,
     pub span: Span,
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
 }
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -1603,54 +1603,43 @@ pub struct FnSig {
     pub decl: P<FnDecl>,
 }
 
-/// Represents an item declaration within a trait declaration,
-/// possibly including a default implementation. A trait item is
-/// either required (meaning it doesn't have an implementation, just a
-/// signature) or provided (meaning it has a default implementation).
+/// Represents associated items.
+/// These include items in `impl` and `trait` definitions.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct TraitItem {
+pub struct AssocItem {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
     pub ident: Ident,
 
+    pub defaultness: Defaultness,
     pub generics: Generics,
-    pub kind: TraitItemKind,
+    pub kind: AssocItemKind,
     /// See `Item::tokens` for what this is.
     pub tokens: Option<TokenStream>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum TraitItemKind {
+/// Represents various kinds of content within an `impl`.
+///
+/// The term "provided" in the variants below refers to the item having a default
+/// definition / body. Meanwhile, a "required" item lacks a definition / body.
+/// In an implementation, all items must be provided.
+/// The `Option`s below denote the bodies, where `Some(_)`
+/// means "provided" and conversely `None` means "required".
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum AssocItemKind  {
+    /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
+    /// If `def` is parsed, then the associated constant is provided, and otherwise required.
     Const(P<Ty>, Option<P<Expr>>),
-    Method(FnSig, Option<P<Block>>),
-    Type(GenericBounds, Option<P<Ty>>),
-    Macro(Mac),
-}
 
-/// Represents anything within an `impl` block.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct ImplItem {
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
-    pub ident: Ident,
+    /// An associated function.
+    Fn(FnSig, Option<P<Block>>),
 
-    pub defaultness: Defaultness,
-    pub generics: Generics,
-    pub kind: ImplItemKind,
-    /// See `Item::tokens` for what this is.
-    pub tokens: Option<TokenStream>,
-}
+    /// An associated type.
+    TyAlias(GenericBounds, Option<P<Ty>>),
 
-/// Represents various kinds of content within an `impl`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum ImplItemKind {
-    Const(P<Ty>, P<Expr>),
-    Method(FnSig, P<Block>),
-    TyAlias(P<Ty>),
+    /// A macro expanding to an associated item.
     Macro(Mac),
 }
 
@@ -1972,7 +1961,7 @@ pub struct InlineAsm {
 /// E.g., `bar: usize` as in `fn foo(bar: usize)`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Param {
-    pub attrs: ThinVec<Attribute>,
+    pub attrs: AttrVec,
     pub ty: P<Ty>,
     pub pat: P<Pat>,
     pub id: NodeId,
@@ -2025,7 +2014,7 @@ impl Param {
     }
 
     /// Builds a `Param` object from `ExplicitSelf`.
-    pub fn from_self(attrs: ThinVec<Attribute>, eself: ExplicitSelf, eself_ident: Ident) -> Param {
+    pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
         let span = eself.span.to(eself_ident.span);
         let infer_ty = P(Ty {
             id: DUMMY_NODE_ID,
@@ -2048,7 +2037,7 @@ impl Param {
             SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
             SelfKind::Value(mutbl) => param(mutbl, infer_ty),
             SelfKind::Region(lt, mutbl) => param(
-                Mutability::Immutable,
+                Mutability::Not,
                 P(Ty {
                     id: DUMMY_NODE_ID,
                     kind: TyKind::Rptr(
@@ -2189,7 +2178,7 @@ impl fmt::Debug for ImplPolarity {
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum FunctionRetTy {
+pub enum FunctionRetTy { // FIXME(Centril): Rename to `FnRetTy` and in HIR also.
     /// Returns type is not specified.
     ///
     /// Functions default to `()` and closures default to inference.
@@ -2343,6 +2332,9 @@ pub struct AttrItem {
     pub args: MacArgs,
 }
 
+/// A list of attributes.
+pub type AttrVec = ThinVec<Attribute>;
+
 /// Metadata associated with an item.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Attribute {
@@ -2602,7 +2594,7 @@ pub enum ItemKind {
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
-    Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>),
+    Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<AssocItem>),
     /// Trait alias
     ///
     /// E.g., `trait Foo = Bar + Quux;`.
@@ -2617,7 +2609,7 @@ pub enum ItemKind {
         Generics,
         Option<TraitRef>, // (optional) trait this impl implements
         P<Ty>,            // self
-        Vec<ImplItem>,
+        Vec<AssocItem>,
     ),
     /// A macro invocation.
     ///
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index a37b27f67bc..d780d0ad764 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -376,11 +376,11 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
                     match (feature, reason, issue) {
                         (Some(feature), reason, Some(issue)) => {
                             let issue = match &*issue.as_str() {
-                                // FIXME(rossmacarthur): remove "0" because "none" should be used
-                                // See #41260
-                                "none" | "0" => None,
+                                "none" => None,
                                 issue => {
                                     if let Ok(num) = issue.parse() {
+                                        // FIXME(rossmacarthur): disallow 0
+                                        // Disallowing this requires updates to some submodules
                                         NonZeroU32::new(num)
                                     } else {
                                         span_err!(
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 079a0f6fafa..ae6d50ba083 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -9,7 +9,7 @@ pub use StabilityLevel::*;
 pub use crate::ast::Attribute;
 
 use crate::ast;
-use crate::ast::{AttrItem, AttrId, AttrKind, AttrStyle, Name, Ident, Path, PathSegment};
+use crate::ast::{AttrVec, AttrItem, AttrId, AttrKind, AttrStyle, Name, Ident, Path, PathSegment};
 use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
 use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam};
 use crate::mut_visit::visit_clobber;
@@ -17,7 +17,6 @@ use crate::source_map::{BytePos, Spanned};
 use crate::token::{self, Token};
 use crate::ptr::P;
 use crate::symbol::{sym, Symbol};
-use crate::ThinVec;
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 use crate::GLOBALS;
 
@@ -665,7 +664,7 @@ impl HasAttrs for Vec<Attribute> {
     }
 }
 
-impl HasAttrs for ThinVec<Attribute> {
+impl HasAttrs for AttrVec {
     fn attrs(&self) -> &[Attribute] {
         self
     }
@@ -749,6 +748,6 @@ macro_rules! derive_has_attrs {
 }
 
 derive_has_attrs! {
-    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
+    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::AssocItem, ast::Arm,
     ast::Field, ast::FieldPat, ast::Variant, ast::Param
 }
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index 99d89183e5b..aacd14c3af7 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -589,54 +589,52 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_assoc_ty_constraint(self, constraint)
     }
 
-    fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) {
         match ti.kind {
-            ast::TraitItemKind::Method(ref sig, ref block) => {
+            ast::AssocItemKind::Fn(ref sig, ref block) => {
                 if block.is_none() {
                     self.check_extern(sig.header.ext);
                 }
-                if sig.decl.c_variadic() {
-                    gate_feature_post!(&self, c_variadic, ti.span,
-                                       "C-variadic functions are unstable");
-                }
                 if sig.header.constness.node == ast::Constness::Const {
                     gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
                 }
             }
-            ast::TraitItemKind::Type(_, ref default) => {
-                if let Some(ty) = default {
-                    self.check_impl_trait(ty);
-                    gate_feature_post!(&self, associated_type_defaults, ti.span,
-                                       "associated type defaults are unstable");
+            ast::AssocItemKind::TyAlias(_, ref default) => {
+                if let Some(_) = default {
+                    gate_feature_post!(
+                        &self, associated_type_defaults, ti.span,
+                        "associated type defaults are unstable"
+                    );
                 }
-                self.check_gat(&ti.generics, ti.span);
             }
             _ => {}
         }
         visit::walk_trait_item(self, ti)
     }
 
-    fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
+    fn visit_assoc_item(&mut self, ii: &'a ast::AssocItem) {
         if ii.defaultness == ast::Defaultness::Default {
-            gate_feature_post!(&self, specialization,
-                              ii.span,
-                              "specialization is unstable");
+            gate_feature_post!(&self, specialization, ii.span, "specialization is unstable");
         }
 
         match ii.kind {
-            ast::ImplItemKind::Method(ref sig, _) => {
+            ast::AssocItemKind::Fn(ref sig, _) => {
                 if sig.decl.c_variadic() {
-                    gate_feature_post!(&self, c_variadic, ii.span,
-                                       "C-variadic functions are unstable");
+                    gate_feature_post!(
+                        &self, c_variadic, ii.span,
+                        "C-variadic functions are unstable"
+                    );
                 }
             }
-            ast::ImplItemKind::TyAlias(ref ty) => {
-                self.check_impl_trait(ty);
+            ast::AssocItemKind::TyAlias(_, ref ty) => {
+                if let Some(ty) = ty {
+                    self.check_impl_trait(ty);
+                }
                 self.check_gat(&ii.generics, ii.span);
             }
             _ => {}
         }
-        visit::walk_impl_item(self, ii)
+        visit::walk_assoc_item(self, ii)
     }
 
     fn visit_vis(&mut self, vis: &'a ast::Visibility) {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 36173801eae..30fd23ea909 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -24,7 +24,6 @@
 pub use errors;
 use rustc_data_structures::sync::Lock;
 use rustc_index::bit_set::GrowableBitSet;
-pub use rustc_data_structures::thin_vec::ThinVec;
 use ast::AttrId;
 use syntax_pos::edition::Edition;
 
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index f8795d885d2..1d27f70f5a5 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -11,7 +11,6 @@ use crate::ast::*;
 use crate::source_map::{Spanned, respan};
 use crate::token::{self, Token};
 use crate::ptr::P;
-use crate::ThinVec;
 use crate::tokenstream::*;
 use crate::util::map_in_place::MapInPlace;
 
@@ -103,12 +102,12 @@ pub trait MutVisitor: Sized {
         noop_visit_item_kind(i, self);
     }
 
-    fn flat_map_trait_item(&mut self, i: TraitItem) -> SmallVec<[TraitItem; 1]> {
-        noop_flat_map_trait_item(i, self)
+    fn flat_map_trait_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> {
+        noop_flat_map_assoc_item(i, self)
     }
 
-    fn flat_map_impl_item(&mut self, i: ImplItem) -> SmallVec<[ImplItem; 1]> {
-        noop_flat_map_impl_item(i, self)
+    fn flat_map_impl_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> {
+        noop_flat_map_assoc_item(i, self)
     }
 
     fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
@@ -337,7 +336,7 @@ pub fn visit_attrs<T: MutVisitor>(attrs: &mut Vec<Attribute>, vis: &mut T) {
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_thin_attrs<T: MutVisitor>(attrs: &mut ThinVec<Attribute>, vis: &mut T) {
+pub fn visit_thin_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
     for attr in attrs.iter_mut() {
         vis.visit_attribute(attr);
     }
@@ -553,7 +552,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(args: &mut Parenth
                                                               vis: &mut T) {
     let ParenthesizedArgs { inputs, output, span } = args;
     visit_vec(inputs, |input| vis.visit_ty(input));
-    visit_opt(output, |output| vis.visit_ty(output));
+    noop_visit_fn_ret_ty(output, vis);
     vis.visit_span(span);
 }
 
@@ -742,7 +741,11 @@ pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T)
 pub fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) {
     let FnDecl { inputs, output } = decl.deref_mut();
     inputs.flat_map_in_place(|param| vis.flat_map_param(param));
-    match output {
+    noop_visit_fn_ret_ty(output, vis);
+}
+
+pub fn noop_visit_fn_ret_ty<T: MutVisitor>(fn_ret_ty: &mut FunctionRetTy, vis: &mut T) {
+    match fn_ret_ty {
         FunctionRetTy::Default(span) => vis.visit_span(span),
         FunctionRetTy::Ty(ty) => vis.visit_ty(ty),
     }
@@ -936,58 +939,30 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
     }
 }
 
-pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
-    -> SmallVec<[TraitItem; 1]>
+pub fn noop_flat_map_assoc_item<T: MutVisitor>(mut item: AssocItem, visitor: &mut T)
+    -> SmallVec<[AssocItem; 1]>
 {
-    let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item;
+    let AssocItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
+        &mut item;
     visitor.visit_id(id);
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
     visit_attrs(attrs, visitor);
     visitor.visit_generics(generics);
-    match kind {
-        TraitItemKind::Const(ty, default) => {
+    match kind  {
+        AssocItemKind::Const(ty, expr) => {
             visitor.visit_ty(ty);
-            visit_opt(default, |default| visitor.visit_expr(default));
+            visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
-        TraitItemKind::Method(sig, body) => {
+        AssocItemKind::Fn(sig, body) => {
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        TraitItemKind::Type(bounds, default) => {
+        AssocItemKind::TyAlias(bounds, ty) => {
             visit_bounds(bounds, visitor);
-            visit_opt(default, |default| visitor.visit_ty(default));
-        }
-        TraitItemKind::Macro(mac) => {
-            visitor.visit_mac(mac);
-        }
-    }
-    visitor.visit_span(span);
-
-    smallvec![item]
-}
-
-pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut T)
-                                              -> SmallVec<[ImplItem; 1]>
-{
-    let ImplItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
-        &mut item;
-    visitor.visit_id(id);
-    visitor.visit_ident(ident);
-    visitor.visit_vis(vis);
-    visit_attrs(attrs, visitor);
-    visitor.visit_generics(generics);
-    match kind  {
-        ImplItemKind::Const(ty, expr) => {
-            visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
-        }
-        ImplItemKind::Method(sig, body) => {
-            visit_fn_sig(sig, visitor);
-            visitor.visit_block(body);
+            visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
-        ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty),
-        ImplItemKind::Macro(mac) => visitor.visit_mac(mac),
+        AssocItemKind::Macro(mac) => visitor.visit_mac(mac),
     }
     visitor.visit_span(span);
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f0c5fb32fb1..e63d11ce832 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -335,8 +335,8 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
         token::NtLifetime(e)        => e.to_string(),
         token::NtLiteral(ref e)     => expr_to_string(e),
         token::NtTT(ref tree)       => tt_to_string(tree.clone()),
-        token::NtImplItem(ref e)    => impl_item_to_string(e),
-        token::NtTraitItem(ref e)   => trait_item_to_string(e),
+        // FIXME(Centril): merge these variants.
+        token::NtImplItem(ref e) | token::NtTraitItem(ref e) => assoc_item_to_string(e),
         token::NtVis(ref e)         => vis_to_string(e),
         token::NtForeignItem(ref e) => foreign_item_to_string(e),
     }
@@ -374,12 +374,8 @@ pub fn item_to_string(i: &ast::Item) -> String {
     to_string(|s| s.print_item(i))
 }
 
-fn impl_item_to_string(i: &ast::ImplItem) -> String {
-    to_string(|s| s.print_impl_item(i))
-}
-
-fn trait_item_to_string(i: &ast::TraitItem) -> String {
-    to_string(|s| s.print_trait_item(i))
+fn assoc_item_to_string(i: &ast::AssocItem) -> String {
+    to_string(|s| s.print_assoc_item(i))
 }
 
 pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
@@ -887,17 +883,9 @@ impl<'a> PrintState<'a> for State<'a> {
 
             ast::GenericArgs::Parenthesized(ref data) => {
                 self.s.word("(");
-                self.commasep(
-                    Inconsistent,
-                    &data.inputs,
-                    |s, ty| s.print_type(ty));
+                self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty));
                 self.s.word(")");
-
-                if let Some(ref ty) = data.output {
-                    self.space_if_not_bol();
-                    self.word_space("->");
-                    self.print_type(ty);
-                }
+                self.print_fn_ret_ty(&data.output);
             }
         }
     }
@@ -1083,7 +1071,7 @@ impl<'a> State<'a> {
             }
             ast::ForeignItemKind::Static(ref t, m) => {
                 self.head(visibility_qualified(&item.vis, "static"));
-                if m == ast::Mutability::Mutable {
+                if m == ast::Mutability::Mut {
                     self.word_space("mut");
                 }
                 self.print_ident(item.ident);
@@ -1128,16 +1116,15 @@ impl<'a> State<'a> {
         self.s.word(";")
     }
 
-    fn print_associated_type(&mut self,
-                             ident: ast::Ident,
-                             bounds: Option<&ast::GenericBounds>,
-                             ty: Option<&ast::Ty>)
-                             {
+    fn print_associated_type(
+        &mut self,
+        ident: ast::Ident,
+        bounds: &ast::GenericBounds,
+        ty: Option<&ast::Ty>,
+    ) {
         self.word_space("type");
         self.print_ident(ident);
-        if let Some(bounds) = bounds {
-            self.print_type_bounds(":", bounds);
-        }
+        self.print_type_bounds(":", bounds);
         if let Some(ty) = ty {
             self.s.space();
             self.word_space("=");
@@ -1175,7 +1162,7 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::Static(ref ty, m, ref expr) => {
                 self.head(visibility_qualified(&item.vis, "static"));
-                if m == ast::Mutability::Mutable {
+                if m == ast::Mutability::Mut {
                     self.word_space("mut");
                 }
                 self.print_ident(item.ident);
@@ -1310,7 +1297,7 @@ impl<'a> State<'a> {
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
                 for impl_item in impl_items {
-                    self.print_impl_item(impl_item);
+                    self.print_assoc_item(impl_item);
                 }
                 self.bclose(item.span);
             }
@@ -1337,7 +1324,7 @@ impl<'a> State<'a> {
                 self.s.word(" ");
                 self.bopen();
                 for trait_item in trait_items {
-                    self.print_trait_item(trait_item);
+                    self.print_assoc_item(trait_item);
                 }
                 self.bclose(item.span);
             }
@@ -1531,92 +1518,39 @@ impl<'a> State<'a> {
         }
     }
 
-    crate fn print_method_sig(&mut self,
-                            ident: ast::Ident,
-                            generics: &ast::Generics,
-                            m: &ast::FnSig,
-                            vis: &ast::Visibility)
-                            {
-        self.print_fn(&m.decl,
-                      m.header,
-                      Some(ident),
-                      &generics,
-                      vis)
-    }
-
-    crate fn print_trait_item(&mut self, ti: &ast::TraitItem)
-                            {
-        self.ann.pre(self, AnnNode::SubItem(ti.id));
+    crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
+        self.ann.pre(self, AnnNode::SubItem(item.id));
         self.hardbreak_if_not_bol();
-        self.maybe_print_comment(ti.span.lo());
-        self.print_outer_attributes(&ti.attrs);
-        match ti.kind {
-            ast::TraitItemKind::Const(ref ty, ref default) => {
-                self.print_associated_const(
-                    ti.ident,
-                    ty,
-                    default.as_ref().map(|expr| &**expr),
-                    &source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                );
+        self.maybe_print_comment(item.span.lo());
+        self.print_outer_attributes(&item.attrs);
+        self.print_defaultness(item.defaultness);
+        match &item.kind {
+            ast::AssocItemKind::Const(ty, expr) => {
+                self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis);
             }
-            ast::TraitItemKind::Method(ref sig, ref body) => {
+            ast::AssocItemKind::Fn(sig, body) => {
                 if body.is_some() {
                     self.head("");
                 }
-                self.print_method_sig(
-                    ti.ident,
-                    &ti.generics,
-                    sig,
-                    &source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                );
-                if let Some(ref body) = *body {
+                self.print_fn(&sig.decl, sig.header, Some(item.ident), &item.generics, &item.vis);
+                if let Some(body) = body {
                     self.nbsp();
-                    self.print_block_with_attrs(body, &ti.attrs);
+                    self.print_block_with_attrs(body, &item.attrs);
                 } else {
                     self.s.word(";");
                 }
             }
-            ast::TraitItemKind::Type(ref bounds, ref default) => {
-                self.print_associated_type(ti.ident, Some(bounds),
-                                           default.as_ref().map(|ty| &**ty));
+            ast::AssocItemKind::TyAlias(bounds, ty) => {
+                self.print_associated_type(item.ident, bounds, ty.as_deref());
             }
-            ast::TraitItemKind::Macro(ref mac) => {
+            ast::AssocItemKind::Macro(mac) => {
                 self.print_mac(mac);
                 if mac.args.need_semicolon() {
                     self.s.word(";");
                 }
             }
         }
-        self.ann.post(self, AnnNode::SubItem(ti.id))
-    }
-
-    crate fn print_impl_item(&mut self, ii: &ast::ImplItem) {
-        self.ann.pre(self, AnnNode::SubItem(ii.id));
-        self.hardbreak_if_not_bol();
-        self.maybe_print_comment(ii.span.lo());
-        self.print_outer_attributes(&ii.attrs);
-        self.print_defaultness(ii.defaultness);
-        match ii.kind {
-            ast::ImplItemKind::Const(ref ty, ref expr) => {
-                self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis);
-            }
-            ast::ImplItemKind::Method(ref sig, ref body) => {
-                self.head("");
-                self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis);
-                self.nbsp();
-                self.print_block_with_attrs(body, &ii.attrs);
-            }
-            ast::ImplItemKind::TyAlias(ref ty) => {
-                self.print_associated_type(ii.ident, None, Some(ty));
-            }
-            ast::ImplItemKind::Macro(ref mac) => {
-                self.print_mac(mac);
-                if mac.args.need_semicolon() {
-                    self.s.word(";");
-                }
-            }
-        }
-        self.ann.post(self, AnnNode::SubItem(ii.id))
+        self.ann.post(self, AnnNode::SubItem(item.id))
     }
 
     crate fn print_stmt(&mut self, st: &ast::Stmt) {
@@ -2109,7 +2043,7 @@ impl<'a> State<'a> {
                 self.print_asyncness(asyncness);
                 self.print_capture_clause(capture_clause);
 
-                self.print_fn_block_params(decl);
+                self.print_fn_params_and_ret(decl, true);
                 self.s.space();
                 self.print_expr(body);
                 self.end(); // need to close a box
@@ -2368,8 +2302,8 @@ impl<'a> State<'a> {
                         self.word_nbsp("ref");
                         self.print_mutability(mutbl, false);
                     }
-                    ast::BindingMode::ByValue(ast::Mutability::Immutable) => {}
-                    ast::BindingMode::ByValue(ast::Mutability::Mutable) => {
+                    ast::BindingMode::ByValue(ast::Mutability::Not) => {}
+                    ast::BindingMode::ByValue(ast::Mutability::Mut) => {
                         self.word_nbsp("mut");
                     }
                 }
@@ -2432,7 +2366,7 @@ impl<'a> State<'a> {
             }
             PatKind::Ref(ref inner, mutbl) => {
                 self.s.word("&");
-                if mutbl == ast::Mutability::Mutable {
+                if mutbl == ast::Mutability::Mut {
                     self.s.word("mut ");
                 }
                 self.print_pat(inner);
@@ -2540,36 +2474,16 @@ impl<'a> State<'a> {
             self.print_ident(name);
         }
         self.print_generic_params(&generics.params);
-        self.print_fn_params_and_ret(decl);
+        self.print_fn_params_and_ret(decl, false);
         self.print_where_clause(&generics.where_clause)
     }
 
-    crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl) {
-        self.popen();
-        self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, false));
-        self.pclose();
-
-        self.print_fn_output(decl)
-    }
-
-    crate fn print_fn_block_params(&mut self, decl: &ast::FnDecl) {
-        self.s.word("|");
-        self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, true));
-        self.s.word("|");
-
-        if let ast::FunctionRetTy::Default(..) = decl.output {
-            return;
-        }
-
-        self.space_if_not_bol();
-        self.word_space("->");
-        match decl.output {
-            ast::FunctionRetTy::Ty(ref ty) => {
-                self.print_type(ty);
-                self.maybe_print_comment(ty.span.lo())
-            }
-            ast::FunctionRetTy::Default(..) => unreachable!(),
-        }
+    crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
+        let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") };
+        self.word(open);
+        self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure));
+        self.word(close);
+        self.print_fn_ret_ty(&decl.output)
     }
 
     crate fn print_movability(&mut self, movability: ast::Movability) {
@@ -2753,8 +2667,8 @@ impl<'a> State<'a> {
 
     pub fn print_mutability(&mut self, mutbl: ast::Mutability, print_const: bool) {
         match mutbl {
-            ast::Mutability::Mutable => self.word_nbsp("mut"),
-            ast::Mutability::Immutable => if print_const { self.word_nbsp("const"); },
+            ast::Mutability::Mut => self.word_nbsp("mut"),
+            ast::Mutability::Not => if print_const { self.word_nbsp("const"); },
         }
     }
 
@@ -2791,24 +2705,14 @@ impl<'a> State<'a> {
         self.end();
     }
 
-    crate fn print_fn_output(&mut self, decl: &ast::FnDecl) {
-        if let ast::FunctionRetTy::Default(..) = decl.output {
-            return;
-        }
-
-        self.space_if_not_bol();
-        self.ibox(INDENT_UNIT);
-        self.word_space("->");
-        match decl.output {
-            ast::FunctionRetTy::Default(..) => unreachable!(),
-            ast::FunctionRetTy::Ty(ref ty) =>
-                self.print_type(ty),
-        }
-        self.end();
-
-        match decl.output {
-            ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo()),
-            _ => {}
+    crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FunctionRetTy) {
+        if let ast::FunctionRetTy::Ty(ty) = fn_ret_ty {
+            self.space_if_not_bol();
+            self.ibox(INDENT_UNIT);
+            self.word_space("->");
+            self.print_type(ty);
+            self.end();
+            self.maybe_print_comment(ty.span.lo());
         }
     }
 
diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs
index 6f45211ac5f..263f8192241 100644
--- a/src/libsyntax/token.rs
+++ b/src/libsyntax/token.rs
@@ -685,8 +685,8 @@ pub enum Nonterminal {
     // Used only for passing items to proc macro attributes (they are not
     // strictly necessary for that, `Annotatable` can be converted into
     // tokens directly, but doing that naively regresses pretty-printing).
-    NtTraitItem(ast::TraitItem),
-    NtImplItem(ast::ImplItem),
+    NtTraitItem(ast::AssocItem),
+    NtImplItem(ast::AssocItem),
     NtForeignItem(ast::ForeignItem),
 }
 
diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs
index a64fec70961..3db9955d304 100644
--- a/src/libsyntax/util/node_count.rs
+++ b/src/libsyntax/util/node_count.rs
@@ -73,13 +73,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
         self.count += 1;
         walk_fn(self, fk, fd, s)
     }
-    fn visit_trait_item(&mut self, ti: &TraitItem) {
+    fn visit_assoc_item(&mut self, ti: &AssocItem) {
         self.count += 1;
-        walk_trait_item(self, ti)
-    }
-    fn visit_impl_item(&mut self, ii: &ImplItem) {
-        self.count += 1;
-        walk_impl_item(self, ii)
+        walk_assoc_item(self, ti)
     }
     fn visit_trait_ref(&mut self, t: &TraitRef) {
         self.count += 1;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 4ee09b4b87a..51e7fa1eb38 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -25,7 +25,7 @@ pub enum FnKind<'a> {
     ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
 
     /// E.g., `fn foo(&self)`.
-    Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a Block),
+    Method(Ident, &'a FnSig, &'a Visibility, &'a Block),
 
     /// E.g., `|x, y| body`.
     Closure(&'a Expr),
@@ -83,8 +83,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
         walk_fn(self, fk, fd, s)
     }
-    fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) }
-    fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) }
+    fn visit_trait_item(&mut self, i: &'ast AssocItem) { walk_trait_item(self, i) }
+    fn visit_impl_item(&mut self, i: &'ast AssocItem) { walk_impl_item(self, i) }
+    fn visit_assoc_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) }
     fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) }
     fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
         walk_param_bound(self, bounds)
@@ -420,7 +421,7 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V,
         }
         GenericArgs::Parenthesized(ref data) => {
             walk_list!(visitor, visit_ty, &data.inputs);
-            walk_list!(visitor, visit_ty, &data.output);
+            walk_fn_ret_ty(visitor, &data.output);
         }
     }
 }
@@ -581,52 +582,37 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
     }
 }
 
-pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
-    visitor.visit_vis(&trait_item.vis);
-    visitor.visit_ident(trait_item.ident);
-    walk_list!(visitor, visit_attribute, &trait_item.attrs);
-    visitor.visit_generics(&trait_item.generics);
-    match trait_item.kind {
-        TraitItemKind::Const(ref ty, ref default) => {
+pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
+    visitor.visit_assoc_item(item);
+}
+
+pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
+    visitor.visit_assoc_item(item);
+}
+
+pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
+    visitor.visit_vis(&item.vis);
+    visitor.visit_ident(item.ident);
+    walk_list!(visitor, visit_attribute, &item.attrs);
+    visitor.visit_generics(&item.generics);
+    match item.kind {
+        AssocItemKind::Const(ref ty, ref expr) => {
             visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, default);
+            walk_list!(visitor, visit_expr, expr);
         }
-        TraitItemKind::Method(ref sig, None) => {
+        AssocItemKind::Fn(ref sig, None) => {
             visitor.visit_fn_header(&sig.header);
             walk_fn_decl(visitor, &sig.decl);
         }
-        TraitItemKind::Method(ref sig, Some(ref body)) => {
-            visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body),
-                             &sig.decl, trait_item.span, trait_item.id);
+        AssocItemKind::Fn(ref sig, Some(ref body)) => {
+            visitor.visit_fn(FnKind::Method(item.ident, sig, &item.vis, body),
+                             &sig.decl, item.span, item.id);
         }
-        TraitItemKind::Type(ref bounds, ref default) => {
+        AssocItemKind::TyAlias(ref bounds, ref ty) => {
             walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_ty, default);
-        }
-        TraitItemKind::Macro(ref mac) => {
-            visitor.visit_mac(mac);
-        }
-    }
-}
-
-pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplItem) {
-    visitor.visit_vis(&impl_item.vis);
-    visitor.visit_ident(impl_item.ident);
-    walk_list!(visitor, visit_attribute, &impl_item.attrs);
-    visitor.visit_generics(&impl_item.generics);
-    match impl_item.kind {
-        ImplItemKind::Const(ref ty, ref expr) => {
-            visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
-        }
-        ImplItemKind::Method(ref sig, ref body) => {
-            visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
-                             &sig.decl, impl_item.span, impl_item.id);
-        }
-        ImplItemKind::TyAlias(ref ty) => {
-            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_ty, ty);
         }
-        ImplItemKind::Macro(ref mac) => {
+        AssocItemKind::Macro(ref mac) => {
             visitor.visit_mac(mac);
         }
     }
diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs
index 72c0b3fde02..2ad327e872e 100644
--- a/src/libsyntax_expand/base.rs
+++ b/src/libsyntax_expand/base.rs
@@ -9,7 +9,6 @@ use syntax::mut_visit::{self, MutVisitor};
 use syntax::ptr::P;
 use syntax::sess::ParseSess;
 use syntax::symbol::{kw, sym, Ident, Symbol};
-use syntax::ThinVec;
 use syntax::token;
 use syntax::tokenstream::{self, TokenStream};
 use syntax::visit::Visitor;
@@ -31,8 +30,8 @@ crate use syntax_pos::hygiene::MacroKind;
 #[derive(Debug,Clone)]
 pub enum Annotatable {
     Item(P<ast::Item>),
-    TraitItem(P<ast::TraitItem>),
-    ImplItem(P<ast::ImplItem>),
+    TraitItem(P<ast::AssocItem>),
+    ImplItem(P<ast::AssocItem>),
     ForeignItem(P<ast::ForeignItem>),
     Stmt(P<ast::Stmt>),
     Expr(P<ast::Expr>),
@@ -137,14 +136,14 @@ impl Annotatable {
         }
     }
 
-    pub fn expect_trait_item(self) -> ast::TraitItem {
+    pub fn expect_trait_item(self) -> ast::AssocItem {
         match self {
             Annotatable::TraitItem(i) => i.into_inner(),
             _ => panic!("expected Item")
         }
     }
 
-    pub fn expect_impl_item(self) -> ast::ImplItem {
+    pub fn expect_impl_item(self) -> ast::AssocItem {
         match self {
             Annotatable::ImplItem(i) => i.into_inner(),
             _ => panic!("expected Item")
@@ -382,12 +381,12 @@ pub trait MacResult {
     }
 
     /// Creates zero or more impl items.
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
+    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
         None
     }
 
     /// Creates zero or more trait items.
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
+    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
         None
     }
 
@@ -468,8 +467,8 @@ make_MacEager! {
     expr: P<ast::Expr>,
     pat: P<ast::Pat>,
     items: SmallVec<[P<ast::Item>; 1]>,
-    impl_items: SmallVec<[ast::ImplItem; 1]>,
-    trait_items: SmallVec<[ast::TraitItem; 1]>,
+    impl_items: SmallVec<[ast::AssocItem; 1]>,
+    trait_items: SmallVec<[ast::AssocItem; 1]>,
     foreign_items: SmallVec<[ast::ForeignItem; 1]>,
     stmts: SmallVec<[ast::Stmt; 1]>,
     ty: P<ast::Ty>,
@@ -484,11 +483,11 @@ impl MacResult for MacEager {
         self.items
     }
 
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
+    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
         self.impl_items
     }
 
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
+    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
         self.trait_items
     }
 
@@ -552,7 +551,7 @@ impl DummyResult {
             id: ast::DUMMY_NODE_ID,
             kind: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(Vec::new()) },
             span: sp,
-            attrs: ThinVec::new(),
+            attrs: ast::AttrVec::new(),
         })
     }
 
@@ -588,11 +587,11 @@ impl MacResult for DummyResult {
         Some(SmallVec::new())
     }
 
-    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::ImplItem; 1]>> {
+    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::TraitItem; 1]>> {
+    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::AssocItem; 1]>> {
         Some(SmallVec::new())
     }
 
diff --git a/src/libsyntax_expand/build.rs b/src/libsyntax_expand/build.rs
index 3d082101c41..7c69be56beb 100644
--- a/src/libsyntax_expand/build.rs
+++ b/src/libsyntax_expand/build.rs
@@ -1,11 +1,10 @@
 use crate::base::ExtCtxt;
 
-use syntax::ast::{self, Ident, Expr, BlockCheckMode, UnOp, PatKind};
+use syntax::ast::{self, AttrVec, Ident, Expr, BlockCheckMode, UnOp, PatKind};
 use syntax::attr;
 use syntax::source_map::{respan, Spanned};
 use syntax::ptr::P;
 use syntax::symbol::{kw, sym, Symbol};
-use syntax::ThinVec;
 
 use syntax_pos::{Pos, Span};
 
@@ -81,7 +80,7 @@ impl<'a> ExtCtxt<'a> {
                 id: ast::DUMMY_NODE_ID,
                 kind,
                 span,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
             })
         }
     }
@@ -179,7 +178,7 @@ impl<'a> ExtCtxt<'a> {
     pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident,
                 ex: P<ast::Expr>) -> ast::Stmt {
         let pat = if mutbl {
-            let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable);
+            let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mut);
             self.pat_ident_binding_mode(sp, ident, binding_mode)
         } else {
             self.pat_ident(sp, ident)
@@ -190,7 +189,7 @@ impl<'a> ExtCtxt<'a> {
             init: Some(ex),
             id: ast::DUMMY_NODE_ID,
             span: sp,
-            attrs: ThinVec::new(),
+            attrs: AttrVec::new(),
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -207,7 +206,7 @@ impl<'a> ExtCtxt<'a> {
             init: None,
             id: ast::DUMMY_NODE_ID,
             span,
-            attrs: ThinVec::new(),
+            attrs: AttrVec::new(),
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -245,7 +244,7 @@ impl<'a> ExtCtxt<'a> {
             id: ast::DUMMY_NODE_ID,
             kind,
             span,
-            attrs: ThinVec::new(),
+            attrs: AttrVec::new(),
         })
     }
 
@@ -270,7 +269,7 @@ impl<'a> ExtCtxt<'a> {
     }
 
     pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
-        self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Immutable, e))
+        self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
     }
 
     pub fn expr_call(
@@ -304,7 +303,7 @@ impl<'a> ExtCtxt<'a> {
             expr: e,
             span,
             is_shorthand: false,
-            attrs: ThinVec::new(),
+            attrs: AttrVec::new(),
             id: ast::DUMMY_NODE_ID,
             is_placeholder: false,
         }
@@ -422,7 +421,7 @@ impl<'a> ExtCtxt<'a> {
         self.pat(span, PatKind::Lit(expr))
     }
     pub fn pat_ident(&self, span: Span, ident: ast::Ident) -> P<ast::Pat> {
-        let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Immutable);
+        let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Not);
         self.pat_ident_binding_mode(span, ident, binding_mode)
     }
 
@@ -549,7 +548,7 @@ impl<'a> ExtCtxt<'a> {
     pub fn param(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Param {
         let arg_pat = self.pat_ident(span, ident);
         ast::Param {
-            attrs: ThinVec::default(),
+            attrs: AttrVec::default(),
             id: ast::DUMMY_NODE_ID,
             pat: arg_pat,
             span,
diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs
index dc3d5789d1b..25c6c287120 100644
--- a/src/libsyntax_expand/expand.rs
+++ b/src/libsyntax_expand/expand.rs
@@ -154,10 +154,10 @@ ast_fragments! {
     Items(SmallVec<[P<ast::Item>; 1]>) {
         "item"; many fn flat_map_item; fn visit_item; fn make_items;
     }
-    TraitItems(SmallVec<[ast::TraitItem; 1]>) {
+    TraitItems(SmallVec<[ast::AssocItem; 1]>) {
         "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items;
     }
-    ImplItems(SmallVec<[ast::ImplItem; 1]>) {
+    ImplItems(SmallVec<[ast::AssocItem; 1]>) {
         "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
     }
     ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
@@ -1316,7 +1316,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
+    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
         let mut item = configure!(self, item);
 
         let (attr, traits, after_derive) = self.classify_item(&mut item);
@@ -1326,16 +1326,16 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match item.kind {
-            ast::TraitItemKind::Macro(mac) => {
-                let ast::TraitItem { attrs, span, .. } = item;
+            ast::AssocItemKind::Macro(mac) => {
+                let ast::AssocItem { attrs, span, .. } = item;
                 self.check_attributes(&attrs);
                 self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
             }
-            _ => noop_flat_map_trait_item(item, self),
+            _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
+    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
         let mut item = configure!(self, item);
 
         let (attr, traits, after_derive) = self.classify_item(&mut item);
@@ -1345,12 +1345,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match item.kind {
-            ast::ImplItemKind::Macro(mac) => {
-                let ast::ImplItem { attrs, span, .. } = item;
+            ast::AssocItemKind::Macro(mac) => {
+                let ast::AssocItem { attrs, span, .. } = item;
                 self.check_attributes(&attrs);
                 self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
             }
-            _ => noop_flat_map_impl_item(item, self),
+            _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
diff --git a/src/libsyntax_expand/mbe/macro_rules.rs b/src/libsyntax_expand/mbe/macro_rules.rs
index 2dd15872a9f..107fe388ed0 100644
--- a/src/libsyntax_expand/mbe/macro_rules.rs
+++ b/src/libsyntax_expand/mbe/macro_rules.rs
@@ -63,6 +63,30 @@ crate fn annotate_err_with_kind(
     };
 }
 
+/// Instead of e.g. `vec![a, b, c]` in a pattern context, suggest `[a, b, c]`.
+fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Parser<'_>) {
+    let mut suggestion = None;
+    if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) {
+        if let Some(bang) = code.find('!') {
+            suggestion = Some(code[bang + 1..].to_string());
+        }
+    }
+    if let Some(suggestion) = suggestion {
+        e.span_suggestion(
+            site_span,
+            "use a slice pattern here instead",
+            suggestion,
+            Applicability::MachineApplicable,
+        );
+    } else {
+        e.span_label(site_span, "use a slice pattern here instead");
+    }
+    e.help(
+        "for more information, see https://doc.rust-lang.org/edition-guide/\
+        rust-2018/slice-patterns.html"
+    );
+}
+
 impl<'a> ParserAnyMacro<'a> {
     crate fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
         let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self;
@@ -92,27 +116,7 @@ impl<'a> ParserAnyMacro<'a> {
             }
             match kind {
                 AstFragmentKind::Pat if macro_ident.name == sym::vec => {
-                    let mut suggestion = None;
-                    if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) {
-                        if let Some(bang) = code.find('!') {
-                            suggestion = Some(code[bang + 1..].to_string());
-                        }
-                    }
-                    if let Some(suggestion) = suggestion {
-                        e.span_suggestion(
-                            site_span,
-                            "use a slice pattern here instead",
-                            suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        e.span_label(
-                            site_span,
-                            "use a slice pattern here instead",
-                        );
-                    }
-                    e.help("for more information, see https://doc.rust-lang.org/edition-guide/\
-                            rust-2018/slice-patterns.html");
+                    suggest_slice_pat(&mut e, site_span, parser);
                 }
                 _ => annotate_err_with_kind(&mut e, kind, site_span),
             };
diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs
index faea04e691b..4298e0e74b6 100644
--- a/src/libsyntax_expand/placeholders.rs
+++ b/src/libsyntax_expand/placeholders.rs
@@ -5,7 +5,6 @@ use syntax::ast;
 use syntax::source_map::{DUMMY_SP, dummy_spanned};
 use syntax::mut_visit::*;
 use syntax::ptr::P;
-use syntax::ThinVec;
 
 use smallvec::{smallvec, SmallVec};
 
@@ -28,7 +27,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
     let span = DUMMY_SP;
     let expr_placeholder = || P(ast::Expr {
         id, span,
-        attrs: ThinVec::new(),
+        attrs: ast::AttrVec::new(),
         kind: ast::ExprKind::Mac(mac_placeholder()),
     });
     let ty = || P(ast::Ty {
@@ -50,14 +49,15 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
             kind: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
         })]),
-        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
+        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::AssocItem {
             id, span, ident, vis, attrs, generics,
-            kind: ast::TraitItemKind::Macro(mac_placeholder()),
+            kind: ast::AssocItemKind::Macro(mac_placeholder()),
+            defaultness: ast::Defaultness::Final,
             tokens: None,
         }]),
-        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
+        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::AssocItem {
             id, span, ident, vis, attrs, generics,
-            kind: ast::ImplItemKind::Macro(mac_placeholder()),
+            kind: ast::AssocItemKind::Macro(mac_placeholder()),
             defaultness: ast::Defaultness::Final,
             tokens: None,
         }]),
@@ -74,7 +74,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
             id, span, kind: ast::TyKind::Mac(mac_placeholder()),
         })),
         AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
-            let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
+            let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new()));
             ast::Stmt { id, span, kind: ast::StmtKind::Mac(mac) }
         }]),
         AstFragmentKind::Arms => AstFragment::Arms(smallvec![
@@ -252,17 +252,17 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
         noop_flat_map_item(item, self)
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
+    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
         match item.kind {
-            ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
-            _ => noop_flat_map_trait_item(item, self),
+            ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
+            _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
+    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
         match item.kind {
-            ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
-            _ => noop_flat_map_impl_item(item, self),
+            ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
+            _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index bd345a9a7da..5ec24b7a7ac 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -3,7 +3,6 @@
 use State::*;
 
 use errors::{DiagnosticBuilder, PResult};
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_parse::parser::Parser;
 use syntax_expand::base::*;
 use syntax_pos::Span;
@@ -63,7 +62,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
         id: ast::DUMMY_NODE_ID,
         kind: ast::ExprKind::InlineAsm(P(inline_asm)),
         span: cx.with_def_site_ctxt(sp),
-        attrs: ThinVec::new(),
+        attrs: ast::AttrVec::new(),
     }))
 }
 
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 8a1bc56cf1c..7d8bc8b87bc 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -1,5 +1,3 @@
-use rustc_data_structures::thin_vec::ThinVec;
-
 use syntax::ast;
 use syntax_expand::base::{self, *};
 use syntax::token::{self, Token};
@@ -49,7 +47,7 @@ pub fn expand_concat_idents<'cx>(cx: &'cx mut ExtCtxt<'_>,
                 id: ast::DUMMY_NODE_ID,
                 kind: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
                 span: self.ident.span,
-                attrs: ThinVec::new(),
+                attrs: ast::AttrVec::new(),
             }))
         }
 
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 35298211e4d..1b1a231f2d8 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -2,8 +2,6 @@ use crate::deriving::path_std;
 use crate::deriving::generic::*;
 use crate::deriving::generic::ty::*;
 
-use rustc_data_structures::thin_vec::ThinVec;
-
 use syntax::ast::{self, Ident};
 use syntax::ast::{Expr, MetaItem};
 use syntax_expand::base::{Annotatable, ExtCtxt};
@@ -18,7 +16,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt<'_>,
                              push: &mut dyn FnMut(Annotatable)) {
     // &mut ::std::fmt::Formatter
     let fmtr = Ptr(Box::new(Literal(path_std!(cx, fmt::Formatter))),
-                   Borrowed(None, ast::Mutability::Mutable));
+                   Borrowed(None, ast::Mutability::Mut));
 
     let trait_def = TraitDef {
         span,
@@ -127,7 +125,7 @@ fn stmt_let_undescore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> ast
         init: Some(expr),
         id: ast::DUMMY_NODE_ID,
         span: sp,
-        attrs: ThinVec::new(),
+        attrs: ast::AttrVec::new(),
     });
     ast::Stmt {
         id: ast::DUMMY_NODE_ID,
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index 3a0379a0eb0..5cc5aebaba0 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -39,7 +39,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>,
                           },
                           explicit_self: None,
                           args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
-                                         Borrowed(None, Mutability::Mutable)), "d")],
+                                         Borrowed(None, Mutability::Mut)), "d")],
                           ret_ty:
                               Literal(Path::new_(pathvec_std!(cx, result::Result),
                                                  None,
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 2105946b666..99ee0f47d6d 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -123,7 +123,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>,
                 },
                 explicit_self: borrowed_explicit_self(),
                 args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
-                           Borrowed(None, Mutability::Mutable)), "s")],
+                           Borrowed(None, Mutability::Mut)), "s")],
                 ret_ty: Literal(Path::new_(
                     pathvec_std!(cx, result::Result),
                     None,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 5bd84b43a78..5fecd13db98 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -181,7 +181,6 @@ use std::cell::RefCell;
 use std::iter;
 use std::vec;
 
-use rustc_data_structures::thin_vec::ThinVec;
 use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
 use syntax::ast::{VariantData, GenericParamKind, GenericArg};
 use syntax::attr;
@@ -504,13 +503,13 @@ impl<'a> TraitDef<'a> {
                            type_ident: Ident,
                            generics: &Generics,
                            field_tys: Vec<P<ast::Ty>>,
-                           methods: Vec<ast::ImplItem>)
+                           methods: Vec<ast::AssocItem>)
                            -> P<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
-        // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem`
+        // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem`
         let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
-            ast::ImplItem {
+            ast::AssocItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
                 ident,
@@ -518,8 +517,10 @@ impl<'a> TraitDef<'a> {
                 defaultness: ast::Defaultness::Final,
                 attrs: Vec::new(),
                 generics: Generics::default(),
-                kind: ast::ImplItemKind::TyAlias(
-                    type_def.to_ty(cx, self.span, type_ident, generics)),
+                kind: ast::AssocItemKind::TyAlias(
+                    Vec::new(),
+                    Some(type_def.to_ty(cx, self.span, type_ident, generics)),
+                ),
                 tokens: None,
             }
         });
@@ -910,14 +911,14 @@ impl<'a> MethodDef<'a> {
                      explicit_self: Option<ast::ExplicitSelf>,
                      arg_types: Vec<(Ident, P<ast::Ty>)>,
                      body: P<Expr>)
-                     -> ast::ImplItem {
+                     -> ast::AssocItem {
         // Create the generics that aren't for `Self`.
         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
 
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
                 let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span);
-                ast::Param::from_self(ThinVec::default(), explicit_self, ident)
+                ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident)
             });
             let nonself_args = arg_types.into_iter()
                 .map(|(name, ty)| cx.param(trait_.span, name, ty));
@@ -948,7 +949,7 @@ impl<'a> MethodDef<'a> {
         };
 
         // Create the method.
-        ast::ImplItem {
+        ast::AssocItem {
             id: ast::DUMMY_NODE_ID,
             attrs: self.attributes.clone(),
             generics: fn_generics,
@@ -956,7 +957,7 @@ impl<'a> MethodDef<'a> {
             vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited),
             defaultness: ast::Defaultness::Final,
             ident: method_ident,
-            kind: ast::ImplItemKind::Method(sig, body_block),
+            kind: ast::AssocItemKind::Fn(sig, Some(body_block)),
             tokens: None,
         }
     }
@@ -1016,7 +1017,7 @@ impl<'a> MethodDef<'a> {
                                                                  struct_path,
                                                                  struct_def,
                                                                  &format!("__self_{}", i),
-                                                                 ast::Mutability::Immutable,
+                                                                 ast::Mutability::Not,
                                                                  use_temporaries);
             patterns.push(pat);
             raw_fields.push(ident_expr);
@@ -1226,8 +1227,8 @@ impl<'a> MethodDef<'a> {
                                                      type_ident,
                                                      variant,
                                                      self_arg_name,
-                                                     ast::Mutability::Immutable);
-                    (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Immutable)), idents)
+                                                     ast::Mutability::Not);
+                    (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Not)), idents)
                 };
 
                 // A single arm has form (&VariantK, &VariantK, ...) => BodyK
@@ -1557,7 +1558,7 @@ impl<'a> TraitDef<'a> {
         field_paths.iter()
             .map(|path| {
                 let binding_mode = if use_temporaries {
-                    ast::BindingMode::ByValue(ast::Mutability::Immutable)
+                    ast::BindingMode::ByValue(ast::Mutability::Not)
                 } else {
                     ast::BindingMode::ByRef(mutbl)
                 };
@@ -1606,7 +1607,7 @@ impl<'a> TraitDef<'a> {
                         ast::FieldPat {
                             ident: ident.unwrap(),
                             is_shorthand: false,
-                            attrs: ThinVec::new(),
+                            attrs: ast::AttrVec::new(),
                             id: ast::DUMMY_NODE_ID,
                             span: pat.span.with_ctxt(self.span.ctxt()),
                             pat,
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index 607746597a5..b7aa8874aad 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -108,7 +108,7 @@ pub enum Ty<'a> {
 }
 
 pub fn borrowed_ptrty() -> PtrTy {
-    Borrowed(None, ast::Mutability::Immutable)
+    Borrowed(None, ast::Mutability::Not)
 }
 pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
     Ptr(ty, borrowed_ptrty())
@@ -268,7 +268,7 @@ pub fn get_explicit_self(cx: &ExtCtxt<'_>,
     // this constructs a fresh `self` path
     let self_path = cx.expr_self(span);
     match *self_ptr {
-        None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable))),
+        None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Not))),
         Some(ref ptr) => {
             let self_ty =
                 respan(span,
diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs
index fe9ef78bb1b..3ea8dcf46ec 100644
--- a/src/libsyntax_ext/deriving/hash.rs
+++ b/src/libsyntax_ext/deriving/hash.rs
@@ -35,7 +35,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>,
                           },
                           explicit_self: borrowed_explicit_self(),
                           args: vec![(Ptr(Box::new(Literal(arg)),
-                                         Borrowed(None, Mutability::Mutable)), "state")],
+                                         Borrowed(None, Mutability::Mut)), "state")],
                           ret_ty: nil_ty(),
                           attributes: vec![],
                           is_unsafe: false,
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 6fb48bf8173..1ea202f630b 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -31,7 +31,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
                                                      cx.ty_ident(sp,
                                                                  Ident::new(sym::str, sp)),
                                                      Some(lt),
-                                                     ast::Mutability::Immutable))],
+                                                     ast::Mutability::Not))],
                                      ))
         }
         Ok(s) => {
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
index dc29e057455..025d3e91c81 100644
--- a/src/libsyntax_ext/global_allocator.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -180,6 +180,6 @@ impl AllocFnFactory<'_, '_> {
     fn ptr_u8(&self) -> P<Ty> {
         let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
         let ty_u8 = self.cx.ty_path(u8);
-        self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
+        self.cx.ty_ptr(self.span, ty_u8, Mutability::Mut)
     }
 }
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 604400c3cc2..bcc38c8644a 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -415,8 +415,8 @@ fn mk_decls(
             cx.ty(span, ast::TyKind::Slice(
                 cx.ty_path(cx.path(span,
                     vec![proc_macro, bridge, client, proc_macro_ty])))),
-            None, ast::Mutability::Immutable),
-        ast::Mutability::Immutable,
+            None, ast::Mutability::Not),
+        ast::Mutability::Not,
         cx.expr_vec_slice(span, decls),
     ).map(|mut i| {
         let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index ae34064c926..d3e80fc4fdd 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -773,6 +773,7 @@ symbols! {
         usize,
         v1,
         val,
+        var,
         vec,
         Vec,
         vis,
diff --git a/src/stage0.txt b/src/stage0.txt
index 999218efa29..494944720d9 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -16,6 +16,11 @@ date: 2019-12-18
 rustc: beta
 cargo: beta
 
+# We use a nightly rustfmt to format the source because it solves some bootstrapping
+# issues with use of new syntax in this repo. If you're looking at the beta/stable branch, this key should be omitted,
+# as we don't want to depend on rustfmt from nightly there.
+rustfmt: nightly-2019-12-18
+
 # When making a stable release the process currently looks like:
 #
 #   1. Produce stable build, upload it to dev-static
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs
new file mode 100644
index 00000000000..42168dd273e
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs
@@ -0,0 +1,62 @@
+// revisions: cfail1 cfail2
+// compile-flags: -O -Zhuman-readable-cgu-names -Cllvm-args=-import-instr-limit=10
+// build-pass
+
+// rust-lang/rust#59535:
+//
+// This is analgous to cgu_invalidated_when_import_removed.rs, but it covers
+// the other direction:
+//
+// We start with a call-graph like `[A] -> [B -> D] [C]` (where the letters are
+// functions and the modules are enclosed in `[]`), and add a new call `D <- C`,
+// yielding the new call-graph: `[A] -> [B -> D] <- [C]`
+//
+// The effect of this is that the compiler previously classfied `D` as internal
+// and the import-set of `[A]` to be just `B`. But after adding the `D <- C` call,
+// `D` is no longer classified as internal, and the import-set of `[A]` becomes
+// both `B` and `D`.
+//
+// We check this case because an early proposed pull request included an
+// assertion that the import-sets monotonically decreased over time, a claim
+// which this test case proves to be false.
+
+fn main() {
+    foo::foo();
+    bar::baz();
+}
+
+mod foo {
+
+    // In cfail1, ThinLTO decides that foo() does not get inlined into main, and
+    // instead bar() gets inlined into foo().
+    // In cfail2, foo() gets inlined into main.
+    pub fn foo(){
+        bar()
+    }
+
+    // This function needs to be big so that it does not get inlined by ThinLTO
+    // but *does* get inlined into foo() when it is declared `internal` in
+    // cfail1 (alone).
+    pub fn bar(){
+        println!("quux1");
+        println!("quux2");
+        println!("quux3");
+        println!("quux4");
+        println!("quux5");
+        println!("quux6");
+        println!("quux7");
+        println!("quux8");
+        println!("quux9");
+    }
+}
+
+mod bar {
+
+    #[inline(never)]
+    pub fn baz() {
+        #[cfg(cfail2)]
+        {
+            crate::foo::bar();
+        }
+    }
+}
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
new file mode 100644
index 00000000000..19ce7b3e148
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
@@ -0,0 +1,74 @@
+// revisions: cfail1 cfail2
+// compile-flags: -O -Zhuman-readable-cgu-names -Cllvm-args=-import-instr-limit=10
+// build-pass
+
+// rust-lang/rust#59535:
+//
+// Consider a call-graph like `[A] -> [B -> D] <- [C]` (where the letters are
+// functions and the modules are enclosed in `[]`)
+//
+// In our specific instance, the earlier compilations were inlining the call
+// to`B` into `A`; thus `A` ended up with a external reference to the symbol `D`
+// in its object code, to be resolved at subsequent link time. The LTO import
+// information provided by LLVM for those runs reflected that information: it
+// explicitly says during those runs, `B` definition and `D` declaration were
+// imported into `[A]`.
+//
+// The change between incremental builds was that the call `D <- C` was removed.
+//
+// That change, coupled with other decisions within `rustc`, made the compiler
+// decide to make `D` an internal symbol (since it was no longer accessed from
+// other codegen units, this makes sense locally). And then the definition of
+// `D` was inlined into `B` and `D` itself was eliminated entirely.
+//
+// The current LTO import information reported that `B` alone is imported into
+// `[A]` for the *current compilation*. So when the Rust compiler surveyed the
+// dependence graph, it determined that nothing `[A]` imports changed since the
+// last build (and `[A]` itself has not changed either), so it chooses to reuse
+// the object code generated during the previous compilation.
+//
+// But that previous object code has an unresolved reference to `D`, and that
+// causes a link time failure!
+
+fn main() {
+    foo::foo();
+    bar::baz();
+}
+
+mod foo {
+
+    // In cfail1, foo() gets inlined into main.
+    // In cfail2, ThinLTO decides that foo() does not get inlined into main, and
+    // instead bar() gets inlined into foo(). But faulty logic in our incr.
+    // ThinLTO implementation thought that `main()` is unchanged and thus reused
+    // the object file still containing a call to the now non-existant bar().
+    pub fn foo(){
+        bar()
+    }
+
+    // This function needs to be big so that it does not get inlined by ThinLTO
+    // but *does* get inlined into foo() once it is declared `internal` in
+    // cfail2.
+    pub fn bar(){
+        println!("quux1");
+        println!("quux2");
+        println!("quux3");
+        println!("quux4");
+        println!("quux5");
+        println!("quux6");
+        println!("quux7");
+        println!("quux8");
+        println!("quux9");
+    }
+}
+
+mod bar {
+
+    #[inline(never)]
+    pub fn baz() {
+        #[cfg(cfail1)]
+        {
+            crate::foo::bar();
+        }
+    }
+}
diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs
new file mode 100644
index 00000000000..bbd1ca68a86
--- /dev/null
+++ b/src/test/mir-opt/address-of.rs
@@ -0,0 +1,112 @@
+fn address_of_reborrow() {
+    let y = &[0; 10];
+    let mut z = &mut [0; 10];
+
+    y as *const _;
+    y as *const [i32; 10];
+    y as *const dyn Send;
+    y as *const [i32];
+    y as *const i32;            // This is a cast, not a coercion
+
+    let p: *const _ = y;
+    let p: *const [i32; 10] = y;
+    let p: *const dyn Send = y;
+    let p: *const [i32] = y;
+
+    z as *const _;
+    z as *const [i32; 10];
+    z as *const dyn Send;
+    z as *const [i32];
+
+    let p: *const _ = z;
+    let p: *const [i32; 10] = z;
+    let p: *const dyn Send = z;
+    let p: *const [i32] = z;
+
+    z as *mut _;
+    z as *mut [i32; 10];
+    z as *mut dyn Send;
+    z as *mut [i32];
+
+    let p: *mut _ = z;
+    let p: *mut [i32; 10] = z;
+    let p: *mut dyn Send = z;
+    let p: *mut [i32] = z;
+}
+
+// The normal borrows here should be preserved
+fn borrow_and_cast(mut x: i32) {
+    let p = &x as *const i32;
+    let q = &mut x as *const i32;
+    let r = &mut x as *mut i32;
+}
+
+fn main() {}
+
+// START rustc.address_of_reborrow.SimplifyCfg-initial.after.mir
+// bb0: {
+//  ...
+//  _5 = &raw const (*_1); // & to *const casts
+//  ...
+//  _7 = &raw const (*_1);
+//  ...
+//  _11 = &raw const (*_1);
+//  ...
+//  _14 = &raw const (*_1);
+//  ...
+//  _16 = &raw const (*_1);
+//  ...
+//  _17 = &raw const (*_1); // & to *const coercions
+//  ...
+//  _18 = &raw const (*_1);
+//  ...
+//  _20 = &raw const (*_1);
+//  ...
+//  _22 = &raw const (*_1);
+// ...
+//  _24 = &raw const (*_2); // &mut to *const casts
+// ...
+//  _26 = &raw const (*_2);
+// ...
+//  _30 = &raw const (*_2);
+// ...
+//  _33 = &raw const (*_2);
+// ...
+//  _34 = &raw const (*_2); // &mut to *const coercions
+// ...
+//  _35 = &raw const (*_2);
+// ...
+//  _37 = &raw const (*_2);
+// ...
+//  _39 = &raw const (*_2);
+// ...
+//  _41 = &raw mut (*_2); // &mut to *mut casts
+// ...
+//  _43 = &raw mut (*_2);
+// ...
+//  _47 = &raw mut (*_2);
+// ...
+//  _50 = &raw mut (*_2);
+// ...
+//  _51 = &raw mut (*_2); // &mut to *mut coercions
+// ...
+//  _52 = &raw mut (*_2);
+// ...
+//  _54 = &raw mut (*_2);
+// ...
+//  _56 = &raw mut (*_2);
+// ...
+// }
+// END rustc.address_of_reborrow.SimplifyCfg-initial.after.mir
+
+// START rustc.borrow_and_cast.EraseRegions.after.mir
+// bb0: {
+//  ...
+//  _4 = &_1;
+//  ...
+//  _7 = &mut _1;
+//  ...
+//  _10 = &mut _1;
+//  ...
+// }
+// END rustc.borrow_and_cast.EraseRegions.after.mir
diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs
index 00a6b26d0cf..096f98bade2 100644
--- a/src/test/mir-opt/array-index-is-temporary.rs
+++ b/src/test/mir-opt/array-index-is-temporary.rs
@@ -18,24 +18,23 @@ fn main() {
 // START rustc.main.EraseRegions.after.mir
 //     bb0: {
 //         ...
-//         _5 = &mut _2;
-//         _4 = &mut (*_5);
-//         _3 = move _4 as *mut usize (Misc);
+//         _4 = &mut _2;
+//         _3 = &raw mut (*_4);
 //         ...
-//         _7 = _3;
-//         _6 = const foo(move _7) -> bb1;
+//         _6 = _3;
+//         _5 = const foo(move _6) -> bb1;
 //     }
 //
 //     bb1: {
 //         ...
-//         _8 = _2;
-//         _9 = Len(_1);
-//         _10 = Lt(_8, _9);
-//         assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2;
+//         _7 = _2;
+//         _8 = Len(_1);
+//         _9 = Lt(_7, _8);
+//         assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2;
 //     }
 //
 //     bb2: {
-//         _1[_8] = move _6;
+//         _1[_7] = move _5;
 //         ...
 //         return;
 //     }
diff --git a/src/test/mir-opt/const_prop/aggregate.rs b/src/test/mir-opt/const_prop/aggregate.rs
index 0937d37be6b..d04dcc6a05c 100644
--- a/src/test/mir-opt/const_prop/aggregate.rs
+++ b/src/test/mir-opt/const_prop/aggregate.rs
@@ -19,7 +19,7 @@ fn main() {
 //      ...
 //      _3 = (const 0i32, const 1i32, const 2i32);
 //      _2 = const 1i32;
-//      _1 = Add(move _2, const 0i32);
+//      _1 = const 1i32;
 //      ...
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs
index dd22eb5d604..406585b5cab 100644
--- a/src/test/mir-opt/const_prop/array_index.rs
+++ b/src/test/mir-opt/const_prop/array_index.rs
@@ -26,7 +26,7 @@ fn main() {
 //      assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
 //  }
 //  bb1: {
-//      _1 = _2[_3];
+//      _1 = const 2u32;
 //      ...
 //      return;
 //  }
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
index 3f82b81a47d..3c8c0ff4493 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
@@ -11,25 +11,21 @@ fn main() {
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _3 = _4;
-//      _2 = move _3 as *const i32 (Misc);
-//      ...
+//      _2 = &raw const (*_3);
 //      _1 = move _2 as usize (Misc);
 //      ...
-//      _6 = _1;
-//      _5 = const read(move _6) -> bb1;
+//      _5 = _1;
+//      _4 = const read(move _5) -> bb1;
 //  }
 // END rustc.main.ConstProp.before.mir
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _4 = const main::FOO;
-//      _3 = _4;
-//      _2 = move _3 as *const i32 (Misc);
-//      ...
+//      _3 = const main::FOO;
+//      _2 = &raw const (*_3);
 //      _1 = move _2 as usize (Misc);
 //      ...
-//      _6 = _1;
-//      _5 = const read(move _6) -> bb1;
+//      _5 = _1;
+//      _4 = const read(move _5) -> bb1;
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.rs b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
new file mode 100644
index 00000000000..93a53db9093
--- /dev/null
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
@@ -0,0 +1,149 @@
+// compile-flags: -C overflow-checks=on
+
+struct Point {
+    x: u32,
+    y: u32,
+}
+
+fn main() {
+    let x = 2 + 2;
+    let y = [0, 1, 2, 3, 4, 5][3];
+    let z = (Point { x: 12, y: 42}).y;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+// let mut _0: ();
+// let _1: i32;
+// let mut _2: (i32, bool);
+// let mut _4: [i32; 6];
+// let _5: usize;
+// let mut _6: usize;
+// let mut _7: bool;
+// let mut _9: Point;
+// scope 1 {
+//   debug x => _1;
+//   let _3: i32;
+//   scope 2 {
+//     debug y => _3;
+//     let _8: u32;
+//     scope 3 {
+//       debug z => _8;
+//     }
+//   }
+// }
+// bb0: {
+//   StorageLive(_1);
+//   _2 = CheckedAdd(const 2i32, const 2i32);
+//   assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
+// }
+// bb1: {
+//   _1 = move (_2.0: i32);
+//   StorageLive(_3);
+//   StorageLive(_4);
+//   _4 = [const 0i32, const 1i32, const 2i32, const 3i32, const 4i32, const 5i32];
+//   StorageLive(_5);
+//   _5 = const 3usize;
+//   _6 = const 6usize;
+//   _7 = Lt(_5, _6);
+//   assert(move _7, "index out of bounds: the len is move _6 but the index is _5") -> bb2;
+// }
+// bb2: {
+//   _3 = _4[_5];
+//   StorageDead(_5);
+//   StorageDead(_4);
+//   StorageLive(_8);
+//   StorageLive(_9);
+//   _9 = Point { x: const 12u32, y: const 42u32 };
+//   _8 = (_9.1: u32);
+//   StorageDead(_9);
+//   _0 = ();
+//   StorageDead(_8);
+//   StorageDead(_3);
+//   StorageDead(_1);
+//   return;
+// }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+// let mut _0: ();
+// let _1: i32;
+// let mut _2: (i32, bool);
+// let mut _4: [i32; 6];
+// let _5: usize;
+// let mut _6: usize;
+// let mut _7: bool;
+// let mut _9: Point;
+// scope 1 {
+//   debug x => _1;
+//   let _3: i32;
+//   scope 2 {
+//     debug y => _3;
+//     let _8: u32;
+//     scope 3 {
+//       debug z => _8;
+//     }
+//   }
+// }
+// bb0: {
+//   StorageLive(_1);
+//   _2 = (const 4i32, const false);
+//   assert(!const false, "attempt to add with overflow") -> bb1;
+// }
+// bb1: {
+//   _1 = const 4i32;
+//   StorageLive(_3);
+//   StorageLive(_4);
+//   _4 = [const 0i32, const 1i32, const 2i32, const 3i32, const 4i32, const 5i32];
+//   StorageLive(_5);
+//   _5 = const 3usize;
+//   _6 = const 6usize;
+//   _7 = const true;
+//   assert(const true, "index out of bounds: the len is move _6 but the index is _5") -> bb2;
+// }
+// bb2: {
+//   _3 = const 3i32;
+//   StorageDead(_5);
+//   StorageDead(_4);
+//   StorageLive(_8);
+//   StorageLive(_9);
+//   _9 = Point { x: const 12u32, y: const 42u32 };
+//   _8 = const 42u32;
+//   StorageDead(_9);
+//   _0 = ();
+//   StorageDead(_8);
+//   StorageDead(_3);
+//   StorageDead(_1);
+//   return;
+// }
+// END rustc.main.ConstProp.after.mir
+// START rustc.main.SimplifyLocals.after.mir
+// let mut _0: ();
+// let _1: i32;
+// let mut _3: [i32; 6];
+// scope 1 {
+//   debug x => _1;
+//   let _2: i32;
+//   scope 2 {
+//     debug y => _2;
+//     let _4: u32;
+//     scope 3 {
+//       debug z => _4;
+//     }
+//   }
+// }
+// bb0: {
+//   StorageLive(_1);
+//   _1 = const 4i32;
+//   StorageLive(_2);
+//   StorageLive(_3);
+//   _3 = [const 0i32, const 1i32, const 2i32, const 3i32, const 4i32, const 5i32];
+//   _2 = const 3i32;
+//   StorageDead(_3);
+//   StorageLive(_4);
+//   _4 = const 42u32;
+//   StorageDead(_4);
+//   StorageDead(_2);
+//   StorageDead(_1);
+//   return;
+// }
+// END rustc.main.SimplifyLocals.after.mir
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs
index d14ec039716..d9e0eb623af 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.rs
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -25,7 +25,7 @@ fn main() {
 //      _2 = const 2u8;
 //      ...
 //      _4 = const 2u8;
-//      _1 = Add(move _2, move _4);
+//      _1 = const 4u8;
 //      ...
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/repeat.rs b/src/test/mir-opt/const_prop/repeat.rs
index fb091ad2a3d..48c06290cec 100644
--- a/src/test/mir-opt/const_prop/repeat.rs
+++ b/src/test/mir-opt/const_prop/repeat.rs
@@ -30,7 +30,7 @@ fn main() {
 //  }
 //  bb1: {
 //      _2 = const 42u32;
-//      _1 = Add(move _2, const 0u32);
+//      _1 = const 42u32;
 //      ...
 //      return;
 //  }
diff --git a/src/test/mir-opt/inline-any-operand.rs b/src/test/mir-opt/inline/inline-any-operand.rs
index b5455003719..b5455003719 100644
--- a/src/test/mir-opt/inline-any-operand.rs
+++ b/src/test/mir-opt/inline/inline-any-operand.rs
diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
index 768f4953228..768f4953228 100644
--- a/src/test/mir-opt/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
diff --git a/src/test/mir-opt/inline-closure-captures.rs b/src/test/mir-opt/inline/inline-closure-captures.rs
index e000a418d90..e000a418d90 100644
--- a/src/test/mir-opt/inline-closure-captures.rs
+++ b/src/test/mir-opt/inline/inline-closure-captures.rs
diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline/inline-closure.rs
index bd36e77818e..bd36e77818e 100644
--- a/src/test/mir-opt/inline-closure.rs
+++ b/src/test/mir-opt/inline/inline-closure.rs
diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs
new file mode 100644
index 00000000000..0bb9dfa403d
--- /dev/null
+++ b/src/test/mir-opt/inline/inline-into-box-place.rs
@@ -0,0 +1,71 @@
+// ignore-tidy-linelength
+// ignore-wasm32-bare compiled with panic=abort by default
+#![feature(box_syntax)]
+
+fn main() {
+    let _x: Box<Vec<u32>> = box Vec::new();
+}
+
+// END RUST SOURCE
+// START rustc.main.Inline.before.mir
+// let mut _0: ();
+// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
+// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
+// let mut _3: ();
+// scope 1 {
+//   debug _x => _1;
+// }
+// bb0: {
+//   StorageLive(_1);
+//   StorageLive(_2);
+//   _2 = Box(std::vec::Vec<u32>);
+//   (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4];
+// }
+// bb1 (cleanup): {
+//   resume;
+// }
+// bb2: {
+//   _1 = move _2;
+//   StorageDead(_2);
+//   _0 = ();
+//   drop(_1) -> [return: bb3, unwind: bb1];
+// }
+// bb3: {
+//   StorageDead(_1);
+//   return;
+// }
+// bb4 (cleanup): {
+//   _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1;
+// }
+// END rustc.main.Inline.before.mir
+// START rustc.main.Inline.after.mir
+// let mut _0: ();
+// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
+// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
+// let mut _3: ();
+// let mut _4: &mut std::vec::Vec<u32>;
+// scope 1 {
+//   debug _x => _1;
+// }
+// scope 2 {
+// }
+// bb0: {
+//   StorageLive(_1);
+//   StorageLive(_2);
+//   _2 = Box(std::vec::Vec<u32>);
+//   _4 = &mut (*_2);
+//   ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32>::NEW;
+//   ((*_4).1: usize) = const 0usize;
+//   _1 = move _2;
+//   StorageDead(_2);
+//   _0 = ();
+//   drop(_1) -> [return: bb2, unwind: bb1];
+// }
+// bb1 (cleanup): {
+//   resume;
+// }
+// bb2: {
+//   StorageDead(_1);
+//   return;
+// }
+// END rustc.main.Inline.after.mir
diff --git a/src/test/mir-opt/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs
index 6cdbcfdb0ad..6cdbcfdb0ad 100644
--- a/src/test/mir-opt/inline-retag.rs
+++ b/src/test/mir-opt/inline/inline-retag.rs
diff --git a/src/test/mir-opt/inline-trait-method.rs b/src/test/mir-opt/inline/inline-trait-method.rs
index a2c5fb920cd..a2c5fb920cd 100644
--- a/src/test/mir-opt/inline-trait-method.rs
+++ b/src/test/mir-opt/inline/inline-trait-method.rs
diff --git a/src/test/mir-opt/inline-trait-method_2.rs b/src/test/mir-opt/inline/inline-trait-method_2.rs
index 4ad4311113a..4ad4311113a 100644
--- a/src/test/mir-opt/inline-trait-method_2.rs
+++ b/src/test/mir-opt/inline/inline-trait-method_2.rs
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index 32995448a21..ccecaeac96b 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -82,18 +82,16 @@ fn main() {
 //         _10 = move _8;
 //         Retag(_10);
 //         ...
-//         _13 = &mut (*_10);
-//         Retag(_13);
-//         _12 = move _13 as *mut i32 (Misc);
+//         _12 = &raw mut (*_10);
 //         Retag([raw] _12);
 //         ...
-//         _16 = move _17(move _18) -> bb5;
+//         _15 = move _16(move _17) -> bb5;
 //     }
 //
 //     bb5: {
-//         Retag(_16);
+//         Retag(_15);
 //         ...
-//         _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7];
+//         _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7];
 //     }
 //
 //     ...
diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs
index f270dec5fe2..5a37b67229c 100644
--- a/src/test/mir-opt/slice-drop-shim.rs
+++ b/src/test/mir-opt/slice-drop-shim.rs
@@ -10,15 +10,15 @@ fn main() {
 // let mut _2: usize;
 // let mut _3: usize;
 // let mut _4: usize;
-// let mut _5: &mut std::string::String;
+// let mut _5: *mut std::string::String;
 // let mut _6: bool;
-// let mut _7: &mut std::string::String;
+// let mut _7: *mut std::string::String;
 // let mut _8: bool;
 // let mut _9: *mut std::string::String;
 // let mut _10: *mut std::string::String;
-// let mut _11: &mut std::string::String;
+// let mut _11: *mut std::string::String;
 // let mut _12: bool;
-// let mut _13: &mut std::string::String;
+// let mut _13: *mut std::string::String;
 // let mut _14: bool;
 // let mut _15: *mut [std::string::String];
 // bb0: {
@@ -31,7 +31,7 @@ fn main() {
 //     resume;
 // }
 // bb3 (cleanup): {
-//     _5 = &mut (*_1)[_4];
+//     _5 = &raw mut (*_1)[_4];
 //     _4 = Add(move _4, const 1usize);
 //     drop((*_5)) -> bb4;
 // }
@@ -40,7 +40,7 @@ fn main() {
 //     switchInt(move _6) -> [false: bb3, otherwise: bb2];
 // }
 // bb5: {
-//     _7 = &mut (*_1)[_4];
+//     _7 = &raw mut (*_1)[_4];
 //     _4 = Add(move _4, const 1usize);
 //     drop((*_7)) -> [return: bb6, unwind: bb4];
 // }
@@ -56,7 +56,7 @@ fn main() {
 //     goto -> bb7;
 // }
 // bb9 (cleanup): {
-//     _11 = &mut (*_9);
+//     _11 = _9;
 //     _9 = Offset(move _9, const 1usize);
 //     drop((*_11)) -> bb10;
 // }
@@ -65,7 +65,7 @@ fn main() {
 //     switchInt(move _12) -> [false: bb9, otherwise: bb2];
 // }
 // bb11: {
-//     _13 = &mut (*_9);
+//     _13 = _9;
 //     _9 = Offset(move _9, const 1usize);
 //     drop((*_13)) -> [return: bb12, unwind: bb10];
 // }
@@ -74,7 +74,7 @@ fn main() {
 //     switchInt(move _14) -> [false: bb11, otherwise: bb1];
 // }
 // bb13: {
-//     _15 = &mut (*_1);
+//     _15 = &raw mut (*_1);
 //     _9 = move _15 as *mut std::string::String (Misc);
 //     _10 = Offset(_9, move _3);
 //     goto -> bb12;
diff --git a/src/test/pretty/ast-stmt-expr-attr.rs b/src/test/pretty/ast-stmt-expr-attr.rs
new file mode 100644
index 00000000000..5b975424512
--- /dev/null
+++ b/src/test/pretty/ast-stmt-expr-attr.rs
@@ -0,0 +1,175 @@
+// pp-exact
+
+fn main() { }
+
+#[cfg(FALSE)]
+fn syntax() {
+    let _ = #[attr] box 0;
+    let _ = #[attr] [#![attr] ];
+    let _ = #[attr] [#![attr] 0];
+    let _ = #[attr] [#![attr] 0; 0];
+    let _ = #[attr] [#![attr] 0, 0, 0];
+    let _ = #[attr] foo();
+    let _ = #[attr] x.foo();
+    let _ = #[attr] (#![attr] );
+    let _ = #[attr] (#![attr] #[attr] 0,);
+    let _ = #[attr] (#![attr] #[attr] 0, 0);
+    let _ = #[attr] 0 + #[attr] 0;
+    let _ = #[attr] 0 / #[attr] 0;
+    let _ = #[attr] 0 & #[attr] 0;
+    let _ = #[attr] 0 % #[attr] 0;
+    let _ = #[attr] (0 + 0);
+    let _ = #[attr] !0;
+    let _ = #[attr] -0;
+    let _ = #[attr] false;
+    let _ = #[attr] 0;
+    let _ = #[attr] 'c';
+    let _ = #[attr] x as Y;
+    let _ = #[attr] (x as Y);
+    let _ =
+        #[attr] while true {
+                    #![attr]
+                };
+    let _ =
+        #[attr] while let Some(false) = true {
+                    #![attr]
+                };
+    let _ =
+        #[attr] for x in y {
+                    #![attr]
+                };
+    let _ =
+        #[attr] loop  {
+                    #![attr]
+                };
+    let _ =
+        #[attr] match true {
+                    #![attr]
+                            #[attr]
+                            _ => false,
+                };
+    let _ = #[attr] || #[attr] foo;
+    let _ = #[attr] move || #[attr] foo;
+    let _ =
+        #[attr] ||
+                    #[attr] {
+                                #![attr]
+                                foo
+                            };
+    let _ =
+        #[attr] move ||
+                    #[attr] {
+                                #![attr]
+                                foo
+                            };
+    let _ =
+        #[attr] ||
+                    {
+                        #![attr]
+                        foo
+                    };
+    let _ =
+        #[attr] move ||
+                    {
+                        #![attr]
+                        foo
+                    };
+    let _ =
+        #[attr] {
+                    #![attr]
+                };
+    let _ =
+        #[attr] {
+                    #![attr]
+                    let _ = ();
+                };
+    let _ =
+        #[attr] {
+                    #![attr]
+                    let _ = ();
+                    foo
+                };
+    let _ = #[attr] x = y;
+    let _ = #[attr] (x = y);
+    let _ = #[attr] x += y;
+    let _ = #[attr] (x += y);
+    let _ = #[attr] foo.bar;
+    let _ = (#[attr] foo).bar;
+    let _ = #[attr] foo.0;
+    let _ = (#[attr] foo).0;
+    let _ = #[attr] foo[bar];
+    let _ = (#[attr] foo)[bar];
+    let _ = #[attr] 0..#[attr] 0;
+    let _ = #[attr] 0..;
+    let _ = #[attr] (0..0);
+    let _ = #[attr] (0..);
+    let _ = #[attr] (..0);
+    let _ = #[attr] (..);
+    let _ = #[attr] foo::bar::baz;
+    let _ = #[attr] &0;
+    let _ = #[attr] &mut 0;
+    let _ = #[attr] &#[attr] 0;
+    let _ = #[attr] &mut #[attr] 0;
+    let _ = #[attr] break ;
+    let _ = #[attr] continue ;
+    let _ = #[attr] return;
+    let _ = #[attr] foo!();
+    let _ = #[attr] foo!(# ! [attr]);
+    let _ = #[attr] foo![];
+    let _ = #[attr] foo![# ! [attr]];
+    let _ = #[attr] foo! { };
+    let _ = #[attr] foo! { # ! [attr] };
+    let _ = #[attr] Foo{#![attr] bar: baz,};
+    let _ = #[attr] Foo{#![attr] ..foo};
+    let _ = #[attr] Foo{#![attr] bar: baz, ..foo};
+    let _ = #[attr] (#![attr] 0);
+
+    {
+        #[attr]
+        let _ = 0;
+
+        #[attr]
+        0;
+
+        #[attr]
+        foo!();
+
+        #[attr]
+        foo! { }
+
+        #[attr]
+        foo![];
+    }
+
+    {
+        #[attr]
+        let _ = 0;
+    }
+    {
+
+        #[attr]
+        0
+    }
+    {
+
+        #[attr]
+        {
+            #![attr]
+        }
+    }
+    {
+
+        #[attr]
+        foo!()
+    }
+    {
+
+        #[attr]
+        foo![]
+    }
+    {
+
+        #[attr]
+        foo! { }
+    }
+}
diff --git a/src/test/pretty/raw-address-of.rs b/src/test/pretty/raw-address-of.rs
new file mode 100644
index 00000000000..6ccc434a1e7
--- /dev/null
+++ b/src/test/pretty/raw-address-of.rs
@@ -0,0 +1,12 @@
+// pp-exact
+#![feature(raw_ref_op)]
+
+const C_PTR: () = { let a = 1; &raw const a; };
+static S_PTR: () = { let b = false; &raw const b; };
+
+fn main() {
+    let x = 123;
+    let mut y = 345;
+    let c_p = &raw const x;
+    let parens = unsafe { *(&raw mut (y)) };
+}
diff --git a/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs
index 2a977ed63b1..3dcfb9dadd8 100644
--- a/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs
+++ b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs
@@ -1,5 +1,5 @@
 #![crate_type = "lib"]
 #![feature(staged_api)]
-#![unstable(feature = "unstable_test_feature", issue = "0")]
+#![unstable(feature = "unstable_test_feature", issue = "none")]
 
 pub fn baz() {}
diff --git a/src/test/run-make/wasm-symbols-different-module/Makefile b/src/test/run-make/wasm-symbols-different-module/Makefile
new file mode 100644
index 00000000000..bb6a5d3c9d2
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/Makefile
@@ -0,0 +1,28 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
+
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto
+	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
+
+	$(RUSTC) baz.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate
+
+	$(RUSTC) log.rs --target wasm32-unknown-unknown
+	$(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log
diff --git a/src/test/run-make/wasm-symbols-different-module/bar.rs b/src/test/run-make/wasm-symbols-different-module/bar.rs
new file mode 100644
index 00000000000..7567060d781
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/bar.rs
@@ -0,0 +1,33 @@
+//! Issue #50021
+
+#![crate_type = "cdylib"]
+
+mod m1 {
+    #[link(wasm_import_module = "m1")]
+    extern "C" {
+        pub fn f();
+    }
+    #[link(wasm_import_module = "m1")]
+    extern "C" {
+        pub fn g();
+    }
+}
+
+mod m2 {
+    #[link(wasm_import_module = "m2")]
+    extern "C" {
+        pub fn f(_: i32);
+    }
+}
+
+#[no_mangle]
+pub unsafe fn run() {
+    m1::f();
+    m1::g();
+
+    // In generated code, expected:
+    // (import "m2" "f" (func $f (param i32)))
+    // but got:
+    // (import "m1" "f" (func $f (param i32)))
+    m2::f(0);
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/baz.rs b/src/test/run-make/wasm-symbols-different-module/baz.rs
new file mode 100644
index 00000000000..fbb78619bb8
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/baz.rs
@@ -0,0 +1,22 @@
+//! Issue #63562
+
+#![crate_type = "cdylib"]
+
+mod foo {
+    #[link(wasm_import_module = "sqlite")]
+    extern "C" {
+        pub fn allocate(size: usize) -> i32;
+        pub fn deallocate(ptr: i32, size: usize);
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn allocate() {
+    unsafe {
+        foo::allocate(1);
+        foo::deallocate(1, 2);
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn deallocate() {}
diff --git a/src/test/run-make/wasm-symbols-different-module/foo.rs b/src/test/run-make/wasm-symbols-different-module/foo.rs
new file mode 100644
index 00000000000..a4ba7e714cc
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/foo.rs
@@ -0,0 +1,23 @@
+#![crate_type = "cdylib"]
+
+mod a {
+    #[link(wasm_import_module = "a")]
+    extern "C" {
+        pub fn foo();
+    }
+}
+
+mod b {
+    #[link(wasm_import_module = "b")]
+    extern "C" {
+        pub fn foo();
+    }
+}
+
+#[no_mangle]
+pub fn start() {
+    unsafe {
+        a::foo();
+        b::foo();
+    }
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/log.rs b/src/test/run-make/wasm-symbols-different-module/log.rs
new file mode 100644
index 00000000000..ea3e0b4b2be
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/log.rs
@@ -0,0 +1,16 @@
+//! Issue #56309
+
+#![crate_type = "cdylib"]
+
+#[link(wasm_import_module = "test")]
+extern "C" {
+    fn log(message_data: u32, message_size: u32);
+}
+
+#[no_mangle]
+pub fn main() {
+    let message = "Hello, world!";
+    unsafe {
+        log(message.as_ptr() as u32, message.len() as u32);
+    }
+}
diff --git a/src/test/run-make/wasm-symbols-different-module/verify-imports.js b/src/test/run-make/wasm-symbols-different-module/verify-imports.js
new file mode 100644
index 00000000000..7e9f90cf8bd
--- /dev/null
+++ b/src/test/run-make/wasm-symbols-different-module/verify-imports.js
@@ -0,0 +1,32 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.imports(m);
+console.log('imports', list);
+if (list.length !== process.argv.length - 3)
+  throw new Error("wrong number of imports")
+
+const imports = new Map();
+for (let i = 3; i < process.argv.length; i++) {
+  const [module, name] = process.argv[i].split('/');
+  if (!imports.has(module))
+    imports.set(module, new Map());
+  imports.get(module).set(name, true);
+}
+
+for (let i of list) {
+  if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined)
+    throw new Error(`didn't find import of ${i.module}::${i.name}`);
+  imports.get(i.module).delete(i.name);
+
+  if (imports.get(i.module).size === 0)
+    imports.delete(i.module);
+}
+
+console.log(imports);
+if (imports.size !== 0) {
+  throw new Error('extra imports');
+}
diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs
index bc7ad04b6a2..8e0d230f7d0 100644
--- a/src/test/rustdoc/const-display.rs
+++ b/src/test/rustdoc/const-display.rs
@@ -2,18 +2,18 @@
 
 #![unstable(feature = "humans",
             reason = "who ever let humans program computers, we're apparently really bad at it",
-            issue = "0")]
+            issue = "none")]
 
 #![feature(foo, foo2)]
 #![feature(staged_api)]
 
 // @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32'
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
 pub const unsafe fn foo() -> u32 { 42 }
 
 // @has 'foo/fn.foo2.html' '//pre' 'pub fn foo2() -> u32'
-#[unstable(feature = "humans", issue="0")]
+#[unstable(feature = "humans", issue = "none")]
 pub const fn foo2() -> u32 { 42 }
 
 // @has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32'
@@ -22,7 +22,7 @@ pub const fn foo2() -> u32 { 42 }
 pub const fn bar2() -> u32 { 42 }
 
 // @has 'foo/fn.foo2_gated.html' '//pre' 'pub unsafe fn foo2_gated() -> u32'
-#[unstable(feature = "foo2", issue="0")]
+#[unstable(feature = "foo2", issue = "none")]
 pub const unsafe fn foo2_gated() -> u32 { 42 }
 
 // @has 'foo/fn.bar2_gated.html' '//pre' 'pub const unsafe fn bar2_gated() -> u32'
diff --git a/src/test/rustdoc/inline_cross/auxiliary/macros.rs b/src/test/rustdoc/inline_cross/auxiliary/macros.rs
index 6189b018037..2165be97452 100644
--- a/src/test/rustdoc/inline_cross/auxiliary/macros.rs
+++ b/src/test/rustdoc/inline_cross/auxiliary/macros.rs
@@ -3,7 +3,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 /// docs for my_macro
-#[unstable(feature = "macro_test", issue = "0")]
+#[unstable(feature = "macro_test", issue = "none")]
 #[rustc_deprecated(since = "1.2.3", reason = "text")]
 #[macro_export]
 macro_rules! my_macro {
diff --git a/src/test/rustdoc/stability.rs b/src/test/rustdoc/stability.rs
index 18a21603493..b1b97fe134e 100644
--- a/src/test/rustdoc/stability.rs
+++ b/src/test/rustdoc/stability.rs
@@ -1,6 +1,6 @@
 #![feature(staged_api)]
 
-#![unstable(feature = "test", issue = "0")]
+#![unstable(feature = "test", issue = "none")]
 
 pub struct Unstable {
     // @has stability/struct.Unstable.html \
diff --git a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs
deleted file mode 100644
index d6d49df63ef..00000000000
--- a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs
+++ /dev/null
@@ -1,311 +0,0 @@
-// run-pass
-
-#![allow(unused_imports)]
-// ignore-cross-compile
-
-#![feature(rustc_private)]
-
-extern crate syntax;
-extern crate syntax_expand;
-extern crate rustc_parse;
-extern crate rustc_errors;
-
-use rustc_errors::PResult;
-use rustc_parse::parser::attr::*;
-use rustc_parse::new_parser_from_source_str;
-use rustc_parse::parser::Parser;
-use syntax::ast::*;
-use syntax::attr::*;
-use syntax::ast;
-use syntax::sess::ParseSess;
-use syntax::source_map::{FilePathMapping, FileName};
-use syntax::ptr::P;
-use syntax::print::pprust;
-use syntax::token;
-use std::fmt;
-
-// Copied out of syntax::util::parser_testing
-
-pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
-    new_parser_from_source_str(ps, FileName::Custom(source_str.clone()), source_str)
-}
-
-fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> PResult<'a, T> where
-    F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
-{
-    let mut p = string_to_parser(&ps, s);
-    let x = f(&mut p);
-
-    if ps.span_diagnostic.has_errors() || p.token != token::Eof {
-        if let Err(mut e) = x {
-            e.cancel();
-        }
-        return Err(p.fatal("parse error"));
-    }
-
-    x
-}
-
-fn expr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, P<ast::Expr>> {
-    with_error_checking_parse(s.to_string(), ps, |p| {
-        p.parse_expr()
-    })
-}
-
-fn stmt<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Stmt> {
-    with_error_checking_parse(s.to_string(), ps, |p| {
-        p.parse_stmt().map(|s| s.unwrap())
-    })
-}
-
-fn attr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Attribute> {
-    with_error_checking_parse(s.to_string(), ps, |p| {
-        p.parse_attribute(true)
-    })
-}
-
-fn str_compare<T, F: Fn(&T) -> String>(e: &str, expected: &[T], actual: &[T], f: F) {
-    let expected: Vec<_> = expected.iter().map(|e| f(e)).collect();
-    let actual: Vec<_> = actual.iter().map(|e| f(e)).collect();
-
-    if expected != actual {
-        panic!("parsed `{}` as {:?}, expected {:?}", e, actual, expected);
-    }
-}
-
-fn sess() -> ParseSess {
-    ParseSess::new(FilePathMapping::empty())
-}
-
-fn check_expr_attrs(es: &str, expected: &[&str]) {
-    let ps = sess();
-    let e = expr(es, &ps).expect("parse error");
-    let actual = &e.attrs;
-    str_compare(es,
-                &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
-                &actual,
-                pprust::attribute_to_string);
-}
-
-fn check_stmt_attrs(es: &str, expected: &[&str]) {
-    let ps = sess();
-    let e = stmt(es, &ps).expect("parse error");
-    let actual = e.kind.attrs();
-    str_compare(es,
-                &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
-                actual,
-                pprust::attribute_to_string);
-}
-
-fn reject_expr_parse(es: &str) {
-    let ps = sess();
-    match expr(es, &ps) {
-        Ok(_) => panic!("parser did not reject `{}`", es),
-        Err(mut e) => e.cancel(),
-    };
-}
-
-fn reject_stmt_parse(es: &str) {
-    let ps = sess();
-    match stmt(es, &ps) {
-        Ok(_) => panic!("parser did not reject `{}`", es),
-        Err(mut e) => e.cancel(),
-    };
-}
-
-fn main() {
-    syntax::with_default_globals(|| run());
-}
-
-fn run() {
-    let both = &["#[attr]", "#![attr]"];
-    let outer = &["#[attr]"];
-    let none = &[];
-
-    check_expr_attrs("#[attr] box 0", outer);
-    reject_expr_parse("box #![attr] 0");
-
-    check_expr_attrs("#[attr] [#![attr]]", both);
-    check_expr_attrs("#[attr] [#![attr] 0]", both);
-    check_expr_attrs("#[attr] [#![attr] 0; 0]", both);
-    check_expr_attrs("#[attr] [#![attr] 0, 0, 0]", both);
-    reject_expr_parse("[#[attr]]");
-
-    check_expr_attrs("#[attr] foo()", outer);
-    check_expr_attrs("#[attr] x.foo()", outer);
-    reject_expr_parse("foo#[attr]()");
-    reject_expr_parse("foo(#![attr])");
-    reject_expr_parse("x.foo(#![attr])");
-    reject_expr_parse("x.#[attr]foo()");
-    reject_expr_parse("x.#![attr]foo()");
-
-    check_expr_attrs("#[attr] (#![attr])", both);
-    check_expr_attrs("#[attr] (#![attr] #[attr] 0,)", both);
-    check_expr_attrs("#[attr] (#![attr] #[attr] 0, 0)", both);
-
-    check_expr_attrs("#[attr] 0 + #[attr] 0", none);
-    check_expr_attrs("#[attr] 0 / #[attr] 0", none);
-    check_expr_attrs("#[attr] 0 & #[attr] 0", none);
-    check_expr_attrs("#[attr] 0 % #[attr] 0", none);
-    check_expr_attrs("#[attr] (0 + 0)", outer);
-    reject_expr_parse("0 + #![attr] 0");
-
-    check_expr_attrs("#[attr] !0", outer);
-    check_expr_attrs("#[attr] -0", outer);
-    reject_expr_parse("!#![attr] 0");
-    reject_expr_parse("-#![attr] 0");
-
-    check_expr_attrs("#[attr] false", outer);
-    check_expr_attrs("#[attr] 0", outer);
-    check_expr_attrs("#[attr] 'c'", outer);
-
-    check_expr_attrs("#[attr] x as Y", none);
-    check_expr_attrs("#[attr] (x as Y)", outer);
-    reject_expr_parse("x #![attr] as Y");
-
-    reject_expr_parse("#[attr] if false {}");
-    reject_expr_parse("if false #[attr] {}");
-    reject_expr_parse("if false {#![attr]}");
-    reject_expr_parse("if false {} #[attr] else {}");
-    reject_expr_parse("if false {} else #[attr] {}");
-    reject_expr_parse("if false {} else {#![attr]}");
-    reject_expr_parse("if false {} else #[attr] if true {}");
-    reject_expr_parse("if false {} else if true #[attr] {}");
-    reject_expr_parse("if false {} else if true {#![attr]}");
-
-    reject_expr_parse("#[attr] if let Some(false) = false {}");
-    reject_expr_parse("if let Some(false) = false #[attr] {}");
-    reject_expr_parse("if let Some(false) = false {#![attr]}");
-    reject_expr_parse("if let Some(false) = false {} #[attr] else {}");
-    reject_expr_parse("if let Some(false) = false {} else #[attr] {}");
-    reject_expr_parse("if let Some(false) = false {} else {#![attr]}");
-    reject_expr_parse("if let Some(false) = false {} else #[attr] if let Some(false) = true {}");
-    reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true #[attr] {}");
-    reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true {#![attr]}");
-
-    check_expr_attrs("#[attr] while true {#![attr]}", both);
-
-    check_expr_attrs("#[attr] while let Some(false) = true {#![attr]}", both);
-
-    check_expr_attrs("#[attr] for x in y {#![attr]}", both);
-
-    check_expr_attrs("#[attr] loop {#![attr]}", both);
-
-    check_expr_attrs("#[attr] match true {#![attr] #[attr] _ => false}", both);
-
-    check_expr_attrs("#[attr]      || #[attr] foo", outer);
-    check_expr_attrs("#[attr] move || #[attr] foo", outer);
-    check_expr_attrs("#[attr]      || #[attr] { #![attr] foo }", outer);
-    check_expr_attrs("#[attr] move || #[attr] { #![attr] foo }", outer);
-    check_expr_attrs("#[attr]      || { #![attr] foo }", outer);
-    check_expr_attrs("#[attr] move || { #![attr] foo }", outer);
-    reject_expr_parse("|| #![attr] foo");
-    reject_expr_parse("move || #![attr] foo");
-    reject_expr_parse("|| #![attr] {foo}");
-    reject_expr_parse("move || #![attr] {foo}");
-
-    check_expr_attrs("#[attr] { #![attr] }", both);
-    check_expr_attrs("#[attr] { #![attr] let _ = (); }", both);
-    check_expr_attrs("#[attr] { #![attr] let _ = (); foo }", both);
-
-    check_expr_attrs("#[attr] x = y", none);
-    check_expr_attrs("#[attr] (x = y)", outer);
-
-    check_expr_attrs("#[attr] x += y", none);
-    check_expr_attrs("#[attr] (x += y)", outer);
-
-    check_expr_attrs("#[attr] foo.bar", outer);
-    check_expr_attrs("(#[attr] foo).bar", none);
-
-    check_expr_attrs("#[attr] foo.0", outer);
-    check_expr_attrs("(#[attr] foo).0", none);
-
-    check_expr_attrs("#[attr] foo[bar]", outer);
-    check_expr_attrs("(#[attr] foo)[bar]", none);
-
-    check_expr_attrs("#[attr] 0..#[attr] 0", none);
-    check_expr_attrs("#[attr] 0..", none);
-    reject_expr_parse("#[attr] ..#[attr] 0");
-    reject_expr_parse("#[attr] ..");
-
-    check_expr_attrs("#[attr] (0..0)", outer);
-    check_expr_attrs("#[attr] (0..)", outer);
-    check_expr_attrs("#[attr] (..0)", outer);
-    check_expr_attrs("#[attr] (..)", outer);
-
-    check_expr_attrs("#[attr] foo::bar::baz", outer);
-
-    check_expr_attrs("#[attr] &0", outer);
-    check_expr_attrs("#[attr] &mut 0", outer);
-    check_expr_attrs("#[attr] & #[attr] 0", outer);
-    check_expr_attrs("#[attr] &mut #[attr] 0", outer);
-    reject_expr_parse("#[attr] &#![attr] 0");
-    reject_expr_parse("#[attr] &mut #![attr] 0");
-
-    check_expr_attrs("#[attr] break", outer);
-    check_expr_attrs("#[attr] continue", outer);
-    check_expr_attrs("#[attr] return", outer);
-
-    check_expr_attrs("#[attr] foo!()", outer);
-    check_expr_attrs("#[attr] foo!(#![attr])", outer);
-    check_expr_attrs("#[attr] foo![]", outer);
-    check_expr_attrs("#[attr] foo![#![attr]]", outer);
-    check_expr_attrs("#[attr] foo!{}", outer);
-    check_expr_attrs("#[attr] foo!{#![attr]}", outer);
-
-    check_expr_attrs("#[attr] Foo { #![attr] bar: baz }", both);
-    check_expr_attrs("#[attr] Foo { #![attr] ..foo }", both);
-    check_expr_attrs("#[attr] Foo { #![attr] bar: baz, ..foo }", both);
-
-    check_expr_attrs("#[attr] (#![attr] 0)", both);
-
-    // Look at statements in their natural habitat...
-    check_expr_attrs("{
-        #[attr] let _ = 0;
-        #[attr] 0;
-        #[attr] foo!();
-        #[attr] foo!{}
-        #[attr] foo![];
-    }", none);
-
-    check_stmt_attrs("#[attr] let _ = 0", outer);
-    check_stmt_attrs("#[attr] 0",         outer);
-    check_stmt_attrs("#[attr] {#![attr]}", both);
-    check_stmt_attrs("#[attr] foo!()",    outer);
-    check_stmt_attrs("#[attr] foo![]",    outer);
-    check_stmt_attrs("#[attr] foo!{}",    outer);
-
-    reject_stmt_parse("#[attr] #![attr] let _ = 0");
-    reject_stmt_parse("#[attr] #![attr] 0");
-    reject_stmt_parse("#[attr] #![attr] foo!()");
-    reject_stmt_parse("#[attr] #![attr] foo![]");
-    reject_stmt_parse("#[attr] #![attr] foo!{}");
-
-    // FIXME: Allow attributes in pattern constexprs?
-    // note: requires parens in patterns to allow disambiguation
-
-    reject_expr_parse("match 0 {
-        0..=#[attr] 10 => ()
-    }");
-    reject_expr_parse("match 0 {
-        0..=#[attr] -10 => ()
-    }");
-    reject_expr_parse("match 0 {
-        0..=-#[attr] 10 => ()
-    }");
-    reject_expr_parse("match 0 {
-        0..=#[attr] FOO => ()
-    }");
-
-    // make sure we don't catch this bug again...
-    reject_expr_parse("{
-        fn foo() {
-            #[attr];
-        }
-    }");
-    reject_expr_parse("{
-        fn foo() {
-            #[attr]
-        }
-    }");
-}
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index f19d13ff5c5..0c050e31413 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -141,7 +141,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             15 => {
                 iter_exprs(
                     depth - 1,
-                    &mut |e| g(ExprKind::AddrOf(BorrowKind::Ref, Mutability::Immutable, e)),
+                    &mut |e| g(ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, e)),
                 );
             },
             16 => {
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
new file mode 100644
index 00000000000..0e767d9613a
--- /dev/null
+++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
@@ -0,0 +1,97 @@
+// Test that slice subslice patterns are correctly handled in const evaluation.
+
+// run-pass
+
+#![feature(slice_patterns, const_fn, const_if_match)]
+#[derive(PartialEq, Debug, Clone)]
+struct N(u8);
+
+#[derive(PartialEq, Debug, Clone)]
+struct Z;
+
+macro_rules! n {
+    ($($e:expr),* $(,)?) => {
+        [$(N($e)),*]
+    }
+}
+
+// This macro has an unused variable so that it can be repeated base on the
+// number of times a repeated variable (`$e` in `z`) occurs.
+macro_rules! zed {
+    ($e:expr) => { Z }
+}
+
+macro_rules! z {
+    ($($e:expr),* $(,)?) => {
+        [$(zed!($e)),*]
+    }
+}
+
+// Compare constant evaluation and runtime evaluation of a given expression.
+macro_rules! compare_evaluation_inner {
+    ($e:expr, $t:ty $(,)?) => {{
+        const CONST_EVAL: $t = $e;
+        const fn const_eval() -> $t { $e }
+        static CONST_EVAL2: $t = const_eval();
+        let runtime_eval = $e;
+        assert_eq!(CONST_EVAL, runtime_eval);
+        assert_eq!(CONST_EVAL2, runtime_eval);
+    }}
+}
+
+// Compare the result of matching `$e` against `$p` using both `if let` and
+// `match`.
+macro_rules! compare_evaluation {
+    ($p:pat, $e:expr, $matches:expr, $t:ty $(,)?) => {{
+        compare_evaluation_inner!(if let $p = $e as &[_] { $matches } else { None }, $t);
+        compare_evaluation_inner!(match $e as &[_] { $p => $matches, _ => None }, $t);
+    }}
+}
+
+// Repeat `$test`, substituting the given macro variables with the given
+// identifiers.
+//
+// For example:
+//
+// repeat! {
+//     ($name); X; Y:
+//     struct $name;
+// }
+//
+// Expands to:
+//
+// struct X; struct Y;
+//
+// This is used to repeat the tests using both the `N` and `Z`
+// types.
+macro_rules! repeat {
+    (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => {
+        macro_rules! single {
+            ($($dollar $placeholder:ident),*) => { $($test)* }
+        }
+        $(single!($($values),+);)*
+    }
+}
+
+fn main() {
+    repeat! {
+        ($arr $Ty); n, N; z, Z:
+        compare_evaluation!([_, x @ .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static [$Ty]>);
+        compare_evaluation!([x, .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>);
+        compare_evaluation!([_, .., x], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>);
+
+        compare_evaluation!([_, x @ .., _], &$arr!(1, 2), Some(x), Option<&'static [$Ty]>);
+        compare_evaluation!([x, .., _], &$arr!(1, 2), Some(x), Option<&'static $Ty>);
+        compare_evaluation!([_, .., x], &$arr!(1, 2), Some(x), Option<&'static $Ty>);
+
+        compare_evaluation!([_, x @ .., _], &$arr!(1), Some(x), Option<&'static [$Ty]>);
+        compare_evaluation!([x, .., _], &$arr!(1), Some(x), Option<&'static $Ty>);
+        compare_evaluation!([_, .., x], &$arr!(1), Some(x), Option<&'static $Ty>);
+    }
+
+    compare_evaluation!([N(x), .., _], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>);
+    compare_evaluation!([_, .., N(x)], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>);
+
+    compare_evaluation!([N(x), .., _], &n!(1, 2), Some(x), Option<&'static u8>);
+    compare_evaluation!([_, .., N(x)], &n!(1, 2), Some(x), Option<&'static u8>);
+}
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
new file mode 100644
index 00000000000..5444f8a9051
--- /dev/null
+++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
@@ -0,0 +1,97 @@
+// Test that array subslice patterns are correctly handled in const evaluation.
+
+// run-pass
+
+#![feature(slice_patterns)]
+
+#[derive(PartialEq, Debug, Clone)]
+struct N(u8);
+
+#[derive(PartialEq, Debug, Clone)]
+struct Z;
+
+macro_rules! n {
+    ($($e:expr),* $(,)?) => {
+        [$(N($e)),*]
+    }
+}
+
+// This macro has an unused variable so that it can be repeated base on the
+// number of times a repeated variable (`$e` in `z`) occurs.
+macro_rules! zed {
+    ($e:expr) => { Z }
+}
+
+macro_rules! z {
+    ($($e:expr),* $(,)?) => {
+        [$(zed!($e)),*]
+    }
+}
+
+// Compare constant evaluation and runtime evaluation of a given expression.
+macro_rules! compare_evaluation {
+    ($e:expr, $t:ty $(,)?) => {{
+        const CONST_EVAL: $t = $e;
+        const fn const_eval() -> $t { $e }
+        static CONST_EVAL2: $t = const_eval();
+        let runtime_eval = $e;
+        assert_eq!(CONST_EVAL, runtime_eval);
+        assert_eq!(CONST_EVAL2, runtime_eval);
+    }}
+}
+
+// Repeat `$test`, substituting the given macro variables with the given
+// identifiers.
+//
+// For example:
+//
+// repeat! {
+//     ($name); X; Y:
+//     struct $name;
+// }
+//
+// Expands to:
+//
+// struct X; struct Y;
+//
+// This is used to repeat the tests using both the `N` and `Z`
+// types.
+macro_rules! repeat {
+    (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => {
+        macro_rules! single {
+            ($($dollar $placeholder:ident),*) => { $($test)* }
+        }
+        $(single!($($values),+);)*
+    }
+}
+
+fn main() {
+    repeat! {
+        ($arr $Ty); n, N; z, Z:
+        compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]);
+        compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]);
+        compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]);
+
+        compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]);
+        compare_evaluation!(
+            { let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x },
+            &'static [$Ty; 0],
+        );
+        compare_evaluation!(
+            { let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x },
+            &'static [$Ty; 0],
+        );
+
+        compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty);
+        compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty);
+        compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty);
+    }
+
+    compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8);
+    compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8);
+    compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8);
+
+    compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8);
+    compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8);
+    compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8);
+}
diff --git a/src/test/ui/asm/issue-51431.rs b/src/test/ui/asm/issue-51431.rs
index d29c31fafc2..4cef42d17d6 100644
--- a/src/test/ui/asm/issue-51431.rs
+++ b/src/test/ui/asm/issue-51431.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-emscripten no asm! support
 
 #![feature(asm)]
diff --git a/src/test/ui/asm/issue-51431.stderr b/src/test/ui/asm/issue-51431.stderr
index f78d1831973..a024f3311f1 100644
--- a/src/test/ui/asm/issue-51431.stderr
+++ b/src/test/ui/asm/issue-51431.stderr
@@ -1,5 +1,5 @@
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/issue-51431.rs:7:32
+  --> $DIR/issue-51431.rs:8:32
    |
 LL |         asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)}
    |                                ^^^^
diff --git a/src/test/ui/auxiliary/stability-cfg2.rs b/src/test/ui/auxiliary/stability-cfg2.rs
index 8a2899584b9..c995038e5a8 100644
--- a/src/test/ui/auxiliary/stability-cfg2.rs
+++ b/src/test/ui/auxiliary/stability-cfg2.rs
@@ -1,5 +1,5 @@
 // compile-flags:--cfg foo
 
-#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "0"))]
+#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))]
 #![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
 #![feature(staged_api)]
diff --git a/src/test/ui/bad/bad-intrinsic-monomorphization.rs b/src/test/ui/bad/bad-intrinsic-monomorphization.rs
index a29723f34b4..f36a5f1acc1 100644
--- a/src/test/ui/bad/bad-intrinsic-monomorphization.rs
+++ b/src/test/ui/bad/bad-intrinsic-monomorphization.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(repr_simd, platform_intrinsics, core_intrinsics)]
 #![allow(warnings)]
 #![crate_type = "rlib"]
diff --git a/src/test/ui/bad/bad-intrinsic-monomorphization.stderr b/src/test/ui/bad/bad-intrinsic-monomorphization.stderr
index dee33f574d8..c070f018181 100644
--- a/src/test/ui/bad/bad-intrinsic-monomorphization.stderr
+++ b/src/test/ui/bad/bad-intrinsic-monomorphization.stderr
@@ -1,17 +1,17 @@
 error[E0511]: invalid monomorphization of `cttz` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/bad-intrinsic-monomorphization.rs:18:5
+  --> $DIR/bad-intrinsic-monomorphization.rs:20:5
    |
 LL |     intrinsics::cttz(v)
    |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `fadd_fast` intrinsic: expected basic float type, found `Foo`
-  --> $DIR/bad-intrinsic-monomorphization.rs:23:5
+  --> $DIR/bad-intrinsic-monomorphization.rs:25:5
    |
 LL |     intrinsics::fadd_fast(a, b)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
-  --> $DIR/bad-intrinsic-monomorphization.rs:28:5
+  --> $DIR/bad-intrinsic-monomorphization.rs:30:5
    |
 LL |     simd_add(a, b)
    |     ^^^^^^^^^^^^^^
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs
new file mode 100644
index 00000000000..f25fd7f66b3
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs
@@ -0,0 +1,22 @@
+#![feature(raw_ref_op)]
+
+fn address_of_shared() {
+    let mut x = 0;
+    let y = &x;
+
+    let q = &raw mut x;                 //~ ERROR cannot borrow
+
+    drop(y);
+}
+
+fn address_of_mutably_borrowed() {
+    let mut x = 0;
+    let y = &mut x;
+
+    let p = &raw const x;               //~ ERROR cannot borrow
+    let q = &raw mut x;                 //~ ERROR cannot borrow
+
+    drop(y);
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr
new file mode 100644
index 00000000000..ff461b748be
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrow-raw-address-of-borrowed.rs:7:13
+   |
+LL |     let y = &x;
+   |             -- immutable borrow occurs here
+LL | 
+LL |     let q = &raw mut x;
+   |             ^^^^^^^^^^ mutable borrow occurs here
+LL | 
+LL |     drop(y);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrow-raw-address-of-borrowed.rs:16:13
+   |
+LL |     let y = &mut x;
+   |             ------ mutable borrow occurs here
+LL | 
+LL |     let p = &raw const x;
+   |             ^^^^^^^^^^^^ immutable borrow occurs here
+...
+LL |     drop(y);
+   |          - mutable borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrow-raw-address-of-borrowed.rs:17:13
+   |
+LL |     let y = &mut x;
+   |             ------ first mutable borrow occurs here
+...
+LL |     let q = &raw mut x;
+   |             ^^^^^^^^^^ second mutable borrow occurs here
+LL | 
+LL |     drop(y);
+   |          - first borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs
new file mode 100644
index 00000000000..e381384fe65
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(raw_ref_op)]
+
+fn raw_reborrow() {
+    let x = &0;
+    let y = &mut 0;
+
+    let p = &raw const *x;
+    let r = &raw const *y;
+    let s = &raw mut *y;
+}
+
+unsafe fn raw_reborrow_of_raw() {
+    let x = &0 as *const i32;
+    let y = &mut 0 as *mut i32;
+
+    let p = &raw const *x;
+    let r = &raw const *y;
+    let s = &raw mut *y;
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs
new file mode 100644
index 00000000000..712873528b5
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs
@@ -0,0 +1,17 @@
+// Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`.
+
+#![feature(raw_ref_op)]
+
+fn raw_reborrow() {
+    let x = &0;
+
+    let q = &raw mut *x;                //~ ERROR cannot borrow
+}
+
+unsafe fn raw_reborrow_of_raw() {
+    let x = &0 as *const i32;
+
+    let q = &raw mut *x;                //~ ERROR cannot borrow
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr
new file mode 100644
index 00000000000..31af38507c7
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13
+   |
+LL |     let x = &0;
+   |             -- help: consider changing this to be a mutable reference: `&mut 0`
+LL | 
+LL |     let q = &raw mut *x;
+   |             ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer
+  --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13
+   |
+LL |     let x = &0 as *const i32;
+   |             -- help: consider changing this to be a mutable pointer: `&mut 0`
+LL | 
+LL |     let q = &raw mut *x;
+   |             ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs
new file mode 100644
index 00000000000..e1cf2dc5386
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs
@@ -0,0 +1,44 @@
+// check-pass
+
+#![feature(raw_ref_op)]
+
+fn mutable_address_of() {
+    let mut x = 0;
+    let y = &raw mut x;
+}
+
+fn mutable_address_of_closure() {
+    let mut x = 0;
+    let mut f = || {
+        let y = &raw mut x;
+    };
+    f();
+}
+
+fn const_address_of_closure() {
+    let x = 0;
+    let f = || {
+        let y = &raw const x;
+    };
+    f();
+}
+
+fn make_fn<F: Fn()>(f: F) -> F { f }
+
+fn const_address_of_fn_closure() {
+    let x = 0;
+    let f = make_fn(|| {
+        let y = &raw const x;
+    });
+    f();
+}
+
+fn const_address_of_fn_closure_move() {
+    let x = 0;
+    let f = make_fn(move || {
+        let y = &raw const x;
+    });
+    f();
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs
new file mode 100644
index 00000000000..320c54b806a
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs
@@ -0,0 +1,42 @@
+#![feature(raw_ref_op)]
+
+fn mutable_address_of() {
+    let x = 0;
+    let y = &raw mut x;                 //~ ERROR cannot borrow
+}
+
+fn mutable_address_of_closure() {
+    let x = 0;
+    let mut f = || {
+        let y = &raw mut x;             //~ ERROR cannot borrow
+    };
+    f();
+}
+
+fn mutable_address_of_imm_closure() {
+    let mut x = 0;
+    let f = || {
+        let y = &raw mut x;
+    };
+    f();                                //~ ERROR cannot borrow
+}
+
+fn make_fn<F: Fn()>(f: F) -> F { f }
+
+fn mutable_address_of_fn_closure() {
+    let mut x = 0;
+    let f = make_fn(|| {
+        let y = &raw mut x;             //~ ERROR cannot borrow
+    });
+    f();
+}
+
+fn mutable_address_of_fn_closure_move() {
+    let mut x = 0;
+    let f = make_fn(move || {
+        let y = &raw mut x;             //~ ERROR cannot borrow
+    });
+    f();
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr
new file mode 100644
index 00000000000..cf01c362d50
--- /dev/null
+++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr
@@ -0,0 +1,59 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrow-raw-address-of-mutability.rs:5:13
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     let y = &raw mut x;
+   |             ^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrow-raw-address-of-mutability.rs:11:17
+   |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     let mut f = || {
+LL |         let y = &raw mut x;
+   |                 ^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
+  --> $DIR/borrow-raw-address-of-mutability.rs:21:5
+   |
+LL |     let f = || {
+   |         - help: consider changing this to be mutable: `mut f`
+...
+LL |     f();
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-raw-address-of-mutability.rs:29:17
+   |
+LL |         let y = &raw mut x;
+   |                 ^^^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-raw-address-of-mutability.rs:28:21
+   |
+LL |       let f = make_fn(|| {
+   |  _____________________^
+LL | |         let y = &raw mut x;
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/borrow-raw-address-of-mutability.rs:37:17
+   |
+LL |         let y = &raw mut x;
+   |                 ^^^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/borrow-raw-address-of-mutability.rs:36:21
+   |
+LL |       let f = make_fn(move || {
+   |  _____________________^
+LL | |         let y = &raw mut x;
+LL | |     });
+   | |_____^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
new file mode 100644
index 00000000000..a70ccb7aa4b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
@@ -0,0 +1,118 @@
+// Check that closure captures for slice patterns are inferred correctly
+
+#![feature(slice_patterns)]
+#![allow(unused_variables)]
+
+// run-pass
+
+fn arr_by_ref(x: [String; 3]) {
+    let r = &x;
+    let f = || {
+        let [ref y, ref z @ ..] = x;
+    };
+    f();
+    f();
+    // Ensure `x` was borrowed
+    drop(r);
+    // Ensure that `x` wasn't moved from.
+    drop(x);
+}
+
+fn arr_by_mut(mut x: [String; 3]) {
+    let mut f = || {
+        let [ref mut y, ref mut z @ ..] = x;
+    };
+    f();
+    f();
+    drop(x);
+}
+
+fn arr_by_move(x: [String; 3]) {
+    let f = || {
+        let [y, z @ ..] = x;
+    };
+    f();
+}
+
+fn arr_ref_by_ref(x: &[String; 3]) {
+    let r = &x;
+    let f = || {
+        let [ref y, ref z @ ..] = *x;
+    };
+    let g = || {
+        let [y, z @ ..] = x;
+    };
+    f();
+    g();
+    f();
+    g();
+    drop(r);
+    drop(x);
+}
+
+fn arr_ref_by_mut(x: &mut [String; 3]) {
+    let mut f = || {
+        let [ref mut y, ref mut z @ ..] = *x;
+    };
+    f();
+    f();
+    let mut g = || {
+        let [y, z @ ..] = x;
+        // Ensure binding mode was chosen correctly:
+        std::mem::swap(y, &mut z[0]);
+    };
+    g();
+    g();
+    drop(x);
+}
+
+fn arr_box_by_move(x: Box<[String; 3]>) {
+    let f = || {
+        let [y, z @ ..] = *x;
+    };
+    f();
+}
+
+fn slice_by_ref(x: &[String]) {
+    let r = &x;
+    let f = || {
+        if let [ref y, ref z @ ..] = *x {}
+    };
+    let g = || {
+        if let [y, z @ ..] = x {}
+    };
+    f();
+    g();
+    f();
+    g();
+    drop(r);
+    drop(x);
+}
+
+fn slice_by_mut(x: &mut [String]) {
+    let mut f = || {
+        if let [ref mut y, ref mut z @ ..] = *x {}
+    };
+    f();
+    f();
+    let mut g = || {
+        if let [y, z @ ..] = x {
+            // Ensure binding mode was chosen correctly:
+            std::mem::swap(y, &mut z[0]);
+        }
+    };
+    g();
+    g();
+    drop(x);
+}
+
+fn main() {
+    arr_by_ref(Default::default());
+    arr_by_mut(Default::default());
+    arr_by_move(Default::default());
+    arr_ref_by_ref(&Default::default());
+    arr_ref_by_mut(&mut Default::default());
+    arr_box_by_move(Default::default());
+    slice_by_ref(&<[_; 3]>::default());
+    slice_by_mut(&mut <[_; 3]>::default());
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
new file mode 100644
index 00000000000..984eb8804b7
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
@@ -0,0 +1,84 @@
+// Check that closure captures for slice patterns are inferred correctly
+
+#![feature(slice_patterns)]
+
+fn arr_by_ref(mut x: [String; 3]) {
+    let f = || {
+        let [ref y, ref z @ ..] = x;
+    };
+    let r = &mut x;
+    //~^ ERROR cannot borrow
+    f();
+}
+
+fn arr_by_mut(mut x: [String; 3]) {
+    let mut f = || {
+        let [ref mut y, ref mut z @ ..] = x;
+    };
+    let r = &x;
+    //~^ ERROR cannot borrow
+    f();
+}
+
+fn arr_by_move(x: [String; 3]) {
+    let f = || {
+        let [y, z @ ..] = x;
+    };
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn arr_ref_by_ref(x: &mut [String; 3]) {
+    let f = || {
+        let [ref y, ref z @ ..] = *x;
+    };
+    let r = &mut *x;
+    //~^ ERROR cannot borrow
+    f();
+}
+
+fn arr_ref_by_uniq(x: &mut [String; 3]) {
+    let mut f = || {
+        let [ref mut y, ref mut z @ ..] = *x;
+    };
+    let r = &x;
+    //~^ ERROR cannot borrow
+    f();
+}
+
+fn arr_box_by_move(x: Box<[String; 3]>) {
+    let f = || {
+        let [y, z @ ..] = *x;
+    };
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn slice_by_ref(x: &mut [String]) {
+    let f = || {
+        if let [ref y, ref z @ ..] = *x {}
+    };
+    let r = &mut *x;
+    //~^ ERROR cannot borrow
+    f();
+}
+
+fn slice_by_uniq(x: &mut [String]) {
+    let mut f = || {
+        if let [ref mut y, ref mut z @ ..] = *x {}
+    };
+    let r = &x;
+    //~^ ERROR cannot borrow
+    f();
+}
+
+fn main() {
+    arr_by_ref(Default::default());
+    arr_by_mut(Default::default());
+    arr_by_move(Default::default());
+    arr_ref_by_ref(&mut Default::default());
+    arr_ref_by_uniq(&mut Default::default());
+    arr_box_by_move(Default::default());
+    slice_by_ref(&mut <[_; 3]>::default());
+    slice_by_uniq(&mut <[_; 3]>::default());
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
new file mode 100644
index 00000000000..c5b27f5f8b4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
@@ -0,0 +1,114 @@
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-slice-patterns.rs:9:13
+   |
+LL |     let f = || {
+   |             -- immutable borrow occurs here
+LL |         let [ref y, ref z @ ..] = x;
+   |                                   - first borrow occurs due to use of `x` in closure
+LL |     };
+LL |     let r = &mut x;
+   |             ^^^^^^ mutable borrow occurs here
+LL |
+LL |     f();
+   |     - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-closures-slice-patterns.rs:18:13
+   |
+LL |     let mut f = || {
+   |                 -- mutable borrow occurs here
+LL |         let [ref mut y, ref mut z @ ..] = x;
+   |                                           - first borrow occurs due to use of `x` in closure
+LL |     };
+LL |     let r = &x;
+   |             ^^ immutable borrow occurs here
+LL |
+LL |     f();
+   |     - mutable borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/borrowck-closures-slice-patterns.rs:27:5
+   |
+LL | fn arr_by_move(x: [String; 3]) {
+   |                - move occurs because `x` has type `[std::string::String; 3]`, which does not implement the `Copy` trait
+LL |     let f = || {
+   |             -- value moved into closure here
+LL |         let [y, z @ ..] = x;
+   |                           - variable moved due to use in closure
+LL |     };
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-slice-patterns.rs:35:13
+   |
+LL |     let f = || {
+   |             -- immutable borrow occurs here
+LL |         let [ref y, ref z @ ..] = *x;
+   |                                    - first borrow occurs due to use of `x` in closure
+LL |     };
+LL |     let r = &mut *x;
+   |             ^^^^^^^ mutable borrow occurs here
+LL |
+LL |     f();
+   |     - immutable borrow later used here
+
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/borrowck-closures-slice-patterns.rs:44:13
+   |
+LL |     let mut f = || {
+   |                 -- closure construction occurs here
+LL |         let [ref mut y, ref mut z @ ..] = *x;
+   |                                            - first borrow occurs due to use of `x` in closure
+LL |     };
+LL |     let r = &x;
+   |             ^^ second borrow occurs here
+LL |
+LL |     f();
+   |     - first borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/borrowck-closures-slice-patterns.rs:53:5
+   |
+LL | fn arr_box_by_move(x: Box<[String; 3]>) {
+   |                    - move occurs because `x` has type `std::boxed::Box<[std::string::String; 3]>`, which does not implement the `Copy` trait
+LL |     let f = || {
+   |             -- value moved into closure here
+LL |         let [y, z @ ..] = *x;
+   |                            - variable moved due to use in closure
+LL |     };
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-closures-slice-patterns.rs:61:13
+   |
+LL |     let f = || {
+   |             -- immutable borrow occurs here
+LL |         if let [ref y, ref z @ ..] = *x {}
+   |                                       - first borrow occurs due to use of `x` in closure
+LL |     };
+LL |     let r = &mut *x;
+   |             ^^^^^^^ mutable borrow occurs here
+LL |
+LL |     f();
+   |     - immutable borrow later used here
+
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/borrowck-closures-slice-patterns.rs:70:13
+   |
+LL |     let mut f = || {
+   |                 -- closure construction occurs here
+LL |         if let [ref mut y, ref mut z @ ..] = *x {}
+   |                                               - first borrow occurs due to use of `x` in closure
+LL |     };
+LL |     let r = &x;
+   |             ^^ second borrow occurs here
+LL |
+LL |     f();
+   |     - first borrow later used here
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0382, E0501, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/move-from-union-field-issue-66500.rs b/src/test/ui/borrowck/move-from-union-field-issue-66500.rs
new file mode 100644
index 00000000000..8fbf120fc1c
--- /dev/null
+++ b/src/test/ui/borrowck/move-from-union-field-issue-66500.rs
@@ -0,0 +1,30 @@
+// Moving from a reference/raw pointer should be an error, even when they're
+// the field of a union.
+
+#![feature(untagged_unions)]
+
+union Pointers {
+    a: &'static String,
+    b: &'static mut String,
+    c: *const String,
+    d: *mut String,
+}
+
+unsafe fn move_ref(u: Pointers) -> String {
+    *u.a
+    //~^ ERROR cannot move out of `*u.a`
+}
+unsafe fn move_ref_mut(u: Pointers) -> String {
+    *u.b
+    //~^ ERROR cannot move out of `*u.b`
+}
+unsafe fn move_ptr(u: Pointers) -> String {
+    *u.c
+    //~^ ERROR cannot move out of `*u.c`
+}
+unsafe fn move_ptr_mut(u: Pointers) -> String {
+    *u.d
+    //~^ ERROR cannot move out of `*u.d`
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr b/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr
new file mode 100644
index 00000000000..a7cb1c9e221
--- /dev/null
+++ b/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr
@@ -0,0 +1,27 @@
+error[E0507]: cannot move out of `*u.a` which is behind a shared reference
+  --> $DIR/move-from-union-field-issue-66500.rs:14:5
+   |
+LL |     *u.a
+   |     ^^^^ move occurs because `*u.a` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `*u.b` which is behind a mutable reference
+  --> $DIR/move-from-union-field-issue-66500.rs:18:5
+   |
+LL |     *u.b
+   |     ^^^^ move occurs because `*u.b` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `*u.c` which is behind a raw pointer
+  --> $DIR/move-from-union-field-issue-66500.rs:22:5
+   |
+LL |     *u.c
+   |     ^^^^ move occurs because `*u.c` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
+  --> $DIR/move-from-union-field-issue-66500.rs:26:5
+   |
+LL |     *u.d
+   |     ^^^^ move occurs because `*u.d` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
index cb6060525fc..7af38c88f43 100644
--- a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
@@ -1,8 +1,8 @@
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-no-fixed-args.rs:2:11
+  --> $DIR/variadic-ffi-no-fixed-args.rs:2:12
    |
 LL |     fn foo(...);
-   |           ^
+   |            ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs
index 8130f4dedc9..1aed218aeb4 100644
--- a/src/test/ui/cast/cast-as-bool.rs
+++ b/src/test/ui/cast/cast-as-bool.rs
@@ -5,5 +5,5 @@ fn main() {
     let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
                              //~| HELP compare with zero instead
                              //~| SUGGESTION (1 + 2) != 0
-    let v = "hello" as bool; //~ ERROR cannot cast as `bool`
+    let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid
 }
diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr
index 30f8459c2e1..15d94ab69d8 100644
--- a/src/test/ui/cast/cast-as-bool.stderr
+++ b/src/test/ui/cast/cast-as-bool.stderr
@@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool`
 LL |     let t = (1 + 2) as bool;
    |             ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
 
-error[E0054]: cannot cast as `bool`
+error[E0606]: casting `&'static str` as `bool` is invalid
   --> $DIR/cast-as-bool.rs:8:13
    |
 LL |     let v = "hello" as bool;
-   |             ^^^^^^^^^^^^^^^ unsupported cast
+   |             ^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0054`.
+Some errors have detailed explanations: E0054, E0606.
+For more information about an error, try `rustc --explain E0054`.
diff --git a/src/test/ui/cdylib-deps-must-be-static.rs b/src/test/ui/cdylib-deps-must-be-static.rs
index 8530c9e24b2..abf954d8fb2 100644
--- a/src/test/ui/cdylib-deps-must-be-static.rs
+++ b/src/test/ui/cdylib-deps-must-be-static.rs
@@ -1,3 +1,4 @@
+// build-fail
 // error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
 // aux-build:cdylib-dep.rs
 // ignore-musl
diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs
index 161715685b5..e2984e3ca97 100644
--- a/src/test/ui/commandline-argfile-badutf8.rs
+++ b/src/test/ui/commandline-argfile-badutf8.rs
@@ -1,6 +1,5 @@
 // Check to see if we can get parameters from an @argsfile file
 //
-// build-fail
 // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
 
 #[cfg(not(cmdline_set))]
diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs
index a29b4ab062d..020c3ff3c7e 100644
--- a/src/test/ui/commandline-argfile-missing.rs
+++ b/src/test/ui/commandline-argfile-missing.rs
@@ -1,7 +1,6 @@
 // Check to see if we can get parameters from an @argsfile file
 //
 // ignore-tidy-linelength
-// build-fail
 // normalize-stderr-test: "os error \d+" -> "os error $$ERR"
 // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
 // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs
index 8397d204f35..7fa059583f5 100644
--- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs
+++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs
@@ -6,6 +6,7 @@ pub fn no_debug() {
 pub fn no_hash() {
     use std::collections::HashSet;
     let mut set = HashSet::new();
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
     set.insert([0_usize; 33]);
     //~^ ERROR arrays only have std trait implementations for lengths 0..=32
 }
diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr
index 594a0d4b5d8..d885c98dcb2 100644
--- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr
+++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr
@@ -8,15 +8,24 @@ LL |     println!("{:?}", [0_usize; 33]);
    = note: required by `std::fmt::Debug::fmt`
 
 error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/core-traits-no-impls-length-33.rs:9:16
+  --> $DIR/core-traits-no-impls-length-33.rs:10:16
    |
 LL |     set.insert([0_usize; 33]);
    |                ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
    |
    = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
 
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/core-traits-no-impls-length-33.rs:8:19
+   |
+LL |     let mut set = HashSet::new();
+   |                   ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
+   = note: required by `std::collections::HashSet::<T>::new`
+
 error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
-  --> $DIR/core-traits-no-impls-length-33.rs:14:19
+  --> $DIR/core-traits-no-impls-length-33.rs:15:19
    |
 LL |     [0_usize; 33] == [1_usize; 33]
    |     ------------- ^^ ------------- [usize; 33]
@@ -26,7 +35,7 @@ LL |     [0_usize; 33] == [1_usize; 33]
    = note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]`
 
 error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
-  --> $DIR/core-traits-no-impls-length-33.rs:19:19
+  --> $DIR/core-traits-no-impls-length-33.rs:20:19
    |
 LL |     [0_usize; 33] < [1_usize; 33]
    |     ------------- ^ ------------- [usize; 33]
@@ -36,7 +45,7 @@ LL |     [0_usize; 33] < [1_usize; 33]
    = note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]`
 
 error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
-  --> $DIR/core-traits-no-impls-length-33.rs:24:14
+  --> $DIR/core-traits-no-impls-length-33.rs:25:14
    |
 LL |     for _ in &[0_usize; 33] {
    |              ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
@@ -48,7 +57,7 @@ LL |     for _ in &[0_usize; 33] {
              <&'a mut [T] as std::iter::IntoIterator>
    = note: required by `std::iter::IntoIterator::into_iter`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0277, E0369.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs
index 492182921ba..1de6bafd293 100644
--- a/src/test/ui/consts/array-literal-index-oob.rs
+++ b/src/test/ui/consts/array-literal-index-oob.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 fn main() {
     &{[1, 2, 3][4]};
     //~^ ERROR index out of bounds
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index f4d4e6f969b..f3ef16659dd 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -1,5 +1,5 @@
 error: index out of bounds: the len is 3 but the index is 4
-  --> $DIR/array-literal-index-oob.rs:2:7
+  --> $DIR/array-literal-index-oob.rs:4:7
    |
 LL |     &{[1, 2, 3][4]};
    |       ^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     &{[1, 2, 3][4]};
    = note: `#[deny(const_err)]` on by default
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/array-literal-index-oob.rs:2:7
+  --> $DIR/array-literal-index-oob.rs:4:7
    |
 LL |     &{[1, 2, 3][4]};
    |     --^^^^^^^^^^^^-
diff --git a/src/test/ui/consts/assoc_const_generic_impl.rs b/src/test/ui/consts/assoc_const_generic_impl.rs
index 62702a8ec5c..83f334dca9e 100644
--- a/src/test/ui/consts/assoc_const_generic_impl.rs
+++ b/src/test/ui/consts/assoc_const_generic_impl.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![warn(const_err)]
 
 trait ZeroSized: Sized {
diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr
index a114d5c6ccd..4b13f52e762 100644
--- a/src/test/ui/consts/assoc_const_generic_impl.stderr
+++ b/src/test/ui/consts/assoc_const_generic_impl.stderr
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/assoc_const_generic_impl.rs:9:34
+  --> $DIR/assoc_const_generic_impl.rs:11:34
    |
 LL |     const I_AM_ZERO_SIZED: ()  = [()][std::mem::size_of::<Self>()];
    |     -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -7,13 +7,13 @@ LL |     const I_AM_ZERO_SIZED: ()  = [()][std::mem::size_of::<Self>()];
    |                                  index out of bounds: the len is 1 but the index is 4
    |
 note: lint level defined here
-  --> $DIR/assoc_const_generic_impl.rs:1:9
+  --> $DIR/assoc_const_generic_impl.rs:3:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 error: erroneous constant encountered
-  --> $DIR/assoc_const_generic_impl.rs:11:18
+  --> $DIR/assoc_const_generic_impl.rs:13:18
    |
 LL |         let () = Self::I_AM_ZERO_SIZED;
    |                  ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-address-of-interior-mut.rs b/src/test/ui/consts/const-address-of-interior-mut.rs
new file mode 100644
index 00000000000..60c7c31daca
--- /dev/null
+++ b/src/test/ui/consts/const-address-of-interior-mut.rs
@@ -0,0 +1,16 @@
+#![feature(raw_ref_op)]
+
+use std::cell::Cell;
+
+const A: () = { let x = Cell::new(2); &raw const x; };      //~ ERROR interior mutability
+
+static B: () = { let x = Cell::new(2); &raw const x; };     //~ ERROR interior mutability
+
+static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability
+
+const fn foo() {
+    let x = Cell::new(0);
+    let y = &raw const x;                                   //~ ERROR interior mutability
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr
new file mode 100644
index 00000000000..f15174c33b3
--- /dev/null
+++ b/src/test/ui/consts/const-address-of-interior-mut.stderr
@@ -0,0 +1,27 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/const-address-of-interior-mut.rs:5:39
+   |
+LL | const A: () = { let x = Cell::new(2); &raw const x; };
+   |                                       ^^^^^^^^^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/const-address-of-interior-mut.rs:7:40
+   |
+LL | static B: () = { let x = Cell::new(2); &raw const x; };
+   |                                        ^^^^^^^^^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/const-address-of-interior-mut.rs:9:44
+   |
+LL | static mut C: () = { let x = Cell::new(2); &raw const x; };
+   |                                            ^^^^^^^^^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/const-address-of-interior-mut.rs:13:13
+   |
+LL |     let y = &raw const x;
+   |             ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/const-address-of-mut.rs b/src/test/ui/consts/const-address-of-mut.rs
new file mode 100644
index 00000000000..fe9188cb490
--- /dev/null
+++ b/src/test/ui/consts/const-address-of-mut.rs
@@ -0,0 +1,14 @@
+#![feature(raw_ref_op)]
+
+const A: () = { let mut x = 2; &raw mut x; };           //~ ERROR `&raw mut` is not allowed
+
+static B: () = { let mut x = 2; &raw mut x; };          //~ ERROR `&raw mut` is not allowed
+
+static mut C: () = { let mut x = 2; &raw mut x; };      //~ ERROR `&raw mut` is not allowed
+
+const fn foo() {
+    let mut x = 0;
+    let y = &raw mut x;                                 //~ ERROR `&raw mut` is not allowed
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr
new file mode 100644
index 00000000000..15f2296c42c
--- /dev/null
+++ b/src/test/ui/consts/const-address-of-mut.stderr
@@ -0,0 +1,39 @@
+error[E0658]: `&raw mut` is not allowed in constants
+  --> $DIR/const-address-of-mut.rs:3:32
+   |
+LL | const A: () = { let mut x = 2; &raw mut x; };
+   |                                ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: `&raw mut` is not allowed in statics
+  --> $DIR/const-address-of-mut.rs:5:33
+   |
+LL | static B: () = { let mut x = 2; &raw mut x; };
+   |                                 ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: `&raw mut` is not allowed in statics
+  --> $DIR/const-address-of-mut.rs:7:37
+   |
+LL | static mut C: () = { let mut x = 2; &raw mut x; };
+   |                                     ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: `&raw mut` is not allowed in constant functions
+  --> $DIR/const-address-of-mut.rs:11:13
+   |
+LL |     let y = &raw mut x;
+   |             ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-address-of.rs b/src/test/ui/consts/const-address-of.rs
new file mode 100644
index 00000000000..ba162f2a2ba
--- /dev/null
+++ b/src/test/ui/consts/const-address-of.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(raw_ref_op)]
+
+const A: *const i32 = &raw const *&2;
+static B: () = { &raw const *&2; };
+static mut C: *const i32 = &raw const *&2;
+const D: () = { let x = 2; &raw const x; };
+static E: () = { let x = 2; &raw const x; };
+static mut F: () = { let x = 2; &raw const x; };
+
+const fn const_ptr() {
+    let x = 0;
+    let ptr = &raw const x;
+    let r = &x;
+    let ptr2 = &raw const *r;
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-err.rs b/src/test/ui/consts/const-err.rs
index 7dfcda69058..b204f705a96 100644
--- a/src/test/ui/consts/const-err.rs
+++ b/src/test/ui/consts/const-err.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -Zforce-overflow-checks=on
 
 #![allow(exceeding_bitshifts)]
diff --git a/src/test/ui/consts/const-err.stderr b/src/test/ui/consts/const-err.stderr
index 429e2ae7600..495b221d7d7 100644
--- a/src/test/ui/consts/const-err.stderr
+++ b/src/test/ui/consts/const-err.stderr
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/const-err.rs:10:17
+  --> $DIR/const-err.rs:11:17
    |
 LL | const FOO: u8 = [5u8][1];
    | ----------------^^^^^^^^-
@@ -7,19 +7,19 @@ LL | const FOO: u8 = [5u8][1];
    |                 index out of bounds: the len is 1 but the index is 1
    |
 note: lint level defined here
-  --> $DIR/const-err.rs:4:9
+  --> $DIR/const-err.rs:5:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 error[E0080]: erroneous constant used
-  --> $DIR/const-err.rs:14:16
+  --> $DIR/const-err.rs:15:16
    |
 LL |     black_box((FOO, FOO));
    |                ^^^ referenced constant has errors
 
 error[E0080]: erroneous constant used
-  --> $DIR/const-err.rs:14:21
+  --> $DIR/const-err.rs:15:21
    |
 LL |     black_box((FOO, FOO));
    |                     ^^^ referenced constant has errors
diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs
index ecbcc2a4b49..351dfd2e0f5 100644
--- a/src/test/ui/consts/const-err2.rs
+++ b/src/test/ui/consts/const-err2.rs
@@ -1,6 +1,8 @@
 // needed because negating int::MIN will behave differently between
 // optimized compilation and unoptimized compilation and thus would
 // lead to different lints being emitted
+
+// build-fail
 // compile-flags: -O
 
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr
index 1d84d44dc27..2ca1019d494 100644
--- a/src/test/ui/consts/const-err2.stderr
+++ b/src/test/ui/consts/const-err2.stderr
@@ -1,35 +1,35 @@
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:16:13
+  --> $DIR/const-err2.rs:18:13
    |
 LL |     let a = -std::i8::MIN;
    |             ^^^^^^^^^^^^^ attempt to negate with overflow
    |
 note: lint level defined here
-  --> $DIR/const-err2.rs:9:9
+  --> $DIR/const-err2.rs:11:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:18:13
+  --> $DIR/const-err2.rs:20:13
    |
 LL |     let b = 200u8 + 200u8 + 200u8;
    |             ^^^^^^^^^^^^^ attempt to add with overflow
 
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:20:13
+  --> $DIR/const-err2.rs:22:13
    |
 LL |     let c = 200u8 * 4;
    |             ^^^^^^^^^ attempt to multiply with overflow
 
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:22:13
+  --> $DIR/const-err2.rs:24:13
    |
 LL |     let d = 42u8 - (42u8 + 1);
    |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/const-err2.rs:24:14
+  --> $DIR/const-err2.rs:26:14
    |
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs
index a9cf04cda7a..ab3823efd30 100644
--- a/src/test/ui/consts/const-err3.rs
+++ b/src/test/ui/consts/const-err3.rs
@@ -1,6 +1,8 @@
 // needed because negating int::MIN will behave differently between
 // optimized compilation and unoptimized compilation and thus would
 // lead to different lints being emitted
+
+// build-fail
 // compile-flags: -C overflow-checks=on -O
 
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr
index 0602707be70..c374637bec2 100644
--- a/src/test/ui/consts/const-err3.stderr
+++ b/src/test/ui/consts/const-err3.stderr
@@ -1,35 +1,35 @@
 error: attempt to negate with overflow
-  --> $DIR/const-err3.rs:16:13
+  --> $DIR/const-err3.rs:18:13
    |
 LL |     let a = -std::i8::MIN;
    |             ^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/const-err3.rs:9:9
+  --> $DIR/const-err3.rs:11:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: attempt to add with overflow
-  --> $DIR/const-err3.rs:18:13
+  --> $DIR/const-err3.rs:20:13
    |
 LL |     let b = 200u8 + 200u8 + 200u8;
    |             ^^^^^^^^^^^^^
 
 error: attempt to multiply with overflow
-  --> $DIR/const-err3.rs:20:13
+  --> $DIR/const-err3.rs:22:13
    |
 LL |     let c = 200u8 * 4;
    |             ^^^^^^^^^
 
 error: attempt to subtract with overflow
-  --> $DIR/const-err3.rs:22:13
+  --> $DIR/const-err3.rs:24:13
    |
 LL |     let d = 42u8 - (42u8 + 1);
    |             ^^^^^^^^^^^^^^^^^
 
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/const-err3.rs:24:14
+  --> $DIR/const-err3.rs:26:14
    |
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/auxiliary/stability.rs b/src/test/ui/consts/const-eval/auxiliary/stability.rs
index 830db55207f..70531114f21 100644
--- a/src/test/ui/consts/const-eval/auxiliary/stability.rs
+++ b/src/test/ui/consts/const-eval/auxiliary/stability.rs
@@ -7,5 +7,5 @@
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
 pub const fn foo() -> u32 { 42 }
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs
index 12e51c24605..96f67c92a5e 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![warn(const_err)]
 
 const X: u32 = 5;
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
index 7f94d849c00..ec18f8f011d 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/conditional_array_execution.rs:5:19
+  --> $DIR/conditional_array_execution.rs:7:19
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    | ------------------^^^^^---------------------------
@@ -7,13 +7,13 @@ LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   attempt to subtract with overflow
    |
 note: lint level defined here
-  --> $DIR/conditional_array_execution.rs:1:9
+  --> $DIR/conditional_array_execution.rs:3:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/conditional_array_execution.rs:9:20
+  --> $DIR/conditional_array_execution.rs:11:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
index b300119509c..a5f04d088b6 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
@@ -1,4 +1,6 @@
+// build-fail
 // compile-flags: -Zunleash-the-miri-inside-of-you
+
 #![feature(const_fn)]
 #![allow(const_err)]
 
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
index 9d74d3b0bf2..19f37fa0079 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
@@ -1,11 +1,11 @@
 warning: skipping const checks
-  --> $DIR/const_fn_ptr_fail2.rs:9:5
+  --> $DIR/const_fn_ptr_fail2.rs:11:5
    |
 LL |     x(y)
    |     ^^^^
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/const_fn_ptr_fail2.rs:16:5
+  --> $DIR/const_fn_ptr_fail2.rs:18:5
    |
 LL |     assert_eq!(Y, 4);
    |     ^^^^^^^^^^^-^^^^^
@@ -15,7 +15,7 @@ LL |     assert_eq!(Y, 4);
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/const_fn_ptr_fail2.rs:18:5
+  --> $DIR/const_fn_ptr_fail2.rs:20:5
    |
 LL |     assert_eq!(Z, 4);
    |     ^^^^^^^^^^^-^^^^^
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
index c4b89b50bc4..3729285956b 100644
--- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
@@ -1,13 +1,13 @@
 #![unstable(feature = "humans",
             reason = "who ever let humans program computers,
             we're apparently really bad at it",
-            issue = "0")]
+            issue = "none")]
 
 #![feature(const_fn)]
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
 const fn foo() -> u32 { 42 }
 
 fn meh() -> u32 { 42 }
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
index f6ab0bd7dbe..2a983e42683 100644
--- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 // Regression test for #66975
 #![warn(const_err)]
 #![feature(never_type)]
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
index 24830f7344c..e664a4aab3c 100644
--- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/index-out-of-bounds-never-type.rs:8:61
+  --> $DIR/index-out-of-bounds-never-type.rs:10:61
    |
 LL |     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
    |     --------------------------------------------------------^^^^^---
@@ -7,13 +7,13 @@ LL |     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
    |                                                             index out of bounds: the len is 0 but the index is 0
    |
 note: lint level defined here
-  --> $DIR/index-out-of-bounds-never-type.rs:2:9
+  --> $DIR/index-out-of-bounds-never-type.rs:4:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 error: erroneous constant encountered
-  --> $DIR/index-out-of-bounds-never-type.rs:13:13
+  --> $DIR/index-out-of-bounds-never-type.rs:15:13
    |
 LL |     let _ = PrintName::<T>::VOID;
    |             ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
index 4b487c09a11..6d6bb94d4df 100644
--- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 fn main() {
     let array = [std::env::args().len()];
     array[1]; //~ ERROR index out of bounds
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
index f330f9caaa2..9519ccd3c24 100644
--- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
@@ -1,5 +1,5 @@
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/index_out_of_bounds_propagated.rs:3:5
+  --> $DIR/index_out_of_bounds_propagated.rs:5:5
    |
 LL |     array[1];
    |     ^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs
index 440862090bd..849c81ad449 100644
--- a/src/test/ui/consts/const-eval/issue-43197.rs
+++ b/src/test/ui/consts/const-eval/issue-43197.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![warn(const_err)]
 
 const fn foo(x: u32) -> u32 {
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
index d971d825f27..a1b3a05ed41 100644
--- a/src/test/ui/consts/const-eval/issue-43197.stderr
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/issue-43197.rs:8:20
+  --> $DIR/issue-43197.rs:10:20
    |
 LL |     const X: u32 = 0-1;
    |     ---------------^^^-
@@ -7,13 +7,13 @@ LL |     const X: u32 = 0-1;
    |                    attempt to subtract with overflow
    |
 note: lint level defined here
-  --> $DIR/issue-43197.rs:1:9
+  --> $DIR/issue-43197.rs:3:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: any use of this value will cause an error
-  --> $DIR/issue-43197.rs:10:24
+  --> $DIR/issue-43197.rs:12:24
    |
 LL |     const Y: u32 = foo(0-1);
    |     -------------------^^^--
@@ -21,13 +21,13 @@ LL |     const Y: u32 = foo(0-1);
    |                        attempt to subtract with overflow
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-43197.rs:12:23
+  --> $DIR/issue-43197.rs:14:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-43197.rs:12:26
+  --> $DIR/issue-43197.rs:14:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs
index 4d93130f2af..7da9256bb39 100644
--- a/src/test/ui/consts/const-eval/issue-44578.rs
+++ b/src/test/ui/consts/const-eval/issue-44578.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![allow(const_err)]
 
 trait Foo {
diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr
index 3fadeac1d5c..f4323713e68 100644
--- a/src/test/ui/consts/const-eval/issue-44578.stderr
+++ b/src/test/ui/consts/const-eval/issue-44578.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-44578.rs:25:20
+  --> $DIR/issue-44578.rs:27:20
    |
 LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.rs b/src/test/ui/consts/const-eval/issue-50814-2.rs
index b13c19c660e..8f5c8f097a2 100644
--- a/src/test/ui/consts/const-eval/issue-50814-2.rs
+++ b/src/test/ui/consts/const-eval/issue-50814-2.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 trait C {
     const BOO: usize;
 }
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr
index d68f72d36e2..e04bf03a20c 100644
--- a/src/test/ui/consts/const-eval/issue-50814-2.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/issue-50814-2.rs:12:24
+  --> $DIR/issue-50814-2.rs:14:24
    |
 LL |     const BAR: usize = [5, 6, 7][T::BOO];
    |     -------------------^^^^^^^^^^^^^^^^^-
@@ -9,7 +9,7 @@ LL |     const BAR: usize = [5, 6, 7][T::BOO];
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814-2.rs:16:5
+  --> $DIR/issue-50814-2.rs:18:5
    |
 LL |     &<A<T> as Foo<T>>::BAR
    |     ^---------------------
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index b85cecda16e..e589126a942 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 trait Unsigned {
     const MAX: u8;
 }
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 707dfee7cd5..f8b017e4b53 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/issue-50814.rs:13:21
+  --> $DIR/issue-50814.rs:15:21
    |
 LL |     const MAX: u8 = A::MAX + B::MAX;
    |     ----------------^^^^^^^^^^^^^^^-
@@ -9,7 +9,7 @@ LL |     const MAX: u8 = A::MAX + B::MAX;
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814.rs:17:5
+  --> $DIR/issue-50814.rs:19:5
    |
 LL |     &Sum::<U8,U8>::MAX
    |     ^-----------------
diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
index a7cbdb40ef1..21ee64fa6d9 100644
--- a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
+++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 // Regression test for #66975
 #![warn(const_err)]
 #![feature(const_panic)]
diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
index e15952c20e4..575c3648b70 100644
--- a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
+++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
@@ -1,20 +1,20 @@
 warning: any use of this value will cause an error
-  --> $DIR/panic-assoc-never-type.rs:9:21
+  --> $DIR/panic-assoc-never-type.rs:11:21
    |
 LL |     const VOID: ! = panic!();
    |     ----------------^^^^^^^^-
    |                     |
-   |                     the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:9:21
+   |                     the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:11:21
    |
 note: lint level defined here
-  --> $DIR/panic-assoc-never-type.rs:2:9
+  --> $DIR/panic-assoc-never-type.rs:4:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
    = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error[E0080]: erroneous constant used
-  --> $DIR/panic-assoc-never-type.rs:14:13
+  --> $DIR/panic-assoc-never-type.rs:16:13
    |
 LL |     let _ = PrintName::VOID;
    |             ^^^^^^^^^^^^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/const-eval/panic-never-type.rs b/src/test/ui/consts/const-eval/panic-never-type.rs
index b1a7d8ae676..3b28b2fdd24 100644
--- a/src/test/ui/consts/const-eval/panic-never-type.rs
+++ b/src/test/ui/consts/const-eval/panic-never-type.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 // Regression test for #66975
 #![warn(const_err)]
 #![feature(const_panic)]
diff --git a/src/test/ui/consts/const-eval/panic-never-type.stderr b/src/test/ui/consts/const-eval/panic-never-type.stderr
index 9e91fdf4514..4d1686a8d8f 100644
--- a/src/test/ui/consts/const-eval/panic-never-type.stderr
+++ b/src/test/ui/consts/const-eval/panic-never-type.stderr
@@ -1,20 +1,20 @@
 warning: any use of this value will cause an error
-  --> $DIR/panic-never-type.rs:6:17
+  --> $DIR/panic-never-type.rs:8:17
    |
 LL | const VOID: ! = panic!();
    | ----------------^^^^^^^^-
    |                 |
-   |                 the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:6:17
+   |                 the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:8:17
    |
 note: lint level defined here
-  --> $DIR/panic-never-type.rs:2:9
+  --> $DIR/panic-never-type.rs:4:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
    = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error[E0080]: erroneous constant used
-  --> $DIR/panic-never-type.rs:10:13
+  --> $DIR/panic-never-type.rs:12:13
    |
 LL |     let _ = VOID;
    |             ^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index dfa6863082c..2eed8ca7d32 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -O
 
 #![deny(const_err)]
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
index 848a880ba49..8f17ef05f23 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -1,47 +1,47 @@
 error: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:7:14
+  --> $DIR/promoted_errors.rs:8:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^ attempt to subtract with overflow
    |
 note: lint level defined here
-  --> $DIR/promoted_errors.rs:3:9
+  --> $DIR/promoted_errors.rs:4:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:9:20
+  --> $DIR/promoted_errors.rs:10:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:9:20
+  --> $DIR/promoted_errors.rs:10:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:12:14
+  --> $DIR/promoted_errors.rs:13:14
    |
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:14:20
+  --> $DIR/promoted_errors.rs:15:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:14:20
+  --> $DIR/promoted_errors.rs:15:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:17:14
+  --> $DIR/promoted_errors.rs:18:14
    |
 LL |     let _x = 1/(false as u32);
    |              ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs
index 58b17940912..ae680b4f107 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors2.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -C overflow-checks=on -O
 
 #![deny(const_err)]
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr
index 6f4b1c045f4..60a3cba6e1f 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr
@@ -1,53 +1,53 @@
 error: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:6:20
+  --> $DIR/promoted_errors2.rs:7:20
    |
 LL |     println!("{}", 0u32 - 1);
    |                    ^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/promoted_errors2.rs:3:9
+  --> $DIR/promoted_errors2.rs:4:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:8:14
+  --> $DIR/promoted_errors2.rs:9:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:10:20
+  --> $DIR/promoted_errors2.rs:11:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:10:20
+  --> $DIR/promoted_errors2.rs:11:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:13:14
+  --> $DIR/promoted_errors2.rs:14:14
    |
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:15:20
+  --> $DIR/promoted_errors2.rs:16:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:15:20
+  --> $DIR/promoted_errors2.rs:16:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:18:14
+  --> $DIR/promoted_errors2.rs:19:14
    |
 LL |     let _x = 1/(false as u32);
    |              ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index 1f810c40572..a5c2a57c6c8 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -2,7 +2,6 @@
 #![allow(unused)]
 #![allow(const_err)] // make sure we cannot allow away the errors tested here
 
-// normalize-stderr-test "alignment \d+" -> "alignment N"
 // normalize-stderr-test "offset \d+" -> "offset N"
 // normalize-stderr-test "allocation \d+" -> "allocation N"
 // normalize-stderr-test "size \d+" -> "size N"
@@ -149,11 +148,23 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }
 //~^ ERROR it is undefined behavior to use this value
 
 // # raw trait object
-const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust};
+const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
 //~^ ERROR it is undefined behavior to use this value
 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
 //~^ ERROR it is undefined behavior to use this value
 const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw
 
+// Const eval fails for these, so they need to be statics to error.
+static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
+    DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
+    //~^ ERROR could not evaluate static initializer
+};
+static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
+    DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
+    //~^ ERROR could not evaluate static initializer
+};
+
 fn main() {
+    let _ = RAW_TRAIT_OBJ_VTABLE_NULL;
+    let _ = RAW_TRAIT_OBJ_VTABLE_INVALID;
 }
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
index 85fb8ac2a4a..ce57d680dc9 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:87:1
+  --> $DIR/ub-wide-ptr.rs:86:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
@@ -7,7 +7,7 @@ LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr:
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:89:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
@@ -15,7 +15,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr {
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:93:1
+  --> $DIR/ub-wide-ptr.rs:92:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
@@ -23,7 +23,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:97:1
+  --> $DIR/ub-wide-ptr.rs:96:1
    |
 LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
@@ -31,7 +31,7 @@ LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:100:1
+  --> $DIR/ub-wide-ptr.rs:99:1
    |
 LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
@@ -39,7 +39,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:107:1
+  --> $DIR/ub-wide-ptr.rs:106:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
@@ -47,7 +47,7 @@ LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.sli
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:110:1
+  --> $DIR/ub-wide-ptr.rs:109:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
@@ -55,7 +55,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { p
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:113:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
@@ -63,7 +63,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:117:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something less or equal to 1
@@ -71,7 +71,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:123:1
+  --> $DIR/ub-wide-ptr.rs:122:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something less or equal to 1
@@ -79,7 +79,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute {
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:126:1
+  --> $DIR/ub-wide-ptr.rs:125:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something less or equal to 1
@@ -87,7 +87,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTrans
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:133:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
@@ -95,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:138:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
@@ -103,7 +103,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr:
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:140:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
@@ -111,7 +111,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2:
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:144:1
+  --> $DIR/ub-wide-ptr.rs:143:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
@@ -119,7 +119,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDy
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:148:1
+  --> $DIR/ub-wide-ptr.rs:147:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
@@ -127,21 +127,33 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:152:1
+  --> $DIR/ub-wide-ptr.rs:151:1
    |
-LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:154:1
+  --> $DIR/ub-wide-ptr.rs:153:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
-error: aborting due to 18 previous errors
+error[E0080]: could not evaluate static initializer
+  --> $DIR/ub-wide-ptr.rs:159:5
+   |
+LL |     DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
+
+error[E0080]: could not evaluate static initializer
+  --> $DIR/ub-wide-ptr.rs:163:5
+   |
+LL |     DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
+
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
new file mode 100644
index 00000000000..130ba9283b1
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+#![feature(const_mut_refs)]
+#![feature(const_fn)]
+#![feature(raw_ref_op)]
+
+struct Foo {
+    x: usize
+}
+
+const fn foo() -> Foo {
+    Foo { x: 0 }
+}
+
+impl Foo {
+    const fn bar(&mut self) -> *mut usize {
+        &raw mut self.x
+    }
+}
+
+const fn baz(foo: &mut Foo)-> *mut usize {
+    &raw mut foo.x
+}
+
+const _: () = {
+    foo().bar();
+    baz(&mut foo());
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs
index 13309f978b6..8682d2ee901 100644
--- a/src/test/ui/consts/const-prop-ice.rs
+++ b/src/test/ui/consts/const-prop-ice.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 fn main() {
     [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
 }
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
index 4b3880198bf..65502a4ff71 100644
--- a/src/test/ui/consts/const-prop-ice.stderr
+++ b/src/test/ui/consts/const-prop-ice.stderr
@@ -1,5 +1,5 @@
 error: index out of bounds: the len is 3 but the index is 3
-  --> $DIR/const-prop-ice.rs:2:5
+  --> $DIR/const-prop-ice.rs:4:5
    |
 LL |     [0; 3][3u64 as usize];
    |     ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-prop-ice2.rs b/src/test/ui/consts/const-prop-ice2.rs
index e5fd79f1167..6a73483026f 100644
--- a/src/test/ui/consts/const-prop-ice2.rs
+++ b/src/test/ui/consts/const-prop-ice2.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 fn main() {
     enum Enum { One=1 }
     let xs=[0;1 as usize];
diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr
index dc17876eae4..cbb8fde80f9 100644
--- a/src/test/ui/consts/const-prop-ice2.stderr
+++ b/src/test/ui/consts/const-prop-ice2.stderr
@@ -1,5 +1,5 @@
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/const-prop-ice2.rs:4:20
+  --> $DIR/const-prop-ice2.rs:6:20
    |
 LL |     println!("{}", xs[Enum::One as usize]);
    |                    ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-prop-ice3.rs b/src/test/ui/consts/const-prop-ice3.rs
new file mode 100644
index 00000000000..8ab011661e3
--- /dev/null
+++ b/src/test/ui/consts/const-prop-ice3.rs
@@ -0,0 +1,7 @@
+// run-pass (ensure that const-prop is run)
+
+struct A<T: ?Sized>(T);
+
+fn main() {
+    let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32;
+}
diff --git a/src/test/ui/consts/min_const_fn/address_of.rs b/src/test/ui/consts/min_const_fn/address_of.rs
new file mode 100644
index 00000000000..f8506d70b24
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/address_of.rs
@@ -0,0 +1,17 @@
+#![feature(raw_ref_op)]
+
+const fn mutable_address_of_in_const() {
+    let mut a = 0;
+    let b = &raw mut a;         //~ ERROR `&raw mut` is not allowed
+}
+
+struct X;
+
+impl X {
+    const fn inherent_mutable_address_of_in_const() {
+        let mut a = 0;
+        let b = &raw mut a;     //~ ERROR `&raw mut` is not allowed
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/address_of.stderr b/src/test/ui/consts/min_const_fn/address_of.stderr
new file mode 100644
index 00000000000..3554b8112b1
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/address_of.stderr
@@ -0,0 +1,21 @@
+error[E0658]: `&raw mut` is not allowed in constant functions
+  --> $DIR/address_of.rs:5:13
+   |
+LL |     let b = &raw mut a;
+   |             ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: `&raw mut` is not allowed in constant functions
+  --> $DIR/address_of.rs:13:17
+   |
+LL |         let b = &raw mut a;
+   |                 ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/address_of_const.rs b/src/test/ui/consts/min_const_fn/address_of_const.rs
new file mode 100644
index 00000000000..3db19e9cde8
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/address_of_const.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(raw_ref_op)]
+
+const fn const_address_of_in_const() {
+    let mut a = 0;
+    let b = &raw const a;
+}
+
+struct X;
+
+impl X {
+    const fn inherent_const_address_of_in_const() {
+        let mut a = 0;
+        let b = &raw const a;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
index 97e467aece2..df10f3496c3 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
@@ -1,13 +1,13 @@
 #![unstable(feature = "humans",
             reason = "who ever let humans program computers,
             we're apparently really bad at it",
-            issue = "0")]
+            issue = "none")]
 
 #![feature(const_fn, foo, foo2)]
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
 const fn foo() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -15,7 +15,7 @@ const fn foo() -> u32 { 42 }
 // can't call non-min_const_fn
 const fn bar() -> u32 { foo() } //~ ERROR can only call other `const fn`
 
-#[unstable(feature = "rust1", issue="0")]
+#[unstable(feature = "rust1", issue = "none")]
 const fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -29,7 +29,7 @@ const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `const fn`
 const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
 
 // check whether this function cannot be called even with the feature gate active
-#[unstable(feature = "foo2", issue="0")]
+#[unstable(feature = "foo2", issue = "none")]
 const fn foo2_gated() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
index 102b3801441..12b41ee2b0d 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
@@ -1,13 +1,13 @@
 #![unstable(feature = "humans",
             reason = "who ever let humans program computers,
             we're apparently really bad at it",
-            issue = "0")]
+            issue = "none")]
 
 #![feature(const_fn, foo, foo2)]
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
 const unsafe fn foo() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -15,7 +15,7 @@ const unsafe fn foo() -> u32 { 42 }
 // can't call non-min_const_fn
 const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `const fn`
 
-#[unstable(feature = "rust1", issue="0")]
+#[unstable(feature = "rust1", issue = "none")]
 const unsafe fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -29,7 +29,7 @@ const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call othe
 const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op
 
 // check whether this function cannot be called even with the feature gate active
-#[unstable(feature = "foo2", issue="0")]
+#[unstable(feature = "foo2", issue = "none")]
 const unsafe fn foo2_gated() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
index 121177f8366..44a62094987 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
@@ -1,13 +1,13 @@
 #![unstable(feature = "humans",
             reason = "who ever let humans program computers,
             we're apparently really bad at it",
-            issue = "0")]
+            issue = "none")]
 
 #![feature(const_fn, foo, foo2)]
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
 const fn foo() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -15,7 +15,7 @@ const fn foo() -> u32 { 42 }
 // can't call non-min_const_fn
 const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `const fn`
 
-#[unstable(feature = "rust1", issue="0")]
+#[unstable(feature = "rust1", issue = "none")]
 const fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -24,7 +24,7 @@ const fn foo2() -> u32 { 42 }
 const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `const fn`
 
 // check whether this function cannot be called even with the feature gate active
-#[unstable(feature = "foo2", issue="0")]
+#[unstable(feature = "foo2", issue = "none")]
 const fn foo2_gated() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.rs b/src/test/ui/consts/miri_unleashed/assoc_const.rs
index b8959667cc2..cfbcc959d3b 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.rs
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.rs
@@ -1,4 +1,6 @@
+// build-fail
 // compile-flags: -Zunleash-the-miri-inside-of-you
+
 #![allow(const_err)]
 
 // a test demonstrating why we do need to run static const qualification on associated constants
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
index 6a6cb343f17..1ccf2b196fd 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
@@ -1,11 +1,11 @@
 warning: skipping const checks
-  --> $DIR/assoc_const.rs:12:20
+  --> $DIR/assoc_const.rs:14:20
    |
 LL |     const F: u32 = (U::X, 42).1;
    |                    ^^^^^^^^^^
 
 error[E0080]: erroneous constant used
-  --> $DIR/assoc_const.rs:29:13
+  --> $DIR/assoc_const.rs:31:13
    |
 LL |     let y = <String as Bar<Vec<u32>, String>>::F;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.rs b/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
index c87b6389848..30dd2a51585 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![allow(const_err)]
 
 // a test demonstrating that const qualification cannot prevent monomorphization time errors
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
index dbfe1d93aa4..e15717979c5 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
@@ -1,5 +1,5 @@
 error[E0080]: erroneous constant used
-  --> $DIR/assoc_const_2.rs:27:13
+  --> $DIR/assoc_const_2.rs:29:13
    |
 LL |     let y = <String as Bar<String>>::F;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
index e1ac4306575..32a713ebaa4 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
@@ -1,4 +1,6 @@
+// build-fail
 // compile-flags: -Zunleash-the-miri-inside-of-you
+
 #![warn(const_err)]
 
 // A test demonstrating that we prevent calling non-const fn during CTFE.
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
index 7a574b34304..75f532a81bd 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
@@ -1,11 +1,11 @@
 warning: skipping const checks
-  --> $DIR/non_const_fn.rs:8:15
+  --> $DIR/non_const_fn.rs:10:15
    |
 LL | const C: () = foo();
    |               ^^^^^
 
 warning: any use of this value will cause an error
-  --> $DIR/non_const_fn.rs:8:15
+  --> $DIR/non_const_fn.rs:10:15
    |
 LL | const C: () = foo();
    | --------------^^^^^-
@@ -13,13 +13,13 @@ LL | const C: () = foo();
    |               calling non-const function `foo`
    |
 note: lint level defined here
-  --> $DIR/non_const_fn.rs:2:9
+  --> $DIR/non_const_fn.rs:4:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/non_const_fn.rs:12:22
+  --> $DIR/non_const_fn.rs:14:22
    |
 LL |     println!("{:?}", C);
    |                      ^ referenced constant has errors
diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr
index 1bd09034bfc..ac08b2f2427 100644
--- a/src/test/ui/consts/offset_from_ub.stderr
+++ b/src/test/ui/consts/offset_from_ub.stderr
@@ -1,11 +1,11 @@
 error: any use of this value will cause an error
-  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
    |
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
    |           ptr_offset_from cannot compute offset of pointers into different allocations.
-   |           inside call to `std::ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:19:27
+   |           inside call to `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:19:27
    | 
   ::: $DIR/offset_from_ub.rs:13:1
    |
@@ -21,13 +21,13 @@ LL | | };
    = note: `#[deny(const_err)]` on by default
 
 error: any use of this value will cause an error
-  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
    |
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
    |           a memory access tried to interpret some bytes as a pointer
-   |           inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:25:14
+   |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:25:14
    | 
   ::: $DIR/offset_from_ub.rs:23:1
    |
@@ -38,13 +38,13 @@ LL | | };
    | |__-
 
 error: any use of this value will cause an error
-  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
    |
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
    |           exact_div: 1 cannot be divided by 2 without remainder
-   |           inside call to `std::ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:14
+   |           inside call to `std::ptr::const_ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:14
    | 
   ::: $DIR/offset_from_ub.rs:28:1
    |
@@ -58,13 +58,13 @@ LL | | };
    | |__-
 
 error: any use of this value will cause an error
-  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
    |
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
    |           invalid use of NULL pointer
-   |           inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:39:14
+   |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:39:14
    | 
   ::: $DIR/offset_from_ub.rs:36:1
    |
@@ -76,13 +76,13 @@ LL | | };
    | |__-
 
 error: any use of this value will cause an error
-  --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
    |
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
    |           a memory access tried to interpret some bytes as a pointer
-   |           inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:46:14
+   |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:46:14
    | 
   ::: $DIR/offset_from_ub.rs:42:1
    |
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.rs b/src/test/ui/consts/uninhabited-const-issue-61744.rs
index e10b38a614a..945017b4937 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.rs
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.rs
@@ -1,4 +1,4 @@
-// compile-fail
+// build-fail
 
 pub const unsafe fn fake_type<T>() -> T {
     hint_unreachable()
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
index 655ad7b548a..0b64786ccce 100644
--- a/src/test/ui/consts/unstable-const-fn-in-libcore.rs
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
@@ -14,7 +14,7 @@ enum Opt<T> {
 }
 
 impl<T> Opt<T> {
-    #[rustc_const_unstable(feature = "foo", issue = "0")]
+    #[rustc_const_unstable(feature = "foo", issue = "none")]
     #[stable(feature = "rust1", since = "1.0.0")]
     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
     //~^ ERROR destructors cannot be evaluated at compile-time
diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs
index b3c1f60b7eb..ea21592997b 100644
--- a/src/test/ui/did_you_mean/issue-40006.rs
+++ b/src/test/ui/did_you_mean/issue-40006.rs
@@ -18,10 +18,10 @@ trait A { //~ ERROR missing
 trait B {
     fn xxx() { ### } //~ ERROR expected
 }
-trait C { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration
+trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration
     L = M;
 }
-trait D { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration
+trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration
     Z = { 2 + 3 };
 }
 trait E {
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index 30ae6ed4c6d..d1e995013cb 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -1,4 +1,4 @@
-error: missing `fn`, `type`, or `const` for impl-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-40006.rs:1:13
    |
 LL |   impl dyn A {
@@ -6,7 +6,7 @@ LL |   impl dyn A {
 LL | |     Y
    | |____^ missing `fn`, `type`, or `const`
 
-error: missing `fn`, `type`, or `const` for trait-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-40006.rs:7:10
    |
 LL |   trait X {
@@ -14,7 +14,7 @@ LL |   trait X {
 LL | |     X() {}
    | |____^ missing `fn`, `type`, or `const`
 
-error: missing `fn`, `type`, or `const` for trait-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-40006.rs:15:10
    |
 LL |   trait A {
@@ -28,7 +28,7 @@ error: expected `[`, found `#`
 LL |     fn xxx() { ### }
    |                 ^ expected `[`
 
-error: missing `fn`, `type`, or `const` for trait-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-40006.rs:21:10
    |
 LL |   trait C {
@@ -36,7 +36,7 @@ LL |   trait C {
 LL | |     L = M;
    | |____^ missing `fn`, `type`, or `const`
 
-error: missing `fn`, `type`, or `const` for trait-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-40006.rs:24:10
    |
 LL |   trait D {
@@ -50,7 +50,7 @@ error: expected one of `!` or `::`, found `(`
 LL |     ::Y ();
    |         ^ expected one of `!` or `::`
 
-error: missing `fn`, `type`, or `const` for impl-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-40006.rs:32:8
    |
 LL |     pub hello_method(&self) {
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
index 687479bad3f..44421b077fa 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
@@ -1,17 +1,25 @@
+fn main() {}
+
 fn test_and() {
     let a = true;
     let b = false;
-    if a and b {
-        //~^ ERROR expected `{`, found `and`
+
+    let _ = a and b; //~ ERROR `and` is not a logical operator
+
+    if a and b { //~ ERROR `and` is not a logical operator
         println!("both");
     }
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
 }
 
 fn test_or() {
     let a = true;
     let b = false;
-    if a or b {
-        //~^ ERROR expected `{`, found `or`
+
+    let _ = a or b; //~ ERROR `or` is not a logical operator
+
+    if a or b { //~ ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -19,8 +27,7 @@ fn test_or() {
 fn test_and_par() {
     let a = true;
     let b = false;
-    if (a and b) {
-        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
+    if (a and b) {  //~ ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -28,8 +35,7 @@ fn test_and_par() {
 fn test_or_par() {
     let a = true;
     let b = false;
-    if (a or b) {
-        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
+    if (a or b) {  //~ ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -37,8 +43,7 @@ fn test_or_par() {
 fn test_while_and() {
     let a = true;
     let b = false;
-    while a and b {
-        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
+    while a and b {  //~ ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -46,11 +51,7 @@ fn test_while_and() {
 fn test_while_or() {
     let a = true;
     let b = false;
-    while a or b {
-        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
+    while a or b { //~ ERROR `or` is not a logical operator
         println!("both");
     }
 }
-
-fn main() {
-}
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
index f230395f7a5..528c62f501e 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
@@ -1,58 +1,75 @@
-error: expected `{`, found `and`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:4:10
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15
+   |
+LL |     let _ = a and b;
+   |               ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
    |
 LL |     if a and b {
-   |     --   ^^^
-   |     |    |
-   |     |    expected `{`
-   |     |    help: use `&&` instead of `and` for the boolean operator
-   |     this `if` statement has a condition, but no block
+   |          ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
+   |
+LL |     let _ = a or b;
+   |               ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected `{`, found `or`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:10
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
    |
 LL |     if a or b {
-   |     --   ^^
-   |     |    |
-   |     |    expected `{`
-   |     |    help: use `||` instead of `or` for the boolean operator
-   |     this `if` statement has a condition, but no block
+   |          ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:11
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
    |
 LL |     if (a and b) {
-   |           ^^^
-   |           |
-   |           expected one of 8 possible tokens
-   |           help: use `&&` instead of `and` for the boolean operator
+   |           ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:31:11
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
    |
 LL |     if (a or b) {
-   |           ^^
-   |           |
-   |           expected one of 8 possible tokens
-   |           help: use `||` instead of `or` for the boolean operator
+   |           ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:40:13
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
    |
 LL |     while a and b {
-   |             ^^^
-   |             |
-   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator
-   |             help: use `&&` instead of `and` for the boolean operator
+   |             ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:49:13
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
    |
 LL |     while a or b {
-   |             ^^
-   |             |
-   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator
-   |             help: use `||` instead of `or` for the boolean operator
+   |             ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dropck/dropck_fn_type.rs b/src/test/ui/dropck/dropck_fn_type.rs
new file mode 100644
index 00000000000..2934217df34
--- /dev/null
+++ b/src/test/ui/dropck/dropck_fn_type.rs
@@ -0,0 +1,20 @@
+// run-pass
+//! Regression test for #58311, regarding the usage of Fn types in drop impls
+
+// All of this Drop impls should compile.
+
+#[allow(dead_code)]
+struct S<F: Fn() -> [u8; 1]>(F);
+
+impl<F: Fn() -> [u8; 1]> Drop for S<F> {
+    fn drop(&mut self) {}
+}
+
+#[allow(dead_code)]
+struct P<A, F: FnOnce() -> [A; 10]>(F);
+
+impl<A, F: FnOnce() -> [A; 10]> Drop for P<A, F> {
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/dropck/dropck_traits.rs b/src/test/ui/dropck/dropck_traits.rs
new file mode 100644
index 00000000000..98e8e88a259
--- /dev/null
+++ b/src/test/ui/dropck/dropck_traits.rs
@@ -0,0 +1,68 @@
+// run-pass
+//! Regression test for #34426, regarding HRTB in drop impls
+
+// All of this Drop impls should compile.
+
+pub trait Lifetime<'a> {}
+impl<'a> Lifetime<'a> for i32 {}
+
+#[allow(dead_code)]
+struct Foo<L>
+where
+    for<'a> L: Lifetime<'a>,
+{
+    l: L,
+}
+
+impl<L> Drop for Foo<L>
+where
+    for<'a> L: Lifetime<'a>,
+{
+    fn drop(&mut self) {}
+}
+
+#[allow(dead_code)]
+struct Foo2<L>
+where
+    for<'a> L: Lifetime<'a>,
+{
+    l: L,
+}
+
+impl<T: for<'a> Lifetime<'a>> Drop for Foo2<T>
+where
+    for<'x> T: Lifetime<'x>,
+{
+    fn drop(&mut self) {}
+}
+
+pub trait Lifetime2<'a, 'b> {}
+impl<'a, 'b> Lifetime2<'a, 'b> for i32 {}
+
+#[allow(dead_code)]
+struct Bar<L>
+where
+    for<'a, 'b> L: Lifetime2<'a, 'b>,
+{
+    l: L,
+}
+
+impl<L> Drop for Bar<L>
+where
+    for<'a, 'b> L: Lifetime2<'a, 'b>,
+{
+    fn drop(&mut self) {}
+}
+
+#[allow(dead_code)]
+struct FnHolder<T: for<'a> Fn(&'a T, dyn for<'b> Lifetime2<'a, 'b>) -> u8>(T);
+
+impl<T: for<'a> Fn(&'a T, dyn for<'b> Lifetime2<'a, 'b>) -> u8> Drop for FnHolder<T> {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let _foo = Foo { l: 0 };
+
+    let _bar = Bar { l: 0 };
+}
diff --git a/src/test/ui/duplicate/dupe-symbols-1.rs b/src/test/ui/duplicate/dupe-symbols-1.rs
index f943c7b1110..28e329b56ca 100644
--- a/src/test/ui/duplicate/dupe-symbols-1.rs
+++ b/src/test/ui/duplicate/dupe-symbols-1.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 //
 #![crate_type="rlib"]
 #![allow(warnings)]
diff --git a/src/test/ui/duplicate/dupe-symbols-1.stderr b/src/test/ui/duplicate/dupe-symbols-1.stderr
index c46ac0c6ed4..cca8b4d25da 100644
--- a/src/test/ui/duplicate/dupe-symbols-1.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-1.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/dupe-symbols-1.rs:10:1
+  --> $DIR/dupe-symbols-1.rs:12:1
    |
 LL | / pub fn b() {
 LL | |
diff --git a/src/test/ui/duplicate/dupe-symbols-2.rs b/src/test/ui/duplicate/dupe-symbols-2.rs
index 9257f97fb93..d9edd77a199 100644
--- a/src/test/ui/duplicate/dupe-symbols-2.rs
+++ b/src/test/ui/duplicate/dupe-symbols-2.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 //
 #![crate_type="rlib"]
 #![allow(warnings)]
diff --git a/src/test/ui/duplicate/dupe-symbols-2.stderr b/src/test/ui/duplicate/dupe-symbols-2.stderr
index 821bdd03392..017aade3129 100644
--- a/src/test/ui/duplicate/dupe-symbols-2.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-2.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/dupe-symbols-2.rs:13:5
+  --> $DIR/dupe-symbols-2.rs:15:5
    |
 LL | /     pub extern fn fail() {
 LL | |
diff --git a/src/test/ui/duplicate/dupe-symbols-3.rs b/src/test/ui/duplicate/dupe-symbols-3.rs
index 03b3a0ab207..1af2fe98e50 100644
--- a/src/test/ui/duplicate/dupe-symbols-3.rs
+++ b/src/test/ui/duplicate/dupe-symbols-3.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 //
 #![crate_type="rlib"]
 #![allow(warnings)]
diff --git a/src/test/ui/duplicate/dupe-symbols-3.stderr b/src/test/ui/duplicate/dupe-symbols-3.stderr
index f30c88e4760..2e2ac3a98b8 100644
--- a/src/test/ui/duplicate/dupe-symbols-3.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-3.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/dupe-symbols-3.rs:10:1
+  --> $DIR/dupe-symbols-3.rs:12:1
    |
 LL | / pub fn fail() {
 LL | |
diff --git a/src/test/ui/duplicate/dupe-symbols-4.rs b/src/test/ui/duplicate/dupe-symbols-4.rs
index 8fbf1151f7c..de6610c3e79 100644
--- a/src/test/ui/duplicate/dupe-symbols-4.rs
+++ b/src/test/ui/duplicate/dupe-symbols-4.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 //
 // error-pattern: symbol `fail` is already defined
 #![crate_type="rlib"]
diff --git a/src/test/ui/duplicate/dupe-symbols-4.stderr b/src/test/ui/duplicate/dupe-symbols-4.stderr
index 84d57766c35..10b93891b66 100644
--- a/src/test/ui/duplicate/dupe-symbols-4.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-4.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/dupe-symbols-4.rs:21:5
+  --> $DIR/dupe-symbols-4.rs:23:5
    |
 LL |     fn fail(self) {}
    |     ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/duplicate/dupe-symbols-5.rs b/src/test/ui/duplicate/dupe-symbols-5.rs
index 4a96a685821..ea801cef64f 100644
--- a/src/test/ui/duplicate/dupe-symbols-5.rs
+++ b/src/test/ui/duplicate/dupe-symbols-5.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 //
 #![crate_type="rlib"]
 #![allow(warnings)]
diff --git a/src/test/ui/duplicate/dupe-symbols-5.stderr b/src/test/ui/duplicate/dupe-symbols-5.stderr
index cee72660e4f..ebeb19f94f6 100644
--- a/src/test/ui/duplicate/dupe-symbols-5.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-5.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/dupe-symbols-5.rs:9:1
+  --> $DIR/dupe-symbols-5.rs:11:1
    |
 LL | / pub fn b() {
 LL | |
diff --git a/src/test/ui/duplicate/dupe-symbols-6.rs b/src/test/ui/duplicate/dupe-symbols-6.rs
index 5a1b917f179..018f4bb7f07 100644
--- a/src/test/ui/duplicate/dupe-symbols-6.rs
+++ b/src/test/ui/duplicate/dupe-symbols-6.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![crate_type="rlib"]
 #![allow(warnings)]
 
diff --git a/src/test/ui/duplicate/dupe-symbols-6.stderr b/src/test/ui/duplicate/dupe-symbols-6.stderr
index 69781ee3e0d..8d5b7fb35bf 100644
--- a/src/test/ui/duplicate/dupe-symbols-6.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-6.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/dupe-symbols-6.rs:8:1
+  --> $DIR/dupe-symbols-6.rs:10:1
    |
 LL | static HELLO_TWICE: u16 = 0;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/duplicate/dupe-symbols-7.rs b/src/test/ui/duplicate/dupe-symbols-7.rs
index b838aaa102e..89a32c61620 100644
--- a/src/test/ui/duplicate/dupe-symbols-7.rs
+++ b/src/test/ui/duplicate/dupe-symbols-7.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 //
 // error-pattern: entry symbol `main` defined multiple times
 
diff --git a/src/test/ui/duplicate/dupe-symbols-7.stderr b/src/test/ui/duplicate/dupe-symbols-7.stderr
index d2cb4e0970e..608ae27110a 100644
--- a/src/test/ui/duplicate/dupe-symbols-7.stderr
+++ b/src/test/ui/duplicate/dupe-symbols-7.stderr
@@ -1,5 +1,5 @@
 error: entry symbol `main` defined multiple times
-  --> $DIR/dupe-symbols-7.rs:10:1
+  --> $DIR/dupe-symbols-7.rs:12:1
    |
 LL | fn main(){}
    | ^^^^^^^^^^^
diff --git a/src/test/ui/error-codes/E0511.rs b/src/test/ui/error-codes/E0511.rs
index 3590f12e5f9..a52f81a6c5d 100644
--- a/src/test/ui/error-codes/E0511.rs
+++ b/src/test/ui/error-codes/E0511.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(platform_intrinsics)]
 
 extern "platform-intrinsic" {
diff --git a/src/test/ui/error-codes/E0511.stderr b/src/test/ui/error-codes/E0511.stderr
index 1362a3d1f25..d797b10d5a6 100644
--- a/src/test/ui/error-codes/E0511.stderr
+++ b/src/test/ui/error-codes/E0511.stderr
@@ -1,5 +1,5 @@
 error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/E0511.rs:8:14
+  --> $DIR/E0511.rs:10:14
    |
 LL |     unsafe { simd_add(0, 1); }
    |              ^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gate/stability-attribute-consistency.rs b/src/test/ui/feature-gate/stability-attribute-consistency.rs
index caafd8b8854..6ee7003c31e 100644
--- a/src/test/ui/feature-gate/stability-attribute-consistency.rs
+++ b/src/test/ui/feature-gate/stability-attribute-consistency.rs
@@ -9,7 +9,7 @@ fn foo_stable_1_0_0() {}
 //~^ ERROR feature `foo` is declared stable since 1.29.0
 fn foo_stable_1_29_0() {}
 
-#[unstable(feature = "foo", issue = "0")]
+#[unstable(feature = "foo", issue = "none")]
 //~^ ERROR feature `foo` is declared unstable
 fn foo_unstable() {}
 
diff --git a/src/test/ui/feature-gate/stability-attribute-consistency.stderr b/src/test/ui/feature-gate/stability-attribute-consistency.stderr
index 9b4b28a3922..d49b44c8a35 100644
--- a/src/test/ui/feature-gate/stability-attribute-consistency.stderr
+++ b/src/test/ui/feature-gate/stability-attribute-consistency.stderr
@@ -7,8 +7,8 @@ LL | #[stable(feature = "foo", since = "1.29.0")]
 error[E0711]: feature `foo` is declared unstable, but was previously declared stable
   --> $DIR/stability-attribute-consistency.rs:12:1
    |
-LL | #[unstable(feature = "foo", issue = "0")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[unstable(feature = "foo", issue = "none")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs b/src/test/ui/feature-gate/unstable-attribute-allow-issue-0.rs
index 3ce9de3fb1b..c8ad0d13a14 100644
--- a/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs
+++ b/src/test/ui/feature-gate/unstable-attribute-allow-issue-0.rs
@@ -1,4 +1,4 @@
-// Check that an issue value can be explicitly set to "none" instead of "0"
+// Check that an issue value can be explicitly set to "0" instead of "none"
 #![crate_type = "lib"]
 #![feature(staged_api)]
 #![stable(feature = "stable_test_feature", since = "1.0.0")]
diff --git a/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr b/src/test/ui/feature-gate/unstable-attribute-allow-issue-0.stderr
index fc031f5f8c5..10bd6f373d9 100644
--- a/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr
+++ b/src/test/ui/feature-gate/unstable-attribute-allow-issue-0.stderr
@@ -1,5 +1,5 @@
 error[E0545]: incorrect 'issue'
-  --> $DIR/unstable-attribute-allow-issue-none.rs:12:1
+  --> $DIR/unstable-attribute-allow-issue-0.rs:12:1
    |
 LL | #[unstable(feature = "unstable_test_feature", issue = "something")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
index 17548d7b9e8..7ff348aca7c 100644
--- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
@@ -3,9 +3,11 @@ use std::ops::Deref;
 trait PointerFamily<U> {
     type Pointer<T>: Deref<Target = T>;
     //~^ ERROR generic associated types are unstable
+    //~| ERROR type-generic associated types are not yet implemented
     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
     //~^ ERROR generic associated types are unstable
     //~| ERROR where clauses on associated types are unstable
+    //~| ERROR type-generic associated types are not yet implemented
 }
 
 struct Foo;
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
index 04473f41069..ab17c9a28ae 100644
--- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
@@ -8,7 +8,7 @@ LL |     type Pointer<T>: Deref<Target = T>;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:6:5
+  --> $DIR/feature-gate-generic_associated_types.rs:7:5
    |
 LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: where clauses on associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:6:5
+  --> $DIR/feature-gate-generic_associated_types.rs:7:5
    |
 LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:14:5
+  --> $DIR/feature-gate-generic_associated_types.rs:16:5
    |
 LL |     type Pointer<Usize> = Box<Usize>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ LL |     type Pointer<Usize> = Box<Usize>;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:16:5
+  --> $DIR/feature-gate-generic_associated_types.rs:18:5
    |
 LL |     type Pointer2<U32> = Box<U32>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     type Pointer2<U32> = Box<U32>;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: where clauses on associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:21:5
+  --> $DIR/feature-gate-generic_associated_types.rs:23:5
    |
 LL |     type Assoc where Self: Sized;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL |     type Assoc where Self: Sized;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: where clauses on associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:26:5
+  --> $DIR/feature-gate-generic_associated_types.rs:28:5
    |
 LL |     type Assoc where Self: Sized = Foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,6 +61,22 @@ LL |     type Assoc where Self: Sized = Foo;
    = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
-error: aborting due to 7 previous errors
+error: type-generic associated types are not yet implemented
+  --> $DIR/feature-gate-generic_associated_types.rs:4:5
+   |
+LL |     type Pointer<T>: Deref<Target = T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/feature-gate-generic_associated_types.rs:7:5
+   |
+LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
index d9ebcdecb9b..1f61473c9d2 100644
--- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
+++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
@@ -16,15 +16,6 @@ LL |     type Baa = impl Debug;
    = note: for more information, see https://github.com/rust-lang/rust/issues/63063
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
-error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18
-   |
-LL |     type Assoc = impl Debug;
-   |                  ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/63063
-   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
-
 error[E0658]: associated type defaults are unstable
   --> $DIR/feature-gate-type_alias_impl_trait.rs:18:5
    |
@@ -35,6 +26,15 @@ LL |     type Assoc = impl Debug;
    = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18
+   |
+LL |     type Assoc = impl Debug;
+   |                  ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/63063
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+
+error[E0658]: `impl Trait` in type aliases is unstable
   --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs
index ede6a3b2b39..6f018f04018 100644
--- a/src/test/ui/rfc1598-generic-associated-types/collections.rs
+++ b/src/test/ui/generic-associated-types/collections.rs
@@ -1,10 +1,7 @@
+#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 #![feature(associated_type_defaults)]
 
-// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
-// follow-up PR.
-
 // A Collection trait and collection families. Based on
 // http://smallcultfollowing.com/babysteps/blog/2016/11/03/
 // associated-type-constructors-part-2-family-traits/
@@ -15,18 +12,18 @@ trait Collection<T> {
     // Test associated type defaults with parameters
     type Sibling<U>: Collection<U> =
         <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^^ ERROR type-generic associated types are not yet implemented
 
     fn empty() -> Self;
 
     fn add(&mut self, value: T);
 
     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
 }
 
 trait CollectionFamily {
     type Member<T>: Collection<T, Family = Self>;
+    //~^ ERROR type-generic associated types are not yet implemented
 }
 
 struct VecFamily;
@@ -48,13 +45,11 @@ impl<T> Collection<T> for Vec<T> {
     }
 
     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
         self.iter()
     }
 }
 
 fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>
-//~^ ERROR type arguments are not allowed for this type [E0109]
 where
     C: Collection<i32>,
 {
@@ -66,7 +61,6 @@ where
 }
 
 fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
-//~^ ERROR type arguments are not allowed for this type [E0109]
 where
     C: Collection<i32>,
 {
diff --git a/src/test/ui/generic-associated-types/collections.stderr b/src/test/ui/generic-associated-types/collections.stderr
new file mode 100644
index 00000000000..e99ae78f714
--- /dev/null
+++ b/src/test/ui/generic-associated-types/collections.stderr
@@ -0,0 +1,19 @@
+error: type-generic associated types are not yet implemented
+  --> $DIR/collections.rs:13:5
+   |
+LL | /     type Sibling<U>: Collection<U> =
+LL | |         <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
+   | |_________________________________________________________________________^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/collections.rs:25:5
+   |
+LL |     type Member<T>: Collection<T, Family = Self>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.rs b/src/test/ui/generic-associated-types/construct_with_other_type.rs
new file mode 100644
index 00000000000..2198b99db25
--- /dev/null
+++ b/src/test/ui/generic-associated-types/construct_with_other_type.rs
@@ -0,0 +1,26 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+// FIXME(#30472) normalize enough to handle this.
+
+use std::ops::Deref;
+
+trait Foo {
+    type Bar<'a, 'b>;
+}
+
+trait Baz {
+    type Quux<'a>: Foo where Self: 'a;
+
+    // This weird type tests that we can use universal function call syntax to access the Item on
+    type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>  where Self: 'a;
+}
+
+impl<T> Baz for T where T: Foo {
+//~^ ERROR type mismatch resolving
+    type Quux<'a> where T: 'a = T;
+
+    type Baa<'a> where T: 'a = &'a <T as Foo>::Bar<'a, 'static>;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.stderr b/src/test/ui/generic-associated-types/construct_with_other_type.stderr
new file mode 100644
index 00000000000..bad746f7ef1
--- /dev/null
+++ b/src/test/ui/generic-associated-types/construct_with_other_type.stderr
@@ -0,0 +1,13 @@
+error[E0271]: type mismatch resolving `for<'a> <<T as Baz>::Baa<'a> as std::ops::Deref>::Target == <<T as Baz>::Quux<'a> as Foo>::Bar<'a, 'static>`
+  --> $DIR/construct_with_other_type.rs:19:9
+   |
+LL | impl<T> Baz for T where T: Foo {
+   |         ^^^ expected type parameter `T`, found associated type
+   |
+   = note: expected associated type `<T as Foo>::Bar<'_, 'static>`
+              found associated type `<<T as Baz>::Quux<'_> as Foo>::Bar<'_, 'static>`
+   = note: you might be missing a type parameter or trait bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs b/src/test/ui/generic-associated-types/empty_generics.rs
index afc27701920..522e23ca43d 100644
--- a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
+++ b/src/test/ui/generic-associated-types/empty_generics.rs
@@ -1,5 +1,5 @@
+#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 
 trait Foo {
     type Bar<,>;
diff --git a/src/test/ui/generic-associated-types/empty_generics.stderr b/src/test/ui/generic-associated-types/empty_generics.stderr
new file mode 100644
index 00000000000..d3acad47831
--- /dev/null
+++ b/src/test/ui/generic-associated-types/empty_generics.stderr
@@ -0,0 +1,8 @@
+error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+  --> $DIR/empty_generics.rs:5:14
+   |
+LL |     type Bar<,>;
+   |              ^ expected one of `>`, `const`, identifier, or lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs
new file mode 100644
index 00000000000..f88df6a608a
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs
@@ -0,0 +1,17 @@
+// rust-lang/rust#60654: Do not ICE on an attempt to use GATs that is
+// missing the feature gate.
+
+struct Foo;
+
+trait MyTrait {
+    type Item<T>;
+    //~^ ERROR generic associated types are unstable [E0658]
+    //~| ERROR type-generic associated types are not yet implemented
+}
+
+impl MyTrait for Foo {
+    type Item<T> = T;
+    //~^ ERROR generic associated types are unstable [E0658]
+}
+
+fn main() { }
diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr
new file mode 100644
index 00000000000..a7d280d6359
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr
@@ -0,0 +1,29 @@
+error[E0658]: generic associated types are unstable
+  --> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5
+   |
+LL |     type Item<T>;
+   |     ^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+   = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
+
+error[E0658]: generic associated types are unstable
+  --> $DIR/gat-dont-ice-on-absent-feature-2.rs:13:5
+   |
+LL |     type Item<T> = T;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+   = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5
+   |
+LL |     type Item<T>;
+   |     ^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.rs b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.rs
index 84fbb47301f..e8fc47d2a59 100644
--- a/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.rs
+++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.rs
@@ -4,7 +4,9 @@
 struct Foo;
 
 impl Iterator for Foo {
-    type Item<'b> = &'b Foo; //~ ERROR generic associated types are unstable [E0658]
+    type Item<'b> = &'b Foo;
+    //~^ ERROR generic associated types are unstable [E0658]
+    //~| ERROR lifetime parameters or bounds on type `Item` do not match the trait declaration
 
     fn next(&mut self) -> Option<Self::Item> {
         None
diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr
new file mode 100644
index 00000000000..9031071ff69
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature.stderr
@@ -0,0 +1,19 @@
+error[E0658]: generic associated types are unstable
+  --> $DIR/gat-dont-ice-on-absent-feature.rs:7:5
+   |
+LL |     type Item<'b> = &'b Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+   = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
+
+error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration
+  --> $DIR/gat-dont-ice-on-absent-feature.rs:7:14
+   |
+LL |     type Item<'b> = &'b Foo;
+   |              ^^^^ lifetimes do not match type in trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0195, E0658.
+For more information about an error, try `rustc --explain E0195`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs b/src/test/ui/generic-associated-types/gat-incomplete-warning.rs
index 33593884de3..33593884de3 100644
--- a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs
+++ b/src/test/ui/generic-associated-types/gat-incomplete-warning.rs
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr b/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr
index d75f9fb8451..d75f9fb8451 100644
--- a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr
+++ b/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs
index 01daf307c00..589024e1621 100644
--- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs
+++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs
@@ -1,4 +1,5 @@
-#![feature(generic_associated_types)] //~ WARN `generic_associated_types` is incomplete
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
 
 // Checking the interaction with this other feature
 #![feature(associated_type_defaults)]
@@ -8,8 +9,11 @@ use std::fmt::{Display, Debug};
 trait Foo {
     type Assoc where Self: Sized;
     type Assoc2<T> where T: Display;
+    //~^ ERROR type-generic associated types are not yet implemented
     type Assoc3<T>;
-    type WithDefault<T> where T: Debug = dyn Iterator<Item=T>;
+    //~^ ERROR type-generic associated types are not yet implemented
+    type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
+    //~^ ERROR type-generic associated types are not yet implemented
     type NoGenerics;
 }
 
@@ -19,7 +23,7 @@ impl Foo for Bar {
     type Assoc = usize;
     type Assoc2<T> = Vec<T>;
     type Assoc3<T> where T: Iterator = Vec<T>;
-    type WithDefault<'a, T> = &'a dyn Iterator<T>;
+    type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
     type NoGenerics = ::std::cell::Cell<i32>;
 }
 
diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
new file mode 100644
index 00000000000..2144a5e7d9c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
@@ -0,0 +1,26 @@
+error: type-generic associated types are not yet implemented
+  --> $DIR/generic-associated-types-where.rs:11:5
+   |
+LL |     type Assoc2<T> where T: Display;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/generic-associated-types-where.rs:13:5
+   |
+LL |     type Assoc3<T>;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/generic-associated-types-where.rs:15:5
+   |
+LL |     type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
new file mode 100644
index 00000000000..4b4e59a5124
--- /dev/null
+++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
@@ -0,0 +1,16 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+use std::ops::Deref;
+
+trait Iterable {
+    type Item<'a>;
+    type Iter<'a>: Iterator<Item = Self::Item<'a>>
+        + Deref<Target = Self::Item<'b>>;
+    //~^ ERROR undeclared lifetime
+
+    fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
+    //~^ ERROR undeclared lifetime
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
new file mode 100644
index 00000000000..81137e81dc4
--- /dev/null
+++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
@@ -0,0 +1,15 @@
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:9:37
+   |
+LL |         + Deref<Target = Self::Item<'b>>;
+   |                                     ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'undeclared`
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:12:41
+   |
+LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
+   |                                         ^^^^^^^^^^^ undeclared lifetime
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs
new file mode 100644
index 00000000000..3ffa6c6eec4
--- /dev/null
+++ b/src/test/ui/generic-associated-types/impl_bounds.rs
@@ -0,0 +1,23 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+#![feature(associated_type_defaults)]
+
+trait Foo {
+    type A<'a> where Self: 'a;
+    type B<'a, 'b> where 'a: 'b;
+    type C where Self: Clone;
+}
+
+#[derive(Copy, Clone)]
+struct Fooy<T>(T);
+
+impl<T> Foo for Fooy<T> {
+    type A<'a> where Self: 'static = (&'a ());
+    //~^ ERROR the parameter type `T` may not live long enough
+    type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+    //~^ ERROR lifetime bound not satisfied
+    type C where Self: Copy = String;
+    //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
new file mode 100644
index 00000000000..01799007693
--- /dev/null
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -0,0 +1,46 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/impl_bounds.rs:15:5
+   |
+LL |     type A<'a> where Self: 'static = (&'a ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
+  --> $DIR/impl_bounds.rs:15:5
+   |
+LL |     type A<'a> where Self: 'static = (&'a ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/impl_bounds.rs:17:5
+   |
+LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
+  --> $DIR/impl_bounds.rs:17:16
+   |
+LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+   |                ^^
+note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
+  --> $DIR/impl_bounds.rs:17:12
+   |
+LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+   |            ^^
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/impl_bounds.rs:19:5
+   |
+LL | impl<T> Foo for Fooy<T> {
+   |      - help: consider restricting this bound: `T: std::marker::Copy`
+...
+LL |     type C where Self: Copy = String;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = note: required because of the requirements on the impl of `std::marker::Copy` for `Fooy<T>`
+   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl typebut not on the corresponding associated trait type
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0310, E0478.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/impl_bounds_ok.rs b/src/test/ui/generic-associated-types/impl_bounds_ok.rs
new file mode 100644
index 00000000000..2387b891755
--- /dev/null
+++ b/src/test/ui/generic-associated-types/impl_bounds_ok.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+#![feature(associated_type_defaults)]
+
+trait Foo {
+    type A<'a> where Self: 'a;
+    type B<'a, 'b> where 'a: 'b;
+    type C where Self: Clone;
+}
+
+struct Fooy;
+
+impl Foo for Fooy {
+    type A<'a> = (&'a ());
+    type B<'a, 'b> = (&'a(), &'b ());
+    type C = String;
+}
+
+#[derive(Clone)]
+struct Fooer<T>(T);
+
+impl<T> Foo for Fooer<T> {
+    type A<'x> where T: 'x = (&'x ());
+    type B<'u, 'v> where 'u: 'v = (&'v &'u ());
+    type C where Self: ToOwned = String;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs
new file mode 100644
index 00000000000..53e350aacf8
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs
@@ -0,0 +1,17 @@
+// Check that this program doesn't cause the compiler to error without output.
+
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait Foo {
+    type Assoc3<T>;
+    //~^ type-generic associated types are not yet implemented
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    type Assoc3<T> where T: Iterator = Vec<T>;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
new file mode 100644
index 00000000000..52207d759b9
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
@@ -0,0 +1,10 @@
+error: type-generic associated types are not yet implemented
+  --> $DIR/issue-47206-where-clause.rs:7:5
+   |
+LL |     type Assoc3<T>;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs
new file mode 100644
index 00000000000..2298aa5b0b7
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait Cert {
+    type PublicKey<'a>: From<&'a [u8]>;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs
new file mode 100644
index 00000000000..db0da40aab0
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+// FIXME(generic-associated-types) Investigate why this doesn't compile.
+
+trait Iterator {
+//~^ ERROR the requirement `for<'a> <Self as Iterator>::Item<'a> : 'a` is not satisfied
+    type Item<'a>: 'a;
+}
+
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr
new file mode 100644
index 00000000000..07169700f39
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr
@@ -0,0 +1,15 @@
+error[E0280]: the requirement `for<'a> <Self as Iterator>::Item<'a> : 'a` is not satisfied
+  --> $DIR/issue-62326-parameter-out-of-range.rs:6:1
+   |
+LL |   trait Iterator {
+   |   ^-------------
+   |   |
+   |  _required by `Iterator`
+   | |
+LL | |
+LL | |     type Item<'a>: 'a;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs
new file mode 100644
index 00000000000..105ab4a8adc
--- /dev/null
+++ b/src/test/ui/generic-associated-types/iterable.rs
@@ -0,0 +1,51 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+// FIXME(#30472) normalize enough to handle this.
+
+trait Iterable {
+    type Item<'a> where Self: 'a;
+    type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a>;
+}
+
+// Impl for struct type
+impl<T> Iterable for Vec<T> {
+    type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
+    //~^ ERROR type mismatch resolving
+    type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a> {
+    //~^ ERROR type mismatch resolving
+        self.iter()
+    }
+}
+
+// Impl for a primitive type
+impl<T> Iterable for [T] {
+    type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
+    //~^ ERROR type mismatch resolving
+    type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a> {
+    //~^ ERROR type mismatch resolving
+        self.iter()
+    }
+}
+
+fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
+    it.iter()
+}
+
+fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
+    it.iter().next()
+}
+
+fn main() {
+    let v = vec![1, 2, 3];
+    assert_eq!(v, make_iter(&v).copied().collect());
+    assert_eq!(v, make_iter(&*v).copied().collect());
+    assert_eq!(1, get_first(&v));
+    assert_eq!(1, get_first(&*v));
+}
diff --git a/src/test/ui/generic-associated-types/iterable.stderr b/src/test/ui/generic-associated-types/iterable.stderr
new file mode 100644
index 00000000000..d0d75f3cc63
--- /dev/null
+++ b/src/test/ui/generic-associated-types/iterable.stderr
@@ -0,0 +1,63 @@
+error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
+  --> $DIR/iterable.rs:15:5
+   |
+LL | impl<T> Iterable for Vec<T> {
+   | --------------------------- in this `impl` item
+LL |     type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
+   |
+   = note:    expected reference `&T`
+           found associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
+   = note: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
+  --> $DIR/iterable.rs:27:5
+   |
+LL | impl<T> Iterable for [T] {
+   | ------------------------ in this `impl` item
+LL |     type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
+   |
+   = note:    expected reference `&T`
+           found associated type `<[T] as Iterable>::Item<'_>`
+   = note: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
+  --> $DIR/iterable.rs:19:5
+   |
+LL |   trait Iterable {
+   |   -------------- required by `Iterable`
+...
+LL | /     fn iter<'a>(&'a self) -> Self::Iter<'a> {
+LL | |
+LL | |         self.iter()
+LL | |     }
+   | |_____^ expected associated type, found reference
+   |
+   = note: expected associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
+                    found reference `&T`
+   = note: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` or calling a method that returns `<std::vec::Vec<T> as Iterable>::Item<'_>`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
+  --> $DIR/iterable.rs:31:5
+   |
+LL |   trait Iterable {
+   |   -------------- required by `Iterable`
+...
+LL | /     fn iter<'a>(&'a self) -> Self::Iter<'a> {
+LL | |
+LL | |         self.iter()
+LL | |     }
+   | |_____^ expected associated type, found reference
+   |
+   = note: expected associated type `<[T] as Iterable>::Item<'_>`
+                    found reference `&T`
+   = note: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
new file mode 100644
index 00000000000..0edc5c48c01
--- /dev/null
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs
@@ -0,0 +1,24 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+#![feature(associated_type_defaults)]
+
+trait Foo {
+    type A<'a>;
+    type B<'a, 'b>;
+    type C;
+    type D<T>;
+    //~^ ERROR type-generic associated types are not yet implemented
+    type E<'a, T>;
+    //~^ ERROR type-generic associated types are not yet implemented
+    // Test parameters in default values
+    type FOk<T> = Self::E<'static, T>;
+    //~^ ERROR type-generic associated types are not yet implemented
+    type FErr1 = Self::E<'static, 'static>;
+    //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
+    //~| ERROR wrong number of type arguments: expected 1, found 0
+    type FErr2<T> = Self::E<'static, T, u32>;
+    //~^ ERROR type-generic associated types are not yet implemented
+    //~| ERROR wrong number of type arguments: expected 1, found 2
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
new file mode 100644
index 00000000000..6b5683611a2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr
@@ -0,0 +1,53 @@
+error: type-generic associated types are not yet implemented
+  --> $DIR/parameter_number_and_kind.rs:9:5
+   |
+LL |     type D<T>;
+   |     ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/parameter_number_and_kind.rs:11:5
+   |
+LL |     type E<'a, T>;
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/parameter_number_and_kind.rs:14:5
+   |
+LL |     type FOk<T> = Self::E<'static, T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/parameter_number_and_kind.rs:19:5
+   |
+LL |     type FErr2<T> = Self::E<'static, T, u32>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error[E0107]: wrong number of lifetime arguments: expected 1, found 2
+  --> $DIR/parameter_number_and_kind.rs:16:35
+   |
+LL |     type FErr1 = Self::E<'static, 'static>;
+   |                                   ^^^^^^^ unexpected lifetime argument
+
+error[E0107]: wrong number of type arguments: expected 1, found 0
+  --> $DIR/parameter_number_and_kind.rs:16:18
+   |
+LL |     type FErr1 = Self::E<'static, 'static>;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
+
+error[E0107]: wrong number of type arguments: expected 1, found 2
+  --> $DIR/parameter_number_and_kind.rs:19:41
+   |
+LL |     type FErr2<T> = Self::E<'static, T, u32>;
+   |                                         ^^^ unexpected type argument
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs
new file mode 100644
index 00000000000..74b9cec1da3
--- /dev/null
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs
@@ -0,0 +1,35 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+#![feature(associated_type_defaults)]
+
+// FIXME(#44265) add tests for type-generic and const-genertic associated types.
+
+trait Foo {
+    type A<'a>;
+    type B<'a, 'b>;
+    type C;
+}
+
+struct Fooy;
+
+impl Foo for Fooy {
+    type A = u32;
+    //~^ ERROR lifetime parameters or bounds on type `A` do not match the trait declaration
+    type B<'a, T> = Vec<T>;
+    //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters
+    type C<'a> = u32;
+    //~^ ERROR lifetime parameters or bounds on type `C` do not match the trait declaration
+}
+
+struct Fooer;
+
+impl Foo for Fooer {
+    type A<T> = u32;
+    //~^ ERROR type `A` has 1 type parameter but its trait declaration has 0 type parameters
+    type B<'a> = u32;
+    //~^ ERROR lifetime parameters or bounds on type `B` do not match the trait declaration
+    type C<T> = T;
+    //~^ ERROR type `C` has 1 type parameter but its trait declaration has 0 type parameters
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
new file mode 100644
index 00000000000..bdd1c895fd9
--- /dev/null
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
@@ -0,0 +1,62 @@
+error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration
+  --> $DIR/parameter_number_and_kind_impl.rs:16:11
+   |
+LL |     type A<'a>;
+   |           ---- lifetimes in impl do not match this type in trait
+...
+LL |     type A = u32;
+   |           ^ lifetimes do not match type in trait
+
+error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/parameter_number_and_kind_impl.rs:18:12
+   |
+LL |     type B<'a, 'b>;
+   |            --  --
+   |            |
+   |            expected 0 type parameters
+...
+LL |     type B<'a, T> = Vec<T>;
+   |            ^^  ^
+   |            |
+   |            found 1 type parameter
+
+error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration
+  --> $DIR/parameter_number_and_kind_impl.rs:20:11
+   |
+LL |     type C;
+   |           - lifetimes in impl do not match this type in trait
+...
+LL |     type C<'a> = u32;
+   |           ^^^^ lifetimes do not match type in trait
+
+error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/parameter_number_and_kind_impl.rs:27:12
+   |
+LL |     type A<'a>;
+   |            -- expected 0 type parameters
+...
+LL |     type A<T> = u32;
+   |            ^ found 1 type parameter
+
+error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration
+  --> $DIR/parameter_number_and_kind_impl.rs:29:11
+   |
+LL |     type B<'a, 'b>;
+   |           -------- lifetimes in impl do not match this type in trait
+...
+LL |     type B<'a> = u32;
+   |           ^^^^ lifetimes do not match type in trait
+
+error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/parameter_number_and_kind_impl.rs:31:12
+   |
+LL |     type C;
+   |           - expected 0 type parameters
+...
+LL |     type C<T> = T;
+   |            ^ found 1 type parameter
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0049, E0195.
+For more information about an error, try `rustc --explain E0049`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/generic-associated-types/parse/in-trait-impl.rs
index 9fc32d7cc55..7f4775ddbb0 100644
--- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
+++ b/src/test/ui/generic-associated-types/parse/in-trait-impl.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // compile-flags: -Z parse-only
 
 #![feature(generic_associated_types)]
diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs b/src/test/ui/generic-associated-types/parse/in-trait.rs
index 7974ee9d39b..d438795eb1d 100644
--- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
+++ b/src/test/ui/generic-associated-types/parse/in-trait.rs
@@ -1,9 +1,10 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // compile-flags: -Z parse-only
 
 #![feature(generic_associated_types)]
 
 use std::ops::Deref;
+use std::fmt::Debug;
 
 trait Foo {
     type Bar<'a>;
diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs b/src/test/ui/generic-associated-types/pointer_family.rs
index edeeaba7565..1668759b4e3 100644
--- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs
+++ b/src/test/ui/generic-associated-types/pointer_family.rs
@@ -1,7 +1,7 @@
+#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
 
-// FIXME(#44265): "type argument not allowed" errors will be addressed in a follow-up PR.
+// FIXME(#44265): allow type-generic associated types.
 
 use std::rc::Rc;
 use std::sync::Arc;
@@ -9,8 +9,8 @@ use std::ops::Deref;
 
 trait PointerFamily {
     type Pointer<T>: Deref<Target = T>;
+    //~^ ERROR type-generic associated types are not yet implemented
     fn new<T>(value: T) -> Self::Pointer<T>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
 }
 
 struct ArcFamily;
@@ -18,7 +18,6 @@ struct ArcFamily;
 impl PointerFamily for ArcFamily {
     type Pointer<T> = Arc<T>;
     fn new<T>(value: T) -> Self::Pointer<T> {
-    //~^ ERROR type arguments are not allowed for this type [E0109]
         Arc::new(value)
     }
 }
@@ -28,14 +27,12 @@ struct RcFamily;
 impl PointerFamily for RcFamily {
     type Pointer<T> = Rc<T>;
     fn new<T>(value: T) -> Self::Pointer<T> {
-    //~^ ERROR type arguments are not allowed for this type [E0109]
         Rc::new(value)
     }
 }
 
 struct Foo<P: PointerFamily> {
     bar: P::Pointer<String>,
-    //~^ ERROR type arguments are not allowed for this type [E0109]
 }
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/pointer_family.stderr b/src/test/ui/generic-associated-types/pointer_family.stderr
new file mode 100644
index 00000000000..2a784f8b9d7
--- /dev/null
+++ b/src/test/ui/generic-associated-types/pointer_family.stderr
@@ -0,0 +1,10 @@
+error: type-generic associated types are not yet implemented
+  --> $DIR/pointer_family.rs:11:5
+   |
+LL |     type Pointer<T>: Deref<Target = T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs
index f5197fd01bf..7277c0d87c6 100644
--- a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
+++ b/src/test/ui/generic-associated-types/shadowing.rs
@@ -16,15 +16,19 @@ impl<'a> NoShadow<'a> for &'a u32 {
 }
 
 trait ShadowT<T> {
-    type Bar<T>; //~ ERROR the name `T` is already used
+    type Bar<T>;
+    //~^ ERROR the name `T` is already used
+    //~| ERROR type-generic associated types are not yet implemented
 }
 
 trait NoShadowT<T> {
     type Bar<U>; // OK
+    //~^ ERROR type-generic associated types are not yet implemented
 }
 
 impl<T> NoShadowT<T> for Option<T> {
-    type Bar<T> = i32; //~ ERROR the name `T` is already used
+    type Bar<T> = i32;
+    //~^ ERROR the name `T` is already used
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr
index a06c6350845..50c12e822e7 100644
--- a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
+++ b/src/test/ui/generic-associated-types/shadowing.stderr
@@ -7,13 +7,29 @@ LL |     type Bar<T>;
    |              ^ already used
 
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowing.rs:27:14
+  --> $DIR/shadowing.rs:30:14
    |
 LL | impl<T> NoShadowT<T> for Option<T> {
    |      - first use of `T`
 LL |     type Bar<T> = i32;
    |              ^ already used
 
-error: aborting due to 2 previous errors
+error: type-generic associated types are not yet implemented
+  --> $DIR/shadowing.rs:19:5
+   |
+LL |     type Bar<T>;
+   |     ^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/shadowing.rs:25:5
+   |
+LL |     type Bar<U>; // OK
+   |     ^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/ui/generic-associated-types/streaming_iterator.rs
index 4e177fb41d7..d814f7140d9 100644
--- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs
+++ b/src/test/ui/generic-associated-types/streaming_iterator.rs
@@ -1,30 +1,26 @@
-#![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
+// run-pass
 
-// FIXME(#44265): "lifetime argument not allowed on this type" errors will be addressed in a
-// follow-up PR
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
 
 use std::fmt::Display;
 
 trait StreamingIterator {
     type Item<'a>;
     // Applying the lifetime parameter `'a` to `Self::Item` inside the trait.
-    fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
 }
 
 struct Foo<T: StreamingIterator> {
     // Applying a concrete lifetime to the constructor outside the trait.
     bar: <T as StreamingIterator>::Item<'static>,
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
 }
 
 // Users can bound parameters by the type constructed by that trait's associated type constructor
 // of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid:
-//FIXME(sunjay): This next line should parse and be valid
-//fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(iter: T) { /* ... */ }
-fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
-//~^ ERROR lifetime arguments are not allowed for this type [E0109]
+//FIXME(#44265): This next line should parse and be valid
+//fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(_iter: T) { /* ... */ }
+fn _foo<T>(_iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
 
 // Full example of enumerate iterator
 
@@ -36,9 +32,7 @@ struct StreamEnumerate<I> {
 
 impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
     type Item<'a> = (usize, I::Item<'a>);
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-    fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
-        //~^ ERROR lifetime arguments are not allowed for this type [E0109]
+    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
         match self.iter.next() {
             None => None,
             Some(val) => {
@@ -50,24 +44,34 @@ impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
     }
 }
 
+impl<I: Iterator> StreamingIterator for I {
+    type Item<'a> = <I as Iterator>::Item;
+    fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> {
+        Iterator::next(self)
+    }
+}
+
 impl<I> StreamEnumerate<I> {
     pub fn new(iter: I) -> Self {
         StreamEnumerate {
             count: 0,
-            iter: iter,
+            iter,
         }
     }
 }
 
 fn test_stream_enumerate() {
     let v = vec!["a", "b", "c"];
-    let se = StreamEnumerate::new(v.iter());
-    let a: &str = se.next().unwrap().1;
-    for (i, s) in se {
-        println!("{} {}", i, s);
+    let mut se = StreamEnumerate::new(v.iter());
+    while let Some(item) = se.next() {
+        assert_eq!(v[item.0], *item.1);
     }
-    println!("{}", a);
+    let x = Foo::<std::slice::Iter<'static, u32>> {
+        bar: &0u32,
+    };
+    assert_eq!(*x.bar, 0u32);
 }
 
-
-fn main() {}
+fn main() {
+    test_stream_enumerate();
+}
diff --git a/src/test/ui/huge-array-simple-32.rs b/src/test/ui/huge-array-simple-32.rs
index 9f98f4d7531..3e574dfa07b 100644
--- a/src/test/ui/huge-array-simple-32.rs
+++ b/src/test/ui/huge-array-simple-32.rs
@@ -1,4 +1,5 @@
 // ignore-64bit
+// build-fail
 
 // FIXME https://github.com/rust-lang/rust/issues/59774
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
diff --git a/src/test/ui/huge-array-simple-32.stderr b/src/test/ui/huge-array-simple-32.stderr
index 16372b02750..d734a9689e0 100644
--- a/src/test/ui/huge-array-simple-32.stderr
+++ b/src/test/ui/huge-array-simple-32.stderr
@@ -1,5 +1,5 @@
 error: the type `[u8; 2147516416]` is too big for the current architecture
-  --> $DIR/huge-array-simple-32.rs:9:9
+  --> $DIR/huge-array-simple-32.rs:10:9
    |
 LL |     let _fat: [u8; (1<<31)+(1<<15)] =
    |         ^^^^
diff --git a/src/test/ui/huge-array-simple-64.rs b/src/test/ui/huge-array-simple-64.rs
index f72d69ee747..d4c93301283 100644
--- a/src/test/ui/huge-array-simple-64.rs
+++ b/src/test/ui/huge-array-simple-64.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-32bit
 
 // FIXME https://github.com/rust-lang/rust/issues/59774
diff --git a/src/test/ui/huge-array-simple-64.stderr b/src/test/ui/huge-array-simple-64.stderr
index 6ed89269f0f..791baa84687 100644
--- a/src/test/ui/huge-array-simple-64.stderr
+++ b/src/test/ui/huge-array-simple-64.stderr
@@ -1,5 +1,5 @@
 error: the type `[u8; 2305843011361177600]` is too big for the current architecture
-  --> $DIR/huge-array-simple-64.rs:9:9
+  --> $DIR/huge-array-simple-64.rs:10:9
    |
 LL |     let _fat: [u8; (1<<61)+(1<<31)] =
    |         ^^^^
diff --git a/src/test/ui/huge-array.rs b/src/test/ui/huge-array.rs
index 1ecf012e04b..846380586a0 100644
--- a/src/test/ui/huge-array.rs
+++ b/src/test/ui/huge-array.rs
@@ -1,4 +1,6 @@
 // FIXME https://github.com/rust-lang/rust/issues/59774
+
+// build-fail
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
 
diff --git a/src/test/ui/huge-array.stderr b/src/test/ui/huge-array.stderr
index 823d974f429..23d9e87ae00 100644
--- a/src/test/ui/huge-array.stderr
+++ b/src/test/ui/huge-array.stderr
@@ -1,5 +1,5 @@
 error: the type `[[u8; 1518599999]; 1518600000]` is too big for the current architecture
-  --> $DIR/huge-array.rs:6:9
+  --> $DIR/huge-array.rs:8:9
    |
 LL |     let s: [T; 1518600000] = [t; 1518600000];
    |         ^
diff --git a/src/test/ui/huge-enum.rs b/src/test/ui/huge-enum.rs
index 98d0ba6e15c..8a713c3a26e 100644
--- a/src/test/ui/huge-enum.rs
+++ b/src/test/ui/huge-enum.rs
@@ -1,3 +1,4 @@
+// build-fail
 // normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE"
 // normalize-stderr-test "\[u32; \d+\]" -> "TYPE"
 
diff --git a/src/test/ui/huge-enum.stderr b/src/test/ui/huge-enum.stderr
index 1f16c81a8f4..8398c511b9f 100644
--- a/src/test/ui/huge-enum.stderr
+++ b/src/test/ui/huge-enum.stderr
@@ -1,5 +1,5 @@
 error: the type `TYPE` is too big for the current architecture
-  --> $DIR/huge-enum.rs:15:9
+  --> $DIR/huge-enum.rs:16:9
    |
 LL |     let big: BIG = None;
    |         ^^^
diff --git a/src/test/ui/huge-struct.rs b/src/test/ui/huge-struct.rs
index e50ca5f54d1..71169a11047 100644
--- a/src/test/ui/huge-struct.rs
+++ b/src/test/ui/huge-struct.rs
@@ -1,3 +1,4 @@
+// build-fail
 // normalize-stderr-test "S32" -> "SXX"
 // normalize-stderr-test "S1M" -> "SXX"
 // error-pattern: too big for the current
diff --git a/src/test/ui/huge-struct.stderr b/src/test/ui/huge-struct.stderr
index 5c2140df481..72e32a8593b 100644
--- a/src/test/ui/huge-struct.stderr
+++ b/src/test/ui/huge-struct.stderr
@@ -1,5 +1,5 @@
 error: the type `SXX<SXX<SXX<u32>>>` is too big for the current architecture
-  --> $DIR/huge-struct.rs:49:9
+  --> $DIR/huge-struct.rs:50:9
    |
 LL |     let fat: Option<SXX<SXX<SXX<u32>>>> = None;
    |         ^^^
diff --git a/src/test/ui/infinite/infinite-instantiation.rs b/src/test/ui/infinite/infinite-instantiation.rs
index 4220c8837d2..6f53680f7c8 100644
--- a/src/test/ui/infinite/infinite-instantiation.rs
+++ b/src/test/ui/infinite/infinite-instantiation.rs
@@ -4,6 +4,8 @@
 // so for now just live with it.
 // This test case was originally for issue #2258.
 
+// build-fail
+
 trait ToOpt: Sized {
     fn to_option(&self) -> Option<Self>;
 }
diff --git a/src/test/ui/infinite/infinite-instantiation.stderr b/src/test/ui/infinite/infinite-instantiation.stderr
index d75dc0403a2..ae81c680a7b 100644
--- a/src/test/ui/infinite/infinite-instantiation.stderr
+++ b/src/test/ui/infinite/infinite-instantiation.stderr
@@ -1,5 +1,5 @@
 error: reached the recursion limit while instantiating `function::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<usize>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/infinite-instantiation.rs:23:1
+  --> $DIR/infinite-instantiation.rs:25:1
    |
 LL | / fn function<T:ToOpt + Clone>(counter: usize, t: T) {
 LL | |
diff --git a/src/test/ui/inline-asm-bad-constraint.rs b/src/test/ui/inline-asm-bad-constraint.rs
index cf72afff50b..04fd5760cf8 100644
--- a/src/test/ui/inline-asm-bad-constraint.rs
+++ b/src/test/ui/inline-asm-bad-constraint.rs
@@ -1,5 +1,6 @@
 // Test that the compiler will catch invalid inline assembly constraints.
 
+// build-fail
 // ignore-emscripten
 
 #![feature(asm)]
diff --git a/src/test/ui/inline-asm-bad-constraint.stderr b/src/test/ui/inline-asm-bad-constraint.stderr
index 59066e5e7fc..f38bfb2af1d 100644
--- a/src/test/ui/inline-asm-bad-constraint.stderr
+++ b/src/test/ui/inline-asm-bad-constraint.stderr
@@ -1,17 +1,17 @@
 error[E0668]: malformed inline assembly
-  --> $DIR/inline-asm-bad-constraint.rs:21:9
+  --> $DIR/inline-asm-bad-constraint.rs:22:9
    |
 LL |         asm!("" :"={rax"(rax))
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0668]: malformed inline assembly
-  --> $DIR/inline-asm-bad-constraint.rs:29:9
+  --> $DIR/inline-asm-bad-constraint.rs:30:9
    |
 LL |         asm!("callq $0" : : "0"(foo))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0668]: malformed inline assembly
-  --> $DIR/inline-asm-bad-constraint.rs:36:9
+  --> $DIR/inline-asm-bad-constraint.rs:37:9
    |
 LL |         asm!("addb $1, $0" : "={rax}"((0i32, rax)));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/inline-asm-bad-operand.rs b/src/test/ui/inline-asm-bad-operand.rs
index 4cfe100d85b..f4e9922164f 100644
--- a/src/test/ui/inline-asm-bad-operand.rs
+++ b/src/test/ui/inline-asm-bad-operand.rs
@@ -1,6 +1,7 @@
 // Test that the compiler will catch passing invalid values to inline assembly
 // operands.
 
+// build-fail
 // ignore-emscripten
 
 #![feature(asm)]
diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr
index b8e7e9acfec..fe6c6c99141 100644
--- a/src/test/ui/inline-asm-bad-operand.stderr
+++ b/src/test/ui/inline-asm-bad-operand.stderr
@@ -1,41 +1,41 @@
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:21:24
+  --> $DIR/inline-asm-bad-operand.rs:22:24
    |
 LL |         asm!("" :: "r"(""));
    |                        ^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:26:32
+  --> $DIR/inline-asm-bad-operand.rs:27:32
    |
 LL |         asm!("ret" : : "{rdi}"(target));
    |                                ^^^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:33:29
+  --> $DIR/inline-asm-bad-operand.rs:34:29
    |
 LL |     unsafe { asm!("" :: "i"(hello)) };
    |                             ^^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:41:38
+  --> $DIR/inline-asm-bad-operand.rs:42:38
    |
 LL |         asm!("movups $1, %xmm0"::"m"(arr));
    |                                      ^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:48:32
+  --> $DIR/inline-asm-bad-operand.rs:49:32
    |
 LL |         asm!("mov sp, $0"::"r"(addr));
    |                                ^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:55:32
+  --> $DIR/inline-asm-bad-operand.rs:56:32
    |
 LL |         asm!("mov sp, $0"::"r"(addr),
    |                                ^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:56:32
+  --> $DIR/inline-asm-bad-operand.rs:57:32
    |
 LL | ...                   "r"("hello e0669"));
    |                           ^^^^^^^^^^^^^
diff --git a/src/test/ui/internal/auxiliary/internal_unstable.rs b/src/test/ui/internal/auxiliary/internal_unstable.rs
index 7c79dcb7522..148cbd1899e 100644
--- a/src/test/ui/internal/auxiliary/internal_unstable.rs
+++ b/src/test/ui/internal/auxiliary/internal_unstable.rs
@@ -1,24 +1,24 @@
 #![feature(staged_api, allow_internal_unstable)]
 #![stable(feature = "stable", since = "1.0.0")]
 
-#[unstable(feature = "function", issue = "0")]
+#[unstable(feature = "function", issue = "none")]
 pub fn unstable() {}
 
 
 #[stable(feature = "stable", since = "1.0.0")]
 pub struct Foo {
-    #[unstable(feature = "struct_field", issue = "0")]
+    #[unstable(feature = "struct_field", issue = "none")]
     pub x: u8
 }
 
 impl Foo {
-    #[unstable(feature = "method", issue = "0")]
+    #[unstable(feature = "method", issue = "none")]
     pub fn method(&self) {}
 }
 
 #[stable(feature = "stable", since = "1.0.0")]
 pub struct Bar {
-    #[unstable(feature = "struct2_field", issue = "0")]
+    #[unstable(feature = "struct2_field", issue = "none")]
     pub x: u8
 }
 
diff --git a/src/test/ui/invalid/invalid-variadic-function.rs b/src/test/ui/invalid/invalid-variadic-function.rs
deleted file mode 100644
index 8d23f0e4770..00000000000
--- a/src/test/ui/invalid/invalid-variadic-function.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-extern "C" fn foo(x: u8, ...);
-//~^ ERROR only foreign functions are allowed to be C-variadic
-//~| ERROR expected one of `->`, `where`, or `{`, found `;`
diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr
deleted file mode 100644
index 7e58b17e7db..00000000000
--- a/src/test/ui/invalid/invalid-variadic-function.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0743]: only foreign functions are allowed to be C-variadic
-  --> $DIR/invalid-variadic-function.rs:1:26
-   |
-LL | extern "C" fn foo(x: u8, ...);
-   |                          ^^^
-
-error: expected one of `->`, `where`, or `{`, found `;`
-  --> $DIR/invalid-variadic-function.rs:1:30
-   |
-LL | extern "C" fn foo(x: u8, ...);
-   |                              ^ expected one of `->`, `where`, or `{`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0743`.
diff --git a/src/test/ui/issues/auxiliary/issue-52489.rs b/src/test/ui/issues/auxiliary/issue-52489.rs
index c649930c2b4..f53bf7db525 100644
--- a/src/test/ui/issues/auxiliary/issue-52489.rs
+++ b/src/test/ui/issues/auxiliary/issue-52489.rs
@@ -1,3 +1,3 @@
 #![crate_type = "lib"]
-#![unstable(feature = "issue_52489_unstable", issue = "0")]
+#![unstable(feature = "issue_52489_unstable", issue = "none")]
 #![feature(staged_api)]
diff --git a/src/test/ui/issues/auxiliary/lint-stability.rs b/src/test/ui/issues/auxiliary/lint-stability.rs
index 3188d706ab0..de4058887cf 100644
--- a/src/test/ui/issues/auxiliary/lint-stability.rs
+++ b/src/test/ui/issues/auxiliary/lint-stability.rs
@@ -15,16 +15,16 @@ pub fn deprecated_text() {}
 #[rustc_deprecated(since = "99.99.99", reason = "text")]
 pub fn deprecated_future() {}
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_unstable() {}
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_unstable_text() {}
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub fn unstable() {}
-#[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
 pub fn unstable_text() {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -43,16 +43,16 @@ impl MethodTester {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_unstable_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub fn method_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     pub fn method_unstable_text(&self) {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -70,16 +70,16 @@ pub trait Trait {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_unstable_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     fn trait_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     fn trait_unstable_text(&self) {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -90,7 +90,7 @@ pub trait Trait {
 
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 pub trait TraitWithAssociatedTypes {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     type TypeUnstable = u8;
     #[stable(feature = "stable_test_feature", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
@@ -100,7 +100,7 @@ pub trait TraitWithAssociatedTypes {
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 impl Trait for MethodTester {}
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub trait UnstableTrait { fn dummy(&self) { } }
 
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
@@ -114,12 +114,12 @@ pub trait DeprecatedTrait {
 pub struct DeprecatedStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct UnstableStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
@@ -127,7 +127,7 @@ pub struct UnstableStruct {
 pub struct StableStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub enum UnstableEnum {}
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum StableEnum {}
@@ -135,10 +135,10 @@ pub enum StableEnum {}
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnitStruct;
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableUnitStruct;
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct UnstableUnitStruct;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableUnitStruct;
@@ -148,10 +148,10 @@ pub enum Enum {
     #[stable(feature = "stable_test_feature", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     DeprecatedVariant,
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     DeprecatedUnstableVariant,
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     UnstableVariant,
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -161,10 +161,10 @@ pub enum Enum {
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
diff --git a/src/test/ui/issues/issue-11154.rs b/src/test/ui/issues/issue-11154.rs
index 7513abd8a5b..e11cdc82f32 100644
--- a/src/test/ui/issues/issue-11154.rs
+++ b/src/test/ui/issues/issue-11154.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -C lto -C prefer-dynamic
 
 // error-pattern: cannot prefer dynamic linking
diff --git a/src/test/ui/issues/issue-15919-32.rs b/src/test/ui/issues/issue-15919-32.rs
index 65d33a61348..3c93f14ccc7 100644
--- a/src/test/ui/issues/issue-15919-32.rs
+++ b/src/test/ui/issues/issue-15919-32.rs
@@ -1,4 +1,5 @@
 // ignore-64bit
+// build-fail
 
 // FIXME https://github.com/rust-lang/rust/issues/59774
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
diff --git a/src/test/ui/issues/issue-15919-32.stderr b/src/test/ui/issues/issue-15919-32.stderr
index 7f5d9262d39..8411313fc81 100644
--- a/src/test/ui/issues/issue-15919-32.stderr
+++ b/src/test/ui/issues/issue-15919-32.stderr
@@ -1,5 +1,5 @@
 error: the type `[usize; 4294967295]` is too big for the current architecture
-  --> $DIR/issue-15919-32.rs:8:9
+  --> $DIR/issue-15919-32.rs:9:9
    |
 LL |     let x = [0usize; 0xffff_ffff];
    |         ^
diff --git a/src/test/ui/issues/issue-15919-64.rs b/src/test/ui/issues/issue-15919-64.rs
index abd20cc1cee..3ecbd34eaaa 100644
--- a/src/test/ui/issues/issue-15919-64.rs
+++ b/src/test/ui/issues/issue-15919-64.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-32bit
 
 // FIXME https://github.com/rust-lang/rust/issues/59774
diff --git a/src/test/ui/issues/issue-15919-64.stderr b/src/test/ui/issues/issue-15919-64.stderr
index 571b87d9961..f624c96ce84 100644
--- a/src/test/ui/issues/issue-15919-64.stderr
+++ b/src/test/ui/issues/issue-15919-64.stderr
@@ -1,5 +1,5 @@
 error: the type `[usize; 18446744073709551615]` is too big for the current architecture
-  --> $DIR/issue-15919-64.rs:8:9
+  --> $DIR/issue-15919-64.rs:9:9
    |
 LL |     let x = [0usize; 0xffff_ffff_ffff_ffff];
    |         ^
diff --git a/src/test/ui/issues/issue-17337.rs b/src/test/ui/issues/issue-17337.rs
index 1126ab7a206..65f2f8fc5ac 100644
--- a/src/test/ui/issues/issue-17337.rs
+++ b/src/test/ui/issues/issue-17337.rs
@@ -1,12 +1,12 @@
 #![feature(staged_api)]
 #![deny(deprecated)]
 
-#![unstable(feature = "unstable_test_feature", issue = "0")]
+#![unstable(feature = "unstable_test_feature", issue = "none")]
 
 struct Foo;
 
 impl Foo {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn foo(self) {}
 }
diff --git a/src/test/ui/issues/issue-17913.rs b/src/test/ui/issues/issue-17913.rs
index 48d8f407aa1..ca13b9bd6ae 100644
--- a/src/test/ui/issues/issue-17913.rs
+++ b/src/test/ui/issues/issue-17913.rs
@@ -1,3 +1,4 @@
+// build-fail
 // normalize-stderr-test "\[&usize; \d+\]" -> "[&usize; N]"
 // error-pattern: too big for the current architecture
 
diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs
index fab24404eba..72c16fddb4b 100644
--- a/src/test/ui/issues/issue-22638.rs
+++ b/src/test/ui/issues/issue-22638.rs
@@ -1,3 +1,4 @@
+// build-fail
 // normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`"
 
 #![allow(unused)]
diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr
index b60e1c29ec0..83dd93b853d 100644
--- a/src/test/ui/issues/issue-22638.stderr
+++ b/src/test/ui/issues/issue-22638.stderr
@@ -1,5 +1,5 @@
 error: reached the type-length limit while instantiating `D::matches::$CLOSURE`
-  --> $DIR/issue-22638.rs:52:5
+  --> $DIR/issue-22638.rs:53:5
    |
 LL | /     pub fn matches<F: Fn()>(&self, f: &F) {
 LL | |
diff --git a/src/test/ui/issues/issue-23458.rs b/src/test/ui/issues/issue-23458.rs
index 90b3f1f9714..521db37170a 100644
--- a/src/test/ui/issues/issue-23458.rs
+++ b/src/test/ui/issues/issue-23458.rs
@@ -1,5 +1,6 @@
 #![feature(asm)]
 
+// build-fail
 // only-x86_64
 
 fn main() {
diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/issues/issue-23458.stderr
index aff0f82af6f..76c3e6da82e 100644
--- a/src/test/ui/issues/issue-23458.stderr
+++ b/src/test/ui/issues/issue-23458.stderr
@@ -1,5 +1,5 @@
 error: invalid operand in inline asm: 'int $3'
-  --> $DIR/issue-23458.rs:7:9
+  --> $DIR/issue-23458.rs:8:9
    |
 LL |         asm!("int $3");
    |         ^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ error: <inline asm>:1:2: error: too few operands for instruction
         int 
         ^
 
-  --> $DIR/issue-23458.rs:7:9
+  --> $DIR/issue-23458.rs:8:9
    |
 LL |         asm!("int $3");
    |         ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-26548.rs b/src/test/ui/issues/issue-26548.rs
index 5b6c77d0bd1..6ee8c0fcfda 100644
--- a/src/test/ui/issues/issue-26548.rs
+++ b/src/test/ui/issues/issue-26548.rs
@@ -2,6 +2,8 @@
 //~| NOTE ...which requires computing layout of
 //~| NOTE ...which again requires computing layout of
 
+// build-fail
+
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
 struct S(Option<<S as Mirror>::It>);
diff --git a/src/test/ui/issues/issue-26548.stderr b/src/test/ui/issues/issue-26548.stderr
index 7c1789cc1e9..3c213674e4b 100644
--- a/src/test/ui/issues/issue-26548.stderr
+++ b/src/test/ui/issues/issue-26548.stderr
@@ -3,7 +3,7 @@ error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
    = note: ...which requires computing layout of `S`...
    = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
 note: cycle used when processing `main`
-  --> $DIR/issue-26548.rs:9:1
+  --> $DIR/issue-26548.rs:11:1
    |
 LL | fn main() {
    | ^^^^^^^^^
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
index 9a8dafe1394..fec4b171536 100644
--- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 trait Mirror {
     type Image;
 }
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
index aead415d23f..7a4b59b5633 100644
--- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
@@ -1,5 +1,5 @@
 error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse`
-  --> $DIR/issue-37311.rs:13:5
+  --> $DIR/issue-37311.rs:15:5
    |
 LL | /     fn recurse(&self) {
 LL | |         (self, self).recurse();
diff --git a/src/test/ui/issues/issue-37433.rs b/src/test/ui/issues/issue-37433.rs
index d3663e24e60..c4d427f3ad3 100644
--- a/src/test/ui/issues/issue-37433.rs
+++ b/src/test/ui/issues/issue-37433.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-emscripten no asm! support
 
 #![feature(asm)]
diff --git a/src/test/ui/issues/issue-37433.stderr b/src/test/ui/issues/issue-37433.stderr
index 956694fc2cd..d9e1c98e9ee 100644
--- a/src/test/ui/issues/issue-37433.stderr
+++ b/src/test/ui/issues/issue-37433.stderr
@@ -1,5 +1,5 @@
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/issue-37433.rs:7:24
+  --> $DIR/issue-37433.rs:8:24
    |
 LL |         asm!("" :: "r"(""));
    |                        ^^
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.rs b/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
index 09e8d55c06b..d911ac5efbe 100644
--- a/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
+++ b/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
@@ -1,5 +1,6 @@
 // Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
 
+// build-fail
 // ignore-emscripten
 
 #![feature(asm)]
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
index f96bcaa492c..b066474f924 100644
--- a/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
+++ b/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
@@ -1,5 +1,5 @@
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/issue-53787-inline-assembler-macro.rs:23:16
+  --> $DIR/issue-53787-inline-assembler-macro.rs:24:16
    |
 LL |     fake_jump!("FirstFunc");
    |                ^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs
index 68d83805477..fd9a9e024aa 100644
--- a/src/test/ui/issues/issue-54348.rs
+++ b/src/test/ui/issues/issue-54348.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 fn main() {
     [1][0u64 as usize];
     [1][1.5 as usize]; //~ ERROR index out of bounds
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
index fa77bd6fd77..7619cd7437e 100644
--- a/src/test/ui/issues/issue-54348.stderr
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -1,5 +1,5 @@
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/issue-54348.rs:3:5
+  --> $DIR/issue-54348.rs:5:5
    |
 LL |     [1][1.5 as usize];
    |     ^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     [1][1.5 as usize];
    = note: `#[deny(const_err)]` on by default
 
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/issue-54348.rs:4:5
+  --> $DIR/issue-54348.rs:6:5
    |
 LL |     [1][1u64 as usize];
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs
index db3984cd189..8b1a39a94e6 100644
--- a/src/test/ui/issues/issue-58856-1.rs
+++ b/src/test/ui/issues/issue-58856-1.rs
@@ -1,6 +1,8 @@
 impl A {
+    //~^ ERROR cannot find type `A` in this scope
     fn b(self>
     //~^ ERROR expected one of `)`, `,`, or `:`, found `>`
+    //~| ERROR expected `;` or `{`, found `>`
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr
index 58ab0a142d6..0ea6b017548 100644
--- a/src/test/ui/issues/issue-58856-1.stderr
+++ b/src/test/ui/issues/issue-58856-1.stderr
@@ -1,10 +1,23 @@
 error: expected one of `)`, `,`, or `:`, found `>`
-  --> $DIR/issue-58856-1.rs:2:14
+  --> $DIR/issue-58856-1.rs:3:14
    |
 LL |     fn b(self>
    |         -    ^ help: `)` may belong here
    |         |
    |         unclosed delimiter
 
-error: aborting due to previous error
+error: expected `;` or `{`, found `>`
+  --> $DIR/issue-58856-1.rs:3:14
+   |
+LL |     fn b(self>
+   |              ^ expected `;` or `{`
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/issue-58856-1.rs:1:6
+   |
+LL | impl A {
+   |      ^ not found in this scope
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-58857.rs b/src/test/ui/issues/issue-58857.rs
index 392e4ea0c2e..4350d7e5b40 100644
--- a/src/test/ui/issues/issue-58857.rs
+++ b/src/test/ui/issues/issue-58857.rs
@@ -2,6 +2,6 @@ struct Conj<A> {a : A}
 trait Valid {}
 
 impl<A: !Valid> Conj<A>{}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-58857.stderr b/src/test/ui/issues/issue-58857.stderr
index ab9a0130c00..e2acec47e5a 100644
--- a/src/test/ui/issues/issue-58857.stderr
+++ b/src/test/ui/issues/issue-58857.stderr
@@ -1,10 +1,8 @@
-error: negative trait bounds are not supported
+error: negative bounds are not supported
   --> $DIR/issue-58857.rs:4:7
    |
 LL | impl<A: !Valid> Conj<A>{}
-   |       ^^^^^^^^ negative trait bounds are not supported
-   |
-   = help: remove the trait bound
+   |       ^^^^^^^^ negative bounds are not supported
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr
index e0b15130c33..e8ef981f515 100644
--- a/src/test/ui/issues/issue-60075.stderr
+++ b/src/test/ui/issues/issue-60075.stderr
@@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
 LL |         });
    |          ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
+error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
   --> $DIR/issue-60075.rs:6:11
    |
 LL |     fn qux() -> Option<usize> {
diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs
new file mode 100644
index 00000000000..83328073972
--- /dev/null
+++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs
@@ -0,0 +1,15 @@
+// This test checks that errors are showed for lines with `collect` rather than `push` method.
+
+fn main() {
+    let v = vec![1_f64, 2.2_f64];
+    let mut fft: Vec<Vec<f64>> = vec![];
+
+    let x1: &[f64] = &v;
+    let x2: Vec<f64> = x1.into_iter().collect();
+    //~^ ERROR a value of type
+    fft.push(x2);
+
+    let x3 = x1.into_iter().collect::<Vec<f64>>();
+    //~^ ERROR a value of type
+    fft.push(x3);
+}
diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
new file mode 100644
index 00000000000..8e7ee97e0b9
--- /dev/null
+++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -0,0 +1,19 @@
+error[E0277]: a value of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
+   |
+LL |     let x2: Vec<f64> = x1.into_iter().collect();
+   |                                       ^^^^^^^ value of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |
+   = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
+
+error[E0277]: a value of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
+   |
+LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
+   |                             ^^^^^^^ value of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |
+   = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs
index 71e2b58031c..c18a0d4d6cb 100644
--- a/src/test/ui/issues/issue-8460-const.rs
+++ b/src/test/ui/issues/issue-8460-const.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -O
 
 #![deny(const_err)]
diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr
index c6750e653d7..170747f8402 100644
--- a/src/test/ui/issues/issue-8460-const.stderr
+++ b/src/test/ui/issues/issue-8460-const.stderr
@@ -1,185 +1,185 @@
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:9:36
+  --> $DIR/issue-8460-const.rs:10:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-8460-const.rs:3:9
+  --> $DIR/issue-8460-const.rs:4:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:9:36
+  --> $DIR/issue-8460-const.rs:10:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:12:36
+  --> $DIR/issue-8460-const.rs:13:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:12:36
+  --> $DIR/issue-8460-const.rs:13:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:15:36
+  --> $DIR/issue-8460-const.rs:16:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:15:36
+  --> $DIR/issue-8460-const.rs:16:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:18:36
+  --> $DIR/issue-8460-const.rs:19:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:18:36
+  --> $DIR/issue-8460-const.rs:19:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:21:36
+  --> $DIR/issue-8460-const.rs:22:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:21:36
+  --> $DIR/issue-8460-const.rs:22:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:24:36
+  --> $DIR/issue-8460-const.rs:25:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:26:36
+  --> $DIR/issue-8460-const.rs:27:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
    |                                    ^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:28:36
+  --> $DIR/issue-8460-const.rs:29:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:30:36
+  --> $DIR/issue-8460-const.rs:31:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:32:36
+  --> $DIR/issue-8460-const.rs:33:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:34:36
+  --> $DIR/issue-8460-const.rs:35:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:34:36
+  --> $DIR/issue-8460-const.rs:35:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:37:36
+  --> $DIR/issue-8460-const.rs:38:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:37:36
+  --> $DIR/issue-8460-const.rs:38:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:40:36
+  --> $DIR/issue-8460-const.rs:41:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:40:36
+  --> $DIR/issue-8460-const.rs:41:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:43:36
+  --> $DIR/issue-8460-const.rs:44:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:43:36
+  --> $DIR/issue-8460-const.rs:44:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:46:36
+  --> $DIR/issue-8460-const.rs:47:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:46:36
+  --> $DIR/issue-8460-const.rs:47:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:49:36
+  --> $DIR/issue-8460-const.rs:50:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:51:36
+  --> $DIR/issue-8460-const.rs:52:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
    |                                    ^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:53:36
+  --> $DIR/issue-8460-const.rs:54:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:55:36
+  --> $DIR/issue-8460-const.rs:56:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:57:36
+  --> $DIR/issue-8460-const.rs:58:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
    |                                    ^^^^^^^^
diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs
index 723a17940a3..0ca850abc1b 100644
--- a/src/test/ui/issues/issue-8460-const2.rs
+++ b/src/test/ui/issues/issue-8460-const2.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -C overflow-checks=on -O
 
 #![deny(const_err)]
diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr
index 87b9b2daa6f..6ad186fb21c 100644
--- a/src/test/ui/issues/issue-8460-const2.stderr
+++ b/src/test/ui/issues/issue-8460-const2.stderr
@@ -1,125 +1,125 @@
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:9:36
+  --> $DIR/issue-8460-const2.rs:10:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-8460-const2.rs:3:9
+  --> $DIR/issue-8460-const2.rs:4:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:11:36
+  --> $DIR/issue-8460-const2.rs:12:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:13:36
+  --> $DIR/issue-8460-const2.rs:14:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:15:36
+  --> $DIR/issue-8460-const2.rs:16:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:17:36
+  --> $DIR/issue-8460-const2.rs:18:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:19:36
+  --> $DIR/issue-8460-const2.rs:20:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:21:36
+  --> $DIR/issue-8460-const2.rs:22:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
    |                                    ^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:23:36
+  --> $DIR/issue-8460-const2.rs:24:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:25:36
+  --> $DIR/issue-8460-const2.rs:26:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:27:36
+  --> $DIR/issue-8460-const2.rs:28:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:29:36
+  --> $DIR/issue-8460-const2.rs:30:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:31:36
+  --> $DIR/issue-8460-const2.rs:32:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:33:36
+  --> $DIR/issue-8460-const2.rs:34:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:35:36
+  --> $DIR/issue-8460-const2.rs:36:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:37:36
+  --> $DIR/issue-8460-const2.rs:38:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:39:36
+  --> $DIR/issue-8460-const2.rs:40:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:41:36
+  --> $DIR/issue-8460-const2.rs:42:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
    |                                    ^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:43:36
+  --> $DIR/issue-8460-const2.rs:44:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:45:36
+  --> $DIR/issue-8460-const2.rs:46:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:47:36
+  --> $DIR/issue-8460-const2.rs:48:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
    |                                    ^^^^^^^^
diff --git a/src/test/ui/issues/issue-8727.rs b/src/test/ui/issues/issue-8727.rs
index 473d237cd87..80f360155cb 100644
--- a/src/test/ui/issues/issue-8727.rs
+++ b/src/test/ui/issues/issue-8727.rs
@@ -1,6 +1,8 @@
 // Verify the compiler fails with an error on infinite function
 // recursions.
 
+// build-fail
+
 fn generic<T>() {
     generic::<Option<T>>();
 }
diff --git a/src/test/ui/issues/issue-8727.stderr b/src/test/ui/issues/issue-8727.stderr
index df01f42ce26..2fd6ea5dc82 100644
--- a/src/test/ui/issues/issue-8727.stderr
+++ b/src/test/ui/issues/issue-8727.stderr
@@ -1,5 +1,5 @@
 warning: function cannot return without recursing
-  --> $DIR/issue-8727.rs:4:1
+  --> $DIR/issue-8727.rs:6:1
    |
 LL | fn generic<T>() {
    | ^^^^^^^^^^^^^^^ cannot return without recursing
@@ -10,7 +10,7 @@ LL |     generic::<Option<T>>();
    = help: a `loop` may express intention better if this is on purpose
 
 error: reached the recursion limit while instantiating `generic::<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<std::option::Option<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-8727.rs:4:1
+  --> $DIR/issue-8727.rs:6:1
    |
 LL | / fn generic<T>() {
 LL | |     generic::<Option<T>>();
diff --git a/src/test/ui/json-and-color.rs b/src/test/ui/json-and-color.rs
index efc07a541be..6f8326fe247 100644
--- a/src/test/ui/json-and-color.rs
+++ b/src/test/ui/json-and-color.rs
@@ -1,4 +1,3 @@
-// build-fail
 // compile-flags: --json=artifacts --error-format=json --color never
 
 fn main() {}
diff --git a/src/test/ui/json-and-error-format.rs b/src/test/ui/json-and-error-format.rs
index 6b369307fa4..6e2d73c76b7 100644
--- a/src/test/ui/json-and-error-format.rs
+++ b/src/test/ui/json-and-error-format.rs
@@ -1,4 +1,3 @@
-// build-fail
 // compile-flags: --json=artifacts --error-format=short
 
 fn main() {}
diff --git a/src/test/ui/json-bom-plus-crlf-multifile.rs b/src/test/ui/json-bom-plus-crlf-multifile.rs
index c71dd325f44..9290e010403 100644
--- a/src/test/ui/json-bom-plus-crlf-multifile.rs
+++ b/src/test/ui/json-bom-plus-crlf-multifile.rs
@@ -1,6 +1,5 @@
 // (This line has BOM so it's ignored by compiletest for directives)

 //

-// build-fail

 // compile-flags: --json=diagnostic-short --error-format=json

 // ignore-tidy-cr

 

diff --git a/src/test/ui/json-bom-plus-crlf.rs b/src/test/ui/json-bom-plus-crlf.rs
index ae54a35d480..be5b7dd2a86 100644
--- a/src/test/ui/json-bom-plus-crlf.rs
+++ b/src/test/ui/json-bom-plus-crlf.rs
@@ -1,6 +1,5 @@
 // (This line has BOM so it's ignored by compiletest for directives)

 //

-// build-fail

 // compile-flags: --json=diagnostic-short --error-format=json

 // ignore-tidy-cr

 

diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr
index a6217f86879..1dd898db3ad 100644
--- a/src/test/ui/json-bom-plus-crlf.stderr
+++ b/src/test/ui/json-bom-plus-crlf.stderr
@@ -15,7 +15,7 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:17:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
 "}
 {"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
@@ -34,7 +34,7 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:19:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
 "}
 {"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
@@ -53,7 +53,7 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:23:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
 "}
 {"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
@@ -72,7 +72,7 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":"    let s : String = (","highlight_start":22,"highlight_end":23},{"text":"    );  // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:25:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":"    let s : String = (","highlight_start":22,"highlight_end":23},{"text":"    );  // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
 "}
 {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
 "}
diff --git a/src/test/ui/json-invalid.rs b/src/test/ui/json-invalid.rs
index a8c0c819a0b..54d0dd1849a 100644
--- a/src/test/ui/json-invalid.rs
+++ b/src/test/ui/json-invalid.rs
@@ -1,4 +1,3 @@
-// build-fail
 // compile-flags: --json=foo --error-format=json
 
 fn main() {}
diff --git a/src/test/ui/json-short.rs b/src/test/ui/json-short.rs
index 01a311b939c..7414a55869c 100644
--- a/src/test/ui/json-short.rs
+++ b/src/test/ui/json-short.rs
@@ -1,2 +1 @@
-// build-fail
 // compile-flags: --json=diagnostic-short --error-format=json
diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr
index 83fc83778a8..226343b1b8c 100644
--- a/src/test/ui/json-short.stderr
+++ b/src/test/ui/json-short.stderr
@@ -10,7 +10,7 @@ fn main() {
 
 If you don't know the basics of Rust, you can go look to the Rust Book to get
 started: https://doc.rust-lang.org/book/
-"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":76,"byte_end":76,"line_start":2,"line_end":2,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:2:63: error[E0601]: `main` function not found in crate `json_short`
+"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:63: error[E0601]: `main` function not found in crate `json_short`
 "}
 {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
 "}
diff --git a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
index 85a9a336b0d..7b2f5365aca 100644
--- a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
+++ b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
@@ -2,6 +2,7 @@
 // collision on the symbol generated for the external linkage item in
 // an extern crate.
 
+// build-fail
 // aux-build:def_colliding_external.rs
 
 extern crate def_colliding_external as dep1;
diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
index dc15798e16a..1e5069612fb 100644
--- a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
+++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(linkage)]
 
 mod dep1 {
diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr
index 117c76f7f26..d008acc6e7c 100644
--- a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr
+++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr
@@ -1,5 +1,5 @@
 error: symbol `collision` is already defined
-  --> $DIR/linkage-detect-local-generated-name-collision.rs:7:9
+  --> $DIR/linkage-detect-local-generated-name-collision.rs:9:9
    |
 LL |         pub static collision: *const i32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
index 014c715be0d..93afc537f7c 100644
--- a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
+++ b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
@@ -1,6 +1,7 @@
 // rust-lang/rust#59548: We used to ICE when trying to use a static
 // with a type that violated its own `#[linkage]`.
 
+// build-fail
 // aux-build:def_illtyped_external.rs
 
 extern crate def_illtyped_external as dep;
diff --git a/src/test/ui/linkage-attr/linkage2.rs b/src/test/ui/linkage-attr/linkage2.rs
index c8af1a69979..41e7819e8cd 100644
--- a/src/test/ui/linkage-attr/linkage2.rs
+++ b/src/test/ui/linkage-attr/linkage2.rs
@@ -1,4 +1,6 @@
 // FIXME https://github.com/rust-lang/rust/issues/59774
+
+// build-fail
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
 // ignore-sgx no weak linkages permitted
diff --git a/src/test/ui/linkage-attr/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr
index 2654ffd67b6..72ee3fb62ec 100644
--- a/src/test/ui/linkage-attr/linkage2.stderr
+++ b/src/test/ui/linkage-attr/linkage2.stderr
@@ -1,5 +1,5 @@
 error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-  --> $DIR/linkage2.rs:9:32
+  --> $DIR/linkage2.rs:11:32
    |
 LL |     #[linkage = "extern_weak"] static foo: i32;
    |                                ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/linkage-attr/linkage3.rs b/src/test/ui/linkage-attr/linkage3.rs
index 1462079acf7..bd4e5ba2d4a 100644
--- a/src/test/ui/linkage-attr/linkage3.rs
+++ b/src/test/ui/linkage-attr/linkage3.rs
@@ -1,4 +1,6 @@
 // FIXME https://github.com/rust-lang/rust/issues/59774
+
+// build-fail
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
 
diff --git a/src/test/ui/linkage-attr/linkage3.stderr b/src/test/ui/linkage-attr/linkage3.stderr
index b74fdc91429..5a0833f2f74 100644
--- a/src/test/ui/linkage-attr/linkage3.stderr
+++ b/src/test/ui/linkage-attr/linkage3.stderr
@@ -1,5 +1,5 @@
 error: invalid linkage specified
-  --> $DIR/linkage3.rs:8:24
+  --> $DIR/linkage3.rs:10:24
    |
 LL |     #[linkage = "foo"] static foo: *const i32;
    |                        ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lint/auxiliary/inherited_stability.rs b/src/test/ui/lint/auxiliary/inherited_stability.rs
index 57af0d3ec9c..1e7eb26fde2 100644
--- a/src/test/ui/lint/auxiliary/inherited_stability.rs
+++ b/src/test/ui/lint/auxiliary/inherited_stability.rs
@@ -1,6 +1,6 @@
 #![crate_name="inherited_stability"]
 #![crate_type = "lib"]
-#![unstable(feature = "unstable_test_feature", issue = "0")]
+#![unstable(feature = "unstable_test_feature", issue = "none")]
 #![feature(staged_api)]
 
 pub fn unstable() {}
@@ -10,14 +10,14 @@ pub fn stable() {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod stable_mod {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub fn unstable() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stable() {}
 }
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub mod unstable_mod {
     #[stable(feature = "stable_test_feature", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
@@ -28,7 +28,7 @@ pub mod unstable_mod {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Stable {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     fn unstable(&self);
 
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/ui/lint/auxiliary/lint_output_format.rs b/src/test/ui/lint/auxiliary/lint_output_format.rs
index 5facb556122..58cae180196 100644
--- a/src/test/ui/lint/auxiliary/lint_output_format.rs
+++ b/src/test/ui/lint/auxiliary/lint_output_format.rs
@@ -1,7 +1,7 @@
 #![crate_name="lint_output_format"]
 #![crate_type = "lib"]
 #![feature(staged_api)]
-#![unstable(feature = "unstable_test_feature", issue = "0")]
+#![unstable(feature = "unstable_test_feature", issue = "none")]
 
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
@@ -9,12 +9,12 @@ pub fn foo() -> usize {
     20
 }
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub fn bar() -> usize {
     40
 }
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub fn baz() -> usize {
     30
 }
diff --git a/src/test/ui/lint/auxiliary/lint_stability.rs b/src/test/ui/lint/auxiliary/lint_stability.rs
index 3188d706ab0..de4058887cf 100644
--- a/src/test/ui/lint/auxiliary/lint_stability.rs
+++ b/src/test/ui/lint/auxiliary/lint_stability.rs
@@ -15,16 +15,16 @@ pub fn deprecated_text() {}
 #[rustc_deprecated(since = "99.99.99", reason = "text")]
 pub fn deprecated_future() {}
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_unstable() {}
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_unstable_text() {}
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub fn unstable() {}
-#[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
 pub fn unstable_text() {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -43,16 +43,16 @@ impl MethodTester {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_unstable_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub fn method_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     pub fn method_unstable_text(&self) {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -70,16 +70,16 @@ pub trait Trait {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_unstable_text(&self) {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     fn trait_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     fn trait_unstable_text(&self) {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -90,7 +90,7 @@ pub trait Trait {
 
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 pub trait TraitWithAssociatedTypes {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     type TypeUnstable = u8;
     #[stable(feature = "stable_test_feature", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
@@ -100,7 +100,7 @@ pub trait TraitWithAssociatedTypes {
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 impl Trait for MethodTester {}
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub trait UnstableTrait { fn dummy(&self) { } }
 
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
@@ -114,12 +114,12 @@ pub trait DeprecatedTrait {
 pub struct DeprecatedStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct UnstableStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
@@ -127,7 +127,7 @@ pub struct UnstableStruct {
 pub struct StableStruct {
     #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
 }
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub enum UnstableEnum {}
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum StableEnum {}
@@ -135,10 +135,10 @@ pub enum StableEnum {}
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnitStruct;
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableUnitStruct;
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct UnstableUnitStruct;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableUnitStruct;
@@ -148,10 +148,10 @@ pub enum Enum {
     #[stable(feature = "stable_test_feature", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     DeprecatedVariant,
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     DeprecatedUnstableVariant,
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     UnstableVariant,
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -161,10 +161,10 @@ pub enum Enum {
 #[stable(feature = "stable_test_feature", since = "1.0.0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
diff --git a/src/test/ui/lint/auxiliary/lint_stability_fields.rs b/src/test/ui/lint/auxiliary/lint_stability_fields.rs
index 2787da7cb71..0efe7686ef7 100644
--- a/src/test/ui/lint/auxiliary/lint_stability_fields.rs
+++ b/src/test/ui/lint/auxiliary/lint_stability_fields.rs
@@ -5,47 +5,47 @@
 pub struct Stable {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub inherit: u8, // it's a lie (stable doesn't inherit)
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub override1: u8,
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub override2: u8,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stable2(#[stable(feature = "rust1", since = "1.0.0")] pub u8,
-                   #[unstable(feature = "unstable_test_feature", issue = "0")] pub u8,
-                   #[unstable(feature = "unstable_test_feature", issue = "0")]
+                   #[unstable(feature = "unstable_test_feature", issue = "none")] pub u8,
+                   #[unstable(feature = "unstable_test_feature", issue = "none")]
                    #[rustc_deprecated(since = "1.0.0", reason = "text")] pub u8);
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct Unstable {
     pub inherit: u8,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub override1: u8,
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub override2: u8,
 }
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub struct Unstable2(pub u8,
                      #[stable(feature = "rust1", since = "1.0.0")] pub u8,
-                     #[unstable(feature = "unstable_test_feature", issue = "0")]
+                     #[unstable(feature = "unstable_test_feature", issue = "none")]
                      #[rustc_deprecated(since = "1.0.0", reason = "text")] pub u8);
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct Deprecated {
     pub inherit: u8,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub override1: u8,
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub override2: u8,
 }
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub struct Deprecated2(pub u8,
                        #[stable(feature = "rust1", since = "1.0.0")] pub u8,
-                       #[unstable(feature = "unstable_test_feature", issue = "0")] pub u8);
+                       #[unstable(feature = "unstable_test_feature", issue = "none")] pub u8);
diff --git a/src/test/ui/lint/auxiliary/stability-cfg2.rs b/src/test/ui/lint/auxiliary/stability-cfg2.rs
index 8a2899584b9..c995038e5a8 100644
--- a/src/test/ui/lint/auxiliary/stability-cfg2.rs
+++ b/src/test/ui/lint/auxiliary/stability-cfg2.rs
@@ -1,5 +1,5 @@
 // compile-flags:--cfg foo
 
-#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "0"))]
+#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))]
 #![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
 #![feature(staged_api)]
diff --git a/src/test/ui/lint/auxiliary/stability_cfg2.rs b/src/test/ui/lint/auxiliary/stability_cfg2.rs
index 8a2899584b9..c995038e5a8 100644
--- a/src/test/ui/lint/auxiliary/stability_cfg2.rs
+++ b/src/test/ui/lint/auxiliary/stability_cfg2.rs
@@ -1,5 +1,5 @@
 // compile-flags:--cfg foo
 
-#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "0"))]
+#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))]
 #![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
 #![feature(staged_api)]
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs
index dd3b8393429..121e5b796bb 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -O
 
 #![deny(exceeding_bitshifts, const_err)]
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
index 25e079b6d81..203cb741539 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
@@ -1,113 +1,113 @@
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:9:15
+  --> $DIR/lint-exceeding-bitshifts.rs:10:15
    |
 LL |       let n = 1u8 << 8;
    |               ^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-exceeding-bitshifts.rs:3:9
+  --> $DIR/lint-exceeding-bitshifts.rs:4:9
    |
 LL | #![deny(exceeding_bitshifts, const_err)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:11:15
+  --> $DIR/lint-exceeding-bitshifts.rs:12:15
    |
 LL |       let n = 1u16 << 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:13:15
+  --> $DIR/lint-exceeding-bitshifts.rs:14:15
    |
 LL |       let n = 1u32 << 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:15:15
+  --> $DIR/lint-exceeding-bitshifts.rs:16:15
    |
 LL |       let n = 1u64 << 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:17:15
+  --> $DIR/lint-exceeding-bitshifts.rs:18:15
    |
 LL |       let n = 1i8 << 8;
    |               ^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:19:15
+  --> $DIR/lint-exceeding-bitshifts.rs:20:15
    |
 LL |       let n = 1i16 << 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:21:15
+  --> $DIR/lint-exceeding-bitshifts.rs:22:15
    |
 LL |       let n = 1i32 << 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:23:15
+  --> $DIR/lint-exceeding-bitshifts.rs:24:15
    |
 LL |       let n = 1i64 << 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:26:15
+  --> $DIR/lint-exceeding-bitshifts.rs:27:15
    |
 LL |       let n = 1u8 >> 8;
    |               ^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:28:15
+  --> $DIR/lint-exceeding-bitshifts.rs:29:15
    |
 LL |       let n = 1u16 >> 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:30:15
+  --> $DIR/lint-exceeding-bitshifts.rs:31:15
    |
 LL |       let n = 1u32 >> 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:32:15
+  --> $DIR/lint-exceeding-bitshifts.rs:33:15
    |
 LL |       let n = 1u64 >> 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:34:15
+  --> $DIR/lint-exceeding-bitshifts.rs:35:15
    |
 LL |       let n = 1i8 >> 8;
    |               ^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:36:15
+  --> $DIR/lint-exceeding-bitshifts.rs:37:15
    |
 LL |       let n = 1i16 >> 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:38:15
+  --> $DIR/lint-exceeding-bitshifts.rs:39:15
    |
 LL |       let n = 1i32 >> 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:40:15
+  --> $DIR/lint-exceeding-bitshifts.rs:41:15
    |
 LL |       let n = 1i64 >> 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:44:15
+  --> $DIR/lint-exceeding-bitshifts.rs:45:15
    |
 LL |       let n = n << 8;
    |               ^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:46:15
+  --> $DIR/lint-exceeding-bitshifts.rs:47:15
    |
 LL |       let n = 1u8 << -8;
    |               ^^^^^^^^^
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
index 2c213daddd7..2a7cbc10f77 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags: -O
 
 #![deny(exceeding_bitshifts, const_err)]
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
index d9c76d233d0..49ac54ab834 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
@@ -1,29 +1,29 @@
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:9:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:10:15
    |
 LL |       let n = 1u8 << (4+4);
    |               ^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-exceeding-bitshifts2.rs:3:9
+  --> $DIR/lint-exceeding-bitshifts2.rs:4:9
    |
 LL | #![deny(exceeding_bitshifts, const_err)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:11:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:12:15
    |
 LL |       let n = 1i64 >> [64][0];
    |               ^^^^^^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:17:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:18:15
    |
 LL |       let n = 1_isize << BITS;
    |               ^^^^^^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:18:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:19:15
    |
 LL |       let n = 1_usize << BITS;
    |               ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lint/lint-shorthand-field.fixed b/src/test/ui/lint/lint-shorthand-field.fixed
new file mode 100644
index 00000000000..7cd5717bc5a
--- /dev/null
+++ b/src/test/ui/lint/lint-shorthand-field.fixed
@@ -0,0 +1,70 @@
+// run-rustfix
+
+#![allow(nonstandard_style, unused_variables, unused_mut)]
+#![deny(non_shorthand_field_patterns)]
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+fn main() {
+    {
+        let Foo {
+            x, //~ ERROR the `x:` in this pattern is redundant
+            ref y, //~ ERROR the `y:` in this pattern is redundant
+        } = Foo { x: 0, y: 0 };
+
+        let Foo {
+            x,
+            ref y,
+        } = Foo { x: 0, y: 0 };
+    }
+
+    {
+        const x: isize = 1;
+
+        match (Foo { x: 1, y: 1 }) {
+            Foo { x: x, ..} => {},
+            _ => {},
+        }
+    }
+
+    {
+        struct Bar {
+            x: x,
+        }
+
+        struct x;
+
+        match (Bar { x: x }) {
+            Bar { x: x } => {},
+        }
+    }
+
+    {
+        struct Bar {
+            x: Foo,
+        }
+
+        enum Foo { x }
+
+        match (Bar { x: Foo::x }) {
+            Bar { x: Foo::x } => {},
+        }
+    }
+
+    {
+        struct Baz {
+            x: isize,
+            y: isize,
+            z: isize,
+        }
+
+        let Baz {
+            mut x, //~ ERROR the `x:` in this pattern is redundant
+            ref y, //~ ERROR the `y:` in this pattern is redundant
+            ref mut z, //~ ERROR the `z:` in this pattern is redundant
+        } = Baz { x: 0, y: 0, z: 0 };
+    }
+}
diff --git a/src/test/ui/lint/lint-shorthand-field.rs b/src/test/ui/lint/lint-shorthand-field.rs
index 5e756d14dc8..22de9c32545 100644
--- a/src/test/ui/lint/lint-shorthand-field.rs
+++ b/src/test/ui/lint/lint-shorthand-field.rs
@@ -1,4 +1,6 @@
-#![allow(nonstandard_style, unused_variables)]
+// run-rustfix
+
+#![allow(nonstandard_style, unused_variables, unused_mut)]
 #![deny(non_shorthand_field_patterns)]
 
 struct Foo {
@@ -51,4 +53,18 @@ fn main() {
             Bar { x: Foo::x } => {},
         }
     }
+
+    {
+        struct Baz {
+            x: isize,
+            y: isize,
+            z: isize,
+        }
+
+        let Baz {
+            x: mut x, //~ ERROR the `x:` in this pattern is redundant
+            y: ref y, //~ ERROR the `y:` in this pattern is redundant
+            z: ref mut z, //~ ERROR the `z:` in this pattern is redundant
+        } = Baz { x: 0, y: 0, z: 0 };
+    }
 }
diff --git a/src/test/ui/lint/lint-shorthand-field.stderr b/src/test/ui/lint/lint-shorthand-field.stderr
index 366ab55d7d4..5c9b21ffdc7 100644
--- a/src/test/ui/lint/lint-shorthand-field.stderr
+++ b/src/test/ui/lint/lint-shorthand-field.stderr
@@ -1,24 +1,38 @@
 error: the `x:` in this pattern is redundant
-  --> $DIR/lint-shorthand-field.rs:12:13
+  --> $DIR/lint-shorthand-field.rs:14:13
    |
 LL |             x: x,
-   |             --^^
-   |             |
-   |             help: remove this
+   |             ^^^^ help: use shorthand field pattern: `x`
    |
 note: lint level defined here
-  --> $DIR/lint-shorthand-field.rs:2:9
+  --> $DIR/lint-shorthand-field.rs:4:9
    |
 LL | #![deny(non_shorthand_field_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `y:` in this pattern is redundant
-  --> $DIR/lint-shorthand-field.rs:13:13
+  --> $DIR/lint-shorthand-field.rs:15:13
    |
 LL |             y: ref y,
-   |             --^^^^^^
-   |             |
-   |             help: remove this
+   |             ^^^^^^^^ help: use shorthand field pattern: `ref y`
 
-error: aborting due to 2 previous errors
+error: the `x:` in this pattern is redundant
+  --> $DIR/lint-shorthand-field.rs:65:13
+   |
+LL |             x: mut x,
+   |             ^^^^^^^^ help: use shorthand field pattern: `mut x`
+
+error: the `y:` in this pattern is redundant
+  --> $DIR/lint-shorthand-field.rs:66:13
+   |
+LL |             y: ref y,
+   |             ^^^^^^^^ help: use shorthand field pattern: `ref y`
+
+error: the `z:` in this pattern is redundant
+  --> $DIR/lint-shorthand-field.rs:67:13
+   |
+LL |             z: ref mut z,
+   |             ^^^^^^^^^^^^ help: use shorthand field pattern: `ref mut z`
+
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/lint-stability-2.rs b/src/test/ui/lint/lint-stability-2.rs
index 53eee35a9ca..2a4f95f555f 100644
--- a/src/test/ui/lint/lint-stability-2.rs
+++ b/src/test/ui/lint/lint-stability-2.rs
@@ -168,16 +168,16 @@ mod cross_crate {
 }
 
 mod this_crate {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated() {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated_text() {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub fn unstable() {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     pub fn unstable_text() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -189,16 +189,16 @@ mod this_crate {
     pub struct MethodTester;
 
     impl MethodTester {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated(&self) {}
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated_text(&self) {}
 
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         pub fn method_unstable(&self) {}
-        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
         pub fn method_unstable_text(&self) {}
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -208,16 +208,16 @@ mod this_crate {
     }
 
     pub trait Trait {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated(&self) {}
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated_text(&self) {}
 
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         fn trait_unstable(&self) {}
-        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
         fn trait_unstable_text(&self) {}
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -228,12 +228,12 @@ mod this_crate {
 
     impl Trait for MethodTester {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedStruct {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableStruct {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
@@ -242,29 +242,29 @@ mod this_crate {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedUnitStruct;
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableUnitStruct;
     #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableUnitStruct;
 
     pub enum Enum {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         DeprecatedVariant,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         UnstableVariant,
 
         #[stable(feature = "rust1", since = "1.0.0")]
         StableVariant,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedTupleStruct(isize);
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableTupleStruct(isize);
     #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableTupleStruct(isize);
@@ -381,7 +381,7 @@ mod this_crate {
         foo.trait_stable();
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
@@ -389,7 +389,7 @@ mod this_crate {
     }
 
     impl MethodTester {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
@@ -397,7 +397,7 @@ mod this_crate {
         }
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub trait DeprecatedTrait {
         fn dummy(&self) { }
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
index 5e747467a12..0585fec99b4 100644
--- a/src/test/ui/lint/lint-stability-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -216,16 +216,16 @@ mod inheritance {
 }
 
 mod this_crate {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated() {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated_text() {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub fn unstable() {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     pub fn unstable_text() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -237,16 +237,16 @@ mod this_crate {
     pub struct MethodTester;
 
     impl MethodTester {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated(&self) {}
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated_text(&self) {}
 
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         pub fn method_unstable(&self) {}
-        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
         pub fn method_unstable_text(&self) {}
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -256,16 +256,16 @@ mod this_crate {
     }
 
     pub trait Trait {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated(&self) {}
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated_text(&self) {}
 
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         fn trait_unstable(&self) {}
-        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
         fn trait_unstable_text(&self) {}
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -276,12 +276,12 @@ mod this_crate {
 
     impl Trait for MethodTester {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedStruct {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableStruct {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
@@ -290,29 +290,29 @@ mod this_crate {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedUnitStruct;
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableUnitStruct;
     #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableUnitStruct;
 
     pub enum Enum {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         DeprecatedVariant,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         UnstableVariant,
 
         #[stable(feature = "rust1", since = "1.0.0")]
         StableVariant,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedTupleStruct(isize);
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableTupleStruct(isize);
     #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableTupleStruct(isize);
@@ -430,7 +430,7 @@ mod this_crate {
         foo.trait_stable();
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
@@ -438,7 +438,7 @@ mod this_crate {
     }
 
     impl MethodTester {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
@@ -446,7 +446,7 @@ mod this_crate {
         }
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub trait DeprecatedTrait {
         fn dummy(&self) { }
diff --git a/src/test/ui/lint/lint-stability-fields-deprecated.rs b/src/test/ui/lint/lint-stability-fields-deprecated.rs
index 9d5b7c51cc8..50e3970c7f0 100644
--- a/src/test/ui/lint/lint-stability-fields-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-fields-deprecated.rs
@@ -153,50 +153,50 @@ mod this_crate {
     #[stable(feature = "rust1", since = "1.0.0")]
     struct Stable {
         inherit: u8,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override1: u8,
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override2: u8,
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     struct Stable2(u8,
                    #[stable(feature = "rust1", since = "1.0.0")] u8,
-                   #[unstable(feature = "unstable_test_feature", issue = "0")]
+                   #[unstable(feature = "unstable_test_feature", issue = "none")]
                    #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     struct Unstable {
         inherit: u8,
         #[stable(feature = "rust1", since = "1.0.0")]
         override1: u8,
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override2: u8,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     struct Unstable2(u8,
                      #[stable(feature = "rust1", since = "1.0.0")] u8,
-                     #[unstable(feature = "unstable_test_feature", issue = "0")]
+                     #[unstable(feature = "unstable_test_feature", issue = "none")]
                      #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     struct Deprecated {
         inherit: u8,
         #[stable(feature = "rust1", since = "1.0.0")]
         override1: u8,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override2: u8,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     struct Deprecated2(u8,
                        #[stable(feature = "rust1", since = "1.0.0")] u8,
-                       #[unstable(feature = "unstable_test_feature", issue = "0")] u8);
+                       #[unstable(feature = "unstable_test_feature", issue = "none")] u8);
 
     pub fn foo() {
         let x = Stable {
diff --git a/src/test/ui/lint/lint-stability-fields.rs b/src/test/ui/lint/lint-stability-fields.rs
index 9be8710bd4c..c5de5748aa3 100644
--- a/src/test/ui/lint/lint-stability-fields.rs
+++ b/src/test/ui/lint/lint-stability-fields.rs
@@ -128,50 +128,50 @@ mod this_crate {
     #[stable(feature = "rust1", since = "1.0.0")]
     struct Stable {
         inherit: u8,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override1: u8,
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override2: u8,
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     struct Stable2(u8,
                    #[stable(feature = "rust1", since = "1.0.0")] u8,
-                   #[unstable(feature = "unstable_test_feature", issue = "0")]
+                   #[unstable(feature = "unstable_test_feature", issue = "none")]
                    #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     struct Unstable {
         inherit: u8,
         #[stable(feature = "rust1", since = "1.0.0")]
         override1: u8,
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override2: u8,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     struct Unstable2(u8,
                      #[stable(feature = "rust1", since = "1.0.0")] u8,
-                     #[unstable(feature = "unstable_test_feature", issue = "0")]
+                     #[unstable(feature = "unstable_test_feature", issue = "none")]
                      #[rustc_deprecated(since = "1.0.0", reason = "text")] u8);
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     struct Deprecated {
         inherit: u8,
         #[stable(feature = "rust1", since = "1.0.0")]
         override1: u8,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         override2: u8,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     struct Deprecated2(u8,
                        #[stable(feature = "rust1", since = "1.0.0")] u8,
-                       #[unstable(feature = "unstable_test_feature", issue = "0")] u8);
+                       #[unstable(feature = "unstable_test_feature", issue = "none")] u8);
 
     pub fn foo() {
         let x = Stable {
diff --git a/src/test/ui/lint/lint-stability.rs b/src/test/ui/lint/lint-stability.rs
index fde27eec7d3..e5620a9f8e7 100644
--- a/src/test/ui/lint/lint-stability.rs
+++ b/src/test/ui/lint/lint-stability.rs
@@ -203,10 +203,10 @@ mod inheritance {
 }
 
 mod this_crate {
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated() {}
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated_text() {}
 
@@ -214,9 +214,9 @@ mod this_crate {
     #[rustc_deprecated(since = "99.99.99", reason = "text")]
     pub fn deprecated_future() {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub fn unstable() {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
     pub fn unstable_text() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -228,16 +228,16 @@ mod this_crate {
     pub struct MethodTester;
 
     impl MethodTester {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated(&self) {}
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated_text(&self) {}
 
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         pub fn method_unstable(&self) {}
-        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
         pub fn method_unstable_text(&self) {}
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -247,16 +247,16 @@ mod this_crate {
     }
 
     pub trait Trait {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated(&self) {}
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated_text(&self) {}
 
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         fn trait_unstable(&self) {}
-        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
         fn trait_unstable_text(&self) {}
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -267,12 +267,12 @@ mod this_crate {
 
     impl Trait for MethodTester {}
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedStruct {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableStruct {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
@@ -281,29 +281,29 @@ mod this_crate {
         #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedUnitStruct;
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableUnitStruct;
     #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableUnitStruct;
 
     pub enum Enum {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         DeprecatedVariant,
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         UnstableVariant,
 
         #[stable(feature = "rust1", since = "1.0.0")]
         StableVariant,
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedTupleStruct(isize);
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     pub struct UnstableTupleStruct(isize);
     #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableTupleStruct(isize);
@@ -422,7 +422,7 @@ mod this_crate {
         foo.trait_stable();
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
@@ -430,7 +430,7 @@ mod this_crate {
     }
 
     impl MethodTester {
-        #[unstable(feature = "unstable_test_feature", issue = "0")]
+        #[unstable(feature = "unstable_test_feature", issue = "none")]
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
@@ -438,7 +438,7 @@ mod this_crate {
         }
     }
 
-    #[unstable(feature = "unstable_test_feature", issue = "0")]
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub trait DeprecatedTrait {
         fn dummy(&self) { }
diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs
index 1af44ecf362..dd8dbda6d43 100644
--- a/src/test/ui/lint/lint-unused-mut-variables.rs
+++ b/src/test/ui/lint/lint-unused-mut-variables.rs
@@ -3,7 +3,7 @@
 // Exercise the unused_mut attribute in some positive and negative cases
 
 #![deny(unused_mut)]
-#![feature(async_closure)]
+#![feature(async_closure, raw_ref_op)]
 
 async fn baz_async(
     mut a: i32,
@@ -177,6 +177,12 @@ fn main() {
     // leading underscore should avoid the warning, just like the
     // unused variable lint.
     let mut _allowed = 1;
+
+    let mut raw_address_of_mut = 1; // OK
+    let mut_ptr = &raw mut raw_address_of_mut;
+
+    let mut raw_address_of_const = 1; //~ ERROR: variable does not need to be mutable
+    let const_ptr = &raw const raw_address_of_const;
 }
 
 fn callback<F>(f: F) where F: FnOnce() {}
diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr
index 92c2b68652d..c1ab0ab33d4 100644
--- a/src/test/ui/lint/lint-unused-mut-variables.stderr
+++ b/src/test/ui/lint/lint-unused-mut-variables.stderr
@@ -181,6 +181,14 @@ LL |     let mut v : &mut Vec<()> = &mut vec![];
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:184:9
+   |
+LL |     let mut raw_address_of_const = 1;
+   |         ----^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
   --> $DIR/lint-unused-mut-variables.rs:106:13
    |
 LL |     fn what(mut foo: isize) {}
@@ -197,7 +205,7 @@ LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
    |                    help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:196:9
+  --> $DIR/lint-unused-mut-variables.rs:202:9
    |
 LL |     let mut b = vec![2];
    |         ----^
@@ -205,10 +213,10 @@ LL |     let mut b = vec![2];
    |         help: remove this `mut`
    |
 note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:192:8
+  --> $DIR/lint-unused-mut-variables.rs:198:8
    |
 LL | #[deny(unused_mut)]
    |        ^^^^^^^^^^
 
-error: aborting due to 25 previous errors
+error: aborting due to 26 previous errors
 
diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs
index aa5518d1a7a..29297d08dca 100644
--- a/src/test/ui/lint/suggestions.rs
+++ b/src/test/ui/lint/suggestions.rs
@@ -60,7 +60,7 @@ fn main() {
         match d {
             Equinox { warp_factor: warp_factor } => {}
             //~^ WARN this pattern is redundant
-            //~| HELP remove this
+            //~| HELP use shorthand field pattern
         }
         println!("{} {}", registry_no, b);
     }
diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr
index 2042ed75537..e42ee0fa640 100644
--- a/src/test/ui/lint/suggestions.stderr
+++ b/src/test/ui/lint/suggestions.stderr
@@ -77,9 +77,7 @@ warning: the `warp_factor:` in this pattern is redundant
   --> $DIR/suggestions.rs:61:23
    |
 LL |             Equinox { warp_factor: warp_factor } => {}
-   |                       ------------^^^^^^^^^^^^
-   |                       |
-   |                       help: remove this
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: use shorthand field pattern: `warp_factor`
    |
    = note: `#[warn(non_shorthand_field_patterns)]` on by default
 
diff --git a/src/test/ui/lto-duplicate-symbols.rs b/src/test/ui/lto-duplicate-symbols.rs
index c95e9fbf406..268cf261219 100644
--- a/src/test/ui/lto-duplicate-symbols.rs
+++ b/src/test/ui/lto-duplicate-symbols.rs
@@ -1,3 +1,4 @@
+// build-fail
 // aux-build:lto-duplicate-symbols1.rs
 // aux-build:lto-duplicate-symbols2.rs
 // error-pattern:Linking globals named 'foo': symbol multiply defined!
diff --git a/src/test/ui/macros/auxiliary/unstable-macros.rs b/src/test/ui/macros/auxiliary/unstable-macros.rs
index e928dc705d7..123e244a53e 100644
--- a/src/test/ui/macros/auxiliary/unstable-macros.rs
+++ b/src/test/ui/macros/auxiliary/unstable-macros.rs
@@ -2,7 +2,7 @@
 #![feature(staged_api)]
 #![stable(feature = "unit_test", since = "1.0.0")]
 
-#[unstable(feature = "unstable_macros", issue = "0")]
+#[unstable(feature = "unstable_macros", issue = "none")]
 #[macro_export]
 macro_rules! unstable_macro{ () => () }
 
@@ -12,5 +12,5 @@ macro_rules! unstable_macro{ () => () }
 macro_rules! deprecated_macro{ () => () }
 
 // FIXME: Cannot use a `pub` macro 2.0 in a staged API crate due to reachability issues.
-// #[unstable(feature = "unstable_macros", issue = "0")]
+// #[unstable(feature = "unstable_macros", issue = "none")]
 // pub macro unstable_macro_modern() {}
diff --git a/src/test/ui/macros/macro-stability-rpass.rs b/src/test/ui/macros/macro-stability-rpass.rs
index 817bddf6956..a5f538ba6b3 100644
--- a/src/test/ui/macros/macro-stability-rpass.rs
+++ b/src/test/ui/macros/macro-stability-rpass.rs
@@ -5,7 +5,7 @@
 
 #[macro_use] extern crate unstable_macros;
 
-#[unstable(feature = "local_unstable", issue = "0")]
+#[unstable(feature = "local_unstable", issue = "none")]
 macro_rules! local_unstable { () => () }
 
 fn main() {
diff --git a/src/test/ui/macros/macro-stability.rs b/src/test/ui/macros/macro-stability.rs
index ab927e419b4..755f55c28de 100644
--- a/src/test/ui/macros/macro-stability.rs
+++ b/src/test/ui/macros/macro-stability.rs
@@ -4,10 +4,10 @@
 #![feature(staged_api)]
 #[macro_use] extern crate unstable_macros;
 
-#[unstable(feature = "local_unstable", issue = "0")]
+#[unstable(feature = "local_unstable", issue = "none")]
 macro_rules! local_unstable { () => () }
 
-#[unstable(feature = "local_unstable", issue = "0")]
+#[unstable(feature = "local_unstable", issue = "none")]
 macro local_unstable_modern() {}
 
 #[stable(feature = "deprecated_macros", since = "1.0.0")]
diff --git a/src/test/ui/missing/missing-stability.rs b/src/test/ui/missing/missing-stability.rs
index 469c22fdb17..0da5808b47d 100644
--- a/src/test/ui/missing/missing-stability.rs
+++ b/src/test/ui/missing/missing-stability.rs
@@ -10,7 +10,7 @@ pub fn unmarked() {
     ()
 }
 
-#[unstable(feature = "unstable_test_feature", issue = "0")]
+#[unstable(feature = "unstable_test_feature", issue = "none")]
 pub mod foo {
     // #[unstable] is inherited
     pub fn unmarked() {}
diff --git a/src/test/ui/moves/move-out-of-array-ref.rs b/src/test/ui/moves/move-out-of-array-ref.rs
new file mode 100644
index 00000000000..4ca60ddfec2
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-array-ref.rs
@@ -0,0 +1,36 @@
+// Ensure that we cannot move out of a reference to a fixed-size array
+
+#![feature(slice_patterns)]
+
+struct D { _x: u8 }
+
+impl Drop for D { fn drop(&mut self) { } }
+
+fn move_elem(a: &[D; 4]) -> D {
+    let [_, e, _, _] = *a;              //~ ERROR cannot move
+    e
+}
+
+fn move_subarr(a: &[D; 4]) -> [D; 2] {
+    let [_, s @ .. , _] = *a;           //~ ERROR cannot move
+    s
+}
+
+fn move_elem_mut(a: &mut [D; 4]) -> D {
+    let [_, e, _, _] = *a;              //~ ERROR cannot move
+    e
+}
+
+fn move_subarr_mut(a: &mut [D; 4]) -> [D; 2] {
+    let [_, s @ .. , _] = *a;           //~ ERROR cannot move
+    s
+}
+
+fn main() {
+    fn d() -> D { D { _x: 0 } }
+
+    move_elem(&[d(), d(), d(), d()]);
+    move_subarr(&[d(), d(), d(), d()]);
+    move_elem_mut(&mut [d(), d(), d(), d()]);
+    move_subarr_mut(&mut [d(), d(), d(), d()]);
+}
diff --git a/src/test/ui/moves/move-out-of-array-ref.stderr b/src/test/ui/moves/move-out-of-array-ref.stderr
new file mode 100644
index 00000000000..ae3d2f5f282
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-array-ref.stderr
@@ -0,0 +1,47 @@
+error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
+  --> $DIR/move-out-of-array-ref.rs:10:24
+   |
+LL |     let [_, e, _, _] = *a;
+   |             -          ^^
+   |             |          |
+   |             |          cannot move out of here
+   |             |          help: consider borrowing here: `&*a`
+   |             data moved here
+   |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+
+error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
+  --> $DIR/move-out-of-array-ref.rs:15:27
+   |
+LL |     let [_, s @ .. , _] = *a;
+   |             ------        ^^
+   |             |             |
+   |             |             cannot move out of here
+   |             |             help: consider borrowing here: `&*a`
+   |             data moved here
+   |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+
+error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
+  --> $DIR/move-out-of-array-ref.rs:20:24
+   |
+LL |     let [_, e, _, _] = *a;
+   |             -          ^^
+   |             |          |
+   |             |          cannot move out of here
+   |             |          help: consider borrowing here: `&*a`
+   |             data moved here
+   |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+
+error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
+  --> $DIR/move-out-of-array-ref.rs:25:27
+   |
+LL |     let [_, s @ .. , _] = *a;
+   |             ------        ^^
+   |             |             |
+   |             |             cannot move out of here
+   |             |             help: consider borrowing here: `&*a`
+   |             data moved here
+   |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/moves/move-out-of-slice-2.rs b/src/test/ui/moves/move-out-of-slice-2.rs
new file mode 100644
index 00000000000..e460246193e
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-slice-2.rs
@@ -0,0 +1,34 @@
+#![feature(slice_patterns, unsized_locals)]
+
+struct A;
+#[derive(Clone, Copy)]
+struct C;
+
+fn main() {
+    let a: Box<[A]> = Box::new([A]);
+    match *a {
+        //~^ ERROR cannot move out of type `[A]`, a non-copy slice
+        [a @ ..] => {},
+        _ => {}
+    }
+    let b: Box<[A]> = Box::new([A, A, A]);
+    match *b {
+        //~^ ERROR cannot move out of type `[A]`, a non-copy slice
+        [_, _, b @ .., _] => {},
+        _ => {}
+    }
+
+    // `[C]` isn't `Copy`, even if `C` is.
+    let c: Box<[C]> = Box::new([C]);
+    match *c {
+        //~^ ERROR cannot move out of type `[C]`, a non-copy slice
+        [c @ ..] => {},
+        _ => {}
+    }
+    let d: Box<[C]> = Box::new([C, C, C]);
+    match *d {
+        //~^ ERROR cannot move out of type `[C]`, a non-copy slice
+        [_, _, d @ .., _] => {},
+        _ => {}
+    }
+}
diff --git a/src/test/ui/moves/move-out-of-slice-2.stderr b/src/test/ui/moves/move-out-of-slice-2.stderr
new file mode 100644
index 00000000000..058f34b24a3
--- /dev/null
+++ b/src/test/ui/moves/move-out-of-slice-2.stderr
@@ -0,0 +1,51 @@
+error[E0508]: cannot move out of type `[A]`, a non-copy slice
+  --> $DIR/move-out-of-slice-2.rs:9:11
+   |
+LL |     match *a {
+   |           ^^ cannot move out of here
+LL |
+LL |         [a @ ..] => {},
+   |          ------
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `[A]`, which does not implement the `Copy` trait
+
+error[E0508]: cannot move out of type `[A]`, a non-copy slice
+  --> $DIR/move-out-of-slice-2.rs:15:11
+   |
+LL |     match *b {
+   |           ^^ cannot move out of here
+LL |
+LL |         [_, _, b @ .., _] => {},
+   |                ------
+   |                |
+   |                data moved here
+   |                move occurs because `b` has type `[A]`, which does not implement the `Copy` trait
+
+error[E0508]: cannot move out of type `[C]`, a non-copy slice
+  --> $DIR/move-out-of-slice-2.rs:23:11
+   |
+LL |     match *c {
+   |           ^^ cannot move out of here
+LL |
+LL |         [c @ ..] => {},
+   |          ------
+   |          |
+   |          data moved here
+   |          move occurs because `c` has type `[C]`, which does not implement the `Copy` trait
+
+error[E0508]: cannot move out of type `[C]`, a non-copy slice
+  --> $DIR/move-out-of-slice-2.rs:29:11
+   |
+LL |     match *d {
+   |           ^^ cannot move out of here
+LL |
+LL |         [_, _, d @ .., _] => {},
+   |                ------
+   |                |
+   |                data moved here
+   |                move occurs because `d` has type `[C]`, which does not implement the `Copy` trait
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/non-integer-atomic.rs b/src/test/ui/non-integer-atomic.rs
index 00d07b7fe48..26d7e66ae3f 100644
--- a/src/test/ui/non-integer-atomic.rs
+++ b/src/test/ui/non-integer-atomic.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(core_intrinsics)]
 #![allow(warnings)]
 #![crate_type = "rlib"]
diff --git a/src/test/ui/non-integer-atomic.stderr b/src/test/ui/non-integer-atomic.stderr
index 2a06b617aec..468e76da666 100644
--- a/src/test/ui/non-integer-atomic.stderr
+++ b/src/test/ui/non-integer-atomic.stderr
@@ -1,95 +1,95 @@
 error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:13:5
+  --> $DIR/non-integer-atomic.rs:15:5
    |
 LL |     intrinsics::atomic_load(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:18:5
+  --> $DIR/non-integer-atomic.rs:20:5
    |
 LL |     intrinsics::atomic_store(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:23:5
+  --> $DIR/non-integer-atomic.rs:25:5
    |
 LL |     intrinsics::atomic_xchg(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
-  --> $DIR/non-integer-atomic.rs:28:5
+  --> $DIR/non-integer-atomic.rs:30:5
    |
 LL |     intrinsics::atomic_cxchg(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:33:5
+  --> $DIR/non-integer-atomic.rs:35:5
    |
 LL |     intrinsics::atomic_load(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:38:5
+  --> $DIR/non-integer-atomic.rs:40:5
    |
 LL |     intrinsics::atomic_store(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:43:5
+  --> $DIR/non-integer-atomic.rs:45:5
    |
 LL |     intrinsics::atomic_xchg(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
-  --> $DIR/non-integer-atomic.rs:48:5
+  --> $DIR/non-integer-atomic.rs:50:5
    |
 LL |     intrinsics::atomic_cxchg(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
-  --> $DIR/non-integer-atomic.rs:53:5
+  --> $DIR/non-integer-atomic.rs:55:5
    |
 LL |     intrinsics::atomic_load(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
-  --> $DIR/non-integer-atomic.rs:58:5
+  --> $DIR/non-integer-atomic.rs:60:5
    |
 LL |     intrinsics::atomic_store(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
-  --> $DIR/non-integer-atomic.rs:63:5
+  --> $DIR/non-integer-atomic.rs:65:5
    |
 LL |     intrinsics::atomic_xchg(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn std::ops::Fn()`
-  --> $DIR/non-integer-atomic.rs:68:5
+  --> $DIR/non-integer-atomic.rs:70:5
    |
 LL |     intrinsics::atomic_cxchg(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:73:5
+  --> $DIR/non-integer-atomic.rs:75:5
    |
 LL |     intrinsics::atomic_load(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:78:5
+  --> $DIR/non-integer-atomic.rs:80:5
    |
 LL |     intrinsics::atomic_store(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:83:5
+  --> $DIR/non-integer-atomic.rs:85:5
    |
 LL |     intrinsics::atomic_xchg(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
-  --> $DIR/non-integer-atomic.rs:88:5
+  --> $DIR/non-integer-atomic.rs:90:5
    |
 LL |     intrinsics::atomic_cxchg(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs
new file mode 100644
index 00000000000..812d23fb580
--- /dev/null
+++ b/src/test/ui/packed/packed-struct-address-of-element.rs
@@ -0,0 +1,37 @@
+// run-pass
+#![allow(dead_code)]
+#![deny(safe_packed_borrows)]
+#![feature(raw_ref_op)]
+// ignore-emscripten weird assertion?
+
+#[repr(packed)]
+struct Foo1 {
+    bar: u8,
+    baz: usize
+}
+
+#[repr(packed(2))]
+struct Foo2 {
+    bar: u8,
+    baz: usize
+}
+
+#[repr(C, packed(4))]
+struct Foo4C {
+    bar: u8,
+    baz: usize
+}
+
+pub fn main() {
+    let foo = Foo1 { bar: 1, baz: 2 };
+    let brw = &raw const foo.baz;
+    unsafe { assert_eq!(brw.read_unaligned(), 2); }
+
+    let foo = Foo2 { bar: 1, baz: 2 };
+    let brw = &raw const foo.baz;
+    unsafe { assert_eq!(brw.read_unaligned(), 2); }
+
+    let mut foo = Foo4C { bar: 1, baz: 2 };
+    let brw = &raw mut foo.baz;
+    unsafe { assert_eq!(brw.read_unaligned(), 2); }
+}
diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs
index 6ac42ed0d47..0072b6191eb 100644
--- a/src/test/ui/packed/packed-struct-borrow-element.rs
+++ b/src/test/ui/packed/packed-struct-borrow-element.rs
@@ -1,4 +1,4 @@
-// run-pass
+// run-pass (note: this is spec-UB, but it works for now)
 #![allow(dead_code)]
 // ignore-emscripten weird assertion?
 
diff --git a/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
index c2deeb7dfd4..4b0f92456e0 100644
--- a/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
+++ b/src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
@@ -1,3 +1,4 @@
+// build-fail
 // compile-flags:-C panic=abort -C prefer-dynamic
 // ignore-musl - no dylibs here
 // ignore-cloudabi
diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
index 5d72771c2dc..1848c986e36 100644
--- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
+++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
@@ -1,3 +1,4 @@
+// build-fail
 // aux-build:panic-runtime-unwind.rs
 // aux-build:panic-runtime-abort.rs
 // aux-build:wants-panic-runtime-unwind.rs
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
index 4c25c09d643..894a5eb38b8 100644
--- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
@@ -1,3 +1,4 @@
+// build-fail
 // error-pattern:is incompatible with this crate's strategy of `unwind`
 // aux-build:panic-runtime-abort.rs
 // aux-build:panic-runtime-lang-items.rs
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
index 478af451e7f..5955075bae5 100644
--- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
@@ -1,3 +1,4 @@
+// build-fail
 // error-pattern:is incompatible with this crate's strategy of `unwind`
 // aux-build:panic-runtime-abort.rs
 // aux-build:wants-panic-runtime-abort.rs
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs
new file mode 100644
index 00000000000..e5ac59ae463
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs
@@ -0,0 +1,2 @@
+#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+//~^ ERROR unexpected token: `#`
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr
new file mode 100644
index 00000000000..ca1043250ba
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `#`
+  --> $DIR/attr-stmt-expr-attr-bad-2.rs:1:34
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+   |                                  ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs
new file mode 100644
index 00000000000..7dc71af52f4
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs
@@ -0,0 +1,2 @@
+#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+//~^ ERROR unexpected token: `#`
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr
new file mode 100644
index 00000000000..ab9366d042a
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `#`
+  --> $DIR/attr-stmt-expr-attr-bad-3.rs:1:34
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+   |                                  ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
new file mode 100644
index 00000000000..ef10010ed0e
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -0,0 +1,107 @@
+fn main() {}
+
+#[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
+//~^ ERROR expected expression, found `]`
+#[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+//~^ ERROR an inner attribute is not permitted in this context
+//~| ERROR expected expression, found `)`
+#[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+//~^ ERROR an inner attribute is not permitted in this context
+//~| ERROR expected expression, found `)`
+#[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
+//~^ ERROR expected expression, found `..`
+#[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
+//~^ ERROR expected expression, found `..`
+#[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+//~| ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+//~| ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+
+#[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+
+// FIXME: Allow attributes in pattern constexprs?
+// note: requires parens in patterns to allow disambiguation
+
+#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+//~^ ERROR `X..=` range patterns are not supported
+//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+//~^ ERROR `X..=` range patterns are not supported
+//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+#[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
+//~^ ERROR unexpected token: `#`
+#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+//~^ ERROR `X..=` range patterns are not supported
+//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+
+// make sure we don't catch this bug again...
+#[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
+//~^ ERROR expected statement after outer attribute
+#[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
new file mode 100644
index 00000000000..9a0d3176714
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -0,0 +1,390 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:3:36
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
+   |                                    ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `]`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:5:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
+   |                                        ^ expected expression
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:7:35
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
+   |                                   ^ expected one of 7 possible tokens
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:36
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+   |                                    ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `)`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:44
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+   |                                            ^ expected expression
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:12:38
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+   |                                      ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `)`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:12:46
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+   |                                              ^ expected expression
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:15:36
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
+   |                                    ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:17:33
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
+   |                                 ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
+   |                                 ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:21:34
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
+   |                                  ^ expected one of 7 possible tokens
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:23:35
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
+   |                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:25:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
+   |                                        ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:27:35
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
+   |                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:29:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
+   |                                        ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `..`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
+   |                                        ^^ expected expression
+
+error: expected expression, found `..`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
+   |                                        ^^ expected expression
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:35:41
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
+   |                                         ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:37:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
+   |                                             ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:39:32
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
+   |                                ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
+   |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                |    |
+   |                                |    expected `{`
+   |                                this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
+   |                                      ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
+   |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
+   |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                             |
+   |                                             expected `{`
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
+   |                                              ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+   |                                             ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+   |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
+   |                                             |
+   |                                             expected `{`
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:54:50
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+   |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                             |    |
+   |                                             |    expected `{`
+   |                                             this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:56:51
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
+   |                                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:58:32
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
+   |                                ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:60:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+   |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                |            |
+   |                                |            expected `{`
+   |                                this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:62:46
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
+   |                                              ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:64:48
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
+   |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:66:53
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+   |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                                     |
+   |                                                     expected `{`
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:68:54
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
+   |                                                      ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+   |                                                     ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+   |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
+   |                                                     |
+   |                                                     expected `{`
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:73:66
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+   |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                                     |            |
+   |                                                     |            expected `{`
+   |                                                     this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:75:67
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
+   |                                                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: `X..=` range patterns are not supported
+  --> $DIR/attr-stmt-expr-attr-bad.rs:92:34
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: expected one of `=>`, `if`, or `|`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:92:38
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+   |                                      ^ expected one of `=>`, `if`, or `|`
+
+error: `X..=` range patterns are not supported
+  --> $DIR/attr-stmt-expr-attr-bad.rs:95:34
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: expected one of `=>`, `if`, or `|`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:95:38
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+   |                                      ^ expected one of `=>`, `if`, or `|`
+
+error: unexpected token: `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:98:39
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
+   |                                       ^
+
+error: `X..=` range patterns are not supported
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: expected one of `=>`, `if`, or `|`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:38
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+   |                                      ^ expected one of `=>`, `if`, or `|`
+
+error: expected statement after outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:105:44
+   |
+LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
+   |                                            ^
+
+error: aborting due to 52 previous errors
+
diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs
index d805ab75882..f64568d06e9 100644
--- a/src/test/ui/parser/do-catch-suggests-try.rs
+++ b/src/test/ui/parser/do-catch-suggests-try.rs
@@ -1,5 +1,10 @@
+#![feature(try_blocks)]
+
 fn main() {
     let _: Option<()> = do catch {};
     //~^ ERROR found removed `do catch` syntax
-    //~^^ HELP following RFC #2388, the new non-placeholder syntax is `try`
+    //~| replace with the new syntax
+    //~| following RFC #2388, the new non-placeholder syntax is `try`
+
+    let _recovery_witness: () = 1; //~ ERROR mismatched types
 }
diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr
index e151d4cf8a6..cd8907b7eac 100644
--- a/src/test/ui/parser/do-catch-suggests-try.stderr
+++ b/src/test/ui/parser/do-catch-suggests-try.stderr
@@ -1,10 +1,19 @@
 error: found removed `do catch` syntax
-  --> $DIR/do-catch-suggests-try.rs:2:25
+  --> $DIR/do-catch-suggests-try.rs:4:25
    |
 LL |     let _: Option<()> = do catch {};
-   |                         ^^
+   |                         ^^^^^^^^ help: replace with the new syntax: `try`
    |
-   = help: following RFC #2388, the new non-placeholder syntax is `try`
+   = note: following RFC #2388, the new non-placeholder syntax is `try`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/do-catch-suggests-try.rs:9:33
+   |
+LL |     let _recovery_witness: () = 1;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/impl-item-const-pass.rs b/src/test/ui/parser/impl-item-const-pass.rs
new file mode 100644
index 00000000000..d1124561374
--- /dev/null
+++ b/src/test/ui/parser/impl-item-const-pass.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+impl X {
+    const Y: u8;
+}
diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.rs b/src/test/ui/parser/impl-item-const-semantic-fail.rs
new file mode 100644
index 00000000000..5d4692f9f14
--- /dev/null
+++ b/src/test/ui/parser/impl-item-const-semantic-fail.rs
@@ -0,0 +1,7 @@
+fn main() {}
+
+struct X;
+
+impl X {
+    const Y: u8; //~ ERROR associated constant in `impl` without body
+}
diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr
new file mode 100644
index 00000000000..ec3bee0ce68
--- /dev/null
+++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr
@@ -0,0 +1,10 @@
+error: associated constant in `impl` without body
+  --> $DIR/impl-item-const-semantic-fail.rs:6:5
+   |
+LL |     const Y: u8;
+   |     ^^^^^^^^^^^-
+   |                |
+   |                help: provide a definition for the constant: `= <expr>;`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/impl-item-fn-no-body-pass.rs b/src/test/ui/parser/impl-item-fn-no-body-pass.rs
new file mode 100644
index 00000000000..16b09d64e8c
--- /dev/null
+++ b/src/test/ui/parser/impl-item-fn-no-body-pass.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+impl X {
+    fn f();
+}
diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs
new file mode 100644
index 00000000000..cb183db5964
--- /dev/null
+++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs
@@ -0,0 +1,7 @@
+fn main() {}
+
+struct X;
+
+impl X {
+    fn f(); //~ ERROR associated function in `impl` without body
+}
diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr
new file mode 100644
index 00000000000..1acb727368b
--- /dev/null
+++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr
@@ -0,0 +1,10 @@
+error: associated function in `impl` without body
+  --> $DIR/impl-item-fn-no-body-semantic-fail.rs:6:5
+   |
+LL |     fn f();
+   |     ^^^^^^-
+   |           |
+   |           help: provide a definition for the function: `{ <body> }`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/impl-item-type-no-body-pass.rs b/src/test/ui/parser/impl-item-type-no-body-pass.rs
new file mode 100644
index 00000000000..74a9c6ab7e8
--- /dev/null
+++ b/src/test/ui/parser/impl-item-type-no-body-pass.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+impl X {
+    type Y;
+    type Z: Ord;
+    type W: Ord where Self: Eq;
+    type W where Self: Eq;
+}
diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
new file mode 100644
index 00000000000..9c321c4bd0d
--- /dev/null
+++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
@@ -0,0 +1,23 @@
+#![feature(generic_associated_types)]
+//~^ WARN the feature `generic_associated_types` is incomplete
+
+fn main() {}
+
+struct X;
+
+impl X {
+    type Y;
+    //~^ ERROR associated type in `impl` without body
+    //~| ERROR associated types are not yet supported in inherent impls
+    type Z: Ord;
+    //~^ ERROR associated type in `impl` without body
+    //~| ERROR bounds on associated `type`s in `impl`s have no effect
+    //~| ERROR associated types are not yet supported in inherent impls
+    type W: Ord where Self: Eq;
+    //~^ ERROR associated type in `impl` without body
+    //~| ERROR bounds on associated `type`s in `impl`s have no effect
+    //~| ERROR associated types are not yet supported in inherent impls
+    type W where Self: Eq;
+    //~^ ERROR associated type in `impl` without body
+    //~| ERROR associated types are not yet supported in inherent impls
+}
diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr
new file mode 100644
index 00000000000..65e1981e3ac
--- /dev/null
+++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr
@@ -0,0 +1,79 @@
+error: associated type in `impl` without body
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
+   |
+LL |     type Y;
+   |     ^^^^^^-
+   |           |
+   |           help: provide a definition for the type: `= <type>;`
+
+error: associated type in `impl` without body
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
+   |
+LL |     type Z: Ord;
+   |     ^^^^^^^^^^^-
+   |                |
+   |                help: provide a definition for the type: `= <type>;`
+
+error: bounds on associated `type`s in `impl`s have no effect
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13
+   |
+LL |     type Z: Ord;
+   |             ^^^
+
+error: associated type in `impl` without body
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
+   |
+LL |     type W: Ord where Self: Eq;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                               |
+   |                               help: provide a definition for the type: `= <type>;`
+
+error: bounds on associated `type`s in `impl`s have no effect
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13
+   |
+LL |     type W: Ord where Self: Eq;
+   |             ^^^
+
+error: associated type in `impl` without body
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5
+   |
+LL |     type W where Self: Eq;
+   |     ^^^^^^^^^^^^^^^^^^^^^-
+   |                          |
+   |                          help: provide a definition for the type: `= <type>;`
+
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
+   |
+LL |     type Y;
+   |     ^^^^^^^
+
+error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
+   |
+LL |     type Z: Ord;
+   |     ^^^^^^^^^^^^
+
+error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
+   |
+LL |     type W: Ord where Self: Eq;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5
+   |
+LL |     type W where Self: Eq;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0202`.
diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr
index 70f55f0aeb9..6e20a9ce3c4 100644
--- a/src/test/ui/parser/issue-21153.stderr
+++ b/src/test/ui/parser/issue-21153.stderr
@@ -1,4 +1,4 @@
-error: missing `fn`, `type`, or `const` for trait-item declaration
+error: missing `fn`, `type`, or `const` for associated-item declaration
   --> $DIR/issue-21153.rs:1:29
    |
 LL |   trait MyTrait<T>: Iterator {
diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr
index 70256a59231..1a97f54160b 100644
--- a/src/test/ui/parser/issue-32446.stderr
+++ b/src/test/ui/parser/issue-32446.stderr
@@ -1,8 +1,8 @@
-error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
+error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
   --> $DIR/issue-32446.rs:4:11
    |
 LL | trait T { ... }
-   |           ^^^ expected one of 9 possible tokens
+   |           ^^^ expected one of 10 possible tokens
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-33418.fixed b/src/test/ui/parser/issue-33418.fixed
index 2aaa3b5b1ea..ed885ae1435 100644
--- a/src/test/ui/parser/issue-33418.fixed
+++ b/src/test/ui/parser/issue-33418.fixed
@@ -1,15 +1,15 @@
 // run-rustfix
 
 trait Tr {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr2: SuperA {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr3: SuperB {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr4: SuperB + SuperD {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr5 {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 
 trait SuperA {}
 trait SuperB {}
diff --git a/src/test/ui/parser/issue-33418.rs b/src/test/ui/parser/issue-33418.rs
index 55331520927..9934284abfb 100644
--- a/src/test/ui/parser/issue-33418.rs
+++ b/src/test/ui/parser/issue-33418.rs
@@ -1,17 +1,17 @@
 // run-rustfix
 
 trait Tr: !SuperA {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr2: SuperA + !SuperB {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr3: !SuperA + SuperB {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr4: !SuperA + SuperB
     + !SuperC + SuperD {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 trait Tr5: !SuperA
     + !SuperB {}
-//~^ ERROR negative trait bounds are not supported
+//~^ ERROR negative bounds are not supported
 
 trait SuperA {}
 trait SuperB {}
diff --git a/src/test/ui/parser/issue-33418.stderr b/src/test/ui/parser/issue-33418.stderr
index 479e7bed101..9a8733e8929 100644
--- a/src/test/ui/parser/issue-33418.stderr
+++ b/src/test/ui/parser/issue-33418.stderr
@@ -1,46 +1,36 @@
-error: negative trait bounds are not supported
+error: negative bounds are not supported
   --> $DIR/issue-33418.rs:3:9
    |
 LL | trait Tr: !SuperA {}
-   |         ^^^^^^^^^ negative trait bounds are not supported
-   |
-   = help: remove the trait bound
+   |         ^^^^^^^^^ negative bounds are not supported
 
-error: negative trait bounds are not supported
+error: negative bounds are not supported
   --> $DIR/issue-33418.rs:5:19
    |
 LL | trait Tr2: SuperA + !SuperB {}
-   |                   ^^^^^^^^^ negative trait bounds are not supported
-   |
-   = help: remove the trait bound
+   |                   ^^^^^^^^^ negative bounds are not supported
 
-error: negative trait bounds are not supported
+error: negative bounds are not supported
   --> $DIR/issue-33418.rs:7:10
    |
 LL | trait Tr3: !SuperA + SuperB {}
-   |          ^^^^^^^^^ negative trait bounds are not supported
-   |
-   = help: remove the trait bound
+   |          ^^^^^^^^^ negative bounds are not supported
 
-error: negative trait bounds are not supported
+error: negative bounds are not supported
   --> $DIR/issue-33418.rs:9:10
    |
 LL | trait Tr4: !SuperA + SuperB
    |          ^^^^^^^^^
 LL |     + !SuperC + SuperD {}
-   |     ^^^^^^^^^ negative trait bounds are not supported
-   |
-   = help: remove the trait bounds
+   |     ^^^^^^^^^ negative bounds are not supported
 
-error: negative trait bounds are not supported
+error: negative bounds are not supported
   --> $DIR/issue-33418.rs:12:10
    |
 LL | trait Tr5: !SuperA
    |          ^^^^^^^^^
 LL |     + !SuperB {}
-   |     ^^^^^^^^^ negative trait bounds are not supported
-   |
-   = help: remove the trait bounds
+   |     ^^^^^^^^^ negative bounds are not supported
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs
new file mode 100644
index 00000000000..c1826f8caae
--- /dev/null
+++ b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs
@@ -0,0 +1,21 @@
+fn main() {
+    auto n = 0;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `auto` to introduce a new variable
+    auto m;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `auto` to introduce a new variable
+    m = 0;
+
+    var n = 0;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `var` to introduce a new variable
+    var m;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `var` to introduce a new variable
+    m = 0;
+
+    mut n = 0;//~ ERROR invalid variable declaration
+    //~^ HELP missing keyword
+    mut var;//~ ERROR invalid variable declaration
+    //~^ HELP missing keyword
+    var = 0;
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr
new file mode 100644
index 00000000000..ad72dd30542
--- /dev/null
+++ b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr
@@ -0,0 +1,67 @@
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:2:5
+   |
+LL |     auto n = 0;
+   |     ^^^^
+   |
+help: write `let` instead of `auto` to introduce a new variable
+   |
+LL |     let n = 0;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:4:5
+   |
+LL |     auto m;
+   |     ^^^^
+   |
+help: write `let` instead of `auto` to introduce a new variable
+   |
+LL |     let m;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:8:5
+   |
+LL |     var n = 0;
+   |     ^^^
+   |
+help: write `let` instead of `var` to introduce a new variable
+   |
+LL |     let n = 0;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:10:5
+   |
+LL |     var m;
+   |     ^^^
+   |
+help: write `let` instead of `var` to introduce a new variable
+   |
+LL |     let m;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:14:5
+   |
+LL |     mut n = 0;
+   |     ^^^ help: missing keyword: `let mut`
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:16:5
+   |
+LL |     mut var;
+   |     ^^^ help: missing keyword: `let mut`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:20:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.rs b/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.rs
new file mode 100644
index 00000000000..5a109ba7c68
--- /dev/null
+++ b/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.rs
@@ -0,0 +1,12 @@
+// In this regression test for #67146, we check that the
+// negative outlives bound `!'a` is rejected by the parser.
+// This regression was first introduced in PR #57364.
+
+fn main() {}
+
+fn f1<T: !'static>() {}
+//~^ ERROR negative bounds are not supported
+fn f2<'a, T: Ord + !'a>() {}
+//~^ ERROR negative bounds are not supported
+fn f3<'a, T: !'a + Ord>() {}
+//~^ ERROR negative bounds are not supported
diff --git a/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.stderr b/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.stderr
new file mode 100644
index 00000000000..4dc06347304
--- /dev/null
+++ b/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.stderr
@@ -0,0 +1,20 @@
+error: negative bounds are not supported
+  --> $DIR/issue-67146-negative-outlives-bound-syntactic-fail.rs:7:8
+   |
+LL | fn f1<T: !'static>() {}
+   |        ^^^^^^^^^^ negative bounds are not supported
+
+error: negative bounds are not supported
+  --> $DIR/issue-67146-negative-outlives-bound-syntactic-fail.rs:9:18
+   |
+LL | fn f2<'a, T: Ord + !'a>() {}
+   |                  ^^^^^ negative bounds are not supported
+
+error: negative bounds are not supported
+  --> $DIR/issue-67146-negative-outlives-bound-syntactic-fail.rs:11:12
+   |
+LL | fn f3<'a, T: !'a + Ord>() {}
+   |            ^^^^^ negative bounds are not supported
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr
index 0a433ab278e..7647ba500e0 100644
--- a/src/test/ui/parser/macro/trait-non-item-macros.stderr
+++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr
@@ -1,8 +1,8 @@
-error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
+error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
   --> $DIR/trait-non-item-macros.rs:2:19
    |
 LL |     ($a:expr) => ($a)
-   |                   ^^ expected one of 8 possible tokens
+   |                   ^^ expected one of 9 possible tokens
 ...
 LL |     bah!(2);
    |     -------- in this macro invocation
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index cbaf9315e85..7e8abf22d55 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -7,11 +7,11 @@ LL | trait T {
 LL | fn main() {}
    |                                                                  ^
 
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
+error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
   --> $DIR/missing-close-brace-in-trait.rs:5:12
    |
 LL | pub(crate) struct Bar<T>();
-   |            ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`
+   |            ^^^^^^ expected one of 7 possible tokens
 
 error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
   --> $DIR/missing-close-brace-in-trait.rs:1:1
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.rs b/src/test/ui/parser/recover-labeled-non-block-expr.rs
new file mode 100644
index 00000000000..be92170acf0
--- /dev/null
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.rs
@@ -0,0 +1,5 @@
+fn main() {
+    'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.stderr b/src/test/ui/parser/recover-labeled-non-block-expr.stderr
new file mode 100644
index 00000000000..771a915288c
--- /dev/null
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.stderr
@@ -0,0 +1,17 @@
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/recover-labeled-non-block-expr.rs:2:13
+   |
+LL |     'label: 1 + 1;
+   |             ^ expected `while`, `for`, `loop` or `{` after a label
+
+error[E0308]: mismatched types
+  --> $DIR/recover-labeled-non-block-expr.rs:4:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs
new file mode 100644
index 00000000000..0d1f5be7b49
--- /dev/null
+++ b/src/test/ui/parser/recovery-attr-on-if.rs
@@ -0,0 +1,9 @@
+fn main() {
+    #[attr] if true {};
+    //~^ ERROR cannot find attribute
+    //~| ERROR attributes are not yet allowed on `if` expressions
+    #[attr] if true {};
+    //~^ ERROR cannot find attribute
+    //~| ERROR attributes are not yet allowed on `if` expressions
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/recovery-attr-on-if.stderr b/src/test/ui/parser/recovery-attr-on-if.stderr
new file mode 100644
index 00000000000..a02846827c9
--- /dev/null
+++ b/src/test/ui/parser/recovery-attr-on-if.stderr
@@ -0,0 +1,35 @@
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/recovery-attr-on-if.rs:2:5
+   |
+LL |     #[attr] if true {};
+   |     ^^^^^^^
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/recovery-attr-on-if.rs:5:5
+   |
+LL |     #[attr] if true {};
+   |     ^^^^^^^
+
+error: cannot find attribute `attr` in this scope
+  --> $DIR/recovery-attr-on-if.rs:5:7
+   |
+LL |     #[attr] if true {};
+   |       ^^^^
+
+error: cannot find attribute `attr` in this scope
+  --> $DIR/recovery-attr-on-if.rs:2:7
+   |
+LL |     #[attr] if true {};
+   |       ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/recovery-attr-on-if.rs:8:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/stmt_expr_attrs_placement.rs b/src/test/ui/parser/stmt_expr_attrs_placement.rs
new file mode 100644
index 00000000000..b8a794f4b92
--- /dev/null
+++ b/src/test/ui/parser/stmt_expr_attrs_placement.rs
@@ -0,0 +1,22 @@
+#![feature(stmt_expr_attributes)]
+
+// Test that various placements of the inner attribute are parsed correctly,
+// or not.
+
+fn main() {
+    let a = #![allow(warnings)] (1, 2);
+    //~^ ERROR an inner attribute is not permitted in this context
+
+    let b = (#![allow(warnings)] 1, 2);
+
+    let c = {
+        #![allow(warnings)]
+        (#![allow(warnings)] 1, 2)
+    };
+
+    let d = {
+        #![allow(warnings)]
+        let e = (#![allow(warnings)] 1, 2);
+        e
+    };
+}
diff --git a/src/test/ui/parser/stmt_expr_attrs_placement.stderr b/src/test/ui/parser/stmt_expr_attrs_placement.stderr
new file mode 100644
index 00000000000..1886a0f9ba0
--- /dev/null
+++ b/src/test/ui/parser/stmt_expr_attrs_placement.stderr
@@ -0,0 +1,10 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/stmt_expr_attrs_placement.rs:7:13
+   |
+LL |     let a = #![allow(warnings)] (1, 2);
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
new file mode 100644
index 00000000000..09f967f161e
--- /dev/null
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
@@ -0,0 +1,12 @@
+#![feature(specialization)]
+
+fn main() {}
+
+trait X {
+    default const A: u8; //~ ERROR `default` is only allowed on items in `impl` definitions
+    default const B: u8 = 0;  //~ ERROR `default` is only allowed on items in `impl` definitions
+    default type D; //~ ERROR `default` is only allowed on items in `impl` definitions
+    default type C: Ord; //~ ERROR `default` is only allowed on items in `impl` definitions
+    default fn f1(); //~ ERROR `default` is only allowed on items in `impl` definitions
+    default fn f2() {} //~ ERROR `default` is only allowed on items in `impl` definitions
+}
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
new file mode 100644
index 00000000000..54111df3423
--- /dev/null
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
@@ -0,0 +1,38 @@
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5
+   |
+LL |     default const A: u8;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5
+   |
+LL |     default const B: u8 = 0;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5
+   |
+LL |     default type D;
+   |     ^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5
+   |
+LL |     default type C: Ord;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:10:5
+   |
+LL |     default fn f1();
+   |     ^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:11:5
+   |
+LL |     default fn f2() {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/parser/trait-item-with-defaultness-pass.rs b/src/test/ui/parser/trait-item-with-defaultness-pass.rs
new file mode 100644
index 00000000000..a6318bd99e2
--- /dev/null
+++ b/src/test/ui/parser/trait-item-with-defaultness-pass.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+trait X {
+    default const A: u8;
+    default const B: u8 = 0;
+    default type D;
+    default type C: Ord;
+    default fn f1();
+    default fn f2() {}
+}
diff --git a/src/test/ui/parser/variadic-ffi-3.rs b/src/test/ui/parser/variadic-ffi-3.rs
deleted file mode 100644
index ce83cc87abe..00000000000
--- a/src/test/ui/parser/variadic-ffi-3.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn foo(x: isize, ...) {
-    //~^ ERROR: only foreign functions are allowed to be C-variadic
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr
deleted file mode 100644
index aeeebdb9914..00000000000
--- a/src/test/ui/parser/variadic-ffi-3.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0743]: only foreign functions are allowed to be C-variadic
-  --> $DIR/variadic-ffi-3.rs:1:18
-   |
-LL | fn foo(x: isize, ...) {
-   |                  ^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0743`.
diff --git a/src/test/ui/parser/variadic-ffi-4.rs b/src/test/ui/parser/variadic-ffi-4.rs
deleted file mode 100644
index 5f8b3f8f539..00000000000
--- a/src/test/ui/parser/variadic-ffi-4.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-extern "C" fn foo(x: isize, ...) {
-    //~^ ERROR: only foreign functions are allowed to be C-variadic
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr
deleted file mode 100644
index da83276c72d..00000000000
--- a/src/test/ui/parser/variadic-ffi-4.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0743]: only foreign functions are allowed to be C-variadic
-  --> $DIR/variadic-ffi-4.rs:1:29
-   |
-LL | extern "C" fn foo(x: isize, ...) {
-   |                             ^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0743`.
diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs
new file mode 100644
index 00000000000..9eeee195e56
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs
@@ -0,0 +1,9 @@
+fn f1<'a>(x: u8, y: &'a ...) {}
+//~^ ERROR C-variadic type `...` may not be nested inside another type
+
+fn f2<'a>(x: u8, y: Vec<&'a ...>) {}
+//~^ ERROR C-variadic type `...` may not be nested inside another type
+
+fn main() {
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
new file mode 100644
index 00000000000..8b9d676a45d
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
@@ -0,0 +1,24 @@
+error[E0743]: C-variadic type `...` may not be nested inside another type
+  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:1:25
+   |
+LL | fn f1<'a>(x: u8, y: &'a ...) {}
+   |                         ^^^
+
+error[E0743]: C-variadic type `...` may not be nested inside another type
+  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:4:29
+   |
+LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {}
+   |                             ^^^
+
+error[E0308]: mismatched types
+  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0743.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
new file mode 100644
index 00000000000..aa85f6d6b52
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
@@ -0,0 +1,76 @@
+#![feature(c_variadic)]
+
+fn main() {}
+
+fn f1_1(x: isize, ...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+
+fn f1_2(...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR C-variadic function must be declared with at least one named argument
+
+extern "C" fn f2_1(x: isize, ...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+
+extern "C" fn f2_2(...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR C-variadic function must be declared with at least one named argument
+
+extern "C" fn f2_3(..., x: isize) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR `...` must be the last argument of a C-variadic function
+
+extern fn f3_1(x: isize, ...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+
+extern fn f3_2(...) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR C-variadic function must be declared with at least one named argument
+
+extern fn f3_3(..., x: isize) {}
+//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+//~| ERROR `...` must be the last argument of a C-variadic function
+
+extern {
+    fn e_f1(...);
+    //~^ ERROR C-variadic function must be declared with at least one named argument
+    fn e_f2(..., x: isize);
+    //~^ ERROR `...` must be the last argument of a C-variadic function
+}
+
+struct X;
+
+impl X {
+    fn i_f1(x: isize, ...) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    fn i_f2(...) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR C-variadic function must be declared with at least one named argument
+    fn i_f3(..., x: isize, ...) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR `...` must be the last argument of a C-variadic function
+    fn i_f4(..., x: isize, ...) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR `...` must be the last argument of a C-variadic function
+}
+
+trait T {
+    fn t_f1(x: isize, ...) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    fn t_f2(x: isize, ...);
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    fn t_f3(...) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR C-variadic function must be declared with at least one named argument
+    fn t_f4(...);
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR C-variadic function must be declared with at least one named argument
+    fn t_f5(..., x: isize) {}
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR `...` must be the last argument of a C-variadic function
+    fn t_f6(..., x: isize);
+    //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
+    //~| ERROR `...` must be the last argument of a C-variadic function
+}
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
new file mode 100644
index 00000000000..21992a29670
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
@@ -0,0 +1,206 @@
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
+   |
+LL | fn f1_1(x: isize, ...) {}
+   |                   ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
+   |
+LL | fn f1_2(...) {}
+   |         ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
+   |
+LL | fn f1_2(...) {}
+   |         ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
+   |
+LL | extern "C" fn f2_1(x: isize, ...) {}
+   |                              ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
+   |
+LL | extern "C" fn f2_2(...) {}
+   |                    ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
+   |
+LL | extern "C" fn f2_2(...) {}
+   |                    ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
+   |
+LL | extern "C" fn f2_3(..., x: isize) {}
+   |                    ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
+   |
+LL | extern "C" fn f2_3(..., x: isize) {}
+   |                    ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
+   |
+LL | extern fn f3_1(x: isize, ...) {}
+   |                          ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
+   |
+LL | extern fn f3_2(...) {}
+   |                ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
+   |
+LL | extern fn f3_2(...) {}
+   |                ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
+   |
+LL | extern fn f3_3(..., x: isize) {}
+   |                ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
+   |
+LL | extern fn f3_3(..., x: isize) {}
+   |                ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
+   |
+LL |     fn e_f1(...);
+   |             ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
+   |
+LL |     fn e_f2(..., x: isize);
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
+   |
+LL |     fn i_f1(x: isize, ...) {}
+   |                       ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
+   |
+LL |     fn i_f2(...) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
+   |
+LL |     fn i_f2(...) {}
+   |             ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
+   |
+LL |     fn i_f3(..., x: isize, ...) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
+   |
+LL |     fn i_f3(..., x: isize, ...) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
+   |
+LL |     fn i_f3(..., x: isize, ...) {}
+   |                            ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
+   |
+LL |     fn i_f4(..., x: isize, ...) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
+   |
+LL |     fn i_f4(..., x: isize, ...) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
+   |
+LL |     fn i_f4(..., x: isize, ...) {}
+   |                            ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
+   |
+LL |     fn t_f1(x: isize, ...) {}
+   |                       ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
+   |
+LL |     fn t_f2(x: isize, ...);
+   |                       ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
+   |
+LL |     fn t_f3(...) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
+   |
+LL |     fn t_f3(...) {}
+   |             ^^^^
+
+error: C-variadic function must be declared with at least one named argument
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
+   |
+LL |     fn t_f4(...);
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
+   |
+LL |     fn t_f4(...);
+   |             ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
+   |
+LL |     fn t_f5(..., x: isize) {}
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
+   |
+LL |     fn t_f5(..., x: isize) {}
+   |             ^^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
+   |
+LL |     fn t_f6(..., x: isize);
+   |             ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
+   |
+LL |     fn t_f6(..., x: isize);
+   |             ^^^^
+
+error: aborting due to 34 previous errors
+
diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs
new file mode 100644
index 00000000000..3875d6af137
--- /dev/null
+++ b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs
@@ -0,0 +1,53 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn f1_1(x: isize, ...) {}
+
+#[cfg(FALSE)]
+fn f1_2(...) {}
+
+#[cfg(FALSE)]
+extern "C" fn f2_1(x: isize, ...) {}
+
+#[cfg(FALSE)]
+extern "C" fn f2_2(...) {}
+
+#[cfg(FALSE)]
+extern "C" fn f2_3(..., x: isize) {}
+
+#[cfg(FALSE)]
+extern fn f3_1(x: isize, ...) {}
+
+#[cfg(FALSE)]
+extern fn f3_2(...) {}
+
+#[cfg(FALSE)]
+extern fn f3_3(..., x: isize) {}
+
+#[cfg(FALSE)]
+extern {
+    fn e_f1(...);
+    fn e_f2(..., x: isize);
+}
+
+struct X;
+
+#[cfg(FALSE)]
+impl X {
+    fn i_f1(x: isize, ...) {}
+    fn i_f2(...) {}
+    fn i_f3(..., x: isize, ...) {}
+    fn i_f4(..., x: isize, ...) {}
+}
+
+#[cfg(FALSE)]
+trait T {
+    fn t_f1(x: isize, ...) {}
+    fn t_f2(x: isize, ...);
+    fn t_f3(...) {}
+    fn t_f4(...);
+    fn t_f5(..., x: isize) {}
+    fn t_f6(..., x: isize);
+}
diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.rs b/src/test/ui/print_type_sizes/zero-sized-fields.rs
index 2ad488e8d8f..71d09167747 100644
--- a/src/test/ui/print_type_sizes/zero-sized-fields.rs
+++ b/src/test/ui/print_type_sizes/zero-sized-fields.rs
@@ -1,5 +1,6 @@
 // compile-flags: -Z print-type-sizes
 // build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
 
 // At one point, zero-sized fields such as those in this file were causing
 // incorrect output from `-Z print-type-sizes`.
diff --git a/src/test/ui/qualified/qualified-path-params-2.rs b/src/test/ui/qualified/qualified-path-params-2.rs
index ebdd7490462..d0cc1fa3d51 100644
--- a/src/test/ui/qualified/qualified-path-params-2.rs
+++ b/src/test/ui/qualified/qualified-path-params-2.rs
@@ -16,7 +16,6 @@ impl S {
 }
 
 type A = <S as Tr>::A::f<u8>;
-//~^ ERROR type arguments are not allowed for this type
-//~| ERROR ambiguous associated type
+//~^ ERROR ambiguous associated type
 
 fn main() {}
diff --git a/src/test/ui/qualified/qualified-path-params-2.stderr b/src/test/ui/qualified/qualified-path-params-2.stderr
index 15da5193e88..948f21fce4b 100644
--- a/src/test/ui/qualified/qualified-path-params-2.stderr
+++ b/src/test/ui/qualified/qualified-path-params-2.stderr
@@ -1,16 +1,9 @@
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/qualified-path-params-2.rs:18:26
-   |
-LL | type A = <S as Tr>::A::f<u8>;
-   |                          ^^ type argument not allowed
-
 error[E0223]: ambiguous associated type
   --> $DIR/qualified-path-params-2.rs:18:10
    |
 LL | type A = <S as Tr>::A::f<u8>;
    |          ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<S as Tr>::A as Trait>::f`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0109, E0223.
-For more information about an error, try `rustc --explain E0109`.
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/raw-ref-op/raw-ref-op.rs b/src/test/ui/raw-ref-op/raw-ref-op.rs
index de847909eb3..0c6e23a00d5 100644
--- a/src/test/ui/raw-ref-op/raw-ref-op.rs
+++ b/src/test/ui/raw-ref-op/raw-ref-op.rs
@@ -1,11 +1,11 @@
-// FIXME(#64490): make this run-pass
+// run-pass
 
 #![feature(raw_ref_op)]
 
 fn main() {
     let mut x = 123;
-    let c_p = &raw const x;                     //~ ERROR not yet implemented
-    let m_p = &raw mut x;                       //~ ERROR not yet implemented
+    let c_p = &raw const x;
+    let m_p = &raw mut x;
     let i_r = &x;
     assert!(c_p == i_r);
     assert!(c_p == m_p);
diff --git a/src/test/ui/raw-ref-op/raw-ref-op.stderr b/src/test/ui/raw-ref-op/raw-ref-op.stderr
deleted file mode 100644
index 04c59c95fca..00000000000
--- a/src/test/ui/raw-ref-op/raw-ref-op.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-op.rs:7:15
-   |
-LL |     let c_p = &raw const x;
-   |               ^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-op.rs:8:15
-   |
-LL |     let m_p = &raw mut x;
-   |               ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs
index d251586de55..a814003aebf 100644
--- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs
+++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs
@@ -1,4 +1,4 @@
-// FIXME(#64490) This should be check-pass
+// check-pass
 // Check that taking the address of a place that contains a dereference is
 // allowed.
 #![feature(raw_ref_op, type_ascription)]
@@ -10,15 +10,15 @@ const SLICE_REF: &[i32] = &[5, 6];
 
 fn main() {
     // These are all OK, we're not taking the address of the temporary
-    let deref_ref = &raw const *PAIR_REF;                       //~ ERROR not yet implemented
-    let field_deref_ref = &raw const PAIR_REF.0;                //~ ERROR not yet implemented
-    let deref_ref = &raw const *ARRAY_REF;                      //~ ERROR not yet implemented
-    let index_deref_ref = &raw const ARRAY_REF[0];              //~ ERROR not yet implemented
-    let deref_ref = &raw const *SLICE_REF;                      //~ ERROR not yet implemented
-    let index_deref_ref = &raw const SLICE_REF[1];              //~ ERROR not yet implemented
+    let deref_ref = &raw const *PAIR_REF;
+    let field_deref_ref = &raw const PAIR_REF.0;
+    let deref_ref = &raw const *ARRAY_REF;
+    let index_deref_ref = &raw const ARRAY_REF[0];
+    let deref_ref = &raw const *SLICE_REF;
+    let index_deref_ref = &raw const SLICE_REF[1];
 
     let x = 0;
-    let ascribe_ref = &raw const (x: i32);                      //~ ERROR not yet implemented
-    let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]);      //~ ERROR not yet implemented
-    let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32);   //~ ERROR not yet implemented
+    let ascribe_ref = &raw const (x: i32);
+    let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]);
+    let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32);
 }
diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr
deleted file mode 100644
index b0bfc74903b..00000000000
--- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr
+++ /dev/null
@@ -1,74 +0,0 @@
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:13:21
-   |
-LL |     let deref_ref = &raw const *PAIR_REF;
-   |                     ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:14:27
-   |
-LL |     let field_deref_ref = &raw const PAIR_REF.0;
-   |                           ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:15:21
-   |
-LL |     let deref_ref = &raw const *ARRAY_REF;
-   |                     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:16:27
-   |
-LL |     let index_deref_ref = &raw const ARRAY_REF[0];
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:17:21
-   |
-LL |     let deref_ref = &raw const *SLICE_REF;
-   |                     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:18:27
-   |
-LL |     let index_deref_ref = &raw const SLICE_REF[1];
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:21:23
-   |
-LL |     let ascribe_ref = &raw const (x: i32);
-   |                       ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:22:25
-   |
-LL |     let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]);
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/raw-ref-temp-deref.rs:23:31
-   |
-LL |     let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32);
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: aborting due to 9 previous errors
-
diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.rs b/src/test/ui/raw-ref-op/raw-ref-temp.rs
index ac2445f049c..32df56468da 100644
--- a/src/test/ui/raw-ref-op/raw-ref-temp.rs
+++ b/src/test/ui/raw-ref-op/raw-ref-temp.rs
@@ -1,6 +1,8 @@
 // Ensure that we don't allow taking the address of temporary values
 #![feature(raw_ref_op, type_ascription)]
 
+const FOUR: u64 = 4;
+
 const PAIR: (i32, i64) = (1, 2);
 
 const ARRAY: [i32; 2] = [1, 2];
@@ -8,8 +10,8 @@ const ARRAY: [i32; 2] = [1, 2];
 fn main() {
     let ref_expr = &raw const 2;                        //~ ERROR cannot take address
     let mut_ref_expr = &raw mut 3;                      //~ ERROR cannot take address
-    let ref_const = &raw const 4;                       //~ ERROR cannot take address
-    let mut_ref_const = &raw mut 5;                     //~ ERROR cannot take address
+    let ref_const = &raw const FOUR;                    //~ ERROR cannot take address
+    let mut_ref_const = &raw mut FOUR;                  //~ ERROR cannot take address
 
     let field_ref_expr = &raw const (1, 2).0;           //~ ERROR cannot take address
     let mut_field_ref_expr = &raw mut (1, 2).0;         //~ ERROR cannot take address
diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.stderr b/src/test/ui/raw-ref-op/raw-ref-temp.stderr
index de070733735..80dea76d595 100644
--- a/src/test/ui/raw-ref-op/raw-ref-temp.stderr
+++ b/src/test/ui/raw-ref-op/raw-ref-temp.stderr
@@ -1,95 +1,95 @@
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:9:31
+  --> $DIR/raw-ref-temp.rs:11:31
    |
 LL |     let ref_expr = &raw const 2;
    |                               ^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:10:33
+  --> $DIR/raw-ref-temp.rs:12:33
    |
 LL |     let mut_ref_expr = &raw mut 3;
    |                                 ^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:11:32
+  --> $DIR/raw-ref-temp.rs:13:32
    |
-LL |     let ref_const = &raw const 4;
-   |                                ^ temporary value
+LL |     let ref_const = &raw const FOUR;
+   |                                ^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:12:34
+  --> $DIR/raw-ref-temp.rs:14:34
    |
-LL |     let mut_ref_const = &raw mut 5;
-   |                                  ^ temporary value
+LL |     let mut_ref_const = &raw mut FOUR;
+   |                                  ^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:14:37
+  --> $DIR/raw-ref-temp.rs:16:37
    |
 LL |     let field_ref_expr = &raw const (1, 2).0;
    |                                     ^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:15:39
+  --> $DIR/raw-ref-temp.rs:17:39
    |
 LL |     let mut_field_ref_expr = &raw mut (1, 2).0;
    |                                       ^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:16:32
+  --> $DIR/raw-ref-temp.rs:18:32
    |
 LL |     let field_ref = &raw const PAIR.0;
    |                                ^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:17:34
+  --> $DIR/raw-ref-temp.rs:19:34
    |
 LL |     let mut_field_ref = &raw mut PAIR.0;
    |                                  ^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:19:37
+  --> $DIR/raw-ref-temp.rs:21:37
    |
 LL |     let index_ref_expr = &raw const [1, 2][0];
    |                                     ^^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:20:39
+  --> $DIR/raw-ref-temp.rs:22:39
    |
 LL |     let mut_index_ref_expr = &raw mut [1, 2][0];
    |                                       ^^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:21:32
+  --> $DIR/raw-ref-temp.rs:23:32
    |
 LL |     let index_ref = &raw const ARRAY[0];
    |                                ^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:22:34
+  --> $DIR/raw-ref-temp.rs:24:34
    |
 LL |     let mut_index_ref = &raw mut ARRAY[1];
    |                                  ^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:24:34
+  --> $DIR/raw-ref-temp.rs:26:34
    |
 LL |     let ref_ascribe = &raw const (2: i32);
    |                                  ^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:25:36
+  --> $DIR/raw-ref-temp.rs:27:36
    |
 LL |     let mut_ref_ascribe = &raw mut (3: i32);
    |                                    ^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:27:40
+  --> $DIR/raw-ref-temp.rs:29:40
    |
 LL |     let ascribe_field_ref = &raw const (PAIR.0: i32);
    |                                        ^^^^^^^^^^^^^ temporary value
 
 error[E0745]: cannot take address of a temporary
-  --> $DIR/raw-ref-temp.rs:28:38
+  --> $DIR/raw-ref-temp.rs:30:38
    |
 LL |     let ascribe_index_ref = &raw mut (ARRAY[0]: i32);
    |                                      ^^^^^^^^^^^^^^^ temporary value
diff --git a/src/test/ui/raw-ref-op/unusual_locations.rs b/src/test/ui/raw-ref-op/unusual_locations.rs
index f0a6bcce2ac..6bf37408a8b 100644
--- a/src/test/ui/raw-ref-op/unusual_locations.rs
+++ b/src/test/ui/raw-ref-op/unusual_locations.rs
@@ -1,25 +1,22 @@
-// FIXME(#64490): make this check-pass
+// check-pass
 
 #![feature(raw_ref_op)]
 
-const USES_PTR: () = { let u = (); &raw const u; };         //~ ERROR not yet implemented
-static ALSO_USES_PTR: () = { let u = (); &raw const u; };   //~ ERROR not yet implemented
+const USES_PTR: () = { let u = (); &raw const u; };
+static ALSO_USES_PTR: () = { let u = (); &raw const u; };
 
 fn main() {
-    #[cfg(FALSE)]
-    {
-        let x: [i32; { let u = 2; let x = &raw const u; 4 }]
-            = [2; { let v = 3; let y = &raw const v; 4 }];
-        let mut one = 1;
-        let two = 2;
-        if &raw const one == &raw mut one {
-            match &raw const two {
-                _ => {}
-            }
+    let x: [i32; { let u = 2; let x = &raw const u; 4 }]
+        = [2; { let v = 3; let y = &raw const v; 4 }];
+    let mut one = 1;
+    let two = 2;
+    if &raw const one == &raw mut one {
+        match &raw const two {
+            _ => {}
         }
-        let three = 3;
-        let mut four = 4;
-        println!("{:p}", &raw const three);
-        unsafe { &raw mut four; }
     }
+    let three = 3;
+    let mut four = 4;
+    println!("{:p}", &raw const three);
+    unsafe { &raw mut four; }
 }
diff --git a/src/test/ui/raw-ref-op/unusual_locations.stderr b/src/test/ui/raw-ref-op/unusual_locations.stderr
deleted file mode 100644
index 3fae5db3d51..00000000000
--- a/src/test/ui/raw-ref-op/unusual_locations.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error: raw borrows are not yet implemented
-  --> $DIR/unusual_locations.rs:5:36
-   |
-LL | const USES_PTR: () = { let u = (); &raw const u; };
-   |                                    ^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: raw borrows are not yet implemented
-  --> $DIR/unusual_locations.rs:6:42
-   |
-LL | static ALSO_USES_PTR: () = { let u = (); &raw const u; };
-   |                                          ^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/64490
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/recursion/recursion.rs b/src/test/ui/recursion/recursion.rs
index ba3cc33dc30..9d939e13182 100644
--- a/src/test/ui/recursion/recursion.rs
+++ b/src/test/ui/recursion/recursion.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 enum Nil {NilValue}
 struct Cons<T> {head:isize, tail:T}
 trait Dot {fn dot(&self, other:Self) -> isize;}
diff --git a/src/test/ui/recursion/recursion.stderr b/src/test/ui/recursion/recursion.stderr
index 751d56b70f1..17293720a43 100644
--- a/src/test/ui/recursion/recursion.stderr
+++ b/src/test/ui/recursion/recursion.stderr
@@ -1,5 +1,5 @@
 error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Nil>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/recursion.rs:12:1
+  --> $DIR/recursion.rs:14:1
    |
 LL | / fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
 LL | |   match n {    0 => {first.dot(second)}
diff --git a/src/test/ui/required-lang-item.rs b/src/test/ui/required-lang-item.rs
index ee3773675e0..3b17c5b7255 100644
--- a/src/test/ui/required-lang-item.rs
+++ b/src/test/ui/required-lang-item.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(lang_items, no_core)]
 #![no_core]
 
diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.stderr b/src/test/ui/rfc1598-generic-associated-types/collections.stderr
deleted file mode 100644
index fa8fcc99240..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/collections.stderr
+++ /dev/null
@@ -1,41 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/collections.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/collections.rs:56:90
-   |
-LL | fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>
-   |                                                                                          ^^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/collections.rs:68:69
-   |
-LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
-   |                                                                     ^^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/collections.rs:17:71
-   |
-LL |         <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
-   |                                                                       ^ type argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/collections.rs:24:50
-   |
-LL |     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
-   |                                                  ^^^^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/collections.rs:50:50
-   |
-LL |     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
-   |                                                  ^^^^^ lifetime argument not allowed
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
deleted file mode 100644
index 3a459a4551c..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-#![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
-
-use std::ops::Deref;
-
-// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
-// follow-up PR.
-
-trait Foo {
-    type Bar<'a, 'b>;
-}
-
-trait Baz {
-    type Quux<'a>: Foo;
-
-    // This weird type tests that we can use universal function call syntax to access the Item on
-    type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-    //~| ERROR lifetime arguments are not allowed for this type [E0109]
-}
-
-impl<T> Baz for T where T: Foo {
-    type Quux<'a> = T;
-
-    type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr
deleted file mode 100644
index ab161ae21bb..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr
+++ /dev/null
@@ -1,29 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/construct_with_other_type.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/construct_with_other_type.rs:17:46
-   |
-LL |     type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
-   |                                              ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/construct_with_other_type.rs:17:63
-   |
-LL |     type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
-   |                                                               ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/construct_with_other_type.rs:25:40
-   |
-LL |     type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
-   |                                        ^^ lifetime argument not allowed
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
deleted file mode 100644
index 9c8d3f192da..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
-  --> $DIR/empty_generics.rs:5:14
-   |
-LL |     type Bar<,>;
-   |              ^ expected one of `>`, `const`, identifier, or lifetime
-
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/empty_generics.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr b/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr
deleted file mode 100644
index fb43a50df78..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: generic associated types are unstable
-  --> $DIR/gat-dont-ice-on-absent-feature.rs:7:5
-   |
-LL |     type Item<'b> = &'b Foo;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
-   = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
deleted file mode 100644
index 0d319a7a599..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/generic-associated-types-where.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
deleted file mode 100644
index 150899a034b..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
-
-use std::ops::Deref;
-
-// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
-// follow-up PR.
-
-trait Iterable {
-    type Item<'a>;
-    type Iter<'a>: Iterator<Item = Self::Item<'a>>
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-        + Deref<Target = Self::Item<'b>>;
-    //~^ ERROR undeclared lifetime
-    //~| ERROR lifetime arguments are not allowed for this type [E0109]
-
-    fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
-    //~^ ERROR undeclared lifetime
-    //~| ERROR lifetime arguments are not allowed for this type [E0109]
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
deleted file mode 100644
index 40ea42f6243..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
+++ /dev/null
@@ -1,42 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:13:37
-   |
-LL |         + Deref<Target = Self::Item<'b>>;
-   |                                     ^^ undeclared lifetime
-
-error[E0261]: use of undeclared lifetime name `'undeclared`
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:17:41
-   |
-LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
-   |                                         ^^^^^^^^^^^ undeclared lifetime
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:47
-   |
-LL |     type Iter<'a>: Iterator<Item = Self::Item<'a>>
-   |                                               ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:13:37
-   |
-LL |         + Deref<Target = Self::Item<'b>>;
-   |                                     ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:17:41
-   |
-LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
-   |                                         ^^^^^^^^^^^ lifetime argument not allowed
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0109, E0261.
-For more information about an error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.rs b/src/test/ui/rfc1598-generic-associated-types/iterable.rs
deleted file mode 100644
index 29953b9db1a..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/iterable.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-#![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
-
-use std::ops::Deref;
-
-// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
-// follow-up PR.
-
-trait Iterable {
-    type Item<'a>;
-    type Iter<'a>: Iterator<Item = Self::Item<'a>>;
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-
-    fn iter<'a>(&'a self) -> Self::Iter<'a>;
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-}
-
-// Impl for struct type
-impl<T> Iterable for Vec<T> {
-    type Item<'a> = &'a T;
-    type Iter<'a> = std::slice::Iter<'a, T>;
-
-    fn iter<'a>(&'a self) -> Self::Iter<'a> {
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-        self.iter()
-    }
-}
-
-// Impl for a primitive type
-impl<T> Iterable for [T] {
-    type Item<'a> = &'a T;
-    type Iter<'a> = std::slice::Iter<'a, T>;
-
-    fn iter<'a>(&'a self) -> Self::Iter<'a> {
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-        self.iter()
-    }
-}
-
-fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-    it.iter()
-}
-
-fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-    it.iter().next()
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr
deleted file mode 100644
index 51246d3c902..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr
+++ /dev/null
@@ -1,47 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/iterable.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/iterable.rs:11:47
-   |
-LL |     type Iter<'a>: Iterator<Item = Self::Item<'a>>;
-   |                                               ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/iterable.rs:40:53
-   |
-LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
-   |                                                     ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/iterable.rs:45:60
-   |
-LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
-   |                                                            ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/iterable.rs:14:41
-   |
-LL |     fn iter<'a>(&'a self) -> Self::Iter<'a>;
-   |                                         ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/iterable.rs:23:41
-   |
-LL |     fn iter<'a>(&'a self) -> Self::Iter<'a> {
-   |                                         ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/iterable.rs:34:41
-   |
-LL |     fn iter<'a>(&'a self) -> Self::Iter<'a> {
-   |                                         ^^ lifetime argument not allowed
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs
deleted file mode 100644
index aa3f4b186da..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-#![feature(generic_associated_types)]
-//~^ WARNING the feature `generic_associated_types` is incomplete
-#![feature(associated_type_defaults)]
-
-// FIXME(#44265): "lifetime arguments are not allowed for this type" errors will be addressed in a
-// follow-up PR.
-
-// FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`.
-
-trait Foo {
-    type A<'a>;
-    type B<'a, 'b>;
-    type C;
-    type D<T>;
-    type E<'a, T>;
-    // Test parameters in default values
-    type FOk<T> = Self::E<'static, T>;
-    //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~| ERROR lifetime arguments are not allowed for this type [E0109]
-    type FErr1 = Self::E<'static, 'static>; // Error
-    //~^ ERROR lifetime arguments are not allowed for this type [E0109]
-    type FErr2<T> = Self::E<'static, T, u32>; // Error
-    //~^ ERROR type arguments are not allowed for this type [E0109]
-    //~| ERROR lifetime arguments are not allowed for this type [E0109]
-}
-
-struct Fooy;
-
-impl Foo for Fooy {
-    type A = u32; // Error: parameter expected
-    type B<'a, T> = Vec<T>; // Error: lifetime param expected
-    type C<'a> = u32; // Error: no param expected
-    type D<'a> = u32; // Error: type param expected
-    type E<T, U> = u32; // Error: lifetime expected as the first param
-}
-
-struct Fooer;
-
-impl Foo for Fooer {
-    type A<T> = u32; // Error: lifetime parameter expected
-    type B<'a> = u32; // Error: another lifetime param expected
-    type C<T> = T; // Error: no param expected
-    type D<'b, T> = u32; // Error: unexpected lifetime param
-    type E<'a, 'b> = u32; // Error: type expected as the second param
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr
deleted file mode 100644
index 65dbd00c5b1..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr
+++ /dev/null
@@ -1,41 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/parameter_number_and_kind.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/parameter_number_and_kind.rs:17:27
-   |
-LL |     type FOk<T> = Self::E<'static, T>;
-   |                           ^^^^^^^ lifetime argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/parameter_number_and_kind.rs:17:36
-   |
-LL |     type FOk<T> = Self::E<'static, T>;
-   |                                    ^ type argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/parameter_number_and_kind.rs:20:26
-   |
-LL |     type FErr1 = Self::E<'static, 'static>; // Error
-   |                          ^^^^^^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/parameter_number_and_kind.rs:22:29
-   |
-LL |     type FErr2<T> = Self::E<'static, T, u32>; // Error
-   |                             ^^^^^^^ lifetime argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/parameter_number_and_kind.rs:22:38
-   |
-LL |     type FErr2<T> = Self::E<'static, T, u32>; // Error
-   |                                      ^ type argument not allowed
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr
deleted file mode 100644
index 626495350a7..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/pointer_family.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/pointer_family.rs:37:21
-   |
-LL |     bar: P::Pointer<String>,
-   |                     ^^^^^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/pointer_family.rs:12:42
-   |
-LL |     fn new<T>(value: T) -> Self::Pointer<T>;
-   |                                          ^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/pointer_family.rs:20:42
-   |
-LL |     fn new<T>(value: T) -> Self::Pointer<T> {
-   |                                          ^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/pointer_family.rs:30:42
-   |
-LL |     fn new<T>(value: T) -> Self::Pointer<T> {
-   |                                          ^ type argument not allowed
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr
deleted file mode 100644
index 09dd654b575..00000000000
--- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr
+++ /dev/null
@@ -1,41 +0,0 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/streaming_iterator.rs:1:12
-   |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/streaming_iterator.rs:18:41
-   |
-LL |     bar: <T as StreamingIterator>::Item<'static>,
-   |                                         ^^^^^^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/streaming_iterator.rs:26:64
-   |
-LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
-   |                                                                ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/streaming_iterator.rs:12:48
-   |
-LL |     fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
-   |                                                ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/streaming_iterator.rs:38:37
-   |
-LL |     type Item<'a> = (usize, I::Item<'a>);
-   |                                     ^^ lifetime argument not allowed
-
-error[E0109]: lifetime arguments are not allowed for this type
-  --> $DIR/streaming_iterator.rs:40:48
-   |
-LL |     fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
-   |                                                ^^ lifetime argument not allowed
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0109`.
diff --git a/src/test/ui/rmeta_lib.rs b/src/test/ui/rmeta_lib.rs
index 6c74aec32e3..fa6826450c9 100644
--- a/src/test/ui/rmeta_lib.rs
+++ b/src/test/ui/rmeta_lib.rs
@@ -1,3 +1,4 @@
+// build-fail
 // aux-build:rmeta-meta.rs
 // no-prefer-dynamic
 // error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
index 65cf31f2f1f..4d23a1911a3 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-emscripten
 // ignore-tidy-linelength
 #![feature(repr_simd, platform_intrinsics)]
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr
index 0e88540bcc8..1ed472a485d 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr
@@ -1,11 +1,11 @@
 error[E0511]: invalid monomorphization of `simd_saturating_add` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type
-  --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:33:9
+  --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:34:9
    |
 LL |         simd_saturating_add(z, z);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_saturating_sub` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type
-  --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:35:9
+  --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:36:9
    |
 LL |         simd_saturating_sub(z, z);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs
index 7686b389a71..f95f548fee8 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(repr_simd, platform_intrinsics)]
 #![allow(non_camel_case_types)]
 #[repr(simd)]
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr
index 27493950af0..70cdc34684d 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr
@@ -1,83 +1,83 @@
 error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:62:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:64:9
    |
 LL |         simd_add(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:64:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:66:9
    |
 LL |         simd_sub(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:66:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:68:9
    |
 LL |         simd_mul(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:68:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:70:9
    |
 LL |         simd_div(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:70:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:72:9
    |
 LL |         simd_shl(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:72:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:74:9
    |
 LL |         simd_shr(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:74:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:76:9
    |
 LL |         simd_and(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:76:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:78:9
    |
 LL |         simd_or(0, 0);
    |         ^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:78:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:80:9
    |
 LL |         simd_xor(0, 0);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:82:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:84:9
    |
 LL |         simd_shl(z, z);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:84:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:86:9
    |
 LL |         simd_shr(z, z);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:86:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:88:9
    |
 LL |         simd_and(z, z);
    |         ^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:88:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:90:9
    |
 LL |         simd_or(z, z);
    |         ^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32`
-  --> $DIR/simd-intrinsic-generic-arithmetic.rs:90:9
+  --> $DIR/simd-intrinsic-generic-arithmetic.rs:92:9
    |
 LL |         simd_xor(z, z);
    |         ^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
index 931ee9db1fe..ed267d8411a 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 // Test that the simd_bitmask intrinsic produces ok-ish error
 // messages when misused.
 
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
index d016838d098..8cb235b778b 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
@@ -1,29 +1,29 @@
 error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
-  --> $DIR/simd-intrinsic-generic-bitmask.rs:74:22
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:76:22
    |
 LL |         let _: u16 = simd_bitmask(m2);
    |                      ^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
-  --> $DIR/simd-intrinsic-generic-bitmask.rs:77:22
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:79:22
    |
 LL |         let _: u16 = simd_bitmask(m8);
    |                      ^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
-  --> $DIR/simd-intrinsic-generic-bitmask.rs:80:22
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:82:22
    |
 LL |         let _: u32 = simd_bitmask(m16);
    |                      ^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
-  --> $DIR/simd-intrinsic-generic-bitmask.rs:83:22
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:85:22
    |
 LL |         let _: u64 = simd_bitmask(m32);
    |                      ^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
-  --> $DIR/simd-intrinsic-generic-bitmask.rs:86:23
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:88:23
    |
 LL |         let _: u128 = simd_bitmask(m64);
    |                       ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs
index c4016e75b14..4f4fa06b002 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(repr_simd, platform_intrinsics)]
 
 #[repr(simd)]
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr
index 6e33e3b30f5..d794a742b4d 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr
@@ -1,23 +1,23 @@
 error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-cast.rs:32:9
+  --> $DIR/simd-intrinsic-generic-cast.rs:34:9
    |
 LL |         simd_cast::<i32, i32>(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-cast.rs:34:9
+  --> $DIR/simd-intrinsic-generic-cast.rs:36:9
    |
 LL |         simd_cast::<i32, i32x4>(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-cast.rs:36:9
+  --> $DIR/simd-intrinsic-generic-cast.rs:38:9
    |
 LL |         simd_cast::<i32x4, i32>(x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8
-  --> $DIR/simd-intrinsic-generic-cast.rs:38:9
+  --> $DIR/simd-intrinsic-generic-cast.rs:40:9
    |
 LL |         simd_cast::<_, i32x8>(x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs
index 3ac47d17dad..3cd38042f0f 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(repr_simd, platform_intrinsics)]
 
 #[repr(simd)]
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr
index d8da2e5ee57..36c6b934d58 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr
@@ -1,107 +1,107 @@
 error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:26:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:28:9
    |
 LL |         simd_eq::<i32, i32>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:28:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:30:9
    |
 LL |         simd_ne::<i32, i32>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:30:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:32:9
    |
 LL |         simd_lt::<i32, i32>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:32:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:34:9
    |
 LL |         simd_le::<i32, i32>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:34:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:36:9
    |
 LL |         simd_gt::<i32, i32>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:36:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:38:9
    |
 LL |         simd_ge::<i32, i32>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:39:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:41:9
    |
 LL |         simd_eq::<_, i32>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:41:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:43:9
    |
 LL |         simd_ne::<_, i32>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:43:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:45:9
    |
 LL |         simd_lt::<_, i32>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:45:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:47:9
    |
 LL |         simd_le::<_, i32>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:47:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:49:9
    |
 LL |         simd_gt::<_, i32>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-comparison.rs:49:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:51:9
    |
 LL |         simd_ge::<_, i32>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
-  --> $DIR/simd-intrinsic-generic-comparison.rs:52:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:54:9
    |
 LL |         simd_eq::<_, i16x8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
-  --> $DIR/simd-intrinsic-generic-comparison.rs:54:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:56:9
    |
 LL |         simd_ne::<_, i16x8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
-  --> $DIR/simd-intrinsic-generic-comparison.rs:56:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:58:9
    |
 LL |         simd_lt::<_, i16x8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
-  --> $DIR/simd-intrinsic-generic-comparison.rs:58:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:60:9
    |
 LL |         simd_le::<_, i16x8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
-  --> $DIR/simd-intrinsic-generic-comparison.rs:60:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:62:9
    |
 LL |         simd_gt::<_, i16x8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8
-  --> $DIR/simd-intrinsic-generic-comparison.rs:62:9
+  --> $DIR/simd-intrinsic-generic-comparison.rs:64:9
    |
 LL |         simd_ge::<_, i16x8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs
index 28fcb6c57ec..5929d05f4de 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(repr_simd, platform_intrinsics, rustc_attrs)]
 
 #[repr(simd)]
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr
index 2f8ffb6035e..78022c0c8bd 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr
@@ -1,89 +1,89 @@
 error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:53:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:55:9
    |
 LL |         simd_insert(0, 0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
-  --> $DIR/simd-intrinsic-generic-elements.rs:55:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:57:9
    |
 LL |         simd_insert(x, 0, 1.0);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:57:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:59:9
    |
 LL |         simd_extract::<_, f32>(x, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:60:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:62:9
    |
 LL |         simd_shuffle2::<i32, i32>(0, 0, [0; 2]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:62:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:64:9
    |
 LL |         simd_shuffle3::<i32, i32>(0, 0, [0; 3]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:64:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:66:9
    |
 LL |         simd_shuffle4::<i32, i32>(0, 0, [0; 4]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:66:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:68:9
    |
 LL |         simd_shuffle8::<i32, i32>(0, 0, [0; 8]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:69:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:71:9
    |
 LL |         simd_shuffle2::<_, f32x2>(x, x, [0; 2]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:71:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:73:9
    |
 LL |         simd_shuffle3::<_, f32x3>(x, x, [0; 3]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:73:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:75:9
    |
 LL |         simd_shuffle4::<_, f32x4>(x, x, [0; 4]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
-  --> $DIR/simd-intrinsic-generic-elements.rs:75:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:77:9
    |
 LL |         simd_shuffle8::<_, f32x8>(x, x, [0; 8]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8
-  --> $DIR/simd-intrinsic-generic-elements.rs:78:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:80:9
    |
 LL |         simd_shuffle2::<_, i32x8>(x, x, [0; 2]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return type of length 3, found `i32x4` with length 4
-  --> $DIR/simd-intrinsic-generic-elements.rs:80:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:82:9
    |
 LL |         simd_shuffle3::<_, i32x4>(x, x, [0; 3]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x3` with length 3
-  --> $DIR/simd-intrinsic-generic-elements.rs:82:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:84:9
    |
 LL |         simd_shuffle4::<_, i32x3>(x, x, [0; 4]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2
-  --> $DIR/simd-intrinsic-generic-elements.rs:84:9
+  --> $DIR/simd-intrinsic-generic-elements.rs:86:9
    |
 LL |         simd_shuffle8::<_, i32x2>(x, x, [0; 8]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs
index 9a6dbe9d9ab..ede4b26d19c 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-emscripten
 
 // Test that the simd_reduce_{op} intrinsics produce ok-ish error
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr
index 5f2a67dc14e..91a62f6a1c6 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr
@@ -1,59 +1,59 @@
 error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:33:9
+  --> $DIR/simd-intrinsic-generic-reduction.rs:34:9
    |
 LL |         simd_reduce_add_ordered(z, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:35:9
+  --> $DIR/simd-intrinsic-generic-reduction.rs:36:9
    |
 LL |         simd_reduce_mul_ordered(z, 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:38:22
+  --> $DIR/simd-intrinsic-generic-reduction.rs:39:22
    |
 LL |         let _: f32 = simd_reduce_and(x);
    |                      ^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:40:22
+  --> $DIR/simd-intrinsic-generic-reduction.rs:41:22
    |
 LL |         let _: f32 = simd_reduce_or(x);
    |                      ^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:42:22
+  --> $DIR/simd-intrinsic-generic-reduction.rs:43:22
    |
 LL |         let _: f32 = simd_reduce_xor(x);
    |                      ^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: unsupported simd_reduce_and from `f32x4` with element `f32` to `f32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:45:22
+  --> $DIR/simd-intrinsic-generic-reduction.rs:46:22
    |
 LL |         let _: f32 = simd_reduce_and(z);
    |                      ^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: unsupported simd_reduce_or from `f32x4` with element `f32` to `f32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:47:22
+  --> $DIR/simd-intrinsic-generic-reduction.rs:48:22
    |
 LL |         let _: f32 = simd_reduce_or(z);
    |                      ^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:49:22
+  --> $DIR/simd-intrinsic-generic-reduction.rs:50:22
    |
 LL |         let _: f32 = simd_reduce_xor(z);
    |                      ^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_all` intrinsic: unsupported simd_reduce_all from `f32x4` with element `f32` to `bool`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:52:23
+  --> $DIR/simd-intrinsic-generic-reduction.rs:53:23
    |
 LL |         let _: bool = simd_reduce_all(z);
    |                       ^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_reduce_any` intrinsic: unsupported simd_reduce_any from `f32x4` with element `f32` to `bool`
-  --> $DIR/simd-intrinsic-generic-reduction.rs:54:23
+  --> $DIR/simd-intrinsic-generic-reduction.rs:55:23
    |
 LL |         let _: bool = simd_reduce_any(z);
    |                       ^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
index 72f51a895b6..a719b314150 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 // Test that the simd_select intrinsic produces ok-ish error
 // messages when misused.
 
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
index a46352c7308..f68c969d13e 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -1,47 +1,47 @@
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
-  --> $DIR/simd-intrinsic-generic-select.rs:38:9
+  --> $DIR/simd-intrinsic-generic-select.rs:40:9
    |
 LL |         simd_select(m8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_`
-  --> $DIR/simd-intrinsic-generic-select.rs:41:9
+  --> $DIR/simd-intrinsic-generic-select.rs:43:9
    |
 LL |         simd_select(x, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_`
-  --> $DIR/simd-intrinsic-generic-select.rs:44:9
+  --> $DIR/simd-intrinsic-generic-select.rs:46:9
    |
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
-  --> $DIR/simd-intrinsic-generic-select.rs:47:9
+  --> $DIR/simd-intrinsic-generic-select.rs:49:9
    |
 LL |         simd_select(m4, 0u32, 1u32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
-  --> $DIR/simd-intrinsic-generic-select.rs:50:9
+  --> $DIR/simd-intrinsic-generic-select.rs:52:9
    |
 LL |         simd_select_bitmask(0u8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
-  --> $DIR/simd-intrinsic-generic-select.rs:53:9
+  --> $DIR/simd-intrinsic-generic-select.rs:55:9
    |
 LL |         simd_select_bitmask(0u8, 1u32, 2u32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:56:9
+  --> $DIR/simd-intrinsic-generic-select.rs:58:9
    |
 LL |         simd_select_bitmask(0.0f32, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
-  --> $DIR/simd-intrinsic-generic-select.rs:59:9
+  --> $DIR/simd-intrinsic-generic-select.rs:61:9
    |
 LL |         simd_select_bitmask("x", x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd-type-generic-monomorphisation.rs b/src/test/ui/simd-type-generic-monomorphisation.rs
index 68eb78759eb..fc5e23f4986 100644
--- a/src/test/ui/simd-type-generic-monomorphisation.rs
+++ b/src/test/ui/simd-type-generic-monomorphisation.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(repr_simd, platform_intrinsics)]
 
 // error-pattern:monomorphising SIMD type `Simd2<X>` with a non-machine element type `X`
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.rs b/src/test/ui/stability-attribute/stability-attribute-sanity.rs
index 2e3d790d2d8..5db924642e5 100644
--- a/src/test/ui/stability-attribute/stability-attribute-sanity.rs
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity.rs
@@ -22,7 +22,7 @@ mod bogus_attribute_types_1 {
 }
 
 mod missing_feature_names {
-    #[unstable(issue = "0")] //~ ERROR missing 'feature' [E0546]
+    #[unstable(issue = "none")] //~ ERROR missing 'feature' [E0546]
     fn f1() { }
 
     #[unstable(feature = "b")] //~ ERROR missing 'issue' [E0547]
@@ -45,12 +45,12 @@ mod missing_version {
     fn f3() { }
 }
 
-#[unstable(feature = "b", issue = "0")]
+#[unstable(feature = "b", issue = "none")]
 #[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
 fn multiple1() { }
 
-#[unstable(feature = "b", issue = "0")]
-#[unstable(feature = "b", issue = "0")] //~ ERROR multiple stability levels [E0544]
+#[unstable(feature = "b", issue = "none")]
+#[unstable(feature = "b", issue = "none")] //~ ERROR multiple stability levels [E0544]
 fn multiple2() { }
 
 #[stable(feature = "a", since = "b")]
@@ -60,8 +60,8 @@ fn multiple3() { }
 #[stable(feature = "a", since = "b")]
 #[rustc_deprecated(since = "b", reason = "text")]
 #[rustc_deprecated(since = "b", reason = "text")]
-#[rustc_const_unstable(feature = "c", issue = "0")]
-#[rustc_const_unstable(feature = "d", issue = "0")] //~ ERROR multiple stability levels
+#[rustc_const_unstable(feature = "c", issue = "none")]
+#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
 pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
 //~^ ERROR Invalid stability or deprecation version found
 
diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr
index 552e078f45f..d0ca1705037 100644
--- a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr
@@ -31,8 +31,8 @@ LL |     #[stable(feature(b), since = "a")]
 error[E0546]: missing 'feature'
   --> $DIR/stability-attribute-sanity.rs:25:5
    |
-LL |     #[unstable(issue = "0")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[unstable(issue = "none")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0547]: missing 'issue'
   --> $DIR/stability-attribute-sanity.rs:28:5
@@ -73,8 +73,8 @@ LL | #[stable(feature = "a", since = "b")]
 error[E0544]: multiple stability levels
   --> $DIR/stability-attribute-sanity.rs:53:1
    |
-LL | #[unstable(feature = "b", issue = "0")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[unstable(feature = "b", issue = "none")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0544]: multiple stability levels
   --> $DIR/stability-attribute-sanity.rs:57:1
@@ -91,8 +91,8 @@ LL | pub const fn multiple4() { }
 error[E0544]: multiple stability levels
   --> $DIR/stability-attribute-sanity.rs:64:1
    |
-LL | #[rustc_const_unstable(feature = "d", issue = "0")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_const_unstable(feature = "d", issue = "none")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Invalid stability or deprecation version found
   --> $DIR/stability-attribute-sanity.rs:65:1
diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs
index 15b37facc50..e44a203b783 100644
--- a/src/test/ui/structs/struct-path-associated-type.rs
+++ b/src/test/ui/structs/struct-path-associated-type.rs
@@ -31,7 +31,6 @@ fn g<T: Tr<A = S>>() {
 fn main() {
     let s = S::A {}; //~ ERROR ambiguous associated type
     let z = S::A::<u8> {}; //~ ERROR ambiguous associated type
-    //~^ ERROR type arguments are not allowed for this type
     match S {
         S::A {} => {} //~ ERROR ambiguous associated type
     }
diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr
index 7cfbd7b720b..f8a2c7c6b6c 100644
--- a/src/test/ui/structs/struct-path-associated-type.stderr
+++ b/src/test/ui/structs/struct-path-associated-type.stderr
@@ -34,12 +34,6 @@ error[E0223]: ambiguous associated type
 LL |     let s = S::A {};
    |             ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/struct-path-associated-type.rs:33:20
-   |
-LL |     let z = S::A::<u8> {};
-   |                    ^^ type argument not allowed
-
 error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:33:13
    |
@@ -47,12 +41,12 @@ LL |     let z = S::A::<u8> {};
    |             ^^^^^^^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/struct-path-associated-type.rs:36:9
+  --> $DIR/struct-path-associated-type.rs:35:9
    |
 LL |         S::A {} => {}
    |         ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0071, E0109, E0223.
 For more information about an error, try `rustc --explain E0071`.
diff --git a/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs b/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs
index 94c72a31e5e..06ee421fc32 100644
--- a/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs
+++ b/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs
@@ -1,7 +1,6 @@
 pub fn foo(num: i32) -> i32 {
     let foo: i32::from_be(num);
     //~^ ERROR expected type, found local variable `num`
-    //~| ERROR type arguments are not allowed for this type
     //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
     //~| ERROR ambiguous associated type
     foo
diff --git a/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr b/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr
index 5353b3a75b2..63ba7893f04 100644
--- a/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr
+++ b/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr
@@ -15,19 +15,13 @@ LL |     let foo: i32::from_be(num);
    |                   only `Fn` traits may use parentheses
    |                   help: use angle brackets instead: `from_be<num>`
 
-error[E0109]: type arguments are not allowed for this type
-  --> $DIR/let-binding-init-expr-as-ty.rs:2:27
-   |
-LL |     let foo: i32::from_be(num);
-   |                           ^^^ type argument not allowed
-
 error[E0223]: ambiguous associated type
   --> $DIR/let-binding-init-expr-as-ty.rs:2:14
    |
 LL |     let foo: i32::from_be(num);
    |              ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<i32 as Trait>::from_be`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0109, E0214, E0223, E0573.
-For more information about an error, try `rustc --explain E0109`.
+Some errors have detailed explanations: E0214, E0223, E0573.
+For more information about an error, try `rustc --explain E0214`.
diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr
index 52e777285eb..895ff5ae54f 100644
--- a/src/test/ui/symbol-names/basic.legacy.stderr
+++ b/src/test/ui/symbol-names/basic.legacy.stderr
@@ -1,23 +1,23 @@
 error: symbol-name(_ZN5basic4main17h81759b0695851718E)
-  --> $DIR/basic.rs:7:1
+  --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(basic::main::h81759b0695851718)
-  --> $DIR/basic.rs:7:1
+  --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(basic::main)
-  --> $DIR/basic.rs:7:1
+  --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(main)
-  --> $DIR/basic.rs:14:1
+  --> $DIR/basic.rs:15:1
    |
 LL | #[rustc_def_path]
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs
index aa88184eddf..ddc349d7f10 100644
--- a/src/test/ui/symbol-names/basic.rs
+++ b/src/test/ui/symbol-names/basic.rs
@@ -1,3 +1,4 @@
+// build-fail
 // revisions: legacy v0
 //[legacy]compile-flags: -Z symbol-mangling-version=legacy
     //[v0]compile-flags: -Z symbol-mangling-version=v0
diff --git a/src/test/ui/symbol-names/basic.v0.stderr b/src/test/ui/symbol-names/basic.v0.stderr
index 40a39daaedc..36dba0dfc97 100644
--- a/src/test/ui/symbol-names/basic.v0.stderr
+++ b/src/test/ui/symbol-names/basic.v0.stderr
@@ -1,23 +1,23 @@
 error: symbol-name(_RNvCs4fqI2P2rA04_5basic4main)
-  --> $DIR/basic.rs:7:1
+  --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(basic[317d481089b8c8fe]::main)
-  --> $DIR/basic.rs:7:1
+  --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(basic::main)
-  --> $DIR/basic.rs:7:1
+  --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(main)
-  --> $DIR/basic.rs:14:1
+  --> $DIR/basic.rs:15:1
    |
 LL | #[rustc_def_path]
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr
index c9495b597eb..53ab2f9878f 100644
--- a/src/test/ui/symbol-names/impl1.legacy.stderr
+++ b/src/test/ui/symbol-names/impl1.legacy.stderr
@@ -1,71 +1,71 @@
 error: symbol-name(_ZN5impl13foo3Foo3bar17h92cf46db76791039E)
-  --> $DIR/impl1.rs:13:9
+  --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(impl1::foo::Foo::bar::h92cf46db76791039)
-  --> $DIR/impl1.rs:13:9
+  --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(impl1::foo::Foo::bar)
-  --> $DIR/impl1.rs:13:9
+  --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(foo::Foo::bar)
-  --> $DIR/impl1.rs:20:9
+  --> $DIR/impl1.rs:21:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h90c4a800b1aa0df0E)
-  --> $DIR/impl1.rs:31:9
+  --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(impl1::bar::<impl impl1::foo::Foo>::baz::h90c4a800b1aa0df0)
-  --> $DIR/impl1.rs:31:9
+  --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
-  --> $DIR/impl1.rs:31:9
+  --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(bar::<impl foo::Foo>::baz)
-  --> $DIR/impl1.rs:38:9
+  --> $DIR/impl1.rs:39:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h92c563325b7ff21aE)
-  --> $DIR/impl1.rs:61:13
+  --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h92c563325b7ff21a)
-  --> $DIR/impl1.rs:61:13
+  --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method)
-  --> $DIR/impl1.rs:61:13
+  --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
-  --> $DIR/impl1.rs:68:13
+  --> $DIR/impl1.rs:69:13
    |
 LL |             #[rustc_def_path]
    |             ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index add0d10ea6c..c1aaec5169d 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-tidy-linelength
 // revisions: legacy v0
 //[legacy]compile-flags: -Z symbol-mangling-version=legacy
diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr
index 01fe39ddf6c..a931937d1a8 100644
--- a/src/test/ui/symbol-names/impl1.v0.stderr
+++ b/src/test/ui/symbol-names/impl1.v0.stderr
@@ -1,71 +1,71 @@
 error: symbol-name(_RNvMNtCs4fqI2P2rA04_5impl13fooNtB2_3Foo3bar)
-  --> $DIR/impl1.rs:13:9
+  --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<impl1[317d481089b8c8fe]::foo::Foo>::bar)
-  --> $DIR/impl1.rs:13:9
+  --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<impl1::foo::Foo>::bar)
-  --> $DIR/impl1.rs:13:9
+  --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(foo::Foo::bar)
-  --> $DIR/impl1.rs:20:9
+  --> $DIR/impl1.rs:21:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_RNvMNtCs4fqI2P2rA04_5impl13barNtNtB4_3foo3Foo3baz)
-  --> $DIR/impl1.rs:31:9
+  --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<impl1[317d481089b8c8fe]::foo::Foo>::baz)
-  --> $DIR/impl1.rs:31:9
+  --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<impl1::foo::Foo>::baz)
-  --> $DIR/impl1.rs:31:9
+  --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(bar::<impl foo::Foo>::baz)
-  --> $DIR/impl1.rs:38:9
+  --> $DIR/impl1.rs:39:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-  --> $DIR/impl1.rs:61:13
+  --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:61:13
+  --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:61:13
+  --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
-  --> $DIR/impl1.rs:68:13
+  --> $DIR/impl1.rs:69:13
    |
 LL |             #[rustc_def_path]
    |             ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/impl2.rs b/src/test/ui/symbol-names/impl2.rs
index d48b182f2a2..08add29cb9c 100644
--- a/src/test/ui/symbol-names/impl2.rs
+++ b/src/test/ui/symbol-names/impl2.rs
@@ -1,3 +1,5 @@
+// build-fail
+
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
diff --git a/src/test/ui/symbol-names/impl2.stderr b/src/test/ui/symbol-names/impl2.stderr
index de26fed4413..98330031602 100644
--- a/src/test/ui/symbol-names/impl2.stderr
+++ b/src/test/ui/symbol-names/impl2.stderr
@@ -1,5 +1,5 @@
 error: def-path(<[u8; _] as Foo>::baz)
-  --> $DIR/impl2.rs:9:5
+  --> $DIR/impl2.rs:11:5
    |
 LL |     #[rustc_def_path]
    |     ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr
index 19d9740fb16..0e3a34adbc7 100644
--- a/src/test/ui/symbol-names/issue-60925.legacy.stderr
+++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,17 +1,17 @@
 error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hc86312d25b60f6eeE)
-  --> $DIR/issue-60925.rs:21:9
+  --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hc86312d25b60f6ee)
-  --> $DIR/issue-60925.rs:21:9
+  --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
-  --> $DIR/issue-60925.rs:21:9
+  --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs
index 02438351dbc..55b7041935c 100644
--- a/src/test/ui/symbol-names/issue-60925.rs
+++ b/src/test/ui/symbol-names/issue-60925.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-tidy-linelength
 // revisions: legacy v0
 //[legacy]compile-flags: -Z symbol-mangling-version=legacy
diff --git a/src/test/ui/symbol-names/issue-60925.v0.stderr b/src/test/ui/symbol-names/issue-60925.v0.stderr
index 5ead40211d2..78594b88b45 100644
--- a/src/test/ui/symbol-names/issue-60925.v0.stderr
+++ b/src/test/ui/symbol-names/issue-60925.v0.stderr
@@ -1,17 +1,17 @@
 error: symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
-  --> $DIR/issue-60925.rs:21:9
+  --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<issue_60925[317d481089b8c8fe]::foo::Foo<issue_60925[317d481089b8c8fe]::llvm::Foo>>::foo)
-  --> $DIR/issue-60925.rs:21:9
+  --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
-  --> $DIR/issue-60925.rs:21:9
+  --> $DIR/issue-60925.rs:22:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr
index 2f052341fae..648635f0c32 100644
--- a/src/test/ui/type/ascription/issue-47666.stderr
+++ b/src/test/ui/type/ascription/issue-47666.stderr
@@ -11,7 +11,7 @@ LL |     let _ = Option:Some(vec![0, 1]);
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: for more information, see https://github.com/rust-lang/rust/issues/23416
-   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type_length_limit.rs b/src/test/ui/type_length_limit.rs
index 926f12911c5..2f12c041a64 100644
--- a/src/test/ui/type_length_limit.rs
+++ b/src/test/ui/type_length_limit.rs
@@ -1,3 +1,4 @@
+// build-fail
 // ignore-x86 FIXME: missing sysroot spans (#53081)
 // error-pattern: reached the type-length limit while instantiating
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index d92924085e7..7e76604355d 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -453,10 +453,10 @@ impl Builder {
             "lldb-preview", "rust-analysis", "miri-preview"
         ]);
 
-        // The compiler libraries are not stable for end users, but `rustc-dev` was only recently
-        // split out of `rust-std`. We'll include it by default as a transition for nightly users.
+        // The compiler libraries are not stable for end users, and they're also huge, so we only
+        // `rustc-dev` for nightly users, and only in the "complete" profile. It's still possible
+        // for users to install the additional component manually, if needed.
         if self.rust_release == "nightly" {
-            self.extend_profile("default", &mut manifest.profiles, &["rustc-dev"]);
             self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]);
         }
     }
@@ -514,15 +514,6 @@ impl Builder {
             components.push(host_component("rust-mingw"));
         }
 
-        // The compiler libraries are not stable for end users, but `rustc-dev` was only recently
-        // split out of `rust-std`. We'll include it by default as a transition for nightly users,
-        // but ship it as an optional component on the beta and stable channels.
-        if self.rust_release == "nightly" {
-            components.push(host_component("rustc-dev"));
-        } else {
-            extensions.push(host_component("rustc-dev"));
-        }
-
         // Tools are always present in the manifest,
         // but might be marked as unavailable if they weren't built.
         extensions.extend(vec![
@@ -542,7 +533,6 @@ impl Builder {
         );
         extensions.extend(
             HOSTS.iter()
-                .filter(|&&target| target != host)
                 .map(|target| Component::from_str("rustc-dev", target))
         );
         extensions.push(Component::from_str("rust-src", "*"));
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 626f0f40efd32e6b3dbade50cd53fdfaa08446b
+Subproject 19a0de242f442ac7149c511031599aafa35b36d
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 69f99e74ac2266dff4b5adc7c59b35236f0abef
+Subproject cfb332005845883f2abb50fe183fc91221bad9d
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 2358a065d62..09733ffbe6a 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -100,7 +100,6 @@ pub enum PassMode {
     Check,
     Build,
     Run,
-    RunFail,
 }
 
 impl FromStr for PassMode {
@@ -121,12 +120,18 @@ impl fmt::Display for PassMode {
             PassMode::Check => "check",
             PassMode::Build => "build",
             PassMode::Run => "run",
-            PassMode::RunFail => "run-fail",
         };
         fmt::Display::fmt(s, f)
     }
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
+pub enum FailMode {
+    Check,
+    Build,
+    Run,
+}
+
 #[derive(Clone, Debug, PartialEq)]
 pub enum CompareMode {
     Nll,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 46cce6394e6..a9be7ba5f96 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
 
 use log::*;
 
-use crate::common::{self, CompareMode, Config, Mode, PassMode};
+use crate::common::{self, CompareMode, Config, Mode, PassMode, FailMode};
 use crate::util;
 use crate::extract_gdb_version;
 
@@ -366,6 +366,8 @@ pub struct TestProps {
     pass_mode: Option<PassMode>,
     // Ignore `--pass` overrides from the command line for this test.
     ignore_pass: bool,
+    // How far this test should proceed to start failing.
+    pub fail_mode: Option<FailMode>,
     // rustdoc will test the output of the `--test` option
     pub check_test_line_numbers_match: bool,
     // Do not pass `-Z ui-testing` to UI tests
@@ -411,6 +413,7 @@ impl TestProps {
             forbid_output: vec![],
             incremental_dir: None,
             pass_mode: None,
+            fail_mode: None,
             ignore_pass: false,
             check_test_line_numbers_match: false,
             disable_ui_testing_normalization: false,
@@ -437,6 +440,13 @@ impl TestProps {
     pub fn from_file(testfile: &Path, cfg: Option<&str>, config: &Config) -> Self {
         let mut props = TestProps::new();
         props.load_from(testfile, cfg, config);
+
+        match (props.pass_mode, props.fail_mode) {
+            (None, None) => props.fail_mode = Some(FailMode::Check),
+            (Some(_), None) | (None, Some(_)) => {}
+            (Some(_), Some(_)) => panic!("cannot use a *-fail and *-pass mode together"),
+        }
+
         props
     }
 
@@ -548,6 +558,7 @@ impl TestProps {
             }
 
             self.update_pass_mode(ln, cfg, config);
+            self.update_fail_mode(ln, config);
 
             if !self.ignore_pass {
                 self.ignore_pass = config.parse_ignore_pass(ln);
@@ -602,6 +613,29 @@ impl TestProps {
         }
     }
 
+    fn update_fail_mode(&mut self, ln: &str, config: &Config) {
+        let check_ui = |mode: &str| if config.mode != Mode::Ui {
+            panic!("`{}-fail` header is only supported in UI tests", mode);
+        };
+        let fail_mode = if config.parse_name_directive(ln, "check-fail") {
+            check_ui("check");
+            Some(FailMode::Check)
+        } else if config.parse_name_directive(ln, "build-fail") {
+            check_ui("build");
+            Some(FailMode::Build)
+        } else if config.parse_name_directive(ln, "run-fail") {
+            check_ui("run");
+            Some(FailMode::Run)
+        } else {
+            None
+        };
+        match (self.fail_mode, fail_mode) {
+            (None, Some(_)) => self.fail_mode = fail_mode,
+            (Some(_), Some(_)) => panic!("multiple `*-fail` headers in a single test"),
+            (_, None) => {}
+        }
+    }
+
     fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) {
         let check_no_run = |s| {
             if config.mode != Mode::Ui && config.mode != Mode::Incremental {
@@ -624,11 +658,6 @@ impl TestProps {
                 panic!("`run-pass` header is only supported in UI tests")
             }
             Some(PassMode::Run)
-        } else if config.parse_name_directive(ln, "run-fail") {
-            if config.mode != Mode::Ui {
-                panic!("`run-fail` header is only supported in UI tests")
-            }
-            Some(PassMode::RunFail)
         } else {
             None
         };
@@ -640,7 +669,7 @@ impl TestProps {
     }
 
     pub fn pass_mode(&self, config: &Config) -> Option<PassMode> {
-        if !self.ignore_pass {
+        if !self.ignore_pass && self.fail_mode.is_none() && config.mode == Mode::Ui {
             if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) {
                 return mode;
             }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 480868440b8..83a69c321bb 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,6 +1,6 @@
 // ignore-tidy-filelength
 
-use crate::common::{CompareMode, PassMode};
+use crate::common::{CompareMode, PassMode, FailMode};
 use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
 use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::common::{output_base_dir, output_base_name, output_testname_unique};
@@ -264,7 +264,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
         env::var_os("PYTHONPATH").hash(&mut hash);
     }
 
-    if let Ui | Incremental | Pretty = config.mode {
+    if let Ui = config.mode {
         config.force_pass_mode.hash(&mut hash);
     }
 
@@ -294,6 +294,14 @@ enum TestOutput {
     Run,
 }
 
+/// Will this test be executed? Should we use `make_exe_name`?
+#[derive(Copy, Clone, PartialEq)]
+enum WillExecute { Yes, No }
+
+/// Should `--emit metadata` be used?
+#[derive(Copy, Clone)]
+enum EmitMetadata { Yes, No }
+
 impl<'test> TestCx<'test> {
     /// Code executed for each revision in turn (or, if there are no
     /// revisions, exactly once, with revision == None).
@@ -332,27 +340,28 @@ impl<'test> TestCx<'test> {
         self.props.pass_mode(self.config)
     }
 
-    fn should_run(&self) -> bool {
-        let pass_mode = self.pass_mode();
+    fn should_run(&self, pm: Option<PassMode>) -> WillExecute {
         match self.config.mode {
-            Ui => pass_mode == Some(PassMode::Run) || pass_mode == Some(PassMode::RunFail),
+            Ui if pm == Some(PassMode::Run) || self.props.fail_mode == Some(FailMode::Run) => {
+                WillExecute::Yes
+            }
+            Ui => WillExecute::No,
             mode => panic!("unimplemented for mode {:?}", mode),
         }
     }
 
-    fn should_run_successfully(&self) -> bool {
-        let pass_mode = self.pass_mode();
+    fn should_run_successfully(&self, pm: Option<PassMode>) -> bool {
         match self.config.mode {
-            Ui => pass_mode == Some(PassMode::Run),
+            Ui => pm == Some(PassMode::Run),
             mode => panic!("unimplemented for mode {:?}", mode),
         }
     }
 
-    fn should_compile_successfully(&self) -> bool {
+    fn should_compile_successfully(&self, pm: Option<PassMode>) -> bool {
         match self.config.mode {
             CompileFail => false,
             JsDocTest => true,
-            Ui => self.pass_mode().is_some(),
+            Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build),
             Incremental => {
                 let revision = self.revision
                     .expect("incremental tests require a list of revisions");
@@ -360,7 +369,7 @@ impl<'test> TestCx<'test> {
                     true
                 } else if revision.starts_with("cfail") {
                     // FIXME: would be nice if incremental revs could start with "cpass"
-                    self.pass_mode().is_some()
+                    pm.is_some()
                 } else {
                     panic!("revision name must begin with rpass, rfail, or cfail");
                 }
@@ -369,8 +378,8 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn check_if_test_should_compile(&self, proc_res: &ProcRes) {
-        if self.should_compile_successfully() {
+    fn check_if_test_should_compile(&self, proc_res: &ProcRes, pm: Option<PassMode>) {
+        if self.should_compile_successfully(pm) {
             if !proc_res.status.success() {
                 self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res);
             }
@@ -387,8 +396,9 @@ impl<'test> TestCx<'test> {
     }
 
     fn run_cfail_test(&self) {
-        let proc_res = self.compile_test();
-        self.check_if_test_should_compile(&proc_res);
+        let pm = self.pass_mode();
+        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
+        self.check_if_test_should_compile(&proc_res, pm);
         self.check_no_compiler_crash(&proc_res, self.props.should_ice);
 
         let output_to_check = self.get_output(&proc_res);
@@ -399,7 +409,7 @@ impl<'test> TestCx<'test> {
             }
             self.check_expected_errors(expected_errors, &proc_res);
         } else {
-            self.check_error_patterns(&output_to_check, &proc_res);
+            self.check_error_patterns(&output_to_check, &proc_res, pm);
         }
         if self.props.should_ice {
             match proc_res.status.code() {
@@ -412,7 +422,8 @@ impl<'test> TestCx<'test> {
     }
 
     fn run_rfail_test(&self) {
-        let proc_res = self.compile_test();
+        let pm = self.pass_mode();
+        let proc_res = self.compile_test(WillExecute::Yes, self.should_emit_metadata(pm));
 
         if !proc_res.status.success() {
             self.fatal_proc_rec("compilation failed!", &proc_res);
@@ -428,7 +439,7 @@ impl<'test> TestCx<'test> {
 
         let output_to_check = self.get_output(&proc_res);
         self.check_correct_failure_status(&proc_res);
-        self.check_error_patterns(&output_to_check, &proc_res);
+        self.check_error_patterns(&output_to_check, &proc_res, pm);
     }
 
     fn get_output(&self, proc_res: &ProcRes) -> String {
@@ -455,7 +466,8 @@ impl<'test> TestCx<'test> {
     }
 
     fn run_rpass_test(&self) {
-        let proc_res = self.compile_test();
+        let emit_metadata = self.should_emit_metadata(self.pass_mode());
+        let proc_res = self.compile_test(WillExecute::Yes, emit_metadata);
 
         if !proc_res.status.success() {
             self.fatal_proc_rec("compilation failed!", &proc_res);
@@ -482,7 +494,7 @@ impl<'test> TestCx<'test> {
             return self.run_rpass_test();
         }
 
-        let mut proc_res = self.compile_test();
+        let mut proc_res = self.compile_test(WillExecute::Yes, EmitMetadata::No);
 
         if !proc_res.status.success() {
             self.fatal_proc_rec("compilation failed!", &proc_res);
@@ -715,7 +727,7 @@ impl<'test> TestCx<'test> {
 
     fn run_debuginfo_cdb_test_no_opt(&self) {
         // compile test file (it should have 'compile-flags:-g' in the header)
-        let compile_result = self.compile_test();
+        let compile_result = self.compile_test(WillExecute::Yes, EmitMetadata::No);
         if !compile_result.status.success() {
             self.fatal_proc_rec("compilation failed!", &compile_result);
         }
@@ -823,7 +835,7 @@ impl<'test> TestCx<'test> {
         let mut cmds = commands.join("\n");
 
         // compile test file (it should have 'compile-flags:-g' in the header)
-        let compiler_run_result = self.compile_test();
+        let compiler_run_result = self.compile_test(WillExecute::Yes, EmitMetadata::No);
         if !compiler_run_result.status.success() {
             self.fatal_proc_rec("compilation failed!", &compiler_run_result);
         }
@@ -1075,7 +1087,7 @@ impl<'test> TestCx<'test> {
 
     fn run_debuginfo_lldb_test_no_opt(&self) {
         // compile test file (it should have 'compile-flags:-g' in the header)
-        let compile_result = self.compile_test();
+        let compile_result = self.compile_test(WillExecute::Yes, EmitMetadata::No);
         if !compile_result.status.success() {
             self.fatal_proc_rec("compilation failed!", &compile_result);
         }
@@ -1374,10 +1386,16 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn check_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) {
+    fn check_error_patterns(
+        &self,
+        output_to_check: &str,
+        proc_res: &ProcRes,
+        pm: Option<PassMode>,
+    ) {
         debug!("check_error_patterns");
         if self.props.error_patterns.is_empty() {
-            if self.pass_mode().is_some() {
+            if pm.is_some() {
+                // FIXME(#65865)
                 return;
             } else {
                 self.fatal(&format!(
@@ -1553,22 +1571,30 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn compile_test(&self) -> ProcRes {
+    fn should_emit_metadata(&self, pm: Option<PassMode>) -> EmitMetadata {
+        match (pm, self.props.fail_mode, self.config.mode) {
+            (Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => EmitMetadata::Yes,
+            _ => EmitMetadata::No,
+        }
+    }
+
+    fn compile_test(&self, will_execute: WillExecute, emit_metadata: EmitMetadata) -> ProcRes {
+        self.compile_test_general(will_execute, emit_metadata, self.props.local_pass_mode())
+    }
+
+    fn compile_test_general(
+        &self,
+        will_execute: WillExecute,
+        emit_metadata: EmitMetadata,
+        local_pm: Option<PassMode>,
+    ) -> ProcRes {
         // Only use `make_exe_name` when the test ends up being executed.
-        let will_execute = match self.config.mode {
-            Ui => self.should_run(),
-            Incremental => self.revision.unwrap().starts_with("r"),
-            RunFail | RunPassValgrind | MirOpt |
-            DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb => true,
-            _ => false,
-        };
-        let output_file = if will_execute {
-            TargetLocation::ThisFile(self.make_exe_name())
-        } else {
-            TargetLocation::ThisDirectory(self.output_base_dir())
+        let output_file = match will_execute {
+            WillExecute::Yes => TargetLocation::ThisFile(self.make_exe_name()),
+            WillExecute::No => TargetLocation::ThisDirectory(self.output_base_dir()),
         };
 
-        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file, emit_metadata);
 
         rustc.arg("-L").arg(&self.aux_output_dir_name());
 
@@ -1579,11 +1605,12 @@ impl<'test> TestCx<'test> {
                 // want to actually assert warnings about all this code. Instead
                 // let's just ignore unused code warnings by defaults and tests
                 // can turn it back on if needed.
-                if !self.config.src_base.ends_with("rustdoc-ui") &&
-                    // Note that we don't call pass_mode() here as we don't want
+                if !self.is_rustdoc()
+                    // Note that we use the local pass mode here as we don't want
                     // to set unused to allow if we've overriden the pass mode
                     // via command line flags.
-                    self.props.local_pass_mode() != Some(PassMode::Run) {
+                    && local_pm != Some(PassMode::Run)
+                {
                     rustc.args(&["-A", "unused"]);
                 }
             }
@@ -1817,7 +1844,8 @@ impl<'test> TestCx<'test> {
         };
         // Create the directory for the stdout/stderr files.
         create_dir_all(aux_cx.output_base_dir()).unwrap();
-        let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
+        let input_file = &aux_testpaths.file;
+        let mut aux_rustc = aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No);
 
         let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
             (true, None)
@@ -1928,13 +1956,18 @@ impl<'test> TestCx<'test> {
         result
     }
 
+    fn is_rustdoc(&self) -> bool {
+        self.config.src_base.ends_with("rustdoc-ui")
+        || self.config.src_base.ends_with("rustdoc-js")
+    }
+
     fn make_compile_args(
         &self,
         input_file: &Path,
         output_file: TargetLocation,
+        emit_metadata: EmitMetadata,
     ) -> Command {
-        let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui") ||
-                         self.config.src_base.ends_with("rustdoc-js");
+        let is_rustdoc = self.is_rustdoc();
         let mut rustc = if !is_rustdoc {
             Command::new(&self.config.rustc_path)
         } else {
@@ -2029,7 +2062,7 @@ impl<'test> TestCx<'test> {
             }
         }
 
-        if let Some(PassMode::Check) = self.pass_mode() {
+        if let (false, EmitMetadata::Yes) = (is_rustdoc, emit_metadata) {
             rustc.args(&["--emit", "metadata"]);
         }
 
@@ -2278,7 +2311,8 @@ impl<'test> TestCx<'test> {
         let aux_dir = self.aux_output_dir_name();
 
         let output_file = TargetLocation::ThisDirectory(self.output_base_dir());
-        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+        let input_file = &self.testpaths.file;
+        let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No);
         rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir");
 
         self.compose_and_run_compiler(rustc, None)
@@ -2290,7 +2324,8 @@ impl<'test> TestCx<'test> {
         let output_path = self.output_base_name().with_extension("s");
 
         let output_file = TargetLocation::ThisFile(output_path.clone());
-        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+        let input_file = &self.testpaths.file;
+        let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No);
 
         rustc.arg("-L").arg(self.aux_output_dir_name());
 
@@ -2517,7 +2552,7 @@ impl<'test> TestCx<'test> {
     fn run_codegen_units_test(&self) {
         assert!(self.revision.is_none(), "revisions not relevant here");
 
-        let proc_res = self.compile_test();
+        let proc_res = self.compile_test(WillExecute::No, EmitMetadata::No);
 
         if !proc_res.status.success() {
             self.fatal_proc_rec("compilation failed!", &proc_res);
@@ -3033,6 +3068,19 @@ impl<'test> TestCx<'test> {
     }
 
     fn run_ui_test(&self) {
+        if let Some(FailMode::Build) = self.props.fail_mode {
+            // Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck).
+            let pm = Some(PassMode::Check);
+            let proc_res = self.compile_test_general(WillExecute::No, EmitMetadata::Yes, pm);
+            self.check_if_test_should_compile(&proc_res, pm);
+        }
+
+        let pm = self.pass_mode();
+        let should_run = self.should_run(pm);
+        let emit_metadata = self.should_emit_metadata(pm);
+        let proc_res = self.compile_test(should_run, emit_metadata);
+        self.check_if_test_should_compile(&proc_res, pm);
+
         // if the user specified a format in the ui test
         // print the output to the stderr file, otherwise extract
         // the rendered error messages from json and print them
@@ -3041,8 +3089,6 @@ impl<'test> TestCx<'test> {
             .compile_flags
             .iter()
             .any(|s| s.contains("--error-format"));
-        let proc_res = self.compile_test();
-        self.check_if_test_should_compile(&proc_res);
 
         let expected_fixed = self.load_expected_output(UI_FIXED);
 
@@ -3126,7 +3172,7 @@ impl<'test> TestCx<'test> {
 
         let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
 
-        if self.should_run() {
+        if let WillExecute::Yes = should_run {
             let proc_res = self.exec_compiled_test();
             let run_output_errors = if self.props.check_run_results {
                 self.load_compare_outputs(&proc_res, TestOutput::Run, explicit)
@@ -3139,7 +3185,7 @@ impl<'test> TestCx<'test> {
                     &proc_res,
                 );
             }
-            if self.should_run_successfully() {
+            if self.should_run_successfully(pm) {
                 if !proc_res.status.success() {
                     self.fatal_proc_rec("test run failed!", &proc_res);
                 }
@@ -3150,7 +3196,7 @@ impl<'test> TestCx<'test> {
             }
             if !self.props.error_patterns.is_empty() {
                 // "// error-pattern" comments
-                self.check_error_patterns(&proc_res.stderr, &proc_res);
+                self.check_error_patterns(&proc_res.stderr, &proc_res, pm);
             }
         }
 
@@ -3160,7 +3206,7 @@ impl<'test> TestCx<'test> {
                self.props.error_patterns);
         if !explicit && self.config.compare_mode.is_none() {
             let check_patterns =
-                !self.should_run() &&
+                should_run == WillExecute::No &&
                 !self.props.error_patterns.is_empty();
 
             let check_annotations =
@@ -3169,7 +3215,7 @@ impl<'test> TestCx<'test> {
 
             if check_patterns {
                 // "// error-pattern" comments
-                self.check_error_patterns(&proc_res.stderr, &proc_res);
+                self.check_error_patterns(&proc_res.stderr, &proc_res, pm);
             }
 
             if check_annotations {
@@ -3184,6 +3230,7 @@ impl<'test> TestCx<'test> {
             let mut rustc = self.make_compile_args(
                 &self.testpaths.file.with_extension(UI_FIXED),
                 TargetLocation::ThisFile(self.make_exe_name()),
+                emit_metadata,
             );
             rustc.arg("-L").arg(&self.aux_output_dir_name());
             let res = self.compose_and_run_compiler(rustc, None);
@@ -3197,7 +3244,7 @@ impl<'test> TestCx<'test> {
     }
 
     fn run_mir_opt_test(&self) {
-        let proc_res = self.compile_test();
+        let proc_res = self.compile_test(WillExecute::Yes, EmitMetadata::No);
 
         if !proc_res.status.success() {
             self.fatal_proc_rec("compilation failed!", &proc_res);
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 4ea101296b7..82292a6912c 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -12,6 +12,7 @@
 use std::collections::HashMap;
 use std::fmt;
 use std::fs;
+use std::num::NonZeroU32;
 use std::path::Path;
 
 use regex::Regex;
@@ -48,7 +49,7 @@ pub struct Feature {
     pub level: Status,
     pub since: Option<Version>,
     pub has_gate_test: bool,
-    pub tracking_issue: Option<u32>,
+    pub tracking_issue: Option<NonZeroU32>,
 }
 
 pub type Features = HashMap<String, Feature>;
@@ -396,6 +397,14 @@ fn map_lib_features(base_src_path: &Path,
             return;
         }
 
+        let handle_issue_none = |s| match s {
+            "none" => None,
+            issue => {
+                let n = issue.parse().expect("issue number is not a valid integer");
+                assert_ne!(n, 0, "\"none\" should be used when there is no issue, not \"0\"");
+                NonZeroU32::new(n)
+            }
+        };
         let mut becoming_feature: Option<(&str, Feature)> = None;
         let mut iter_lines = contents.lines().enumerate().peekable();
         while let Some((i, line)) = iter_lines.next() {
@@ -407,8 +416,7 @@ fn map_lib_features(base_src_path: &Path,
             };
             if let Some((ref name, ref mut f)) = becoming_feature {
                 if f.tracking_issue.is_none() {
-                    f.tracking_issue = find_attr_val(line, "issue")
-                    .map(|s| s.parse().unwrap());
+                    f.tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none);
                 }
                 if line.ends_with(']') {
                     mf(Ok((name, f.clone())), file, i + 1);
@@ -439,7 +447,7 @@ fn map_lib_features(base_src_path: &Path,
                     // FIXME(#57563): #57563 is now used as a common tracking issue,
                     // although we would like to have specific tracking issues for each
                     // `rustc_const_unstable` in the future.
-                    tracking_issue: Some(57563),
+                    tracking_issue: NonZeroU32::new(57563),
                 };
                 mf(Ok((feature_name, feature)), file, i + 1);
                 continue;
@@ -467,7 +475,7 @@ fn map_lib_features(base_src_path: &Path,
                 }
                 None => None,
             };
-            let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap());
+            let tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none);
 
             let feature = Feature {
                 level,
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index fdb0b6d3e56..39e8d61edeb 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -2,7 +2,7 @@
 
 #![deny(warnings)]
 
-use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features};
+use tidy::features::{Features, collect_lib_features, collect_lang_features};
 use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names,
                           PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR};
 use std::collections::BTreeSet;
@@ -70,15 +70,6 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur
 
 }
 
-fn has_valid_tracking_issue(f: &Feature) -> bool {
-    if let Some(n) = f.tracking_issue {
-        if n > 0 {
-            return true;
-        }
-    }
-    false
-}
-
 fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
     let unstable_features = collect_unstable_feature_names(features);
     let unstable_section_file_names = collect_unstable_book_section_file_names(src);
@@ -89,10 +80,10 @@ fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
         let out_file_path = out.join(&file_name);
         let feature = &features[&feature_name_underscore];
 
-        if has_valid_tracking_issue(&feature) {
+        if let Some(issue) = feature.tracking_issue {
             generate_stub_issue(&out_file_path,
                                 &feature_name_underscore,
-                                feature.tracking_issue.unwrap());
+                                issue.get());
         } else {
             generate_stub_no_issue(&out_file_path, &feature_name_underscore);
         }