about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock67
-rw-r--r--src/bootstrap/builder.rs10
-rw-r--r--src/doc/rustc/src/lints/listing/deny-by-default.md25
-rw-r--r--src/doc/unstable-book/src/compiler-flags/report-time.md80
-rw-r--r--src/liballoc/collections/vec_deque.rs101
-rw-r--r--src/liballoc/collections/vec_deque/tests.rs23
-rw-r--r--src/liballoc/lib.rs3
-rw-r--r--src/liballoc/rc.rs4
-rw-r--r--src/liballoc/slice.rs6
-rw-r--r--src/liballoc/tests/lib.rs1
-rw-r--r--src/libcore/any.rs10
-rw-r--r--src/libcore/char/methods.rs172
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/mem/mod.rs6
-rw-r--r--src/libcore/num/mod.rs2
-rw-r--r--src/libcore/sync/atomic.rs214
-rw-r--r--src/libcore/task/wake.rs2
-rw-r--r--src/libproc_macro/lib.rs1
-rw-r--r--src/librustc/dep_graph/graph.rs2
-rw-r--r--src/librustc/error_codes.rs14
-rw-r--r--src/librustc/hir/lowering.rs2
-rw-r--r--src/librustc/hir/map/mod.rs2
-rw-r--r--src/librustc/hir/mod.rs11
-rw-r--r--src/librustc/infer/mod.rs22
-rw-r--r--src/librustc/infer/region_constraints/leak_check.rs8
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/builtin.rs3
-rw-r--r--src/librustc/middle/stability.rs14
-rw-r--r--src/librustc/mir/interpret/mod.rs8
-rw-r--r--src/librustc/mir/mod.rs9
-rw-r--r--src/librustc/mir/mono.rs1
-rw-r--r--src/librustc/session/config.rs28
-rw-r--r--src/librustc/session/mod.rs10
-rw-r--r--src/librustc/traits/error_reporting.rs120
-rw-r--r--src/librustc/traits/query/evaluate_obligation.rs2
-rw-r--r--src/librustc/traits/select.rs35
-rw-r--r--src/librustc/ty/instance.rs37
-rw-r--r--src/librustc/ty/mod.rs1
-rw-r--r--src/librustc/ty/print/pretty.rs218
-rw-r--r--src/librustc/ty/relate.rs58
-rw-r--r--src/librustc/ty/structural_impls.rs5
-rw-r--r--src/librustc/ty/util.rs33
-rw-r--r--src/librustc_codegen_llvm/attributes.rs44
-rw-r--r--src/librustc_codegen_llvm/context.rs1
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs10
-rw-r--r--src/librustc_codegen_llvm/lib.rs1
-rw-r--r--src/librustc_codegen_ssa/callee.rs17
-rw-r--r--src/librustc_codegen_ssa/lib.rs1
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs41
-rw-r--r--src/librustc_codegen_ssa/mir/mod.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/intrinsic.rs1
-rw-r--r--src/librustc_incremental/persist/load.rs5
-rw-r--r--src/librustc_incremental/persist/save.rs2
-rw-r--r--src/librustc_interface/passes.rs2
-rw-r--r--src/librustc_metadata/cstore_impl.rs5
-rw-r--r--src/librustc_metadata/decoder.rs6
-rw-r--r--src/librustc_mir/borrow_check/conflict_errors.rs30
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs45
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs3
-rw-r--r--src/librustc_mir/build/block.rs70
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs7
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs11
-rw-r--r--src/librustc_mir/build/expr/into.rs46
-rw-r--r--src/librustc_mir/build/into.rs25
-rw-r--r--src/librustc_mir/build/matches/mod.rs20
-rw-r--r--src/librustc_mir/build/mod.rs23
-rw-r--r--src/librustc_mir/build/scope.rs14
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs36
-rw-r--r--src/librustc_mir/interpret/cast.rs9
-rw-r--r--src/librustc_mir/interpret/terminator.rs1
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/monomorphize/collector.rs36
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs20
-rw-r--r--src/librustc_mir/shim.rs9
-rw-r--r--src/librustc_passes/error_codes.rs30
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs14
-rw-r--r--src/librustc_resolve/late/diagnostics.rs3
-rw-r--r--src/librustc_resolve/lib.rs67
-rw-r--r--src/librustc_resolve/macros.rs8
-rw-r--r--src/librustc_typeck/check/method/mod.rs65
-rw-r--r--src/librustc_typeck/check/method/suggest.rs69
-rw-r--r--src/librustc_typeck/collect.rs26
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/librustdoc/config.rs5
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/test.rs2
-rw-r--r--src/libstd/collections/hash/map.rs2
-rw-r--r--src/libstd/error.rs10
-rw-r--r--src/libstd/ffi/c_str.rs2
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/panic.rs32
-rw-r--r--src/libstd/path.rs9
-rw-r--r--src/libstd/sync/mpsc/mod.rs20
-rw-r--r--src/libstd/sys/vxworks/fs.rs26
-rw-r--r--src/libstd/sys/vxworks/rwlock.rs2
-rw-r--r--src/libsyntax/ext/mbe/macro_parser.rs52
-rw-r--r--src/libsyntax/feature_gate/builtin_attrs.rs1
-rw-r--r--src/libsyntax/feature_gate/check.rs22
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/diagnostics.rs20
-rw-r--r--src/libsyntax/parse/literal.rs15
-rw-r--r--src/libsyntax/source_map.rs21
-rw-r--r--src/libsyntax/tokenstream.rs141
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs4
-rw-r--r--src/libsyntax_ext/lib.rs1
-rw-r--r--src/libsyntax_ext/test.rs44
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/libtest/formatters/json.rs9
-rw-r--r--src/libtest/formatters/pretty.rs134
-rw-r--r--src/libtest/formatters/terse.rs2
-rw-r--r--src/libtest/lib.rs438
-rw-r--r--src/libtest/stats.rs2
-rw-r--r--src/libtest/tests.rs125
m---------src/llvm-project0
-rw-r--r--src/test/codegen/extern-functions.rs19
-rw-r--r--src/test/codegen/non-terminate/infinite-loop-1.rs17
-rw-r--r--src/test/codegen/non-terminate/infinite-loop-2.rs19
-rw-r--r--src/test/codegen/non-terminate/infinite-recursion.rs14
-rw-r--r--src/test/codegen/nounwind-extern.rs6
-rw-r--r--src/test/codegen/unwind-extern-exports.rs19
-rw-r--r--src/test/codegen/unwind-extern-imports.rs41
-rw-r--r--src/test/mir-opt/box_expr.rs19
-rw-r--r--src/test/mir-opt/const_prop/reify_fn_ptr.rs2
-rw-r--r--src/test/mir-opt/issue-62289.rs45
-rw-r--r--src/test/run-make-fulldeps/linker-output-non-utf8/Makefile23
-rw-r--r--src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs6
-rw-r--r--src/test/run-make-fulldeps/linker-output-non-utf8/library.rs10
-rw-r--r--src/test/run-make-fulldeps/sanitizer-address/Makefile3
-rw-r--r--src/test/run-make-fulldeps/target-without-atomic-cas/Makefile2
-rw-r--r--src/test/rustdoc-ui/doc-test-doctest-feature.rs15
-rw-r--r--src/test/rustdoc-ui/doc-test-doctest-feature.stdout6
-rw-r--r--src/test/ui/async-await/async-borrowck-escaping-block-error.stderr2
-rw-r--r--src/test/ui/async-await/async-fn-size-uninit-locals.rs2
-rw-r--r--src/test/ui/auto-trait-validation.stderr2
-rw-r--r--src/test/ui/const-generics/fn-const-param-call.rs20
-rw-r--r--src/test/ui/const-generics/fn-const-param-call.stderr8
-rw-r--r--src/test/ui/const-generics/fn-const-param-infer.rs26
-rw-r--r--src/test/ui/const-generics/fn-const-param-infer.stderr45
-rw-r--r--src/test/ui/const-generics/issues/issue-60263.rs (renamed from src/test/ui/const-generics/issue-60263.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-60263.stderr (renamed from src/test/ui/const-generics/issue-60263.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs (renamed from src/test/ui/const-generics/issue-60818-struct-constructors.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr (renamed from src/test/ui/const-generics/issue-60818-struct-constructors.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-1.rs (renamed from src/test/ui/const-generics/issue-61336-1.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-1.stderr (renamed from src/test/ui/const-generics/issue-61336-1.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-2.rs (renamed from src/test/ui/const-generics/issue-61336-2.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-2.stderr (renamed from src/test/ui/const-generics/issue-61336-2.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61336.rs (renamed from src/test/ui/const-generics/issue-61336.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61336.stderr (renamed from src/test/ui/const-generics/issue-61336.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61422.rs (renamed from src/test/ui/const-generics/issue-61422.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61422.stderr (renamed from src/test/ui/const-generics/issue-61422.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61432.rs (renamed from src/test/ui/const-generics/issue-61432.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-61432.stderr (renamed from src/test/ui/const-generics/issue-61432.stderr)0
-rw-r--r--src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs16
-rw-r--r--src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr16
-rw-r--r--src/test/ui/const-generics/issues/issue-64519.rs (renamed from src/test/ui/const-generics/issue-64519.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-64519.stderr (renamed from src/test/ui/const-generics/issue-64519.stderr)0
-rw-r--r--src/test/ui/const-generics/raw-ptr-const-param-deref.rs19
-rw-r--r--src/test/ui/const-generics/raw-ptr-const-param-deref.stderr8
-rw-r--r--src/test/ui/const-generics/raw-ptr-const-param.rs9
-rw-r--r--src/test/ui/const-generics/raw-ptr-const-param.stderr20
-rw-r--r--src/test/ui/consts/auxiliary/external_macro.rs14
-rw-r--r--src/test/ui/consts/const-external-macro-const-err.rs13
-rw-r--r--src/test/ui/consts/const-external-macro-const-err.stderr11
-rw-r--r--src/test/ui/consts/const-match-check.eval1.stderr7
-rw-r--r--src/test/ui/consts/const-match-check.eval2.stderr7
-rw-r--r--src/test/ui/consts/const-match-check.matchck.stderr28
-rw-r--r--src/test/ui/deprecation/derive_on_deprecated.rs6
-rw-r--r--src/test/ui/drop/dynamic-drop-async.rs163
-rw-r--r--src/test/ui/drop/dynamic-drop.rs281
-rw-r--r--src/test/ui/empty/empty-never-array.stderr7
-rw-r--r--src/test/ui/error-codes/E0005.stderr7
-rw-r--r--src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs65
-rw-r--r--src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs83
-rw-r--r--src/test/ui/feature-gates/bench.rs4
-rw-r--r--src/test/ui/feature-gates/bench.stderr13
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr39
-rw-r--r--src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr16
-rw-r--r--src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr7
-rw-r--r--src/test/ui/issues/auxiliary/issue-57271-lib.rs11
-rw-r--r--src/test/ui/issues/issue-31561.stderr7
-rw-r--r--src/test/ui/issues/issue-53912.rs (renamed from src/test/ui/issue-53912.rs)0
-rw-r--r--src/test/ui/issues/issue-57271.rs24
-rw-r--r--src/test/ui/issues/issue-57271.stderr25
-rw-r--r--src/test/ui/issues/issue-57399-self-return-impl-trait.rs22
-rw-r--r--src/test/ui/issues/issue-57399-self-return-impl-trait.stderr8
-rw-r--r--src/test/ui/issues/issue-59020.rs (renamed from src/test/ui/issue-59020.rs)0
-rw-r--r--src/test/ui/issues/issue-64792-bad-unicode-ctor.rs5
-rw-r--r--src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr15
-rw-r--r--src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs11
-rw-r--r--src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr15
-rw-r--r--src/test/ui/match/non-exhaustive-defined-here.stderr28
-rw-r--r--src/test/ui/nll/issue-63154-normalize.rs34
-rw-r--r--src/test/ui/not-panic/not-panic-safe.stderr1
-rw-r--r--src/test/ui/panics/abort-on-panic.rs (renamed from src/test/ui/abi/abort-on-c-abi.rs)30
-rw-r--r--src/test/ui/privacy/privacy5.rs104
-rw-r--r--src/test/ui/privacy/privacy5.stderr344
-rw-r--r--src/test/ui/proc-macro/disappearing-resolution.rs22
-rw-r--r--src/test/ui/proc-macro/disappearing-resolution.stderr15
-rw-r--r--src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr7
-rw-r--r--src/test/ui/refutable-pattern-errors.stderr7
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.rs12
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr42
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.rs2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.stderr7
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/variant.stderr6
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object-literal.rs14
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object-literal.stderr30
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object.rs8
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object.stderr10
-rw-r--r--src/test/ui/suggestions/into-str.stderr1
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.rs23
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr41
-rw-r--r--src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr3
-rw-r--r--src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr1
-rw-r--r--src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr1
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.stderr7
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr7
-rwxr-xr-xsrc/tools/publish_toolstate.py2
m---------src/tools/rls0
m---------src/tools/rustfmt36
222 files changed, 3848 insertions, 1726 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 217ce65c196..844320fff3f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1330,9 +1330,9 @@ checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e"
 
 [[package]]
 name = "home"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3"
+checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8"
 dependencies = [
  "scopeguard 1.0.0",
  "winapi 0.3.6",
@@ -2657,9 +2657,9 @@ dependencies = [
 
 [[package]]
 name = "racer"
-version = "2.1.27"
+version = "2.1.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dde22b84ab75220015cbd91240222402bf885cbe3a5dc856475771abb82533ae"
+checksum = "acc70369054bad4ad0c16a3f45cd73e0695361a3af35c7b465e619ac2674f064"
 dependencies = [
  "bitflags",
  "clap",
@@ -3117,9 +3117,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-arena"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5"
+checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "smallvec",
@@ -3127,15 +3127,15 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-graphviz"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142"
+checksum = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6"
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36"
+checksum = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4"
 dependencies = [
  "cfg-if",
  "crossbeam-utils 0.6.5",
@@ -3144,8 +3144,9 @@ dependencies = [
  "jobserver",
  "lazy_static 1.3.0",
  "log",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
  "rustc-ap-graphviz",
+ "rustc-ap-rustc_index",
  "rustc-ap-serialize",
  "rustc-hash",
  "rustc-rayon 0.2.0",
@@ -3156,9 +3157,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333"
+checksum = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb"
 dependencies = [
  "annotate-snippets",
  "atty",
@@ -3172,19 +3173,29 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc-ap-rustc_index"
+version = "606.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea"
+dependencies = [
+ "rustc-ap-serialize",
+ "smallvec",
+]
+
+[[package]]
 name = "rustc-ap-rustc_lexer"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305"
+checksum = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139"
 dependencies = [
  "unicode-xid 0.2.0",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f"
+checksum = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0"
 dependencies = [
  "itertools 0.8.0",
  "proc-macro2 0.4.30",
@@ -3195,22 +3206,23 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2"
+checksum = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1"
 dependencies = [
  "bitflags",
  "log",
  "rustc-ap-rustc_data_structures",
+ "rustc-ap-rustc_index",
  "rustc-ap-serialize",
  "rustc-ap-syntax_pos",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6"
+checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20"
 dependencies = [
  "indexmap",
  "smallvec",
@@ -3218,17 +3230,17 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9"
+checksum = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e"
 dependencies = [
  "bitflags",
  "lazy_static 1.3.0",
  "log",
  "rustc-ap-rustc_data_structures",
  "rustc-ap-rustc_errors",
+ "rustc-ap-rustc_index",
  "rustc-ap-rustc_lexer",
- "rustc-ap-rustc_macros",
  "rustc-ap-rustc_target",
  "rustc-ap-serialize",
  "rustc-ap-syntax_pos",
@@ -3238,13 +3250,14 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "583.0.0"
+version = "606.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213"
+checksum = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4"
 dependencies = [
  "cfg-if",
  "rustc-ap-arena",
  "rustc-ap-rustc_data_structures",
+ "rustc-ap-rustc_index",
  "rustc-ap-rustc_macros",
  "rustc-ap-serialize",
  "scoped-tls",
@@ -3846,7 +3859,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.8"
+version = "1.4.9"
 dependencies = [
  "annotate-snippets",
  "bytecount",
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 5d586f0c461..0caf2d9b6db 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -817,12 +817,22 @@ impl<'a> Builder<'a> {
 
         let mut rustflags = Rustflags::new(&target);
         if stage != 0 {
+            if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") {
+                cargo.args(s.split_whitespace());
+            }
             rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP");
         } else {
+            if let Ok(s) = env::var("CARGOFLAGS_BOOTSTRAP") {
+                cargo.args(s.split_whitespace());
+            }
             rustflags.env("RUSTFLAGS_BOOTSTRAP");
             rustflags.arg("--cfg=bootstrap");
         }
 
+        if let Ok(s) = env::var("CARGOFLAGS") {
+            cargo.args(s.split_whitespace());
+        }
+
         match mode {
             Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {},
             Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
index 6574267f185..5688e90ada1 100644
--- a/src/doc/rustc/src/lints/listing/deny-by-default.md
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -222,3 +222,28 @@ error: invalid `crate_type` value
   | ^^^^^^^^^^^^^^^^^^^^
   |
 ```
+
+## const-err
+
+This lint detects expressions that will always panic at runtime and would be an
+error in a `const` context.
+
+```rust,ignore
+let _ = [0; 4][4];
+```
+
+This will produce:
+
+```text
+error: index out of bounds: the len is 4 but the index is 4
+ --> src/lib.rs:1:9
+  |
+1 | let _ = [0; 4][4];
+  |         ^^^^^^^^^
+  |
+```
+
+## order-dependent-trait-objects
+
+This lint detects a trait coherency violation that would allow creating two
+trait impls for the same dynamic trait object involving marker traits.
diff --git a/src/doc/unstable-book/src/compiler-flags/report-time.md b/src/doc/unstable-book/src/compiler-flags/report-time.md
new file mode 100644
index 00000000000..ed4e9c6b568
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/report-time.md
@@ -0,0 +1,80 @@
+# `report-time`
+
+The tracking issue for this feature is: [#64888]
+
+[#64888]: https://github.com/rust-lang/rust/issues/64888
+
+------------------------
+
+The `report-time` feature adds a possibility to report execution time of the
+tests generated via `libtest`.
+
+This is unstable feature, so you have to provide `-Zunstable-options` to get
+this feature working.
+
+Sample usage command:
+
+```sh
+./test_executable -Zunstable-options --report-time
+```
+
+Available options:
+
+```sh
+--report-time [plain|colored]
+                Show execution time of each test. Awailable values:
+                plain = do not colorize the execution time (default);
+                colored = colorize output according to the `color`
+                parameter value;
+                Threshold values for colorized output can be
+                configured via
+                `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
+                and
+                `RUST_TEST_TIME_DOCTEST` environment variables.
+                Expected format of environment variable is
+                `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+                Not available for --format=terse
+--ensure-time 
+                Treat excess of the test execution time limit as
+                error.
+                Threshold values for this option can be configured via
+                `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
+                and
+                `RUST_TEST_TIME_DOCTEST` environment variables.
+                Expected format of environment variable is
+                `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+                `CRITICAL_TIME` here means the limit that should not be
+                exceeded by test.
+```
+
+Example of the environment variable format:
+
+```sh
+RUST_TEST_TIME_UNIT=100,200
+```
+
+where 100 stands for warn time, and 200 stands for critical time.
+
+## Examples
+
+```sh
+cargo test --tests -- -Zunstable-options --report-time
+    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
+     Running target/debug/deps/example-27fb188025bec02c
+
+running 3 tests
+test tests::unit_test_quick ... ok <0.000s>
+test tests::unit_test_warn ... ok <0.055s>
+test tests::unit_test_critical ... ok <0.110s>
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+     Running target/debug/deps/tests-cedb06f6526d15d9
+
+running 3 tests
+test unit_test_quick ... ok <0.000s>
+test unit_test_warn ... ok <0.550s>
+test unit_test_critical ... ok <1.100s>
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+```
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index a4a0fbb194d..0bf573f5e25 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -10,8 +10,8 @@
 use core::array::LengthAtMost32;
 use core::cmp::{self, Ordering};
 use core::fmt;
-use core::iter::{repeat_with, FromIterator, FusedIterator};
-use core::mem;
+use core::iter::{once, repeat_with, FromIterator, FusedIterator};
+use core::mem::{self, replace};
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{Index, IndexMut, RangeBounds, Try};
 use core::ptr::{self, NonNull};
@@ -57,11 +57,88 @@ pub struct VecDeque<T> {
     buf: RawVec<T>,
 }
 
+/// PairSlices pairs up equal length slice parts of two deques
+///
+/// For example, given deques "A" and "B" with the following division into slices:
+///
+/// A: [0 1 2] [3 4 5]
+/// B: [a b] [c d e]
+///
+/// It produces the following sequence of matching slices:
+///
+/// ([0 1], [a b])
+/// ([2], [c])
+/// ([3 4], [d e])
+///
+/// and the uneven remainder of either A or B is skipped.
+struct PairSlices<'a, 'b, T> {
+    a0: &'a mut [T],
+    a1: &'a mut [T],
+    b0: &'b [T],
+    b1: &'b [T],
+}
+
+impl<'a, 'b, T> PairSlices<'a, 'b, T> {
+    fn from(to: &'a mut VecDeque<T>, from: &'b VecDeque<T>) -> Self {
+        let (a0, a1) = to.as_mut_slices();
+        let (b0, b1) = from.as_slices();
+        PairSlices { a0, a1, b0, b1 }
+    }
+
+    fn has_remainder(&self) -> bool {
+        !self.b0.is_empty()
+    }
+
+    fn remainder(self) -> impl Iterator<Item=&'b [T]> {
+        once(self.b0).chain(once(self.b1))
+    }
+}
+
+impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T>
+{
+    type Item = (&'a mut [T], &'b [T]);
+    fn next(&mut self) -> Option<Self::Item> {
+        // Get next part length
+        let part = cmp::min(self.a0.len(), self.b0.len());
+        if part == 0 {
+            return None;
+        }
+        let (p0, p1) = replace(&mut self.a0, &mut []).split_at_mut(part);
+        let (q0, q1) = self.b0.split_at(part);
+
+        // Move a1 into a0, if it's empty (and b1, b0 the same way).
+        self.a0 = p1;
+        self.b0 = q1;
+        if self.a0.is_empty() {
+            self.a0 = replace(&mut self.a1, &mut []);
+        }
+        if self.b0.is_empty() {
+            self.b0 = replace(&mut self.b1, &[]);
+        }
+        Some((p0, q0))
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for VecDeque<T> {
     fn clone(&self) -> VecDeque<T> {
         self.iter().cloned().collect()
     }
+
+    fn clone_from(&mut self, other: &Self) {
+        self.truncate(other.len());
+
+        let mut iter = PairSlices::from(self, other);
+        while let Some((dst, src)) = iter.next() {
+            dst.clone_from_slice(&src);
+        }
+
+        if iter.has_remainder() {
+            for remainder in iter.remainder() {
+                self.extend(remainder.iter().cloned());
+            }
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2209,6 +2286,16 @@ impl<'a, T> Iterator for Iter<'a, T> {
         final_res
     }
 
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        if n >= count(self.tail, self.head, self.ring.len()) {
+            self.tail = self.head;
+            None
+        } else {
+            self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len());
+            self.next()
+        }
+    }
+
     #[inline]
     fn last(mut self) -> Option<&'a T> {
         self.next_back()
@@ -2327,6 +2414,16 @@ impl<'a, T> Iterator for IterMut<'a, T> {
         back.iter_mut().fold(accum, &mut f)
     }
 
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        if n >= count(self.tail, self.head, self.ring.len()) {
+            self.tail = self.head;
+            None
+        } else {
+            self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len());
+            self.next()
+        }
+    }
+
     #[inline]
     fn last(mut self) -> Option<&'a mut T> {
         self.next_back()
diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs
index d2535239979..d578ee0dac4 100644
--- a/src/liballoc/collections/vec_deque/tests.rs
+++ b/src/liballoc/collections/vec_deque/tests.rs
@@ -362,6 +362,29 @@ fn test_vec_from_vecdeque() {
 }
 
 #[test]
+fn test_clone_from() {
+    let m = vec![1; 8];
+    let n = vec![2; 12];
+    for pfv in 0..8 {
+        for pfu in 0..8 {
+            for longer in 0..2 {
+                let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) };
+                let mut v = VecDeque::from(vr.clone());
+                for _ in 0..pfv {
+                    v.push_front(1);
+                }
+                let mut u = VecDeque::from(ur.clone());
+                for _ in 0..pfu {
+                    u.push_front(2);
+                }
+                v.clone_from(&u);
+                assert_eq!(&v, &u);
+            }
+        }
+    }
+}
+
+#[test]
 fn issue_53529() {
     use crate::boxed::Box;
 
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 247cd9a0201..3684162d8b1 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -121,7 +121,6 @@
 #![feature(maybe_uninit_extra, maybe_uninit_slice)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
-#![feature(mem_take)]
 #![feature(associated_type_bounds)]
 
 // Allow testing this library
@@ -154,7 +153,7 @@ mod boxed {
 #[cfg(test)]
 mod tests;
 pub mod collections;
-#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "ptr")]
 pub mod sync;
 pub mod rc;
 pub mod raw_vec;
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index a28c6d22abb..b0651f16484 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -773,7 +773,7 @@ impl<T: Clone> Rc<T> {
     /// referred to as clone-on-write.
     ///
     /// If there are no other `Rc` pointers to this value, then [`Weak`]
-    /// pointers to this value will be dissassociated.
+    /// pointers to this value will be disassociated.
     ///
     /// See also [`get_mut`], which will fail rather than cloning.
     ///
@@ -799,7 +799,7 @@ impl<T: Clone> Rc<T> {
     /// assert_eq!(*other_data, 12);
     /// ```
     ///
-    /// [`Weak`] pointers will be dissassociated:
+    /// [`Weak`] pointers will be disassociated:
     ///
     /// ```
     /// use std::rc::Rc;
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 4e4a285c21d..08243ef7c51 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -411,20 +411,16 @@ impl<T> [T] {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(repeat_generic_slice)]
     /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
     /// ```
     ///
     /// A panic upon overflow:
     ///
     /// ```should_panic
-    /// #![feature(repeat_generic_slice)]
     /// // this will panic at runtime
     /// b"0123456789abcdef".repeat(usize::max_value());
     /// ```
-    #[unstable(feature = "repeat_generic_slice",
-               reason = "it's on str, why not on slice?",
-               issue = "48784")]
+    #[stable(feature = "repeat_generic_slice", since = "1.40.0")]
     pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy {
         if n == 0 {
             return Vec::new();
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 5723a30c0f3..f2a2c80f2f7 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -4,7 +4,6 @@
 #![feature(exact_size_is_empty)]
 #![feature(option_flattening)]
 #![feature(pattern)]
-#![feature(repeat_generic_slice)]
 #![feature(trusted_len)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 85b59162620..f75b7a45443 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -2,14 +2,14 @@
 //! of any `'static` type through runtime reflection.
 //!
 //! `Any` itself can be used to get a `TypeId`, and has more features when used
-//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
-//! `downcast_ref` methods, to test if the contained value is of a given type,
-//! and to get a reference to the inner value as a type. As `&mut Any`, there
+//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is`
+//! and `downcast_ref` methods, to test if the contained value is of a given type,
+//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there
 //! is also the `downcast_mut` method, for getting a mutable reference to the
-//! inner value. `Box<Any>` adds the `downcast` method, which attempts to
+//! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to
 //! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
 //!
-//! Note that &Any is limited to testing whether a value is of a specified
+//! Note that `&dyn Any` is limited to testing whether a value is of a specified
 //! concrete type, and cannot be used to test whether a type implements a trait.
 //!
 //! [`Box`]: ../../std/boxed/struct.Box.html
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index a69eb0f6d4b..971d89e0044 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -116,9 +116,9 @@ impl char {
 
         // the code is split up here to improve execution speed for cases where
         // the `radix` is constant and 10 or smaller
-        let val = if radix <= 10  {
+        let val = if radix <= 10 {
             match self {
-                '0' ..= '9' => self as u32 - '0' as u32,
+                '0'..='9' => self as u32 - '0' as u32,
                 _ => return None,
             }
         } else {
@@ -130,8 +130,11 @@ impl char {
             }
         };
 
-        if val < radix { Some(val) }
-        else { None }
+        if val < radix {
+            Some(val)
+        } else {
+            None
+        }
     }
 
     /// Returns an iterator that yields the hexadecimal Unicode escape of a
@@ -303,8 +306,8 @@ impl char {
             '\r' => EscapeDefaultState::Backslash('r'),
             '\n' => EscapeDefaultState::Backslash('n'),
             '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
-            '\x20' ..= '\x7e' => EscapeDefaultState::Char(self),
-            _ => EscapeDefaultState::Unicode(self.escape_unicode())
+            '\x20'..='\x7e' => EscapeDefaultState::Char(self),
+            _ => EscapeDefaultState::Unicode(self.escape_unicode()),
         };
         EscapeDefault { state: init_state }
     }
@@ -436,30 +439,31 @@ impl char {
     pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
         let code = self as u32;
         unsafe {
-            let len =
-            if code < MAX_ONE_B && !dst.is_empty() {
+            let len = if code < MAX_ONE_B && !dst.is_empty() {
                 *dst.get_unchecked_mut(0) = code as u8;
                 1
             } else if code < MAX_TWO_B && dst.len() >= 2 {
                 *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
                 *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
                 2
-            } else if code < MAX_THREE_B && dst.len() >= 3  {
+            } else if code < MAX_THREE_B && dst.len() >= 3 {
                 *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
-                *dst.get_unchecked_mut(1) = (code >>  6 & 0x3F) as u8 | TAG_CONT;
+                *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
                 *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
                 3
             } else if dst.len() >= 4 {
                 *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
                 *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(2) = (code >>  6 & 0x3F) as u8 | TAG_CONT;
+                *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
                 *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
                 4
             } else {
-                panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
+                panic!(
+                    "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
                     from_u32_unchecked(code).len_utf8(),
                     code,
-                    dst.len())
+                    dst.len(),
+                )
             };
             from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
         }
@@ -515,15 +519,24 @@ impl char {
                 *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF);
                 slice::from_raw_parts_mut(dst.as_mut_ptr(), 2)
             } else {
-                panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
+                panic!(
+                    "encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
                     from_u32_unchecked(code).len_utf16(),
                     code,
-                    dst.len())
+                    dst.len(),
+                )
             }
         }
     }
 
-    /// Returns `true` if this `char` is an alphabetic code point, and false if not.
+    /// Returns `true` if this `char` has the `Alphabetic` property.
+    ///
+    /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
+    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
     ///
     /// # Examples
     ///
@@ -547,10 +560,14 @@ impl char {
         }
     }
 
-    /// Returns `true` if this `char` is lowercase.
+    /// Returns `true` if this `char` has the `Lowercase` property.
     ///
-    /// 'Lowercase' is defined according to the terms of the Unicode Derived Core
-    /// Property `Lowercase`.
+    /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
+    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
     ///
     /// # Examples
     ///
@@ -575,10 +592,14 @@ impl char {
         }
     }
 
-    /// Returns `true` if this `char` is uppercase.
+    /// Returns `true` if this `char` has the `Uppercase` property.
+    ///
+    /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
+    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
     ///
-    /// 'Uppercase' is defined according to the terms of the Unicode Derived Core
-    /// Property `Uppercase`.
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
     ///
     /// # Examples
     ///
@@ -603,10 +624,12 @@ impl char {
         }
     }
 
-    /// Returns `true` if this `char` is whitespace.
+    /// Returns `true` if this `char` has the `White_Space` property.
     ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived Core
-    /// Property `White_Space`.
+    /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`].
+    ///
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
     ///
     /// # Examples
     ///
@@ -630,10 +653,10 @@ impl char {
         }
     }
 
-    /// Returns `true` if this `char` is alphanumeric.
+    /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`].
     ///
-    /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories
-    /// `Nd`, `Nl`, `No` and the Derived Core Property `Alphabetic`.
+    /// [`is_alphabetic()`]: #method.is_alphabetic
+    /// [`is_numeric()`]: #method.is_numeric
     ///
     /// # Examples
     ///
@@ -655,10 +678,15 @@ impl char {
         self.is_alphabetic() || self.is_numeric()
     }
 
-    /// Returns `true` if this `char` is a control code point.
+    /// Returns `true` if this `char` has the general category for control codes.
+    ///
+    /// Control codes (code points with the general category of `Cc`) are described in Chapter 4
+    /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character
+    /// Database][ucd] [`UnicodeData.txt`].
     ///
-    /// 'Control code point' is defined in terms of the Unicode General
-    /// Category `Cc`.
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
     ///
     /// # Examples
     ///
@@ -675,19 +703,29 @@ impl char {
         general_category::Cc(self)
     }
 
-    /// Returns `true` if this `char` is an extended grapheme character.
+    /// Returns `true` if this `char` has the `Grapheme_Extend` property.
     ///
-    /// 'Extended grapheme character' is defined in terms of the Unicode Shaping and Rendering
-    /// Category `Grapheme_Extend`.
+    /// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text
+    /// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd]
+    /// [`DerivedCoreProperties.txt`].
+    ///
+    /// [uax29]: https://www.unicode.org/reports/tr29/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
     #[inline]
     pub(crate) fn is_grapheme_extended(self) -> bool {
         derived_property::Grapheme_Extend(self)
     }
 
-    /// Returns `true` if this `char` is numeric.
+    /// Returns `true` if this `char` has one of the general categories for numbers.
+    ///
+    /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
+    /// characters, and `No` for other numeric characters) are specified in the [Unicode Character
+    /// Database][ucd] [`UnicodeData.txt`].
     ///
-    /// 'Numeric'-ness is defined in terms of the Unicode General Categories
-    /// `Nd`, `Nl`, `No`.
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
     ///
     /// # Examples
     ///
@@ -713,25 +751,29 @@ impl char {
         }
     }
 
-    /// Returns an iterator that yields the lowercase equivalent of a `char`
-    /// as one or more `char`s.
+    /// Returns an iterator that yields the lowercase mapping of this `char` as one or more
+    /// `char`s.
     ///
-    /// If a character does not have a lowercase equivalent, the same character
-    /// will be returned back by the iterator.
+    /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
     ///
-    /// This performs complex unconditional mappings with no tailoring: it maps
-    /// one Unicode character to its lowercase equivalent according to the
-    /// [Unicode database] and the additional complex mappings
-    /// [`SpecialCasing.txt`]. Conditional mappings (based on context or
-    /// language) are not considered here.
+    /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character
+    /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
     ///
-    /// For a full reference, see [here][reference].
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
     ///
-    /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
+    /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
+    /// the `char`(s) given by [`SpecialCasing.txt`].
     ///
-    /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+    /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
     ///
-    /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
+    /// This operation performs an unconditional mapping without tailoring. That is, the conversion
+    /// is independent of context and language.
+    ///
+    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
+    /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
     ///
     /// # Examples
     ///
@@ -774,25 +816,29 @@ impl char {
         ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
     }
 
-    /// Returns an iterator that yields the uppercase equivalent of a `char`
-    /// as one or more `char`s.
+    /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
+    /// `char`s.
+    ///
+    /// If this `char` does not have a uppercase mapping, the iterator yields the same `char`.
+    ///
+    /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
+    /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
     ///
-    /// If a character does not have an uppercase equivalent, the same character
-    /// will be returned back by the iterator.
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
     ///
-    /// This performs complex unconditional mappings with no tailoring: it maps
-    /// one Unicode character to its uppercase equivalent according to the
-    /// [Unicode database] and the additional complex mappings
-    /// [`SpecialCasing.txt`]. Conditional mappings (based on context or
-    /// language) are not considered here.
+    /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
+    /// the `char`(s) given by [`SpecialCasing.txt`].
     ///
-    /// For a full reference, see [here][reference].
+    /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
     ///
-    /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
+    /// This operation performs an unconditional mapping without tailoring. That is, the conversion
+    /// is independent of context and language.
     ///
-    /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
+    /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
     ///
-    /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
     ///
     /// # Examples
     ///
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index e8c76b49a8e..30e8dddff85 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -127,7 +127,6 @@
 #![feature(adx_target_feature)]
 #![feature(maybe_uninit_slice)]
 #![feature(external_doc)]
-#![feature(mem_take)]
 #![feature(associated_type_bounds)]
 
 #[prelude_import]
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 95ad4272ced..23608931b1d 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -520,8 +520,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// A simple example:
 ///
 /// ```
-/// #![feature(mem_take)]
-///
 /// use std::mem;
 ///
 /// let mut v: Vec<i32> = vec![1, 2];
@@ -552,8 +550,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// `self`, allowing it to be returned:
 ///
 /// ```
-/// #![feature(mem_take)]
-///
 /// use std::mem;
 ///
 /// # struct Buffer<T> { buf: Vec<T> }
@@ -572,7 +568,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 ///
 /// [`Clone`]: ../../std/clone/trait.Clone.html
 #[inline]
-#[unstable(feature = "mem_take", issue = "61129")]
+#[stable(feature = "mem_take", since = "1.40.0")]
 pub fn take<T: Default>(dest: &mut T) -> T {
     replace(dest, T::default())
 }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index ebde82de834..998c8f81652 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1058,7 +1058,7 @@ $EndFeature, "
             #[inline]
             pub fn saturating_mul(self, rhs: Self) -> Self {
                 self.checked_mul(rhs).unwrap_or_else(|| {
-                    if (self < 0 && rhs < 0) || (self > 0 && rhs > 0) {
+                    if (self < 0) == (rhs < 0) {
                         Self::max_value()
                     } else {
                         Self::min_value()
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index c9ccef972c2..73d5abf1aed 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -18,11 +18,11 @@
 //!
 //! Each method takes an [`Ordering`] which represents the strength of
 //! the memory barrier for that operation. These orderings are the
-//! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
+//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2].
 //!
 //! [`Ordering`]: enum.Ordering.html
 //!
-//! [1]: https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
+//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order
 //! [2]: ../../../nomicon/atomics.html
 //!
 //! Atomic variables are safe to share between threads (they implement [`Sync`])
@@ -113,8 +113,8 @@
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
-#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
-#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
+#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
+#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
 
 use self::Ordering::*;
 
@@ -160,14 +160,14 @@ pub fn spin_loop_hint() {
 /// This type has the same in-memory representation as a [`bool`].
 ///
 /// [`bool`]: ../../../std/primitive.bool.html
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(C, align(1))]
 pub struct AtomicBool {
     v: UnsafeCell<u8>,
 }
 
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Default for AtomicBool {
     /// Creates an `AtomicBool` initialized to `false`.
@@ -177,14 +177,14 @@ impl Default for AtomicBool {
 }
 
 // Send is implicitly implemented for AtomicBool.
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl Sync for AtomicBool {}
 
 /// A raw pointer type which can be safely shared between threads.
 ///
 /// This type has the same in-memory representation as a `*mut T`.
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))]
 #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))]
@@ -193,7 +193,7 @@ pub struct AtomicPtr<T> {
     p: UnsafeCell<*mut T>,
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for AtomicPtr<T> {
     /// Creates a null `AtomicPtr<T>`.
@@ -202,10 +202,10 @@ impl<T> Default for AtomicPtr<T> {
     }
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T> Send for AtomicPtr<T> {}
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T> Sync for AtomicPtr<T> {}
 
@@ -217,8 +217,8 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 /// operations synchronize other memory while additionally preserving a total order of such
 /// operations across all threads.
 ///
-/// Rust's memory orderings are [the same as
-/// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
+/// Rust's memory orderings are [the same as those of
+/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order).
 ///
 /// For more information see the [nomicon].
 ///
@@ -231,9 +231,9 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 pub enum Ordering {
     /// No ordering constraints, only atomic operations.
     ///
-    /// Corresponds to LLVM's [`Monotonic`] ordering.
+    /// Corresponds to [`memory_order_relaxed`] in C++20.
     ///
-    /// [`Monotonic`]: https://llvm.org/docs/Atomics.html#monotonic
+    /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering
     #[stable(feature = "rust1", since = "1.0.0")]
     Relaxed,
     /// When coupled with a store, all previous operations become ordered
@@ -246,11 +246,12 @@ pub enum Ordering {
     ///
     /// This ordering is only applicable for operations that can perform a store.
     ///
-    /// Corresponds to LLVM's [`Release`] ordering.
+    /// Corresponds to [`memory_order_release`] in C++20.
     ///
-    /// [`Release`]: https://llvm.org/docs/Atomics.html#release
-    /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
-    /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic
+    /// [`Release`]: #variant.Release
+    /// [`Acquire`]: #variant.Acquire
+    /// [`Relaxed`]: #variant.Relaxed
+    /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
     #[stable(feature = "rust1", since = "1.0.0")]
     Release,
     /// When coupled with a load, if the loaded value was written by a store operation with
@@ -263,11 +264,12 @@ pub enum Ordering {
     ///
     /// This ordering is only applicable for operations that can perform a load.
     ///
-    /// Corresponds to LLVM's [`Acquire`] ordering.
+    /// Corresponds to [`memory_order_acquire`] in C++20.
     ///
-    /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
-    /// [`Release`]: https://llvm.org/docs/Atomics.html#release
-    /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic
+    /// [`Acquire`]: #variant.Acquire
+    /// [`Release`]: #variant.Release
+    /// [`Relaxed`]: #variant.Relaxed
+    /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
     #[stable(feature = "rust1", since = "1.0.0")]
     Acquire,
     /// Has the effects of both [`Acquire`] and [`Release`] together:
@@ -275,28 +277,28 @@ pub enum Ordering {
     ///
     /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up
     /// not performing any store and hence it has just [`Acquire`] ordering. However,
-    /// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses.
+    /// `AcqRel` will never perform [`Relaxed`] accesses.
     ///
     /// This ordering is only applicable for operations that combine both loads and stores.
     ///
-    /// Corresponds to LLVM's [`AcquireRelease`] ordering.
+    /// Corresponds to [`memory_order_acq_rel`] in C++20.
     ///
-    /// [`AcquireRelease`]: https://llvm.org/docs/Atomics.html#acquirerelease
-    /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
-    /// [`Release`]: https://llvm.org/docs/Atomics.html#release
-    /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic
+    /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
+    /// [`Acquire`]: #variant.Acquire
+    /// [`Release`]: #variant.Release
+    /// [`Relaxed`]: #variant.Relaxed
     #[stable(feature = "rust1", since = "1.0.0")]
     AcqRel,
     /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store
     /// operations, respectively) with the additional guarantee that all threads see all
     /// sequentially consistent operations in the same order.
     ///
-    /// Corresponds to LLVM's [`SequentiallyConsistent`] ordering.
+    /// Corresponds to [`memory_order_seq_cst`] in C++20.
     ///
-    /// [`SequentiallyConsistent`]: https://llvm.org/docs/Atomics.html#sequentiallyconsistent
-    /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
-    /// [`Release`]: https://llvm.org/docs/Atomics.html#release
-    /// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease
+    /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering
+    /// [`Acquire`]: #variant.Acquire
+    /// [`Release`]: #variant.Release
+    /// [`AcqRel`]: #variant.AcqRel
     #[stable(feature = "rust1", since = "1.0.0")]
     SeqCst,
 }
@@ -304,7 +306,7 @@ pub enum Ordering {
 /// An [`AtomicBool`] initialized to `false`.
 ///
 /// [`AtomicBool`]: struct.AtomicBool.html
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(
     since = "1.34.0",
@@ -313,7 +315,7 @@ pub enum Ordering {
 )]
 pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
 
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 impl AtomicBool {
     /// Creates a new `AtomicBool`.
     ///
@@ -462,7 +464,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn swap(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
     }
@@ -500,7 +502,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
         match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
             Ok(x) => x,
@@ -551,7 +553,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn compare_exchange(&self,
                             current: bool,
                             new: bool,
@@ -607,7 +609,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn compare_exchange_weak(&self,
                                  current: bool,
                                  new: bool,
@@ -658,7 +660,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
     }
@@ -700,7 +702,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
         // We can't use atomic_nand here because it can result in a bool with
         // an invalid value. This happens because the atomic operation is done
@@ -753,7 +755,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
     }
@@ -794,13 +796,13 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "8")]
     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
     }
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 impl<T> AtomicPtr<T> {
     /// Creates a new `AtomicPtr`.
     ///
@@ -951,7 +953,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "ptr")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
         unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
     }
@@ -987,7 +989,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "ptr")]
     pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
         match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
             Ok(x) => x,
@@ -1029,7 +1031,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "ptr")]
     pub fn compare_exchange(&self,
                             current: *mut T,
                             new: *mut T,
@@ -1089,7 +1091,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(target_has_atomic = "cas")]
+    #[cfg(target_has_atomic = "ptr")]
     pub fn compare_exchange_weak(&self,
                                  current: *mut T,
                                  new: *mut T,
@@ -1110,7 +1112,7 @@ impl<T> AtomicPtr<T> {
     }
 }
 
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
 impl From<bool> for AtomicBool {
     /// Converts a `bool` into an `AtomicBool`.
@@ -1126,16 +1128,17 @@ impl From<bool> for AtomicBool {
     fn from(b: bool) -> Self { Self::new(b) }
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "atomic_from", since = "1.23.0")]
 impl<T> From<*mut T> for AtomicPtr<T> {
     #[inline]
     fn from(p: *mut T) -> Self { Self::new(p) }
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 macro_rules! atomic_int {
-    ($stable:meta,
+    ($cfg_cas:meta,
+     $stable:meta,
      $stable_cxchg:meta,
      $stable_debug:meta,
      $stable_access:meta,
@@ -1356,7 +1359,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_swap(self.v.get(), val, order) }
                 }
@@ -1396,7 +1399,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn compare_and_swap(&self,
                                         current: $int_type,
                                         new: $int_type,
@@ -1454,7 +1457,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10);
 ```"),
                 #[inline]
                 #[$stable_cxchg]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn compare_exchange(&self,
                                         current: $int_type,
                                         new: $int_type,
@@ -1506,7 +1509,7 @@ loop {
 ```"),
                 #[inline]
                 #[$stable_cxchg]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn compare_exchange_weak(&self,
                                              current: $int_type,
                                              new: $int_type,
@@ -1544,7 +1547,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_add(self.v.get(), val, order) }
                 }
@@ -1576,7 +1579,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_sub(self.v.get(), val, order) }
                 }
@@ -1611,7 +1614,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_and(self.v.get(), val, order) }
                 }
@@ -1647,7 +1650,7 @@ assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
 ```"),
                 #[inline]
                 #[$stable_nand]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_nand(self.v.get(), val, order) }
                 }
@@ -1682,7 +1685,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_or(self.v.get(), val, order) }
                 }
@@ -1717,7 +1720,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_xor(self.v.get(), val, order) }
                 }
@@ -1767,7 +1770,7 @@ assert_eq!(x.load(Ordering::SeqCst), 9);
                 #[unstable(feature = "no_more_cas",
                        reason = "no more CAS loops in user code",
                        issue = "48655")]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_update<F>(&self,
                                        mut f: F,
                                        fetch_order: Ordering,
@@ -1828,7 +1831,7 @@ assert!(max_foo == 42);
                 #[unstable(feature = "atomic_min_max",
                        reason = "easier and faster min/max than writing manual CAS loop",
                        issue = "48655")]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { $max_fn(self.v.get(), val, order) }
                 }
@@ -1880,7 +1883,7 @@ assert_eq!(min_foo, 12);
                 #[unstable(feature = "atomic_min_max",
                        reason = "easier and faster min/max than writing manual CAS loop",
                        issue = "48655")]
-                #[cfg(target_has_atomic = "cas")]
+                #[$cfg_cas]
                 pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { $min_fn(self.v.get(), val, order) }
                 }
@@ -1890,8 +1893,9 @@ assert_eq!(min_foo, 12);
     }
 }
 
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 atomic_int! {
+    cfg(target_has_atomic = "8"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1906,8 +1910,9 @@ atomic_int! {
     "AtomicI8::new(0)",
     i8 AtomicI8 ATOMIC_I8_INIT
 }
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 atomic_int! {
+    cfg(target_has_atomic = "8"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1922,8 +1927,9 @@ atomic_int! {
     "AtomicU8::new(0)",
     u8 AtomicU8 ATOMIC_U8_INIT
 }
-#[cfg(target_has_atomic = "16")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))]
 atomic_int! {
+    cfg(target_has_atomic = "16"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1938,8 +1944,9 @@ atomic_int! {
     "AtomicI16::new(0)",
     i16 AtomicI16 ATOMIC_I16_INIT
 }
-#[cfg(target_has_atomic = "16")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))]
 atomic_int! {
+    cfg(target_has_atomic = "16"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1954,8 +1961,9 @@ atomic_int! {
     "AtomicU16::new(0)",
     u16 AtomicU16 ATOMIC_U16_INIT
 }
-#[cfg(target_has_atomic = "32")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))]
 atomic_int! {
+    cfg(target_has_atomic = "32"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1970,8 +1978,9 @@ atomic_int! {
     "AtomicI32::new(0)",
     i32 AtomicI32 ATOMIC_I32_INIT
 }
-#[cfg(target_has_atomic = "32")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))]
 atomic_int! {
+    cfg(target_has_atomic = "32"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -1986,8 +1995,12 @@ atomic_int! {
     "AtomicU32::new(0)",
     u32 AtomicU32 ATOMIC_U32_INIT
 }
-#[cfg(target_has_atomic = "64")]
+#[cfg(any(
+    all(bootstrap, target_has_atomic = "64"),
+    target_has_atomic_load_store = "64"
+))]
 atomic_int! {
+    cfg(target_has_atomic = "64"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -2002,8 +2015,12 @@ atomic_int! {
     "AtomicI64::new(0)",
     i64 AtomicI64 ATOMIC_I64_INIT
 }
-#[cfg(target_has_atomic = "64")]
+#[cfg(any(
+    all(bootstrap, target_has_atomic = "64"),
+    target_has_atomic_load_store = "64"
+))]
 atomic_int! {
+    cfg(target_has_atomic = "64"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
@@ -2018,8 +2035,9 @@ atomic_int! {
     "AtomicU64::new(0)",
     u64 AtomicU64 ATOMIC_U64_INIT
 }
-#[cfg(target_has_atomic = "128")]
+#[cfg(target_has_atomic_load_store = "128")]
 atomic_int! {
+    cfg(target_has_atomic = "128"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -2034,8 +2052,9 @@ atomic_int! {
     "AtomicI128::new(0)",
     i128 AtomicI128 ATOMIC_I128_INIT
 }
-#[cfg(target_has_atomic = "128")]
+#[cfg(target_has_atomic_load_store = "128")]
 atomic_int! {
+    cfg(target_has_atomic = "128"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -2050,20 +2069,24 @@ atomic_int! {
     "AtomicU128::new(0)",
     u128 AtomicU128 ATOMIC_U128_INIT
 }
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[cfg(target_pointer_width = "16")]
 macro_rules! ptr_width {
     () => { 2 }
 }
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[cfg(target_pointer_width = "32")]
 macro_rules! ptr_width {
     () => { 4 }
 }
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[cfg(target_pointer_width = "64")]
 macro_rules! ptr_width {
     () => { 8 }
 }
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 atomic_int!{
+    cfg(target_has_atomic = "ptr"),
     stable(feature = "rust1", since = "1.0.0"),
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
@@ -2078,8 +2101,9 @@ atomic_int!{
     "AtomicIsize::new(0)",
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 atomic_int!{
+    cfg(target_has_atomic = "ptr"),
     stable(feature = "rust1", since = "1.0.0"),
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
@@ -2096,7 +2120,7 @@ atomic_int!{
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 fn strongest_failure_ordering(order: Ordering) -> Ordering {
     match order {
         Release => Relaxed,
@@ -2130,7 +2154,7 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xchg_acq(dst, val),
@@ -2143,7 +2167,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// Returns the previous value (like __sync_fetch_and_add).
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xadd_acq(dst, val),
@@ -2156,7 +2180,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// Returns the previous value (like __sync_fetch_and_sub).
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xsub_acq(dst, val),
@@ -2168,7 +2192,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
                                      old: T,
                                      new: T,
@@ -2193,7 +2217,7 @@ unsafe fn atomic_compare_exchange<T>(dst: *mut T,
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
                                           old: T,
                                           new: T,
@@ -2218,7 +2242,7 @@ unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_and_acq(dst, val),
@@ -2230,7 +2254,7 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_nand_acq(dst, val),
@@ -2242,7 +2266,7 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_or_acq(dst, val),
@@ -2254,7 +2278,7 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xor_acq(dst, val),
@@ -2267,7 +2291,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the max value (signed comparison)
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_max_acq(dst, val),
@@ -2280,7 +2304,7 @@ unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the min value (signed comparison)
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_min_acq(dst, val),
@@ -2293,7 +2317,7 @@ unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the max value (signed comparison)
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_umax_acq(dst, val),
@@ -2306,7 +2330,7 @@ unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the min value (signed comparison)
 #[inline]
-#[cfg(target_has_atomic = "cas")]
+#[cfg(target_has_atomic = "8")]
 unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_umin_acq(dst, val),
@@ -2504,7 +2528,7 @@ pub fn compiler_fence(order: Ordering) {
 }
 
 
-#[cfg(target_has_atomic = "8")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl fmt::Debug for AtomicBool {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -2512,7 +2536,7 @@ impl fmt::Debug for AtomicBool {
     }
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl<T> fmt::Debug for AtomicPtr<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -2520,7 +2544,7 @@ impl<T> fmt::Debug for AtomicPtr<T> {
     }
 }
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
 #[stable(feature = "atomic_pointer", since = "1.24.0")]
 impl<T> fmt::Pointer for AtomicPtr<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs
index 65e29364287..6f841bd2adf 100644
--- a/src/libcore/task/wake.rs
+++ b/src/libcore/task/wake.rs
@@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> {
 /// This handle encapsulates a [`RawWaker`] instance, which defines the
 /// executor-specific wakeup behavior.
 ///
-/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`].
+/// Implements [`Clone`], [`Send`], and [`Sync`].
 ///
 /// [`RawWaker`]: struct.RawWaker.html
 #[repr(transparent)]
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index e199670b561..f612c52d398 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -25,7 +25,6 @@
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
 #![feature(optin_builtin_traits)]
-#![feature(mem_take)]
 #![feature(non_exhaustive)]
 #![feature(rustc_attrs)]
 #![feature(specialization)]
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 7e506f6e1b7..25cbf8c88de 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -845,6 +845,8 @@ impl DepGraph {
     // This method will only load queries that will end up in the disk cache.
     // Other queries will not be executed.
     pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) {
+        let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion");
+
         let data = self.data.as_ref().unwrap();
         for prev_index in data.colors.values.indices() {
             match data.colors.get(prev_index) {
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index e208e25f6ea..50b6ef57b55 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -259,8 +259,8 @@ trait Foo {
 This is similar to the second sub-error, but subtler. It happens in situations
 like the following:
 
-```compile_fail
-trait Super<A> {}
+```compile_fail,E0038
+trait Super<A: ?Sized> {}
 
 trait Trait: Super<Self> {
 }
@@ -270,17 +270,21 @@ struct Foo;
 impl Super<Foo> for Foo{}
 
 impl Trait for Foo {}
+
+fn main() {
+    let x: Box<dyn Trait>;
+}
 ```
 
 Here, the supertrait might have methods as follows:
 
 ```
-trait Super<A> {
-    fn get_a(&self) -> A; // note that this is object safe!
+trait Super<A: ?Sized> {
+    fn get_a(&self) -> &A; // note that this is object safe!
 }
 ```
 
-If the trait `Foo` was deriving from something like `Super<String>` or
+If the trait `Trait` was deriving from something like `Super<String>` or
 `Super<T>` (where `Foo` itself is `Foo<T>`), this is okay, because given a type
 `get_a()` will definitely return an object of that type.
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index d773c454432..72fd054ee8a 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -242,6 +242,8 @@ pub fn lower_crate(
     // incr. comp. yet.
     dep_graph.assert_ignored();
 
+    let _prof_timer = sess.prof.generic_activity("hir_lowering");
+
     LoweringContext {
         crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
         sess,
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 1705f5692d4..16c4ab7187d 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -1222,6 +1222,8 @@ pub fn map_crate<'hir>(sess: &crate::session::Session,
                        forest: &'hir Forest,
                        definitions: &'hir Definitions)
                        -> Map<'hir> {
+    let _prof_timer = sess.prof.generic_activity("build_hir_map");
+
     // Build the reverse mapping of `node_to_hir_id`.
     let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated()
         .map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 06bd4a42748..7350f89018b 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1053,6 +1053,13 @@ impl Mutability {
             MutImmutable => MutImmutable,
         }
     }
+
+    pub fn invert(self) -> Self {
+        match self {
+            MutMutable => MutImmutable,
+            MutImmutable => MutMutable,
+        }
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)]
@@ -1359,6 +1366,10 @@ impl Body {
             hir_id: self.value.hir_id,
         }
     }
+
+    pub fn generator_kind(&self) -> Option<GeneratorKind> {
+        self.generator_kind
+    }
 }
 
 /// The type of source expression that caused this generator to be created.
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index ea9e931ad83..af74d135724 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -814,16 +814,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// Executes `f` and commit the bindings.
     pub fn commit_unconditionally<R, F>(&self, f: F) -> R
     where
-        F: FnOnce() -> R,
+        F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
     {
-        debug!("commit()");
+        debug!("commit_unconditionally()");
         let snapshot = self.start_snapshot();
-        let r = f();
+        let r = f(&snapshot);
         self.commit_from(snapshot);
         r
     }
 
-    /// Executes `f` and commit the bindings if closure `f` returns `Ok(_)`.
+    /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`.
     pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
     where
         F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>,
@@ -843,19 +843,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         r
     }
 
-    /// Execute `f` in a snapshot, and commit the bindings it creates.
-    pub fn in_snapshot<T, F>(&self, f: F) -> T
-    where
-        F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T,
-    {
-        debug!("in_snapshot()");
-        let snapshot = self.start_snapshot();
-        let r = f(&snapshot);
-        self.commit_from(snapshot);
-        r
-    }
-
-    /// Executes `f` then unroll any bindings it creates.
+    /// Execute `f` then unroll any bindings it creates.
     pub fn probe<R, F>(&self, f: F) -> R
     where
         F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs
index 0c83bbc1e53..3d069425685 100644
--- a/src/librustc/infer/region_constraints/leak_check.rs
+++ b/src/librustc/infer/region_constraints/leak_check.rs
@@ -14,9 +14,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     /// retain the older (arguably incorrect) behavior of the
     /// compiler.
     ///
-    /// NB. The use of snapshot here is mostly an efficiency thing --
-    /// we could search *all* region constraints, but that'd be a
-    /// bigger set and the data structures are not setup for that. If
+    /// NB. Although `_snapshot` isn't used, it's passed in to prove
+    /// that we are in a snapshot, which guarantees that we can just
+    /// search the "undo log" for edges. This is mostly an efficiency
+    /// thing -- we could search *all* region constraints, but that'd be
+    /// a bigger set and the data structures are not setup for that. If
     /// we wind up keeping some form of this check long term, it would
     /// probably be better to remove the snapshot parameter and to
     /// refactor the constraint set.
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 9c3cb3af9e7..197ca191a5d 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -58,7 +58,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(proc_macro_hygiene)]
 #![feature(log_syntax)]
-#![feature(mem_take)]
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 5ca474a8b1d..983e3a9922e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -21,7 +21,8 @@ declare_lint! {
 declare_lint! {
     pub CONST_ERR,
     Deny,
-    "constant evaluation detected erroneous expression"
+    "constant evaluation detected erroneous expression",
+    report_in_external_macro: true
 }
 
 declare_lint! {
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 30a88d155f5..302c11f309d 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -485,7 +485,13 @@ pub fn provide(providers: &mut Providers<'_>) {
 }
 
 pub fn report_unstable(
-    sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, is_soft: bool, span: Span
+    sess: &Session,
+    feature: Symbol,
+    reason: Option<Symbol>,
+    issue: u32,
+    is_soft: bool,
+    span: Span,
+    soft_handler: impl FnOnce(&'static lint::Lint, Span, &str),
 ) {
     let msg = match reason {
         Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
@@ -511,7 +517,7 @@ pub fn report_unstable(
     let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
     if fresh {
         if is_soft {
-            sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg);
+            soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg)
         } else {
             emit_feature_err(
                 &sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
@@ -779,10 +785,12 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Additionally, this function will also check if the item is deprecated. If so, and `id` is
     /// not `None`, a deprecated lint attached to `id` will be emitted.
     pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
+        let soft_handler =
+            |lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg);
         match self.eval_stability(def_id, id, span) {
             EvalResult::Allow => {}
             EvalResult::Deny { feature, reason, issue, is_soft } =>
-                report_unstable(self.sess, feature, reason, issue, is_soft, span),
+                report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler),
             EvalResult::Unmarked => {
                 // The API could be uncallable for other reasons, for example when a private module
                 // was referenced.
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index e925d7429ff..6c31d54e081 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -470,6 +470,14 @@ impl<'tcx> AllocMap<'tcx> {
         }
     }
 
+    /// Panics if the `AllocId` does not refer to a function
+    pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> {
+        match self.get(id) {
+            Some(GlobalAlloc::Function(instance)) => instance,
+            _ => bug!("expected allocation ID {} to point to a function", id),
+        }
+    }
+
     /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
     /// call this function twice, even with the same `Allocation` will ICE the compiler.
     pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 2b5212cb7ef..9ac1465cb0b 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2602,7 +2602,14 @@ impl<'tcx> Debug for Constant<'tcx> {
 impl<'tcx> Display for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         write!(fmt, "const ")?;
-        write!(fmt, "{}", self.literal)
+        // FIXME make the default pretty printing of raw pointers more detailed. Here we output the
+        // debug representation of raw pointers, so that the raw pointers in the mir dump output are
+        // detailed and just not '{pointer}'.
+        if let ty::RawPtr(_) = self.literal.ty.kind {
+            write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty)
+        } else {
+            write!(fmt, "{}", self.literal)
+        }
     }
 }
 
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 313b2a5d50a..265ac975ed7 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -386,6 +386,7 @@ impl<'tcx> CodegenUnit<'tcx> {
                             tcx.hir().as_local_hir_id(def_id)
                         }
                         InstanceDef::VtableShim(..) |
+                        InstanceDef::ReifyShim(..) |
                         InstanceDef::Intrinsic(..) |
                         InstanceDef::FnPtrShim(..) |
                         InstanceDef::Virtual(..) |
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 4618a6277ed..0facf30b627 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1467,6 +1467,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "which mangling version to use for symbol names"),
     binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
         "include artifacts (sysroot, crate dependencies) used during compilation in dep-info"),
+    insert_sideeffect: bool = (false, parse_bool, [TRACKED],
+        "fix undefined behavior when a thread doesn't eventually make progress \
+         (such as entering an empty infinite loop) by inserting llvm.sideeffect"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1510,22 +1513,25 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     }
     for &i in &[8, 16, 32, 64, 128] {
         if i >= min_atomic_width && i <= max_atomic_width {
-            let s = i.to_string();
-            ret.insert((
-                sym::target_has_atomic,
-                Some(Symbol::intern(&s)),
-            ));
-            if &s == wordsz {
+            let mut insert_atomic = |s| {
                 ret.insert((
-                    sym::target_has_atomic,
-                    Some(Symbol::intern("ptr")),
+                    sym::target_has_atomic_load_store,
+                    Some(Symbol::intern(s)),
                 ));
+                if atomic_cas {
+                    ret.insert((
+                        sym::target_has_atomic,
+                        Some(Symbol::intern(s))
+                    ));
+                }
+            };
+            let s = i.to_string();
+            insert_atomic(&s);
+            if &s == wordsz {
+              insert_atomic("ptr");
             }
         }
     }
-    if atomic_cas {
-        ret.insert((sym::target_has_atomic, Some(Symbol::intern("cas"))));
-    }
     if sess.opts.debug_assertions {
         ret.insert((Symbol::intern("debug_assertions"), None));
     }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 9d60221fa3d..fa2902e4f0e 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
 
 use crate::lint;
 use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath};
+use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
 use crate::session::search_paths::{PathKind, SearchPath};
 use crate::util::nodemap::{FxHashMap, FxHashSet};
 use crate::util::common::{duration_to_secs_str, ErrorReported};
@@ -626,6 +626,14 @@ impl Session {
             .output_types
             .contains_key(&OutputType::LlvmAssembly)
             || self.opts.output_types.contains_key(&OutputType::Bitcode);
+
+        // Address sanitizer and memory sanitizer use alloca name when reporting an issue.
+        let more_names = match self.opts.debugging_opts.sanitizer {
+            Some(Sanitizer::Address) => true,
+            Some(Sanitizer::Memory) => true,
+            _ => more_names,
+        };
+
         self.opts.debugging_opts.fewer_names || !more_names
     }
 
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index a1c97d6c687..9eb91569ed5 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -453,21 +453,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    fn find_similar_impl_candidates(&self,
-                                    trait_ref: ty::PolyTraitRef<'tcx>)
-                                    -> Vec<ty::TraitRef<'tcx>>
-    {
-        let simp = fast_reject::simplify_type(self.tcx,
-                                              trait_ref.skip_binder().self_ty(),
-                                              true);
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>> {
+        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
         let all_impls = self.tcx.all_impls(trait_ref.def_id());
 
         match simp {
             Some(simp) => all_impls.iter().filter_map(|&def_id| {
                 let imp = self.tcx.impl_trait_ref(def_id).unwrap();
-                let imp_simp = fast_reject::simplify_type(self.tcx,
-                                                          imp.self_ty(),
-                                                          true);
+                let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
                 if let Some(imp_simp) = imp_simp {
                     if simp != imp_simp {
                         return None
@@ -482,10 +478,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    fn report_similar_impl_candidates(&self,
-                                      impl_candidates: Vec<ty::TraitRef<'tcx>>,
-                                      err: &mut DiagnosticBuilder<'_>)
-    {
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
         if impl_candidates.is_empty() {
             return;
         }
@@ -720,10 +717,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             // which is somewhat confusing.
                             err.help(&format!("consider adding a `where {}` bound",
                                               trait_ref.to_predicate()));
-                        } else if !have_alt_message {
-                            // Can't show anything else useful, try to find similar impls.
-                            let impl_candidates = self.find_similar_impl_candidates(trait_ref);
-                            self.report_similar_impl_candidates(impl_candidates, &mut err);
+                        } else {
+                            if !have_alt_message {
+                                // Can't show anything else useful, try to find similar impls.
+                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
+                                self.report_similar_impl_candidates(impl_candidates, &mut err);
+                            }
+                            self.suggest_change_mut(
+                                &obligation,
+                                &mut err,
+                                &trait_ref,
+                                points_at_arg,
+                            );
                         }
 
                         // If this error is due to `!: Trait` not implemented but `(): Trait` is
@@ -1081,9 +1086,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
                     let substs = self.tcx.mk_substs_trait(trait_type, &[]);
                     let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs);
-                    let new_obligation = Obligation::new(ObligationCause::dummy(),
-                                                         obligation.param_env,
-                                                         new_trait_ref.to_predicate());
+                    let new_obligation = Obligation::new(
+                        ObligationCause::dummy(),
+                        obligation.param_env,
+                        new_trait_ref.to_predicate(),
+                    );
 
                     if self.predicate_may_hold(&new_obligation) {
                         let sp = self.tcx.sess.source_map()
@@ -1105,6 +1112,77 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
+    /// Check if the trait bound is implemented for a different mutability and note it in the
+    /// final error.
+    fn suggest_change_mut(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let span = obligation.cause.span;
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number = snippet.chars()
+                .filter(|c| !c.is_whitespace())
+                .take_while(|c| *c == '&')
+                .count();
+            if let Some('\'') = snippet.chars()
+                .filter(|c| !c.is_whitespace())
+                .skip(refs_number)
+                .next()
+            { // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+            let trait_ref = self.resolve_vars_if_possible(trait_ref);
+            if trait_ref.has_infer_types() {
+                // Do not ICE while trying to find if a reborrow would succeed on a trait with
+                // unresolved bindings.
+                return;
+            }
+
+            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
+                let trait_type = match mutability {
+                    hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type),
+                    hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type),
+                };
+
+                let substs = self.tcx.mk_substs_trait(&trait_type, &[]);
+                let new_trait_ref = ty::TraitRef::new(trait_ref.skip_binder().def_id, substs);
+                let new_obligation = Obligation::new(
+                    ObligationCause::dummy(),
+                    obligation.param_env,
+                    new_trait_ref.to_predicate(),
+                );
+
+                if self.evaluate_obligation_no_overflow(
+                    &new_obligation,
+                ).must_apply_modulo_regions() {
+                    let sp = self.tcx.sess.source_map()
+                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+                    if points_at_arg &&
+                        mutability == hir::Mutability::MutImmutable &&
+                        refs_number > 0
+                    {
+                        err.span_suggestion(
+                            sp,
+                            "consider changing this borrow's mutability",
+                            "&mut ".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.note(&format!(
+                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
+                            trait_ref,
+                            trait_type,
+                            trait_ref.skip_binder().self_ty(),
+                        ));
+                    }
+                }
+            }
+        }
+    }
+
     fn suggest_semicolon_removal(
         &self,
         obligation: &PredicateObligation<'tcx>,
diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs
index 17684df7e9b..0d426cab9b7 100644
--- a/src/librustc/traits/query/evaluate_obligation.rs
+++ b/src/librustc/traits/query/evaluate_obligation.rs
@@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     // Helper function that canonicalizes and runs the query. If an
     // overflow results, we re-run it in the local context so we can
     // report a nice error.
-    fn evaluate_obligation_no_overflow(
+    crate fn evaluate_obligation_no_overflow(
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> EvaluationResult {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 4ee5700f43f..44d611ace77 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2819,7 +2819,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // binder moved -\
                 let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
 
-                self.infcx.in_snapshot(|_| {
+                self.infcx.commit_unconditionally(|_| {
                     let (skol_ty, _) = self.infcx
                         .replace_bound_vars_with_placeholders(&ty);
                     let Normalized {
@@ -2932,7 +2932,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
-        self.infcx.in_snapshot(|snapshot| {
+        self.infcx.commit_unconditionally(|snapshot| {
             let result =
                 self.match_projection_obligation_against_definition_bounds(
                     obligation,
@@ -3054,19 +3054,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             nested,
         );
 
-        let trait_obligations: Vec<PredicateObligation<'_>> = self.infcx.in_snapshot(|_| {
-            let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
-            let (trait_ref, _) = self.infcx
-                .replace_bound_vars_with_placeholders(&poly_trait_ref);
-            let cause = obligation.derived_cause(ImplDerivedObligation);
-            self.impl_or_trait_obligations(
-                cause,
-                obligation.recursion_depth + 1,
-                obligation.param_env,
-                trait_def_id,
-                &trait_ref.substs,
-            )
-        });
+        let trait_obligations: Vec<PredicateObligation<'_>> =
+            self.infcx.commit_unconditionally(|_| {
+                let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
+                let (trait_ref, _) = self.infcx
+                    .replace_bound_vars_with_placeholders(&poly_trait_ref);
+                let cause = obligation.derived_cause(ImplDerivedObligation);
+                self.impl_or_trait_obligations(
+                    cause,
+                    obligation.recursion_depth + 1,
+                    obligation.param_env,
+                    trait_def_id,
+                    &trait_ref.substs,
+                )
+            });
 
         // Adds the predicates from the trait.  Note that this contains a `Self: Trait`
         // predicate as usual.  It won't have any effect since auto traits are coinductive.
@@ -3089,7 +3090,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // First, create the substitutions by matching the impl again,
         // this time not in a probe.
-        self.infcx.in_snapshot(|snapshot| {
+        self.infcx.commit_unconditionally(|snapshot| {
             let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
             debug!("confirm_impl_candidate: substs={:?}", substs);
             let cause = obligation.derived_cause(ImplDerivedObligation);
@@ -3253,7 +3254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             obligation, alias_def_id
         );
 
-        self.infcx.in_snapshot(|_| {
+        self.infcx.commit_unconditionally(|_| {
             let (predicate, _) = self.infcx()
                 .replace_bound_vars_with_placeholders(&obligation.predicate);
             let trait_ref = predicate.trait_ref;
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 93a8341e746..5139c8085a5 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -1,3 +1,4 @@
+use crate::hir::CodegenFnAttrFlags;
 use crate::hir::Unsafety;
 use crate::hir::def::Namespace;
 use crate::hir::def_id::DefId;
@@ -25,6 +26,14 @@ pub enum InstanceDef<'tcx> {
     /// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
     VtableShim(DefId),
 
+    /// `fn()` pointer where the function itself cannot be turned into a pointer.
+    ///
+    /// One example in the compiler today is functions annotated with `#[track_caller]`, which
+    /// must have their implicit caller location argument populated for a call. Because this is a
+    /// required part of the function's ABI but can't be tracked as a property of the function
+    /// pointer, we create a single "caller location" at the site where the function is reified.
+    ReifyShim(DefId),
+
     /// `<fn() as FnTrait>::call_*`
     /// `DefId` is `FnTrait::call_*`
     FnPtrShim(DefId, Ty<'tcx>),
@@ -123,6 +132,7 @@ impl<'tcx> InstanceDef<'tcx> {
         match *self {
             InstanceDef::Item(def_id) |
             InstanceDef::VtableShim(def_id) |
+            InstanceDef::ReifyShim(def_id) |
             InstanceDef::FnPtrShim(def_id, _) |
             InstanceDef::Virtual(def_id, _) |
             InstanceDef::Intrinsic(def_id, ) |
@@ -178,6 +188,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
             InstanceDef::VtableShim(_) => {
                 write!(f, " - shim(vtable)")
             }
+            InstanceDef::ReifyShim(_) => {
+                write!(f, " - shim(reify)")
+            }
             InstanceDef::Intrinsic(_) => {
                 write!(f, " - intrinsic")
             }
@@ -290,6 +303,30 @@ impl<'tcx> Instance<'tcx> {
         result
     }
 
+    pub fn resolve_for_fn_ptr(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+    ) -> Option<Instance<'tcx>> {
+        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
+        Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| {
+            let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
+                .contains(CodegenFnAttrFlags::TRACK_CALLER);
+
+            match resolved.def {
+                InstanceDef::Item(def_id) if has_track_caller(def_id) => {
+                    debug!(" => fn pointer created for function with #[track_caller]");
+                    Instance {
+                        def: InstanceDef::ReifyShim(def_id),
+                        substs,
+                    }
+                },
+                _ => resolved,
+            }
+        })
+    }
+
     pub fn resolve_for_vtable(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index cfd859c33c2..3692caada57 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -3026,6 +3026,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 self.optimized_mir(did)
             }
             ty::InstanceDef::VtableShim(..) |
+            ty::InstanceDef::ReifyShim(..) |
             ty::InstanceDef::Intrinsic(..) |
             ty::InstanceDef::FnPtrShim(..) |
             ty::InstanceDef::Virtual(..) |
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 07c63a92b39..c4967f8d66d 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -863,125 +863,121 @@ pub trait PrettyPrinter<'tcx>:
         }
 
         let u8 = self.tcx().types.u8;
-        if let ty::FnDef(did, substs) = ct.ty.kind {
-            p!(print_value_path(did, substs));
-            return Ok(self);
-        }
-        if let ConstValue::Unevaluated(did, substs) = ct.val {
-            match self.tcx().def_kind(did) {
-                | Some(DefKind::Static)
-                | Some(DefKind::Const)
-                | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
-                _ => if did.is_local() {
-                    let span = self.tcx().def_span(did);
-                    if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
-                        p!(write("{}", snip))
+
+        match (ct.val, &ct.ty.kind) {
+            (_,  ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
+            (ConstValue::Unevaluated(did, substs), _) => {
+                match self.tcx().def_kind(did) {
+                    | Some(DefKind::Static)
+                    | Some(DefKind::Const)
+                    | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
+                    _ => if did.is_local() {
+                        let span = self.tcx().def_span(did);
+                        if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
+                            p!(write("{}", snip))
+                        } else {
+                            p!(write("_: "), print(ct.ty))
+                        }
                     } else {
                         p!(write("_: "), print(ct.ty))
-                    }
+                    },
+                }
+            },
+            (ConstValue::Infer(..), _) =>  p!(write("_: "), print(ct.ty)),
+            (ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
+            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) =>
+                p!(write("{}", if data == 0 { "false" } else { "true" })),
+            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) =>
+                p!(write("{}f32", Single::from_bits(data))),
+            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) =>
+                p!(write("{}f64", Double::from_bits(data))),
+            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => {
+                let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size();
+                let max = truncate(u128::max_value(), bit_size);
+
+                if data == max {
+                    p!(write("std::{}::MAX", ui))
                 } else {
-                    p!(write("_: "), print(ct.ty))
-                },
-            }
-            return Ok(self);
-        }
-        if let ConstValue::Infer(..) = ct.val {
-            p!(write("_: "), print(ct.ty));
-            return Ok(self);
-        }
-        if let ConstValue::Param(ParamConst { name, .. }) = ct.val {
-            p!(write("{}", name));
-            return Ok(self);
-        }
-        if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val {
-            match ct.ty.kind {
-                ty::Bool => {
-                    p!(write("{}", if data == 0 { "false" } else { "true" }));
-                    return Ok(self);
-                },
-                ty::Float(ast::FloatTy::F32) => {
-                    p!(write("{}f32", Single::from_bits(data)));
-                    return Ok(self);
-                },
-                ty::Float(ast::FloatTy::F64) => {
-                    p!(write("{}f64", Double::from_bits(data)));
-                    return Ok(self);
-                },
-                ty::Uint(ui) => {
-                    let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(ui)).size();
-                    let max = truncate(u128::max_value(), bit_size);
+                    p!(write("{}{}", data, ui))
+                };
+            },
+            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {
+                let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i))
+                    .size().bits() as u128;
+                let min = 1u128 << (bit_size - 1);
+                let max = min - 1;
+
+                let ty = self.tcx().lift(&ct.ty).unwrap();
+                let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
+                    .unwrap()
+                    .size;
+                match data {
+                    d if d == min => p!(write("std::{}::MIN", i)),
+                    d if d == max => p!(write("std::{}::MAX", i)),
+                    _ => p!(write("{}{}", sign_extend(data, size) as i128, i))
+                }
+            },
+            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) =>
+                p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())),
+            (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")),
+            (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {
+                let instance = {
+                    let alloc_map = self.tcx().alloc_map.lock();
+                    alloc_map.unwrap_fn(ptr.alloc_id)
+                };
+                p!(print_value_path(instance.def_id(), instance.substs));
+            },
+            _ => {
+                let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
+                    let byte_str = match (ct.val, &ref_ty.kind) {
+                        (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
+                            let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
+                            Some(self.tcx()
+                                .alloc_map.lock()
+                                .unwrap_memory(ptr.alloc_id)
+                                .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
+                        },
+                        (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
+                            // The `inspect` here is okay since we checked the bounds, and there are
+                            // no relocations (we have an active slice reference here). We don't use
+                            // this result to affect interpreter execution.
+                            Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
+                        },
+                        _ => None,
+                    };
 
-                    if data == max {
-                        p!(write("std::{}::MAX", ui))
+                    if let Some(byte_str) = byte_str {
+                        p!(write("b\""));
+                        for &c in byte_str {
+                            for e in std::ascii::escape_default(c) {
+                                self.write_char(e as char)?;
+                            }
+                        }
+                        p!(write("\""));
+                        true
+                    } else if let (ConstValue::Slice { data, start, end }, ty::Str) =
+                        (ct.val, &ref_ty.kind)
+                    {
+                        // The `inspect` here is okay since we checked the bounds, and there are no
+                        // relocations (we have an active `str` reference here). We don't use this
+                        // result to affect interpreter execution.
+                        let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
+                        let s = ::std::str::from_utf8(slice)
+                            .expect("non utf8 str from miri");
+                        p!(write("{:?}", s));
+                        true
                     } else {
-                        p!(write("{}{}", data, ui))
-                    };
-                    return Ok(self);
-                },
-                ty::Int(i) =>{
-                    let bit_size = Integer::from_attr(&self.tcx(), SignedInt(i))
-                        .size().bits() as u128;
-                    let min = 1u128 << (bit_size - 1);
-                    let max = min - 1;
-
-                    let ty = self.tcx().lift(&ct.ty).unwrap();
-                    let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
-                        .unwrap()
-                        .size;
-                    match data {
-                        d if d == min => p!(write("std::{}::MIN", i)),
-                        d if d == max => p!(write("std::{}::MAX", i)),
-                        _ => p!(write("{}{}", sign_extend(data, size) as i128, i))
-                    }
-                    return Ok(self);
-                },
-                ty::Char => {
-                    p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()));
-                    return Ok(self);
-                }
-                _ => {},
-            }
-        }
-        if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
-            let byte_str = match (ct.val, &ref_ty.kind) {
-                (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
-                    let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
-                    Some(self.tcx()
-                        .alloc_map.lock()
-                        .unwrap_memory(ptr.alloc_id)
-                        .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
-                },
-                (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
-                    // The `inspect` here is okay since we checked the bounds, and there are no
-                    // relocations (we have an active slice reference here). We don't use this
-                    // result to affect interpreter execution.
-                    Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
-                },
-                (ConstValue::Slice { data, start, end }, ty::Str) => {
-                    // The `inspect` here is okay since we checked the bounds, and there are no
-                    // relocations (we have an active `str` reference here). We don't use this
-                    // result to affect interpreter execution.
-                    let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
-                    let s = ::std::str::from_utf8(slice)
-                        .expect("non utf8 str from miri");
-                    p!(write("{:?}", s));
-                    return Ok(self);
-                },
-                _ => None,
-            };
-            if let Some(byte_str) = byte_str {
-                p!(write("b\""));
-                for &c in byte_str {
-                    for e in std::ascii::escape_default(c) {
-                        self.write_char(e as char)?;
+                        false
                     }
+                } else {
+                    false
+                };
+                if !printed {
+                    // fallback
+                    p!(write("{:?} : ", ct.val), print(ct.ty))
                 }
-                p!(write("\""));
-                return Ok(self);
             }
-        }
-        p!(write("{:?} : ", ct.val), print(ct.ty));
-
+        };
         Ok(self)
     }
 }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 5489c6f5d5a..41f34703622 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
 use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar};
+use crate::mir::interpret::{ConstValue, get_slice_bytes};
 use std::rc::Rc;
 use std::iter;
 use rustc_target::spec::abi;
@@ -561,37 +561,39 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
     // implement both `PartialEq` and `Eq`, corresponding to
     // `structural_match` types.
     // FIXME(const_generics): check for `structural_match` synthetic attribute.
-    match (eagerly_eval(a), eagerly_eval(b)) {
+    let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) {
         (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
             // The caller should handle these cases!
             bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
         }
         (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => {
-            Ok(a)
+            return Ok(a);
         }
         (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => {
-            Ok(a)
+            return Ok(a);
         }
-        (a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _)
-            if a.ty == b.ty && a_val == b_val =>
-        {
-            Ok(tcx.mk_const(ty::Const {
-                val: a_val,
-                ty: a.ty,
-            }))
+        (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => {
+            if a_val == b_val {
+                Ok(ConstValue::Scalar(a_val))
+            } else if let ty::FnPtr(_) = a.ty.kind {
+                let alloc_map = tcx.alloc_map.lock();
+                let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id);
+                let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id);
+                if a_instance == b_instance {
+                    Ok(ConstValue::Scalar(a_val))
+                } else {
+                    Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                }
+            } else {
+                Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+            }
         }
 
-        // FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
-        // saying that we're not handling it intentionally.
-
         (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
             let a_bytes = get_slice_bytes(&tcx, a_val);
             let b_bytes = get_slice_bytes(&tcx, b_val);
             if a_bytes == b_bytes {
-                Ok(tcx.mk_const(ty::Const {
-                    val: a_val,
-                    ty: a.ty,
-                }))
+                Ok(a_val)
             } else {
                 Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
             }
@@ -602,16 +604,16 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         // FIXME(const_generics): this is wrong, as it is a projection
         (ConstValue::Unevaluated(a_def_id, a_substs),
             ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => {
-                let substs =
-                    relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
-                Ok(tcx.mk_const(ty::Const {
-                    val: ConstValue::Unevaluated(a_def_id, &substs),
-                    ty: a.ty,
-                }))
-            }
-
-        _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
-    }
+            let substs =
+                relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
+            Ok(ConstValue::Unevaluated(a_def_id, &substs))
+        }
+        _ =>  Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
+    };
+    new_const_val.map(|val| tcx.mk_const(ty::Const {
+        val,
+        ty: a.ty,
+    }))
 }
 
 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 5aa59cc309f..8945e1a1deb 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -761,6 +761,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
                 Some(ty::InstanceDef::Item(def_id)),
             ty::InstanceDef::VtableShim(def_id) =>
                 Some(ty::InstanceDef::VtableShim(def_id)),
+            ty::InstanceDef::ReifyShim(def_id) =>
+                Some(ty::InstanceDef::ReifyShim(def_id)),
             ty::InstanceDef::Intrinsic(def_id) =>
                 Some(ty::InstanceDef::Intrinsic(def_id)),
             ty::InstanceDef::FnPtrShim(def_id, ref ty) =>
@@ -966,6 +968,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
             def: match self.def {
                 Item(did) => Item(did.fold_with(folder)),
                 VtableShim(did) => VtableShim(did.fold_with(folder)),
+                ReifyShim(did) => ReifyShim(did.fold_with(folder)),
                 Intrinsic(did) => Intrinsic(did.fold_with(folder)),
                 FnPtrShim(did, ty) => FnPtrShim(
                     did.fold_with(folder),
@@ -994,7 +997,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
         use crate::ty::InstanceDef::*;
         self.substs.visit_with(visitor) ||
         match self.def {
-            Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => {
+            Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
                 did.visit_with(visitor)
             },
             FnPtrShim(did, ty) | CloneShim(did, ty) => {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index d0e95a18c59..5ddf15317a3 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -1017,34 +1017,25 @@ impl<'tcx> ty::TyS<'tcx> {
 }
 
 fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    let (param_env, ty) = query.into_parts();
-    let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
-    tcx.infer_ctxt()
-        .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions(
-            &infcx,
-            param_env,
-            ty,
-            trait_def_id,
-            DUMMY_SP,
-        ))
+    is_item_raw(tcx, query, lang_items::CopyTraitLangItem)
 }
 
 fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    let (param_env, ty) = query.into_parts();
-    let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
-    tcx.infer_ctxt()
-        .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions(
-            &infcx,
-            param_env,
-            ty,
-            trait_def_id,
-            DUMMY_SP,
-        ))
+    is_item_raw(tcx, query, lang_items::SizedTraitLangItem)
+
 }
 
 fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    is_item_raw(tcx, query, lang_items::FreezeTraitLangItem)
+}
+
+fn is_item_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+    item: lang_items::LangItem,
+) -> bool {
     let (param_env, ty) = query.into_parts();
-    let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem, None);
+    let trait_def_id = tcx.require_lang_item(item, None);
     tcx.infer_ctxt()
         .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions(
             &infcx,
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index a0bef5b7815..6a36a4a50cb 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -270,31 +270,37 @@ pub fn from_fn_attrs(
         // optimize based on this!
         false
     } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
-        // If a specific #[unwind] attribute is present, use that
+        // If a specific #[unwind] attribute is present, use that.
         true
     } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
-        // Special attribute for allocator functions, which can't unwind
+        // Special attribute for allocator functions, which can't unwind.
         false
-    } else if let Some(id) = id {
+    } else {
         let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
-        if cx.tcx.is_foreign_item(id) {
-            // Foreign items like `extern "C" { fn foo(); }` are assumed not to
-            // unwind
-            false
-        } else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall {
-            // Any items defined in Rust that *don't* have the `extern` ABI are
-            // defined to not unwind. We insert shims to abort if an unwind
-            // happens to enforce this.
-            false
-        } else {
-            // Anything else defined in Rust is assumed that it can possibly
-            // unwind
+        if sig.abi == Abi::Rust || sig.abi == Abi::RustCall {
+            // Any Rust method (or `extern "Rust" fn` or `extern
+            // "rust-call" fn`) is explicitly allowed to unwind
+            // (unless it has no-unwind attribute, handled above).
             true
+        } else {
+            // Anything else is either:
+            //
+            //  1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
+            //
+            //  2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
+            //
+            // Foreign items (case 1) are assumed to not unwind; it is
+            // UB otherwise. (At least for now; see also
+            // rust-lang/rust#63909 and Rust RFC 2753.)
+            //
+            // Items defined in Rust with non-Rust ABIs (case 2) are also
+            // not supposed to unwind. Whether this should be enforced
+            // (versus stating it is UB) and *how* it would be enforced
+            // is currently under discussion; see rust-lang/rust#58794.
+            //
+            // In either case, we mark item as explicitly nounwind.
+            false
         }
-    } else {
-        // assume this can possibly unwind, avoiding the application of a
-        // `nounwind` attribute below.
-        true
     });
 
     // Always annotate functions with the target-cpu they are compiled for.
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 18a5970fcd0..7ca226914a5 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -537,6 +537,7 @@ impl CodegenCx<'b, 'tcx> {
         ifn!("llvm.trap", fn() -> void);
         ifn!("llvm.debugtrap", fn() -> void);
         ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
+        ifn!("llvm.sideeffect", fn() -> void);
 
         ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
         ifn!("llvm.powi.v2f32", fn(t_v2f32, t_i32) -> t_v2f32);
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index b7a410c3760..68d9af09c42 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -724,6 +724,13 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         self.call(expect, &[cond, self.const_bool(expected)], None)
     }
 
+    fn sideeffect(&mut self) {
+        if self.tcx.sess.opts.debugging_opts.insert_sideeffect {
+            let fnname = self.get_intrinsic(&("llvm.sideeffect"));
+            self.call(fnname, &[], None);
+        }
+    }
+
     fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
         let intrinsic = self.cx().get_intrinsic("llvm.va_start");
         self.call(intrinsic, &[va_list], None)
@@ -810,6 +817,7 @@ fn codegen_msvc_try(
 ) {
     let llfn = get_rust_try_fn(bx, &mut |mut bx| {
         bx.set_personality_fn(bx.eh_personality());
+        bx.sideeffect();
 
         let mut normal = bx.build_sibling_block("normal");
         let mut catchswitch = bx.build_sibling_block("catchswitch");
@@ -933,6 +941,8 @@ fn codegen_gnu_try(
         // expected to be `*mut *mut u8` for this to actually work, but that's
         // managed by the standard library.
 
+        bx.sideeffect();
+
         let mut then = bx.build_sibling_block("then");
         let mut catch = bx.build_sibling_block("catch");
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 87eab484faf..52797e64f7d 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -19,7 +19,6 @@
 #![feature(link_args)]
 #![feature(static_nobundle)]
 #![feature(trusted_len)]
-#![feature(mem_take)]
 
 use back::write::{create_target_machine, create_informational_target_machine};
 use syntax_pos::symbol::Symbol;
diff --git a/src/librustc_codegen_ssa/callee.rs b/src/librustc_codegen_ssa/callee.rs
index 4744dd6302f..6ba6774cbf8 100644
--- a/src/librustc_codegen_ssa/callee.rs
+++ b/src/librustc_codegen_ssa/callee.rs
@@ -18,6 +18,23 @@ pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
     )
 }
 
+pub fn resolve_and_get_fn_for_ptr<'tcx,
+    Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
+>(
+    cx: &Cx,
+    def_id: DefId,
+    substs: SubstsRef<'tcx>,
+) -> Cx::Value {
+    cx.get_fn(
+        ty::Instance::resolve_for_fn_ptr(
+            cx.tcx(),
+            ty::ParamEnv::reveal_all(),
+            def_id,
+            substs
+        ).unwrap()
+    )
+}
+
 pub fn resolve_and_get_fn_for_vtable<'tcx,
     Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
 >(
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 5017a60ca69..d700001430e 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -10,7 +10,6 @@
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(trusted_len)]
-#![feature(mem_take)]
 #![feature(associated_type_bounds)]
 
 #![recursion_limit="256"]
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 3a1d0a25775..b0df81ba1ab 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -149,6 +149,26 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
             }
         }
     }
+
+    // Generate sideeffect intrinsic if jumping to any of the targets can form
+    // a loop.
+    fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>(
+        &self,
+        mir: &'b mir::Body<'tcx>,
+        bx: &mut Bx,
+        targets: &[mir::BasicBlock],
+    ) {
+        if bx.tcx().sess.opts.debugging_opts.insert_sideeffect {
+            if targets.iter().any(|target| {
+                *target <= *self.bb
+                    && target
+                        .start_location()
+                        .is_predecessor_of(self.bb.start_location(), mir)
+            }) {
+                bx.sideeffect();
+            }
+        }
+    }
 }
 
 /// Codegen implementations for some terminator variants.
@@ -197,6 +217,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let lltrue = helper.llblock(self, targets[0]);
             let llfalse = helper.llblock(self, targets[1]);
             if switch_ty == bx.tcx().types.bool {
+                helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice());
                 // Don't generate trivial icmps when switching on bool
                 if let [0] = values[..] {
                     bx.cond_br(discr.immediate(), llfalse, lltrue);
@@ -210,9 +231,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 );
                 let llval = bx.const_uint_big(switch_llty, values[0]);
                 let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
+                helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice());
                 bx.cond_br(cmp, lltrue, llfalse);
             }
         } else {
+            helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice());
             let (otherwise, targets) = targets.split_last().unwrap();
             bx.switch(
                 discr.immediate(),
@@ -308,6 +331,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
             // we don't actually need to drop anything.
+            helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
             helper.funclet_br(self, &mut bx, target);
             return
         }
@@ -338,6 +362,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                  FnType::of_instance(&bx, drop_fn))
             }
         };
+        helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
         helper.do_call(self, &mut bx, fn_ty, drop_fn, args,
                        Some((ReturnDest::Nothing, target)),
                        unwind);
@@ -373,6 +398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // Don't codegen the panic block if success if known.
         if const_cond == Some(expected) {
+            helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
             helper.funclet_br(self, &mut bx, target);
             return;
         }
@@ -383,6 +409,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // Create the failure block and the conditional branch to it.
         let lltarget = helper.llblock(self, target);
         let panic_block = self.new_block("panic");
+        helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
         if expected {
             bx.cond_br(cond, lltarget, panic_block.llbb());
         } else {
@@ -486,6 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             if let Some(destination_ref) = destination.as_ref() {
                 let &(ref dest, target) = destination_ref;
                 self.codegen_transmute(&mut bx, &args[0], dest);
+                helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
                 helper.funclet_br(self, &mut bx, target);
             } else {
                 // If we are trying to transmute to an uninhabited type,
@@ -513,6 +541,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             Some(ty::InstanceDef::DropGlue(_, None)) => {
                 // Empty drop glue; a no-op.
                 let &(_, target) = destination.as_ref().unwrap();
+                helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
                 helper.funclet_br(self, &mut bx, target);
                 return;
             }
@@ -549,6 +578,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let fn_ty = FnType::of_instance(&bx, instance);
                 let llfn = bx.get_fn(instance);
 
+                if let Some((_, target)) = destination.as_ref() {
+                    helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
+                }
                 // Codegen the actual panic invoke/call.
                 helper.do_call(
                     self,
@@ -561,7 +593,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 );
             } else {
                 // a NOP
-                helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1)
+                let target = destination.as_ref().unwrap().1;
+                helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
+                helper.funclet_br(self, &mut bx, target);
             }
             return;
         }
@@ -670,6 +704,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             if let Some((_, target)) = *destination {
+                helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
                 helper.funclet_br(self, &mut bx, target);
             } else {
                 bx.unreachable();
@@ -762,6 +797,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             _ => span_bug!(span, "no llfn for call"),
         };
 
+        if let Some((_, target)) = destination.as_ref() {
+            helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
+        }
         helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs,
                        destination.as_ref().map(|&(_, target)| (ret_dest, target)),
                        cleanup);
@@ -811,6 +849,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             mir::TerminatorKind::Goto { target } => {
+                helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
                 helper.funclet_br(self, &mut bx, target);
             }
 
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 9d2f8b42c70..d5612d7b072 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -200,6 +200,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         bx.set_personality_fn(cx.eh_personality());
     }
 
+    bx.sideeffect();
+
     let cleanup_kinds = analyze::cleanup_kinds(&mir);
     // Allocate a `Block` for every basic block, except
     // the start block, if nothing loops back to it.
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 6ffa561f3fe..978e7218aa7 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -190,7 +190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     bug!("reifying a fn ptr that requires const arguments");
                                 }
                                 OperandValue::Immediate(
-                                    callee::resolve_and_get_fn(bx.cx(), def_id, substs))
+                                    callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs))
                             }
                             _ => {
                                 bug!("{} cannot be reified to a fn ptr", operand.layout.ty)
diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs
index 7c79cd60210..2c484084c4a 100644
--- a/src/librustc_codegen_ssa/traits/intrinsic.rs
+++ b/src/librustc_codegen_ssa/traits/intrinsic.rs
@@ -20,6 +20,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
     fn abort(&mut self);
     fn assume(&mut self, val: Self::Value);
     fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
+    fn sideeffect(&mut self);
     /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in
     /// Rust defined C-variadic functions.
     fn va_start(&mut self, val: Self::Value) -> Self::Value;
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index b7f4df62b49..673da52c325 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -101,6 +101,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
     // before we fire the background thread.
 
     let time_passes = sess.time_passes();
+    let prof = sess.prof.clone();
 
     if sess.opts.incremental.is_none() {
         // No incremental compilation.
@@ -161,6 +162,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
 
     MaybeAsync::Async(std::thread::spawn(move || {
         time_ext(time_passes, "background load prev dep-graph", move || {
+            let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
+
             match load_data(report_incremental_info, &path) {
                 LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
                 LoadResult::Error { message } => LoadResult::Error { message },
@@ -198,6 +201,8 @@ pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> {
         return OnDiskCache::new_empty(sess.source_map());
     }
 
+    let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
+
     match load_data(sess.opts.debugging_opts.incremental_info, &query_cache_path(sess)) {
         LoadResult::Ok{ data: (bytes, start_pos) } => OnDiskCache::new(sess, bytes, start_pos),
         _ => OnDiskCache::new_empty(sess.source_map())
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 6af065513ee..f5935c9969b 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -241,6 +241,8 @@ fn encode_work_product_index(work_products: &FxHashMap<WorkProductId, WorkProduc
 
 fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut Encoder) {
     time(tcx.sess, "serialize query result cache", || {
+        let _timer = tcx.prof.generic_activity("incr_comp_serialize_result_cache");
+
         tcx.serialize_query_result_cache(encoder).unwrap();
     })
 }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 870f804ed44..a1dc5b01aba 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -250,6 +250,8 @@ pub fn register_plugins<'a>(
 
     if sess.opts.incremental.is_some() {
         time(sess, "garbage-collect incremental cache directory", || {
+            let _prof_timer =
+                sess.prof.generic_activity("incr_comp_garbage_collect_session_directories");
             if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
                 warn!(
                     "Error while trying to garbage collect incremental \
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index b701933a540..642a7632b3d 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -33,6 +33,7 @@ use syntax::source_map;
 use syntax::edition::Edition;
 use syntax::parse::source_file_to_stream;
 use syntax::parse::parser::emit_unclosed_delims;
+use syntax::source_map::Spanned;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, FileName};
 use rustc_index::bit_set::BitSet;
@@ -423,8 +424,8 @@ impl cstore::CStore {
         self.get_crate_data(cnum).root.edition
     }
 
-    pub fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
-        self.get_crate_data(def.krate).get_struct_field_names(def.index)
+    pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec<Spanned<Symbol>> {
+        self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
     }
 
     pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind {
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 6f528084348..132ef7d4241 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -30,7 +30,7 @@ use std::u32;
 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
 use syntax::ast::{self, Ident};
-use syntax::source_map;
+use syntax::source_map::{self, respan, Spanned};
 use syntax::symbol::{Symbol, sym};
 use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension};
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}};
@@ -1022,11 +1022,11 @@ impl<'a, 'tcx> CrateMetadata {
         Lrc::from(self.get_attributes(&item, sess))
     }
 
-    pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
+    pub fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<ast::Name>> {
         self.entry(id)
             .children
             .decode(self)
-            .map(|index| self.item_name(index))
+            .map(|index| respan(self.get_span(index, sess), self.item_name(index)))
             .collect()
     }
 
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 2f9df7bd77e..098258994f4 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -1,5 +1,6 @@
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
     LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue,
@@ -788,7 +789,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     ..
                 },
             ) if borrow_spans.for_closure() => self.report_escaping_closure_capture(
-                borrow_spans.args_or_use(),
+                borrow_spans,
                 borrow_span,
                 region_name,
                 category,
@@ -806,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 },
 
             ) if borrow_spans.for_generator() => self.report_escaping_closure_capture(
-                borrow_spans.args_or_use(),
+                borrow_spans,
                 borrow_span,
                 region_name,
                 category,
@@ -1195,7 +1196,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     fn report_escaping_closure_capture(
         &mut self,
-        args_span: Span,
+        use_span: UseSpans,
         var_span: Span,
         fr_name: &RegionName,
         category: ConstraintCategory,
@@ -1203,7 +1204,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         captured_var: &str,
     ) -> DiagnosticBuilder<'cx> {
         let tcx = self.infcx.tcx;
-
+        let args_span = use_span.args_or_use();
         let mut err = self.cannot_capture_in_long_lived_closure(
             args_span,
             captured_var,
@@ -1223,12 +1224,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             },
             Err(_) => "move |<args>| <body>".to_string()
         };
-
+        let kind = match use_span.generator_kind() {
+            Some(generator_kind) => match generator_kind {
+                GeneratorKind::Async(async_kind) => match async_kind {
+                    AsyncGeneratorKind::Block => "async block",
+                    AsyncGeneratorKind::Closure => "async closure",
+                    _ => bug!("async block/closure expected, but async funtion found."),
+                },
+                GeneratorKind::Gen => "generator",
+            }
+            None => "closure",
+        };
         err.span_suggestion(
             args_span,
-            &format!("to force the closure to take ownership of {} (and any \
-                      other referenced variables), use the `move` keyword",
-                      captured_var),
+            &format!(
+                "to force the {} to take ownership of {} (and any \
+                 other referenced variables), use the `move` keyword",
+                 kind,
+                 captured_var
+            ),
             suggestion,
             Applicability::MachineApplicable,
         );
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index dc7e4b22065..5e0727d5157 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1,6 +1,7 @@
 use rustc::hir;
 use rustc::hir::def::Namespace;
 use rustc::hir::def_id::DefId;
+use rustc::hir::GeneratorKind;
 use rustc::mir::{
     AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
     Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
@@ -14,7 +15,7 @@ use syntax_pos::Span;
 use syntax::symbol::sym;
 
 use super::borrow_set::BorrowData;
-use super::{MirBorrowckCtxt};
+use super::MirBorrowckCtxt;
 use crate::dataflow::move_paths::{InitLocation, LookupResult};
 
 pub(super) struct IncludingDowncast(pub(super) bool);
@@ -604,7 +605,7 @@ pub(super) enum UseSpans {
     // The access is caused by capturing a variable for a closure.
     ClosureUse {
         // This is true if the captured variable was from a generator.
-        is_generator: bool,
+        generator_kind: Option<GeneratorKind>,
         // The span of the args of the closure, including the `move` keyword if
         // it's present.
         args_span: Span,
@@ -631,6 +632,13 @@ impl UseSpans {
         }
     }
 
+    pub(super) fn generator_kind(self) -> Option<GeneratorKind> {
+        match self {
+            UseSpans::ClosureUse { generator_kind, .. } => generator_kind,
+            _ => None,
+        }
+    }
+
     // Add a span label to the arguments of the closure, if it exists.
     pub(super) fn args_span_label(
         self,
@@ -656,7 +664,7 @@ impl UseSpans {
     /// Returns `false` if this place is not used in a closure.
     pub(super) fn for_closure(&self) -> bool {
         match *self {
-            UseSpans::ClosureUse { is_generator, .. } => !is_generator,
+            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(),
             _ => false,
         }
     }
@@ -664,7 +672,7 @@ impl UseSpans {
     /// Returns `false` if this place is not used in a generator.
     pub(super) fn for_generator(&self) -> bool {
         match *self {
-            UseSpans::ClosureUse { is_generator, .. } => is_generator,
+            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(),
             _ => false,
         }
     }
@@ -672,7 +680,7 @@ impl UseSpans {
     /// Describe the span associated with a use of a place.
     pub(super) fn describe(&self) -> String {
         match *self {
-            UseSpans::ClosureUse { is_generator, .. } => if is_generator {
+            UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() {
                 " in generator".to_string()
             } else {
                 " in closure".to_string()
@@ -794,19 +802,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let  StatementKind::Assign(
             box(_, Rvalue::Aggregate(ref kind, ref places))
         ) = stmt.kind {
-            let (def_id, is_generator) = match kind {
-                box AggregateKind::Closure(def_id, _) => (def_id, false),
-                box AggregateKind::Generator(def_id, _, _) => (def_id, true),
+            let def_id = match kind {
+                box AggregateKind::Closure(def_id, _)
+                | box AggregateKind::Generator(def_id, _, _) => def_id,
                 _ => return OtherUse(stmt.source_info.span),
             };
 
             debug!(
-                "move_spans: def_id={:?} is_generator={:?} places={:?}",
-                def_id, is_generator, places
+                "move_spans: def_id={:?} places={:?}",
+                def_id, places
             );
-            if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) {
+            if let Some((args_span, generator_kind, var_span))
+                = self.closure_span(*def_id, moved_place, places) {
                 return ClosureUse {
-                    is_generator,
+                    generator_kind,
                     args_span,
                     var_span,
                 };
@@ -857,11 +866,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     "borrow_spans: def_id={:?} is_generator={:?} places={:?}",
                     def_id, is_generator, places
                 );
-                if let Some((args_span, var_span)) = self.closure_span(
+                if let Some((args_span, generator_kind, var_span)) = self.closure_span(
                     *def_id, Place::from(target).as_ref(), places
                 ) {
                     return ClosureUse {
-                        is_generator,
+                        generator_kind,
                         args_span,
                         var_span,
                     };
@@ -884,7 +893,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         def_id: DefId,
         target_place: PlaceRef<'cx, 'tcx>,
         places: &Vec<Operand<'tcx>>,
-    ) -> Option<(Span, Span)> {
+    ) -> Option<(Span, Option<GeneratorKind>, Span)> {
         debug!(
             "closure_span: def_id={:?} target_place={:?} places={:?}",
             def_id, target_place, places
@@ -893,14 +902,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let hir::ExprKind::Closure(
-            .., args_span, _
+            .., body_id, args_span, _
         ) = expr {
             for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
                 match place {
                     Operand::Copy(place) |
                     Operand::Move(place) if target_place == place.as_ref() => {
                         debug!("closure_span: found captured local {:?}", place);
-                        return Some((*args_span, upvar.span));
+                        let body = self.infcx.tcx.hir().body(*body_id);
+                        let generator_kind = body.generator_kind();
+                        return Some((*args_span, generator_kind, upvar.span));
                     },
                     _ => {}
                 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 1563a27250e..ed639e8eee7 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -1396,7 +1396,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 };
 
                 let place_ty = place.ty(body, tcx).ty;
+                let place_ty = self.normalize(place_ty, location);
                 let rv_ty = rv.ty(body, tcx);
+                let rv_ty = self.normalize(rv_ty, location);
                 if let Err(terr) =
                     self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
                 {
@@ -1672,6 +1674,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         match *destination {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(body, tcx).ty;
+                let dest_ty = self.normalize(dest_ty, term_location);
                 let category = match *dest {
                     Place {
                         base: PlaceBase::Local(RETURN_PLACE),
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index f9440866e49..7353ca9285d 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -1,22 +1,18 @@
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::matches::ArmHasGuard;
-use crate::build::scope::DropKind;
 use crate::hair::*;
-use rustc::middle::region;
 use rustc::mir::*;
 use rustc::hir;
 use syntax_pos::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn ast_block(
-        &mut self,
-        destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
-        block: BasicBlock,
-        ast_block: &'tcx hir::Block,
-        source_info: SourceInfo,
-    ) -> BlockAnd<()> {
+    pub fn ast_block(&mut self,
+                     destination: &Place<'tcx>,
+                     block: BasicBlock,
+                     ast_block: &'tcx hir::Block,
+                     source_info: SourceInfo)
+                     -> BlockAnd<()> {
         let Block {
             region_scope,
             opt_destruction_scope,
@@ -25,61 +21,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             expr,
             targeted_by_break,
             safety_mode
-        } = self.hir.mirror(ast_block);
+        } =
+            self.hir.mirror(ast_block);
         self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), move |this| {
             this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
                 if targeted_by_break {
                     // This is a `break`-able block
                     let exit_block = this.cfg.start_new_block();
-                    if let Some(scope) = scope {
-                        // Breakable blocks assign to their destination on each
-                        // `break`, as well as when they exit normally. So we
-                        // can't schedule the drop in the last expression like
-                        // normal blocks do.
-                        let local = destination.as_local()
-                            .expect("cannot schedule drop of non-Local place");
-                        this.schedule_drop(span, scope, local, DropKind::Value);
-                    }
                     let block_exit = this.in_breakable_scope(
                         None, exit_block, destination.clone(), |this| {
-                            this.ast_block_stmts(
-                                destination,
-                                None,
-                                block,
-                                span,
-                                stmts,
-                                expr,
-                                safety_mode,
-                            )
+                            this.ast_block_stmts(destination, block, span, stmts, expr,
+                                                 safety_mode)
                         });
                     this.cfg.terminate(unpack!(block_exit), source_info,
                                        TerminatorKind::Goto { target: exit_block });
                     exit_block.unit()
                 } else {
-                    this.ast_block_stmts(
-                        destination,
-                        scope,
-                        block,
-                        span,
-                        stmts,
-                        expr,
-                        safety_mode,
-                    )
+                    this.ast_block_stmts(destination, block, span, stmts, expr,
+                                         safety_mode)
                 }
             })
         })
     }
 
-    fn ast_block_stmts(
-        &mut self,
-        destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
-        mut block: BasicBlock,
-        span: Span,
-        stmts: Vec<StmtRef<'tcx>>,
-        expr: Option<ExprRef<'tcx>>,
-        safety_mode: BlockSafety,
-    ) -> BlockAnd<()> {
+    fn ast_block_stmts(&mut self,
+                       destination: &Place<'tcx>,
+                       mut block: BasicBlock,
+                       span: Span,
+                       stmts: Vec<StmtRef<'tcx>>,
+                       expr: Option<ExprRef<'tcx>>,
+                       safety_mode: BlockSafety)
+                       -> BlockAnd<()> {
         let this = self;
 
         // This convoluted structure is to avoid using recursion as we walk down a list
@@ -205,7 +177,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.block_context.currently_ignores_tail_results();
             this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
 
-            unpack!(block = this.into(destination, scope, block, expr));
+            unpack!(block = this.into(destination, block, expr));
             let popped = this.block_context.pop();
 
             assert!(popped.map_or(false, |bf|bf.is_tail_expr()));
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index bd9edc56872..87d95a75153 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -136,14 +136,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg
                     .push_assign(block, source_info, &Place::from(result), box_);
 
-                // Initialize the box contents. No scope is needed since the
-                // `Box` is already scheduled to be dropped.
+                // initialize the box contents:
                 unpack!(
                     block = this.into(
                         &Place::from(result).deref(),
-                        None,
-                        block,
-                        value
+                        block, value
                     )
                 );
                 block.and(Rvalue::Use(Operand::Move(Place::from(result))))
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index bd20f27c945..18332ed68f8 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -109,7 +109,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        unpack!(block = this.into(temp_place, temp_lifetime, block, expr));
+        unpack!(block = this.into(temp_place, block, expr));
+
+        if let Some(temp_lifetime) = temp_lifetime {
+            this.schedule_drop(
+                expr_span,
+                temp_lifetime,
+                temp,
+                DropKind::Value,
+            );
+        }
 
         block.and(temp)
     }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index c262215ab9b..8a6bc5a2a76 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -2,9 +2,7 @@
 
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
-use crate::build::scope::DropKind;
 use crate::hair::*;
-use rustc::middle::region;
 use rustc::mir::*;
 use rustc::ty;
 
@@ -13,18 +11,15 @@ use rustc_target::spec::abi::Abi;
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
-    /// If a `drop_scope` is provided, `destination` is scheduled to be dropped
-    /// in `scope` once it has been initialized.
     pub fn into_expr(
         &mut self,
         destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
         mut block: BasicBlock,
         expr: Expr<'tcx>,
     ) -> BlockAnd<()> {
         debug!(
-            "into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})",
-            destination, scope, block, expr
+            "into_expr(destination={:?}, block={:?}, expr={:?})",
+            destination, block, expr
         );
 
         // since we frequently have to reference `self` from within a
@@ -40,14 +35,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             _ => false,
         };
 
-        let schedule_drop = move |this: &mut Self| {
-            if let Some(drop_scope) = scope {
-                let local = destination.as_local()
-                    .expect("cannot schedule drop of non-Local place");
-                this.schedule_drop(expr_span, drop_scope, local, DropKind::Value);
-            }
-        };
-
         if !expr_is_block_or_scope {
             this.block_context.push(BlockFrame::SubExpr);
         }
@@ -60,14 +47,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             } => {
                 let region_scope = (region_scope, source_info);
                 this.in_scope(region_scope, lint_level, |this| {
-                    this.into(destination, scope, block, value)
+                    this.into(destination, block, value)
                 })
             }
             ExprKind::Block { body: ast_block } => {
-                this.ast_block(destination, scope, block, ast_block, source_info)
+                this.ast_block(destination, block, ast_block, source_info)
             }
             ExprKind::Match { scrutinee, arms } => {
-                this.match_expr(destination, scope, expr_span, block, scrutinee, arms)
+                this.match_expr(destination, expr_span, block, scrutinee, arms)
             }
             ExprKind::NeverToAny { source } => {
                 let source = this.hir.mirror(source);
@@ -80,7 +67,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // This is an optimization. If the expression was a call then we already have an
                 // unreachable block. Don't bother to terminate it and create a new one.
-                schedule_drop(this);
                 if is_call {
                     block.unit()
                 } else {
@@ -178,9 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     TerminatorKind::Goto { target: loop_block },
                 );
 
-                // Loops assign to their destination on each `break`. Since we
-                // can't easily unschedule drops, we schedule the drop now.
-                schedule_drop(this);
                 this.in_breakable_scope(
                     Some(loop_block),
                     exit_block,
@@ -202,8 +185,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         // introduce a unit temporary as the destination for the loop body.
                         let tmp = this.get_unit_temp();
                         // Execute the body, branching back to the test.
-                        // No scope is provided, since we've scheduled the drop above.
-                        let body_block_end = unpack!(this.into(&tmp, None, body_block, body));
+                        let body_block_end = unpack!(this.into(&tmp, body_block, body));
                         this.cfg.terminate(
                             body_block_end,
                             source_info,
@@ -252,14 +234,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         is_block_tail: None,
                     });
                     let ptr_temp = Place::from(ptr_temp);
-                    // No need for a scope, ptr_temp doesn't need drop
-                    let block = unpack!(this.into(&ptr_temp, None, block, ptr));
-                    // Maybe we should provide a scope here so that
-                    // `move_val_init` wouldn't leak on panic even with an
-                    // arbitrary `val` expression, but `schedule_drop`,
-                    // borrowck and drop elaboration all prevent us from
-                    // dropping `ptr_temp.deref()`.
-                    this.into(&ptr_temp.deref(), None, block, val)
+                    let block = unpack!(this.into(&ptr_temp, block, ptr));
+                    this.into(&ptr_temp.deref(), block, val)
                 } else {
                     let args: Vec<_> = args
                         .into_iter()
@@ -289,12 +265,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             from_hir_call,
                         },
                     );
-                    schedule_drop(this);
                     success.unit()
                 }
             }
             ExprKind::Use { source } => {
-                this.into(destination, scope, block, source)
+                this.into(destination, block, source)
             }
 
             // These cases don't actually need a destination
@@ -321,7 +296,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
                 this.cfg
                     .push_assign(block, source_info, destination, rvalue);
-                schedule_drop(this);
                 block.unit()
             }
             ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => {
@@ -341,7 +315,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
                 this.cfg
                     .push_assign(block, source_info, destination, rvalue);
-                schedule_drop(this);
                 block.unit()
             }
 
@@ -373,7 +346,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 let rvalue = unpack!(block = this.as_local_rvalue(block, expr));
                 this.cfg.push_assign(block, source_info, destination, rvalue);
-                schedule_drop(this);
                 block.unit()
             }
         };
diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs
index e57f10f0b14..077840c9ccf 100644
--- a/src/librustc_mir/build/into.rs
+++ b/src/librustc_mir/build/into.rs
@@ -6,7 +6,6 @@
 
 use crate::build::{BlockAnd, Builder};
 use crate::hair::*;
-use rustc::middle::region;
 use rustc::mir::*;
 
 pub(in crate::build) trait EvalInto<'tcx> {
@@ -14,23 +13,19 @@ pub(in crate::build) trait EvalInto<'tcx> {
         self,
         builder: &mut Builder<'_, 'tcx>,
         destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
         block: BasicBlock,
     ) -> BlockAnd<()>;
 }
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn into<E>(
-        &mut self,
-        destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
-        block: BasicBlock,
-        expr: E,
-    ) -> BlockAnd<()>
-    where
-        E: EvalInto<'tcx>,
+    pub fn into<E>(&mut self,
+                   destination: &Place<'tcx>,
+                   block: BasicBlock,
+                   expr: E)
+                   -> BlockAnd<()>
+        where E: EvalInto<'tcx>
     {
-        expr.eval_into(self, destination, scope, block)
+        expr.eval_into(self, destination, block)
     }
 }
 
@@ -39,11 +34,10 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
         self,
         builder: &mut Builder<'_, 'tcx>,
         destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
         block: BasicBlock,
     ) -> BlockAnd<()> {
         let expr = builder.hir.mirror(self);
-        builder.into_expr(destination, scope, block, expr)
+        builder.into_expr(destination, block, expr)
     }
 }
 
@@ -52,9 +46,8 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
         self,
         builder: &mut Builder<'_, 'tcx>,
         destination: &Place<'tcx>,
-        scope: Option<region::Scope>,
         block: BasicBlock,
     ) -> BlockAnd<()> {
-        builder.into_expr(destination, scope, block, self)
+        builder.into_expr(destination, block, self)
     }
 }
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index e8cf827aa90..2e451fc88d9 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -102,7 +102,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn match_expr(
         &mut self,
         destination: &Place<'tcx>,
-        destination_scope: Option<region::Scope>,
         span: Span,
         mut block: BasicBlock,
         scrutinee: ExprRef<'tcx>,
@@ -229,14 +228,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         };
 
         // Step 5. Create everything else: the guards and the arms.
-        if let Some(scope) = destination_scope {
-            // `match` assigns to its destination in each arm. Since we can't
-            // easily unschedule drops, we schedule the drop now.
-            let local = destination.as_local()
-                .expect("cannot schedule drop of non-Local place");
-            self.schedule_drop(span, scope, local, DropKind::Value);
-        }
-
         let match_scope = self.scopes.topmost();
 
         let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| {
@@ -284,8 +275,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.source_scope = source_scope;
                 }
 
-                // No scope is provided, since we've scheduled the drop above.
-                this.into(destination, None, arm_block, body)
+                this.into(destination, arm_block, body)
             })
         }).collect();
 
@@ -321,9 +311,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
-                let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
+                unpack!(block = self.into(&place, block, initializer));
 
-                unpack!(block = self.into(&place, Some(region_scope), block, initializer));
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let source_info = self.source_info(irrefutable_pat.span);
@@ -335,6 +324,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     },
                 );
 
+                self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
                 block.unit()
             }
 
@@ -362,10 +352,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     user_ty_span,
                 },
             } => {
-                let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
-                unpack!(block = self.into(&place, Some(region_scope), block, initializer));
+                unpack!(block = self.into(&place, block, initializer));
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let pattern_source_info = self.source_info(irrefutable_pat.span);
@@ -411,6 +400,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     },
                 );
 
+                self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
                 block.unit()
             }
 
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 9a98cf1cb88..ffb70180bbb 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -502,24 +502,21 @@ macro_rules! unpack {
     };
 }
 
-fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool {
-    // Not callable from C, so we can safely unwind through these
-    if abi == Abi::Rust || abi == Abi::RustCall { return false; }
-
-    // Validate `#[unwind]` syntax regardless of platform-specific panic strategy
+fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, _abi: Abi) -> bool {
+    // Validate `#[unwind]` syntax regardless of platform-specific panic strategy.
     let attrs = &tcx.get_attrs(fn_def_id);
     let unwind_attr = attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs);
 
-    // We never unwind, so it's not relevant to stop an unwind
+    // We never unwind, so it's not relevant to stop an unwind.
     if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; }
 
-    // We cannot add landing pads, so don't add one
+    // We cannot add landing pads, so don't add one.
     if tcx.sess.no_landing_pads() { return false; }
 
     // This is a special case: some functions have a C abi but are meant to
     // unwind anyway. Don't stop them.
     match unwind_attr {
-        None => false, // FIXME(#58794)
+        None => false, // FIXME(#58794); should be `!(abi == Abi::Rust || abi == Abi::RustCall)`
         Some(UnwindAttr::Allowed) => false,
         Some(UnwindAttr::Aborts) => true,
     }
@@ -616,7 +613,6 @@ where
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
     unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
-        builder.schedule_drop(span, call_site_scope, RETURN_PLACE, DropKind::Value);
         if should_abort_on_panic(tcx, fn_def_id, abi) {
             builder.schedule_abort();
         }
@@ -647,7 +643,6 @@ where
             builder.cfg.terminate(unreachable_block, source_info,
                                   TerminatorKind::Unreachable);
         }
-        builder.unschedule_return_place_drop();
         return_block.unit()
     }));
     assert_eq!(block, builder.return_block());
@@ -689,9 +684,7 @@ fn construct_const<'a, 'tcx>(
     let mut block = START_BLOCK;
     let ast_expr = &tcx.hir().body(body_id).value;
     let expr = builder.hir.mirror(ast_expr);
-    // We don't provide a scope because we can't unwind in constants, so won't
-    // need to drop the return place.
-    unpack!(block = builder.into_expr(&Place::return_place(), None, block, expr));
+    unpack!(block = builder.into_expr(&Place::return_place(), block, expr));
 
     let source_info = builder.source_info(span);
     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
@@ -892,9 +885,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
 
         let body = self.hir.mirror(ast_body);
-        // No scope is provided, since we've scheduled the drop of the return
-        // place.
-        self.into(&Place::return_place(), None, block, body)
+        self.into(&Place::return_place(), block, body)
     }
 
     fn set_correct_source_scope_for_arg(
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 6206bfd9f3e..a749b4263ea 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -513,7 +513,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             if let Some(value) = value {
                 debug!("stmt_expr Break val block_context.push(SubExpr)");
                 self.block_context.push(BlockFrame::SubExpr);
-                unpack!(block = self.into(&destination, None, block, value));
+                unpack!(block = self.into(&destination, block, value));
                 self.block_context.pop();
             } else {
                 self.cfg.push_assign_unit(block, source_info, &destination)
@@ -1070,18 +1070,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         success_block
     }
 
-    /// Unschedules the drop of the return place.
-    ///
-    /// If the return type of a function requires drop, then we schedule it
-    /// in the outermost scope so that it's dropped if there's a panic while
-    /// we drop any local variables. But we don't want to drop it if we
-    /// return normally.
-    crate fn unschedule_return_place_drop(&mut self) {
-        assert_eq!(self.scopes.len(), 1);
-        assert!(self.scopes.scopes[0].drops.len() <= 1);
-        self.scopes.scopes[0].drops.clear();
-    }
-
     // `match` arm scopes
     // ==================
     /// Unschedules any drops in the top scope.
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index c521b735221..9bed4fb66ea 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -62,12 +62,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
     fn visit_local(&mut self, loc: &'tcx hir::Local) {
         intravisit::walk_local(self, loc);
 
-        self.check_irrefutable(&loc.pat, match loc.source {
-            hir::LocalSource::Normal => "local binding",
-            hir::LocalSource::ForLoopDesugar => "`for` loop binding",
-            hir::LocalSource::AsyncFn => "async fn binding",
-            hir::LocalSource::AwaitDesugar => "`await` future binding",
-        });
+        let (msg, sp) = match loc.source {
+            hir::LocalSource::Normal => ("local binding", Some(loc.span)),
+            hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None),
+            hir::LocalSource::AsyncFn => ("async fn binding", None),
+            hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
+        };
+        self.check_irrefutable(&loc.pat, msg, sp);
 
         // Check legality of move bindings and `@` patterns.
         self.check_patterns(false, &loc.pat);
@@ -77,7 +78,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
         intravisit::walk_body(self, body);
 
         for param in &body.params {
-            self.check_irrefutable(&param.pat, "function argument");
+            self.check_irrefutable(&param.pat, "function argument", None);
             self.check_patterns(false, &param.pat);
         }
     }
@@ -242,7 +243,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
         })
     }
 
-    fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
+    fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str, sp: Option<Span>) {
         let module = self.tcx.hir().get_module_parent(pat.hir_id);
         MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
             let mut patcx = PatCtxt::new(self.tcx,
@@ -266,18 +267,35 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
                 "refutable pattern in {}: {} not covered",
                 origin, joined_patterns
             );
-            match &pat.kind {
+            let suggest_if_let = match &pat.kind {
                 hir::PatKind::Path(hir::QPath::Resolved(None, path))
                     if path.segments.len() == 1 && path.segments[0].args.is_none() =>
                 {
                     const_not_var(&mut err, cx.tcx, pat, path);
+                    false
                 }
                 _ => {
                     err.span_label(
                         pat.span,
                         pattern_not_covered_label(&witnesses, &joined_patterns),
                     );
+                    true
+                }
+            };
+
+            if let (Some(span), true) = (sp, suggest_if_let) {
+                err.note("`let` bindings require an \"irrefutable pattern\", like a `struct` or \
+                          an `enum` with only one variant");
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    err.span_suggestion(
+                        span,
+                        "you might want to use `if let` to ignore the variant that isn't matched",
+                        format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]),
+                        Applicability::HasPlaceholders,
+                    );
                 }
+                err.note("for more information, visit \
+                          https://doc.rust-lang.org/book/ch18-02-refutability.html");
             }
 
             adt_defined_here(cx, &mut err, pattern_ty, &witnesses);
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index d120412c901..9ab347957f9 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -44,7 +44,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
                             bug!("reifying a fn ptr that requires const arguments");
                         }
-                        let instance = self.resolve(def_id, substs)?;
+
+                        let instance = ty::Instance::resolve_for_fn_ptr(
+                            *self.tcx,
+                            self.param_env,
+                            def_id,
+                            substs,
+                        ).ok_or_else(|| err_inval!(TooGeneric))?;
+
                         let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
                         self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                     }
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index ef6b7d626e7..11c7cd0d901 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -263,6 +263,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 Ok(())
             }
             ty::InstanceDef::VtableShim(..) |
+            ty::InstanceDef::ReifyShim(..) |
             ty::InstanceDef::ClosureOnceShim { .. } |
             ty::InstanceDef::FnPtrShim(..) |
             ty::InstanceDef::DropGlue(..) |
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 81c08ee87e9..a837c34e8d4 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -22,7 +22,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(slice_concat_ext)]
 #![feature(trusted_len)]
 #![feature(try_blocks)]
-#![feature(mem_take)]
 #![feature(associated_type_bounds)]
 #![feature(range_is_empty)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 3ac837dd330..ee7452d3e8b 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -285,7 +285,11 @@ pub fn collect_crate_mono_items(
     tcx: TyCtxt<'_>,
     mode: MonoItemCollectionMode,
 ) -> (FxHashSet<MonoItem<'_>>, InliningMap<'_>) {
+    let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
+
     let roots = time(tcx.sess, "collecting roots", || {
+        let _prof_timer = tcx.prof
+            .generic_activity("monomorphization_collector_root_collections");
         collect_roots(tcx, mode)
     });
 
@@ -295,6 +299,9 @@ pub fn collect_crate_mono_items(
     let mut inlining_map = MTLock::new(InliningMap::new());
 
     {
+        let _prof_timer = tcx.prof
+            .generic_activity("monomorphization_collector_graph_walk");
+
         let visited: MTRef<'_, _> = &mut visited;
         let inlining_map: MTRef<'_, _> = &mut inlining_map;
 
@@ -714,10 +721,12 @@ fn visit_fn_use<'tcx>(
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
     if let ty::FnDef(def_id, substs) = ty.kind {
-        let instance = ty::Instance::resolve(tcx,
-                                             ty::ParamEnv::reveal_all(),
-                                             def_id,
-                                             substs).unwrap();
+        let resolver = if is_direct_call {
+            ty::Instance::resolve
+        } else {
+            ty::Instance::resolve_for_fn_ptr
+        };
+        let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
         visit_instance_use(tcx, instance, is_direct_call, output);
     }
 }
@@ -740,6 +749,7 @@ fn visit_instance_use<'tcx>(
             }
         }
         ty::InstanceDef::VtableShim(..) |
+        ty::InstanceDef::ReifyShim(..) |
         ty::InstanceDef::Virtual(..) |
         ty::InstanceDef::DropGlue(_, None) => {
             // don't need to emit shim if we are calling directly.
@@ -766,6 +776,7 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx
     let def_id = match instance.def {
         ty::InstanceDef::Item(def_id) => def_id,
         ty::InstanceDef::VtableShim(..) |
+        ty::InstanceDef::ReifyShim(..) |
         ty::InstanceDef::ClosureOnceShim { .. } |
         ty::InstanceDef::Virtual(..) |
         ty::InstanceDef::FnPtrShim(..) |
@@ -1265,7 +1276,14 @@ fn collect_const<'tcx>(
 ) {
     debug!("visiting const {:?}", constant);
 
-    match constant.val {
+    let param_env = ty::ParamEnv::reveal_all();
+    let substituted_constant = tcx.subst_and_normalize_erasing_regions(
+        param_substs,
+        param_env,
+        &constant,
+    );
+
+    match substituted_constant.val {
         ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
         ConstValue::Slice { data: alloc, start: _, end: _ } |
@@ -1275,12 +1293,6 @@ fn collect_const<'tcx>(
             }
         }
         ConstValue::Unevaluated(def_id, substs) => {
-            let param_env = ty::ParamEnv::reveal_all();
-            let substs = tcx.subst_and_normalize_erasing_regions(
-                param_substs,
-                param_env,
-                &substs,
-            );
             let instance = ty::Instance::resolve(tcx,
                                                 param_env,
                                                 def_id,
@@ -1297,7 +1309,7 @@ fn collect_const<'tcx>(
                     tcx.def_span(def_id), "collection encountered polymorphic constant",
                 ),
             }
-        }
+        },
         _ => {},
     }
 }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 61868b24c0b..b9d38028b72 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -134,10 +134,15 @@ pub fn partition<'tcx, I>(
 where
     I: Iterator<Item = MonoItem<'tcx>>,
 {
+    let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
+
     // In the first step, we place all regular monomorphizations into their
     // respective 'home' codegen unit. Regular monomorphizations are all
     // functions and statics defined in the local crate.
-    let mut initial_partitioning = place_root_mono_items(tcx, mono_items);
+    let mut initial_partitioning = {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
+        place_root_mono_items(tcx, mono_items)
+    };
 
     initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
 
@@ -146,8 +151,8 @@ where
     // If the partitioning should produce a fixed count of codegen units, merge
     // until that count is reached.
     if let PartitioningStrategy::FixedUnitCount(count) = strategy {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
         merge_codegen_units(tcx, &mut initial_partitioning, count);
-
         debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
     }
 
@@ -155,8 +160,11 @@ where
     // monomorphizations have to go into each codegen unit. These additional
     // monomorphizations can be drop-glue, functions from external crates, and
     // local functions the definition of which is marked with `#[inline]`.
-    let mut post_inlining = place_inlined_mono_items(initial_partitioning,
-                                                            inlining_map);
+    let mut post_inlining = {
+        let _prof_timer =
+            tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
+        place_inlined_mono_items(initial_partitioning, inlining_map)
+    };
 
     post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
 
@@ -165,6 +173,8 @@ where
     // Next we try to make as many symbols "internal" as possible, so LLVM has
     // more freedom to optimize.
     if !tcx.sess.opts.cg.link_dead_code {
+        let _prof_timer =
+            tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
         internalize_symbols(tcx, &mut post_inlining, inlining_map);
     }
 
@@ -329,6 +339,7 @@ fn mono_item_visibility(
 
         // These are all compiler glue and such, never exported, always hidden.
         InstanceDef::VtableShim(..) |
+        InstanceDef::ReifyShim(..) |
         InstanceDef::FnPtrShim(..) |
         InstanceDef::Virtual(..) |
         InstanceDef::Intrinsic(..) |
@@ -667,6 +678,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
             let def_id = match instance.def {
                 ty::InstanceDef::Item(def_id) => def_id,
                 ty::InstanceDef::VtableShim(..) |
+                ty::InstanceDef::ReifyShim(..) |
                 ty::InstanceDef::FnPtrShim(..) |
                 ty::InstanceDef::ClosureOnceShim { .. } |
                 ty::InstanceDef::Intrinsic(..) |
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 78008e2fcd3..f532a18072f 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -66,9 +66,12 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
                 Some(arg_tys)
             )
         }
-        ty::InstanceDef::Virtual(def_id, _) => {
-            // We are generating a call back to our def-id, which the
-            // codegen backend knows to turn to an actual virtual call.
+        // We are generating a call back to our def-id, which the
+        // codegen backend knows to turn to an actual virtual call.
+        ty::InstanceDef::Virtual(def_id, _) |
+        // ...or we are generating a direct call to a function for which indirect calls must be
+        // codegen'd differently than direct ones (example: #[track_caller])
+        ty::InstanceDef::ReifyShim(def_id) => {
             build_call_shim(
                 tcx,
                 def_id,
diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs
index e460e9813b3..a2626617afe 100644
--- a/src/librustc_passes/error_codes.rs
+++ b/src/librustc_passes/error_codes.rs
@@ -359,6 +359,35 @@ fn main() {}
 ```
 "##,
 
+E0568: r##"
+A super trait has been added to an auto trait.
+
+Erroneous code example:
+
+```compile_fail,E0568
+#![feature(optin_builtin_traits)]
+
+auto trait Bound : Copy {} // error!
+
+fn main() {}
+```
+
+Since an auto trait is implemented on all existing types, adding a super trait
+would filter out a lot of those types. In the current example, almost none of
+all the existing types could implement `Bound` because very few of them have the
+`Copy` trait.
+
+To fix this issue, just remove the super trait:
+
+```
+#![feature(optin_builtin_traits)]
+
+auto trait Bound {} // ok!
+
+fn main() {}
+```
+"##,
+
 E0571: r##"
 A `break` statement with an argument appeared in a non-`loop` loop.
 
@@ -576,7 +605,6 @@ Switch to the Rust 2018 edition to use `async fn`.
 ;
     E0226, // only a single explicit lifetime bound is permitted
     E0472, // asm! is unsupported on this target
-    E0568, // auto traits can not have super traits
     E0666, // nested `impl Trait` is illegal
     E0667, // `impl Trait` in projections
     E0696, // `continue` pointing to a labeled block
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index f76aa95dd2c..030f9b97eb8 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -38,6 +38,7 @@ use syntax::ext::hygiene::ExpnId;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::parse::token::{self, Token};
 use syntax::{span_err, struct_span_err};
+use syntax::source_map::{respan, Spanned};
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
@@ -301,7 +302,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         }
     }
 
-    fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Name>) {
+    fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Name>>) {
         if !field_names.is_empty() {
             self.r.field_names.insert(def_id, field_names);
         }
@@ -752,12 +753,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 }
 
                 // Record field names for error reporting.
-                let field_names = struct_def.fields().iter().filter_map(|field| {
+                let field_names = struct_def.fields().iter().map(|field| {
                     let field_vis = self.resolve_visibility(&field.vis);
                     if ctor_vis.is_at_least(field_vis, &*self.r) {
                         ctor_vis = field_vis;
                     }
-                    field.ident.map(|ident| ident.name)
+                    respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
                 }).collect();
                 let item_def_id = self.r.definitions.local_def_id(item.id);
                 self.insert_field_names(item_def_id, field_names);
@@ -779,9 +780,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
                 // Record field names for error reporting.
-                let field_names = vdata.fields().iter().filter_map(|field| {
+                let field_names = vdata.fields().iter().map(|field| {
                     self.resolve_visibility(&field.vis);
-                    field.ident.map(|ident| ident.name)
+                    respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
                 }).collect();
                 let item_def_id = self.r.definitions.local_def_id(item.id);
                 self.insert_field_names(item_def_id, field_names);
@@ -895,7 +896,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         // Record some extra data for better diagnostics.
         match res {
             Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
-                let field_names = self.r.cstore.struct_field_names_untracked(def_id);
+                let field_names =
+                    self.r.cstore.struct_field_names_untracked(def_id, self.r.session);
                 self.insert_field_names(def_id, field_names);
             }
             Res::Def(DefKind::Method, def_id) => {
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 1016989ca6e..ace9903a835 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -497,7 +497,8 @@ impl<'a> LateResolutionVisitor<'a, '_> {
                         Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did)
                                 if resolution.unresolved_segments() == 0 => {
                             if let Some(field_names) = self.r.field_names.get(&did) {
-                                if field_names.iter().any(|&field_name| ident.name == field_name) {
+                                if field_names.iter()
+                                        .any(|&field_name| ident.name == field_name.node) {
                                     return Some(AssocSuggestion::Field);
                                 }
                             }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 9c4281bbb62..e0ff1539009 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -11,7 +11,6 @@
 
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
-#![feature(mem_take)]
 #![feature(nll)]
 
 #![recursion_limit="256"]
@@ -29,7 +28,7 @@ use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrK
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::{TraitMap, GlobMap};
-use rustc::ty;
+use rustc::ty::{self, DefIdTree};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 use rustc::span_bug;
 
@@ -46,6 +45,7 @@ use syntax::attr;
 use syntax::ast::{CRATE_NODE_ID, Crate};
 use syntax::ast::{ItemKind, Path};
 use syntax::{struct_span_err, unwrap_or};
+use syntax::source_map::Spanned;
 
 use syntax_pos::{Span, DUMMY_SP};
 use errors::{Applicability, DiagnosticBuilder};
@@ -829,7 +829,7 @@ pub struct Resolver<'a> {
 
     /// Names of fields of an item `DefId` accessible with dot syntax.
     /// Used for hints during error reporting.
-    field_names: FxHashMap<DefId, Vec<Name>>,
+    field_names: FxHashMap<DefId, Vec<Spanned<Name>>>,
 
     /// All imports known to succeed or fail.
     determined_imports: Vec<&'a ImportDirective<'a>>,
@@ -994,7 +994,7 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
     fn as_mut(&mut self) -> &mut Resolver<'a> { self }
 }
 
-impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> {
+impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
     fn parent(self, id: DefId) -> Option<DefId> {
         match id.krate {
             LOCAL_CRATE => self.definitions.def_key(id.index).parent,
@@ -1255,6 +1255,9 @@ impl<'a> Resolver<'a> {
 
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
+        let _prof_timer =
+            self.session.prof.generic_activity("resolve_crate");
+
         ImportResolver { r: self }.finalize_imports();
         self.finalize_macro_resolutions();
 
@@ -2375,32 +2378,38 @@ impl<'a> Resolver<'a> {
         let mut reported_spans = FxHashSet::default();
         for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors {
             if reported_spans.insert(dedup_span) {
-                let mut err = struct_span_err!(
-                    self.session,
-                    ident.span,
-                    E0603,
-                    "{} `{}` is private",
-                    binding.res().descr(),
-                    ident.name,
-                );
-                // FIXME: use the ctor's `def_id` to check wether any of the fields is not visible
-                match binding.kind {
-                    NameBindingKind::Res(Res::Def(DefKind::Ctor(
-                        CtorOf::Struct,
-                        CtorKind::Fn,
-                    ), _def_id), _) => {
-                        err.note("a tuple struct constructor is private if any of its fields \
-                                  is private");
-                    }
-                    NameBindingKind::Res(Res::Def(DefKind::Ctor(
-                        CtorOf::Variant,
-                        CtorKind::Fn,
-                    ), _def_id), _) => {
-                        err.note("a tuple variant constructor is private if any of its fields \
-                                  is private");
+                let session = &self.session;
+                let mk_struct_span_error = |is_constructor| {
+                    struct_span_err!(
+                        session,
+                        ident.span,
+                        E0603,
+                        "{}{} `{}` is private",
+                        binding.res().descr(),
+                        if is_constructor { " constructor"} else { "" },
+                        ident.name,
+                    )
+                };
+
+                let mut err = if let NameBindingKind::Res(
+                    Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _
+                ) = binding.kind {
+                    let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
+                    if let Some(fields) = self.field_names.get(&def_id) {
+                        let mut err = mk_struct_span_error(true);
+                        let first_field = fields.first().expect("empty field list in the map");
+                        err.span_label(
+                            fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
+                            "a constructor is private if any of the fields is private",
+                        );
+                        err
+                    } else {
+                        mk_struct_span_error(false)
                     }
-                    _ => {}
-                }
+                } else {
+                    mk_struct_span_error(false)
+                };
+
                 err.emit();
             }
         }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 73ad0670659..2b87bba8386 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -773,7 +773,6 @@ impl<'a> Resolver<'a> {
                     check_consistency(self, &[seg], ident.span, kind, initial_res, res);
                 }
                 Err(..) => {
-                    assert!(initial_binding.is_none());
                     let expected = kind.descr_expected();
                     let msg = format!("cannot find {} `{}` in this scope", expected, ident);
                     let mut err = self.session.struct_span_err(ident.span, &msg);
@@ -797,7 +796,12 @@ impl<'a> Resolver<'a> {
             if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
                 let feature = stability.feature;
                 if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
-                    stability::report_unstable(self.session, feature, reason, issue, is_soft, span);
+                    let node_id = ast::CRATE_NODE_ID;
+                    let soft_handler =
+                        |lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg);
+                    stability::report_unstable(
+                        self.session, feature, reason, issue, is_soft, span, soft_handler
+                    );
                 }
             }
             if let Some(depr) = &stability.rustc_depr {
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 2be31112721..e57cc809c34 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -58,7 +58,7 @@ pub enum MethodError<'tcx> {
 
     // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
     // forgotten to import a trait.
-    IllegalSizedBound(Vec<DefId>),
+    IllegalSizedBound(Vec<DefId>, bool),
 
     // Found a match, but the return type is wrong
     BadReturnType,
@@ -214,32 +214,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         if result.illegal_sized_bound {
+            let mut needs_mut = false;
+            if let ty::Ref(region, t_type, mutability) = self_ty.kind {
+                let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut {
+                    ty: t_type,
+                    mutbl: mutability.invert(),
+                });
+                // We probe again to see if there might be a borrow mutability discrepancy.
+                match self.lookup_probe(
+                    span,
+                    segment.ident,
+                    trait_type,
+                    call_expr,
+                    ProbeScope::TraitsInScope
+                ) {
+                    Ok(ref new_pick) if *new_pick != pick => {
+                        needs_mut = true;
+                    }
+                    _ => {}
+                }
+            }
+
             // We probe again, taking all traits into account (not only those in scope).
-            let candidates =
-                match self.lookup_probe(span,
-                                        segment.ident,
-                                        self_ty,
-                                        call_expr,
-                                        ProbeScope::AllTraits) {
-
-                    // If we find a different result the caller probably forgot to import a trait.
-                    Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
-                    Err(Ambiguity(ref sources)) => {
-                        sources.iter()
-                               .filter_map(|source| {
-                                   match *source {
-                                       // Note: this cannot come from an inherent impl,
-                                       // because the first probing succeeded.
-                                       ImplSource(def) => self.tcx.trait_id_of_impl(def),
-                                       TraitSource(_) => None,
-                                   }
-                               })
-                               .collect()
+            let candidates = match self.lookup_probe(
+                span,
+                segment.ident,
+                self_ty,
+                call_expr,
+                ProbeScope::AllTraits,
+            ) {
+                // If we find a different result the caller probably forgot to import a trait.
+                Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
+                Err(Ambiguity(ref sources)) => sources.iter().filter_map(|source| {
+                    match *source {
+                        // Note: this cannot come from an inherent impl,
+                        // because the first probing succeeded.
+                        ImplSource(def) => self.tcx.trait_id_of_impl(def),
+                        TraitSource(_) => None,
                     }
-                    _ => Vec::new(),
-                };
+                }).collect(),
+                _ => Vec::new(),
+            };
 
-            return Err(IllegalSizedBound(candidates));
+            return Err(IllegalSizedBound(candidates, needs_mut));
         }
 
         Ok(result.callee)
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 70cb799cc6e..96cc5aa1dc2 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -593,22 +593,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.emit();
             }
 
-            MethodError::IllegalSizedBound(candidates) => {
+            MethodError::IllegalSizedBound(candidates, needs_mut) => {
                 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
                 let mut err = self.sess().struct_span_err(span, &msg);
                 if !candidates.is_empty() {
-                    let help = format!("{an}other candidate{s} {were} found in the following \
-                                        trait{s}, perhaps add a `use` for {one_of_them}:",
-                                    an = if candidates.len() == 1 {"an" } else { "" },
-                                    s = pluralise!(candidates.len()),
-                                    were = if candidates.len() == 1 { "was" } else { "were" },
-                                    one_of_them = if candidates.len() == 1 {
-                                        "it"
-                                    } else {
-                                        "one_of_them"
-                                    });
+                    let help = format!(
+                        "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
+                         add a `use` for {one_of_them}:",
+                        an = if candidates.len() == 1 {"an" } else { "" },
+                        s = pluralise!(candidates.len()),
+                        were = if candidates.len() == 1 { "was" } else { "were" },
+                        one_of_them = if candidates.len() == 1 {
+                            "it"
+                        } else {
+                            "one_of_them"
+                        },
+                    );
                     self.suggest_use_candidates(&mut err, help, candidates);
                 }
+                if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind {
+                    if needs_mut {
+                        let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut {
+                            ty: t_type,
+                            mutbl: mutability.invert(),
+                        });
+                        err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
+                    }
+                }
                 err.emit();
             }
 
@@ -798,31 +809,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // Get the `hir::Param` to verify whether it already has any bounds.
                         // We do this to avoid suggesting code that ends up as `T: FooBar`,
                         // instead we suggest `T: Foo + Bar` in that case.
-                        let mut has_bounds = false;
+                        let mut has_bounds = None;
                         let mut impl_trait = false;
                         if let Node::GenericParam(ref param) = hir.get(id) {
-                            match param.kind {
-                                hir::GenericParamKind::Type { synthetic: Some(_), .. } => {
-                                    // We've found `fn foo(x: impl Trait)` instead of
-                                    // `fn foo<T>(x: T)`. We want to suggest the correct
-                                    // `fn foo(x: impl Trait + TraitBound)` instead of
-                                    // `fn foo<T: TraitBound>(x: T)`. (#63706)
-                                    impl_trait = true;
-                                    has_bounds = param.bounds.len() > 1;
-                                }
-                                _ => {
-                                    has_bounds = !param.bounds.is_empty();
-                                }
+                            let kind = &param.kind;
+                            if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = kind {
+                                // We've found `fn foo(x: impl Trait)` instead of
+                                // `fn foo<T>(x: T)`. We want to suggest the correct
+                                // `fn foo(x: impl Trait + TraitBound)` instead of
+                                // `fn foo<T: TraitBound>(x: T)`. (See #63706.)
+                                impl_trait = true;
+                                has_bounds = param.bounds.get(1);
+                            } else {
+                                has_bounds = param.bounds.get(0);
                             }
                         }
                         let sp = hir.span(id);
-                        // `sp` only covers `T`, change it so that it covers
-                        // `T:` when appropriate
-                        let sp = if has_bounds {
-                            sp.to(self.tcx
-                                .sess
-                                .source_map()
-                                .next_point(self.tcx.sess.source_map().next_point(sp)))
+                        // `sp` only covers `T`, change it so that it covers `T:` when appropriate.
+                        let sp = if let Some(first_bound) = has_bounds {
+                            sp.until(first_bound.span())
                         } else {
                             sp
                         };
@@ -838,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 param,
                                 if impl_trait { " +" } else { ":" },
                                 self.tcx.def_path_str(t.def_id),
-                                if has_bounds { " +"} else { "" },
+                                if has_bounds.is_some() { " + " } else { "" },
                             )),
                             Applicability::MaybeIncorrect,
                         );
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 7f34aa354c9..5b2081bef78 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1508,9 +1508,29 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
         }
 
         Node::GenericParam(param) => match &param.kind {
-            hir::GenericParamKind::Type { default: Some(ref ty), .. } |
-            hir::GenericParamKind::Const { ref ty, .. } => {
-                icx.to_ty(ty)
+            hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
+            hir::GenericParamKind::Const { ty: ref hir_ty, .. } => {
+                let ty = icx.to_ty(hir_ty);
+                if !tcx.features().const_compare_raw_pointers {
+                    let err = match ty.peel_refs().kind {
+                        ty::FnPtr(_) => Some("function pointers"),
+                        ty::RawPtr(_) => Some("raw pointers"),
+                        _ => None,
+                    };
+                    if let Some(unsupported_type) = err {
+                        feature_gate::emit_feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::const_compare_raw_pointers,
+                            hir_ty.span,
+                            feature_gate::GateIssue::Language,
+                            &format!(
+                                "using {} as const generic parameters is unstable",
+                                unsupported_type
+                            ),
+                        );
+                    };
+                }
+                ty
             }
             x => {
                 if !fail {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index e2e8c09bb58..9374113e1c9 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -67,7 +67,6 @@ This API is completely unstable and subject to change.
 #![feature(nll)]
 #![feature(slice_patterns)]
 #![feature(never_type)]
-#![feature(mem_take)]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index fe4e2bd0915..1c0d1b32737 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -343,10 +343,7 @@ impl Options {
         let output = matches.opt_str("o")
                             .map(|s| PathBuf::from(&s))
                             .unwrap_or_else(|| PathBuf::from("doc"));
-        let mut cfgs = matches.opt_strs("cfg");
-        if should_test {
-            cfgs.push("doctest".to_string());
-        }
+        let cfgs = matches.opt_strs("cfg");
 
         let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index c23890e2a05..6bcb4a817d7 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -15,7 +15,6 @@
 #![feature(const_fn)]
 #![feature(drain_filter)]
 #![feature(never_type)]
-#![feature(mem_take)]
 #![feature(unicode_internals)]
 
 #![recursion_limit="256"]
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 3e77ca47e8a..05e6f36c958 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -64,6 +64,7 @@ pub fn run(options: Options) -> i32 {
 
     let mut cfgs = options.cfgs.clone();
     cfgs.push("rustdoc".to_owned());
+    cfgs.push("doctest".to_owned());
     let config = interface::Config {
         opts: sessopts,
         crate_cfg: config::parse_cfgspecs(cfgs),
@@ -704,6 +705,7 @@ impl Tester for Collector {
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
                 allow_fail: config.allow_fail,
+                test_type: testing::TestType::DocTest,
             },
             testfn: testing::DynTestFn(box move || {
                 let res = run_test(
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index fcca112563d..6b0225a1b44 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -2409,6 +2409,8 @@ where
     }
 }
 
+/// Inserts all new key-values from the iterator and replaces values with existing
+/// keys with new values returned from the iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
 where
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 4a1bb75d588..6b9a35fccc4 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -269,8 +269,8 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of
-    /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
+    /// dyn [`Error`] + [`Send`] + [`Sync`].
     ///
     /// [`Error`]: ../error/trait.Error.html
     ///
@@ -313,7 +313,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for Box<dyn Error + Send + Sync> {
-    /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
     /// [`Error`]: ../error/trait.Error.html
     ///
@@ -377,7 +377,7 @@ impl From<String> for Box<dyn Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
     /// [`Error`]: ../error/trait.Error.html
     ///
@@ -420,7 +420,7 @@ impl From<&str> for Box<dyn Error> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
     /// [`Cow`]: ../borrow/enum.Cow.html
     /// [`Error`]: ../error/trait.Error.html
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index d7f4cc5d1fd..483f2ba52ec 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -919,7 +919,7 @@ impl Error for IntoStringError {
         "C string contained non-utf8 bytes"
     }
 
-    fn cause(&self) -> Option<&dyn Error> {
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
         Some(&self.error)
     }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 5ff32d7adaf..af6cb656444 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -277,7 +277,6 @@
 #![feature(log_syntax)]
 #![feature(maybe_uninit_ref)]
 #![feature(maybe_uninit_slice)]
-#![feature(mem_take)]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![feature(nll)]
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 1d4fd98dd75..24c693790e8 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -12,7 +12,9 @@ use crate::ops::{Deref, DerefMut};
 use crate::panicking;
 use crate::ptr::{Unique, NonNull};
 use crate::rc::Rc;
-use crate::sync::{Arc, Mutex, RwLock, atomic};
+use crate::sync::{Arc, Mutex, RwLock};
+#[cfg(not(bootstrap))]
+use crate::sync::atomic;
 use crate::task::{Context, Poll};
 use crate::thread::Result;
 
@@ -240,49 +242,49 @@ impl<T: ?Sized> RefUnwindSafe for Mutex<T> {}
 #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
 impl<T: ?Sized> RefUnwindSafe for RwLock<T> {}
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(target_has_atomic_load_store = "ptr")]
 #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
 impl RefUnwindSafe for atomic::AtomicIsize {}
-#[cfg(target_has_atomic = "8")]
+#[cfg(target_has_atomic_load_store = "8")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicI8 {}
-#[cfg(target_has_atomic = "16")]
+#[cfg(target_has_atomic_load_store = "16")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicI16 {}
-#[cfg(target_has_atomic = "32")]
+#[cfg(target_has_atomic_load_store = "32")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicI32 {}
-#[cfg(target_has_atomic = "64")]
+#[cfg(target_has_atomic_load_store = "64")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicI64 {}
-#[cfg(target_has_atomic = "128")]
+#[cfg(target_has_atomic_load_store = "128")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicI128 {}
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(target_has_atomic_load_store = "ptr")]
 #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
 impl RefUnwindSafe for atomic::AtomicUsize {}
-#[cfg(target_has_atomic = "8")]
+#[cfg(target_hastarget_has_atomic_load_store_atomic = "8")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicU8 {}
-#[cfg(target_has_atomic = "16")]
+#[cfg(target_has_atomic_load_store = "16")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicU16 {}
-#[cfg(target_has_atomic = "32")]
+#[cfg(target_has_atomic_load_store = "32")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicU32 {}
-#[cfg(target_has_atomic = "64")]
+#[cfg(target_has_atomic_load_store = "64")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicU64 {}
-#[cfg(target_has_atomic = "128")]
+#[cfg(target_has_atomic_load_store = "128")]
 #[unstable(feature = "integer_atomics", issue = "32976")]
 impl RefUnwindSafe for atomic::AtomicU128 {}
 
-#[cfg(target_has_atomic = "8")]
+#[cfg(target_has_atomic_load_store = "8")]
 #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
 impl RefUnwindSafe for atomic::AtomicBool {}
 
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(target_has_atomic_load_store = "ptr")]
 #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
 impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
 
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index fd6ff1032bb..ca81044ee85 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1627,7 +1627,7 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Arc<Path> {
-    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
+    /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer.
     #[inline]
     fn from(s: PathBuf) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@@ -1637,7 +1637,7 @@ impl From<PathBuf> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<&Path> for Arc<Path> {
-    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
+    /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer.
     #[inline]
     fn from(s: &Path) -> Arc<Path> {
         let arc: Arc<OsStr> = Arc::from(s.as_os_str());
@@ -1647,7 +1647,7 @@ impl From<&Path> for Arc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Rc<Path> {
-    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
+    /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer.
     #[inline]
     fn from(s: PathBuf) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.into_os_string());
@@ -1657,7 +1657,7 @@ impl From<PathBuf> for Rc<Path> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<&Path> for Rc<Path> {
-    /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
+    /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer.
     #[inline]
     fn from(s: &Path) -> Rc<Path> {
         let rc: Rc<OsStr> = Rc::from(s.as_os_str());
@@ -2219,6 +2219,7 @@ impl Path {
     /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
         self._join(path.as_ref())
     }
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 69ecd201063..c2884a28f3c 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -1581,10 +1581,6 @@ impl<T: Send> error::Error for SendError<T> {
     fn description(&self) -> &str {
         "sending on a closed channel"
     }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        None
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1624,10 +1620,6 @@ impl<T: Send> error::Error for TrySendError<T> {
             }
         }
     }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        None
-    }
 }
 
 #[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
@@ -1652,10 +1644,6 @@ impl error::Error for RecvError {
     fn description(&self) -> &str {
         "receiving on a closed channel"
     }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        None
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1685,10 +1673,6 @@ impl error::Error for TryRecvError {
             }
         }
     }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        None
-    }
 }
 
 #[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
@@ -1726,10 +1710,6 @@ impl error::Error for RecvTimeoutError {
             }
         }
     }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        None
-    }
 }
 
 #[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs
index 51fdb1c0e55..adb08d8005a 100644
--- a/src/libstd/sys/vxworks/fs.rs
+++ b/src/libstd/sys/vxworks/fs.rs
@@ -400,13 +400,27 @@ impl FromInner<c_int> for File {
 
 impl fmt::Debug for File {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fn get_path(_fd: c_int) -> Option<PathBuf> {
-            // FIXME(#:(): implement this for VxWorks
-            None
+        fn get_path(fd: c_int) -> Option<PathBuf> {
+            let mut buf = vec![0;libc::PATH_MAX as usize];
+            let n = unsafe { libc::ioctl(fd, libc::FIOGETNAME, buf.as_ptr()) };
+            if n == -1 {
+                return None;
+            }
+            let l = buf.iter().position(|&c| c == 0).unwrap();
+            buf.truncate(l as usize);
+            Some(PathBuf::from(OsString::from_vec(buf)))
         }
-        fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
-            // FIXME(#:(): implement this for VxWorks
-            None
+        fn get_mode(fd: c_int) -> Option<(bool, bool)> {
+            let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
+            if mode == -1 {
+                return None;
+            }
+            match mode & libc::O_ACCMODE {
+                libc::O_RDONLY => Some((true, false)),
+                libc::O_RDWR => Some((true, true)),
+                libc::O_WRONLY => Some((false, true)),
+                _ => None
+            }
         }
 
         let fd = self.0.raw();
diff --git a/src/libstd/sys/vxworks/rwlock.rs b/src/libstd/sys/vxworks/rwlock.rs
index 718f422ed11..19b123f2b61 100644
--- a/src/libstd/sys/vxworks/rwlock.rs
+++ b/src/libstd/sys/vxworks/rwlock.rs
@@ -25,7 +25,7 @@ impl RWLock {
         let r = libc::pthread_rwlock_rdlock(self.inner.get());
         if r == libc::EAGAIN {
             panic!("rwlock maximum reader count exceeded");
-        } else if r == libc::EDEADLK || *self.write_locked.get() {
+        } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) {
             if r == 0 {
                 self.raw_unlock();
             }
diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs
index d1c50fd8594..0cb5eff1ef2 100644
--- a/src/libsyntax/ext/mbe/macro_parser.rs
+++ b/src/libsyntax/ext/mbe/macro_parser.rs
@@ -76,7 +76,7 @@ use TokenTreeOrTokenTreeSlice::*;
 
 use crate::ast::{Ident, Name};
 use crate::ext::mbe::{self, TokenTree};
-use crate::parse::{Directory, ParseSess};
+use crate::parse::{Directory, ParseSess, PResult};
 use crate::parse::parser::{Parser, PathStyle};
 use crate::parse::token::{self, DocComment, Nonterminal, Token};
 use crate::print::pprust;
@@ -893,26 +893,30 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
     }
     // check at the beginning and the parser checks after each bump
     p.process_potential_macro_variable();
-    match name {
-        sym::item => match panictry!(p.parse_item()) {
+    match parse_nt_inner(p, sp, name) {
+        Ok(nt) => nt,
+        Err(mut err) => {
+            err.emit();
+            FatalError.raise();
+        }
+    }
+}
+
+fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> {
+    Ok(match name {
+        sym::item => match p.parse_item()? {
             Some(i) => token::NtItem(i),
-            None => {
-                p.fatal("expected an item keyword").emit();
-                FatalError.raise();
-            }
+            None => return Err(p.fatal("expected an item keyword")),
         },
-        sym::block => token::NtBlock(panictry!(p.parse_block())),
-        sym::stmt => match panictry!(p.parse_stmt()) {
+        sym::block => token::NtBlock(p.parse_block()?),
+        sym::stmt => match p.parse_stmt()? {
             Some(s) => token::NtStmt(s),
-            None => {
-                p.fatal("expected a statement").emit();
-                FatalError.raise();
-            }
+            None => return Err(p.fatal("expected a statement")),
         },
-        sym::pat => token::NtPat(panictry!(p.parse_pat(None))),
-        sym::expr => token::NtExpr(panictry!(p.parse_expr())),
-        sym::literal => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())),
-        sym::ty => token::NtTy(panictry!(p.parse_ty())),
+        sym::pat => token::NtPat(p.parse_pat(None)?),
+        sym::expr => token::NtExpr(p.parse_expr()?),
+        sym::literal => token::NtLiteral(p.parse_literal_maybe_minus()?),
+        sym::ty => token::NtTy(p.parse_ty()?),
         // this could be handled like a token, since it is one
         sym::ident => if let Some((name, is_raw)) = get_macro_name(&p.token) {
             let span = p.token.span;
@@ -920,21 +924,19 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
             token::NtIdent(Ident::new(name, span), is_raw)
         } else {
             let token_str = pprust::token_to_string(&p.token);
-            p.fatal(&format!("expected ident, found {}", &token_str)).emit();
-            FatalError.raise()
+            return Err(p.fatal(&format!("expected ident, found {}", &token_str)));
         }
-        sym::path => token::NtPath(panictry!(p.parse_path(PathStyle::Type))),
-        sym::meta => token::NtMeta(panictry!(p.parse_attr_item())),
-        sym::vis => token::NtVis(panictry!(p.parse_visibility(true))),
+        sym::path => token::NtPath(p.parse_path(PathStyle::Type)?),
+        sym::meta => token::NtMeta(p.parse_attr_item()?),
+        sym::vis => token::NtVis(p.parse_visibility(true)?),
         sym::lifetime => if p.check_lifetime() {
             token::NtLifetime(p.expect_lifetime().ident)
         } else {
             let token_str = pprust::token_to_string(&p.token);
-            p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit();
-            FatalError.raise();
+            return Err(p.fatal(&format!("expected a lifetime, found `{}`", &token_str)));
         }
         // this is not supposed to happen, since it has been checked
         // when compiling the macro.
         _ => p.span_bug(sp, "invalid fragment specifier"),
-    }
+    })
 }
diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs
index ae23cc5cb93..ab1620b9524 100644
--- a/src/libsyntax/feature_gate/builtin_attrs.rs
+++ b/src/libsyntax/feature_gate/builtin_attrs.rs
@@ -29,6 +29,7 @@ const GATED_CFGS: &[(Symbol, Symbol, GateFn)] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
     (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
     (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
+    (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)),
     (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)),
 ];
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index 9e40b1a26ac..6008f8f3005 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -855,25 +855,19 @@ impl UnstableFeatures {
     pub fn is_nightly_build(&self) -> bool {
         match *self {
             UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
-            _ => false,
+            UnstableFeatures::Disallow => false,
         }
     }
 }
 
 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) {
-    let allow_features = match unstable {
-        UnstableFeatures::Allow => true,
-        UnstableFeatures::Disallow => false,
-        UnstableFeatures::Cheat => true
-    };
-    if !allow_features {
-        for attr in &krate.attrs {
-            if attr.check_name(sym::feature) {
-                let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
-                span_err!(span_handler, attr.span, E0554,
-                          "`#![feature]` may not be used on the {} release channel",
-                          release_channel);
-            }
+    if !unstable.is_nightly_build() {
+        for attr in krate.attrs.iter().filter(|attr| attr.check_name(sym::feature)) {
+            span_err!(
+                span_handler, attr.span, E0554,
+                "`#![feature]` may not be used on the {} release channel",
+                option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
+            );
         }
     }
 }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index d2c76b669dd..09a47795a82 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -12,12 +12,12 @@
 #![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
-#![feature(mem_take)]
 #![feature(nll)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
 #![feature(try_trait)]
+#![feature(slice_patterns)]
 #![feature(unicode_internals)]
 
 #![recursion_limit="256"]
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index f376c19a66c..42cbe28fc17 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -2,7 +2,7 @@ use crate::ast::{
     self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
     Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData,
 };
-use crate::feature_gate::{feature_err, UnstableFeatures};
+use crate::feature_gate::feature_err;
 use crate::parse::{SeqSep, PResult, Parser, ParseSess};
 use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
 use crate::parse::token::{self, TokenKind};
@@ -387,14 +387,17 @@ impl<'a> Parser<'a> {
             let next_pos = sm.lookup_char_pos(self.token.span.lo());
             let op_pos = sm.lookup_char_pos(sp.hi());
 
+            let allow_unstable = self.sess.unstable_features.is_nightly_build();
+
             if likely_path {
                 err.span_suggestion(
                     sp,
                     "maybe write a path separator here",
                     "::".to_string(),
-                    match self.sess.unstable_features {
-                        UnstableFeatures::Disallow => Applicability::MachineApplicable,
-                        _ => Applicability::MaybeIncorrect,
+                    if allow_unstable {
+                        Applicability::MaybeIncorrect
+                    } else {
+                        Applicability::MachineApplicable
                     },
                 );
             } else if op_pos.line != next_pos.line && maybe_expected_semicolon {
@@ -404,14 +407,13 @@ impl<'a> Parser<'a> {
                     ";".to_string(),
                     Applicability::MaybeIncorrect,
                 );
-            } else if let UnstableFeatures::Disallow = self.sess.unstable_features {
-                err.span_label(sp, "tried to parse a type due to this");
-            } else {
+            } else if allow_unstable {
                 err.span_label(sp, "tried to parse a type due to this type ascription");
+            } else {
+                err.span_label(sp, "tried to parse a type due to this");
             }
-            if let UnstableFeatures::Disallow = self.sess.unstable_features {
+            if allow_unstable {
                 // Give extra information about type ascription only if it's a nightly compiler.
-            } else {
                 err.note("`#![feature(type_ascription)]` lets you annotate an expression with a \
                           type: `<expr>: <type>`");
                 err.note("for more information, see \
diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs
index fcd5b2782fd..56a79bfe5d5 100644
--- a/src/libsyntax/parse/literal.rs
+++ b/src/libsyntax/parse/literal.rs
@@ -426,15 +426,12 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
     let symbol = strip_underscores(symbol);
     let s = symbol.as_str();
 
-    let mut base = 10;
-    if s.len() > 1 && s.as_bytes()[0] == b'0' {
-        match s.as_bytes()[1] {
-            b'x' => base = 16,
-            b'o' => base = 8,
-            b'b' => base = 2,
-            _ => {}
-        }
-    }
+    let base = match s.as_bytes() {
+        [b'0', b'x', ..] => 16,
+        [b'0', b'o', ..] => 8,
+        [b'0', b'b', ..] => 2,
+        _ => 10,
+    };
 
     let ty = match suffix {
         Some(suf) => match suf {
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index 7d0d2392945..5e569f9dae3 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -878,25 +878,8 @@ impl SourceMap {
 
     // Returns the index of the `SourceFile` (in `self.files`) that contains `pos`.
     pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
-        let files = self.files.borrow();
-        let files = &files.source_files;
-        let count = files.len();
-
-        // Binary search for the `SourceFile`.
-        let mut a = 0;
-        let mut b = count;
-        while b - a > 1 {
-            let m = (a + b) / 2;
-            if files[m].start_pos > pos {
-                b = m;
-            } else {
-                a = m;
-            }
-        }
-
-        assert!(a < count, "position {} does not resolve to a source location", pos.to_usize());
-
-        return a;
+        self.files.borrow().source_files.binary_search_by_key(&pos, |key| key.start_pos)
+            .unwrap_or_else(|p| p - 1)
     }
 
     pub fn count_lines(&self) -> usize {
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 26cae2a8e7c..bef12ed4fad 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -249,20 +249,47 @@ impl TokenStream {
             0 => TokenStream::empty(),
             1 => streams.pop().unwrap(),
             _ => {
-                // rust-lang/rust#57735: pre-allocate vector to avoid
-                // quadratic blow-up due to on-the-fly reallocations.
-                let tree_count = streams.iter()
-                    .map(|ts| match &ts.0 { None => 0, Some(s) => s.len() })
+                // We are going to extend the first stream in `streams` with
+                // the elements from the subsequent streams. This requires
+                // using `make_mut()` on the first stream, and in practice this
+                // doesn't cause cloning 99.9% of the time.
+                //
+                // One very common use case is when `streams` has two elements,
+                // where the first stream has any number of elements within
+                // (often 1, but sometimes many more) and the second stream has
+                // a single element within.
+
+                // Determine how much the first stream will be extended.
+                // Needed to avoid quadratic blow up from on-the-fly
+                // reallocations (#57735).
+                let num_appends = streams.iter()
+                    .skip(1)
+                    .map(|ts| ts.len())
                     .sum();
-                let mut vec = Vec::with_capacity(tree_count);
 
-                for stream in streams {
-                    match stream.0 {
-                        None => {},
-                        Some(stream2) => vec.extend(stream2.iter().cloned()),
+                // Get the first stream. If it's `None`, create an empty
+                // stream.
+                let mut iter = streams.drain();
+                let mut first_stream_lrc = match iter.next().unwrap().0 {
+                    Some(first_stream_lrc) => first_stream_lrc,
+                    None => Lrc::new(vec![]),
+                };
+
+                // Append the elements to the first stream, after reserving
+                // space for them.
+                let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc);
+                first_vec_mut.reserve(num_appends);
+                for stream in iter {
+                    if let Some(stream) = stream.0 {
+                        first_vec_mut.extend(stream.iter().cloned());
                     }
                 }
-                TokenStream::new(vec)
+
+                // Create the final `TokenStream`.
+                match first_vec_mut.len() {
+                    0 => TokenStream(None),
+                    _ => TokenStream(Some(first_stream_lrc)),
+                }
             }
         }
     }
@@ -363,25 +390,6 @@ impl TokenStream {
                     .collect())
         }))
     }
-
-    fn first_tree_and_joint(&self) -> Option<TreeAndJoint> {
-        self.0.as_ref().map(|stream| {
-            stream.first().unwrap().clone()
-        })
-    }
-
-    fn last_tree_if_joint(&self) -> Option<TokenTree> {
-        match self.0 {
-            None => None,
-            Some(ref stream) => {
-                if let (tree, Joint) = stream.last().unwrap() {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-        }
-    }
 }
 
 // 99.5%+ of the time we have 1 or 2 elements in this vector.
@@ -394,18 +402,49 @@ impl TokenStreamBuilder {
     }
 
     pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
-        let stream = stream.into();
-        let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint);
-        if let Some(TokenTree::Token(last_token)) = last_tree_if_joint {
-            if let Some((TokenTree::Token(token), is_joint)) = stream.first_tree_and_joint() {
-                if let Some(glued_tok) = last_token.glue(&token) {
-                    let last_stream = self.0.pop().unwrap();
-                    self.push_all_but_last_tree(&last_stream);
-                    let glued_tt = TokenTree::Token(glued_tok);
-                    let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]);
-                    self.0.push(glued_tokenstream);
-                    self.push_all_but_first_tree(&stream);
-                    return
+        let mut stream = stream.into();
+
+        // If `self` is not empty and the last tree within the last stream is a
+        // token tree marked with `Joint`...
+        if let Some(TokenStream(Some(ref mut last_stream_lrc))) = self.0.last_mut() {
+            if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() {
+
+                // ...and `stream` is not empty and the first tree within it is
+                // a token tree...
+                if let TokenStream(Some(ref mut stream_lrc)) = stream {
+                    if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() {
+
+                        // ...and the two tokens can be glued together...
+                        if let Some(glued_tok) = last_token.glue(&token) {
+
+                            // ...then do so, by overwriting the last token
+                            // tree in `self` and removing the first token tree
+                            // from `stream`. This requires using `make_mut()`
+                            // on the last stream in `self` and on `stream`,
+                            // and in practice this doesn't cause cloning 99.9%
+                            // of the time.
+
+                            // Overwrite the last token tree with the merged
+                            // token.
+                            let last_vec_mut = Lrc::make_mut(last_stream_lrc);
+                            *last_vec_mut.last_mut().unwrap() =
+                                (TokenTree::Token(glued_tok), *is_joint);
+
+                            // Remove the first token tree from `stream`. (This
+                            // is almost always the only tree in `stream`.)
+                            let stream_vec_mut = Lrc::make_mut(stream_lrc);
+                            stream_vec_mut.remove(0);
+
+                            // Don't push `stream` if it's empty -- that could
+                            // block subsequent token gluing, by getting
+                            // between two token trees that should be glued
+                            // together.
+                            if !stream.is_empty() {
+                                self.0.push(stream);
+                            }
+                            return;
+                        }
+                    }
                 }
             }
         }
@@ -415,26 +454,6 @@ impl TokenStreamBuilder {
     pub fn build(self) -> TokenStream {
         TokenStream::from_streams(self.0)
     }
-
-    fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
-        if let Some(ref streams) = stream.0 {
-            let len = streams.len();
-            match len {
-                1 => {}
-                _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))),
-            }
-        }
-    }
-
-    fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
-        if let Some(ref streams) = stream.0 {
-            let len = streams.len();
-            match len {
-                1 => {}
-                _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))),
-            }
-        }
-    }
 }
 
 #[derive(Clone)]
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 9f75f72e820..abdcb6c8e3d 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -192,7 +192,7 @@ use syntax::util::map_in_place::MapInPlace;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, kw, sym};
 use syntax::parse::ParseSess;
-use syntax_pos::{DUMMY_SP, Span};
+use syntax_pos::{Span};
 
 use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
 
@@ -1022,7 +1022,7 @@ impl<'a> MethodDef<'a> {
                                  // [fields of next Self arg], [etc]>
         let mut patterns = Vec::new();
         for i in 0..self_args.len() {
-            let struct_path = cx.path(DUMMY_SP, vec![type_ident]);
+            let struct_path = cx.path(trait_.span, vec![type_ident]);
             let (pat, ident_expr) = trait_.create_struct_pattern(cx,
                                                                  struct_path,
                                                                  struct_def,
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 631ab7a3310..64d46a84cba 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -5,7 +5,6 @@
 
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
-#![feature(mem_take)]
 #![feature(nll)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index 5d68a92579f..d4638c45473 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -106,6 +106,11 @@ pub fn expand_test_or_bench(
         cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)])
     };
 
+    // creates test::TestType::$name
+    let test_type_path = |name| {
+        cx.path(sp, vec![test_id, cx.ident_of("TestType", sp), cx.ident_of(name, sp)])
+    };
+
     // creates $name: $expr
     let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr);
 
@@ -181,6 +186,17 @@ pub fn expand_test_or_bench(
                             cx.expr_path(should_panic_path("YesWithMessage")),
                             vec![cx.expr_str(sp, sym)]),
                     }),
+                    // test_type: ...
+                    field("test_type", match test_type(cx) {
+                        // test::TestType::UnitTest
+                        TestType::UnitTest => cx.expr_path(test_type_path("UnitTest")),
+                        // test::TestType::IntegrationTest
+                        TestType::IntegrationTest => cx.expr_path(
+                            test_type_path("IntegrationTest")
+                        ),
+                        // test::TestPath::Unknown
+                        TestType::Unknown => cx.expr_path(test_type_path("Unknown")),
+                    }),
                 // },
                 ])),
                 // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...)
@@ -261,6 +277,34 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
     }
 }
 
+enum TestType {
+    UnitTest,
+    IntegrationTest,
+    Unknown,
+}
+
+/// Attempts to determine the type of test.
+/// Since doctests are created without macro expanding, only possible variants here
+/// are `UnitTest`, `IntegrationTest` or `Unknown`.
+fn test_type(cx: &ExtCtxt<'_>) -> TestType {
+    // Root path from context contains the topmost sources directory of the crate.
+    // I.e., for `project` with sources in `src` and tests in `tests` folders
+    // (no matter how many nested folders lie inside),
+    // there will be two different root paths: `/project/src` and `/project/tests`.
+    let crate_path = cx.root_path.as_path();
+
+    if crate_path.ends_with("src") {
+        // `/src` folder contains unit-tests.
+        TestType::UnitTest
+    } else if crate_path.ends_with("tests") {
+        // `/tests` folder contains integration tests.
+        TestType::IntegrationTest
+    } else {
+        // Crate layout doesn't match expected one, test type is unknown.
+        TestType::Unknown
+    }
+}
+
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
     let ref sd = cx.parse_sess.span_diagnostic;
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 2b005c3fc42..c37efde9923 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -658,6 +658,7 @@ symbols! {
         suggestion,
         target_feature,
         target_has_atomic,
+        target_has_atomic_load_store,
         target_thread_local,
         task,
         tbm_target_feature,
diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs
index d9e4abf61c3..dcd733620bf 100644
--- a/src/libtest/formatters/json.rs
+++ b/src/libtest/formatters/json.rs
@@ -94,6 +94,15 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
                 self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None)
             }
 
+            TrTimedFail => self.write_event(
+                "test",
+                desc.name.as_slice(),
+                "failed",
+                exec_time,
+                stdout,
+                Some(r#""reason": "time limit exceeded""#),
+            ),
+
             TrFailedMsg(ref m) => self.write_event(
                 "test",
                 desc.name.as_slice(),
diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs
index 184726c67d3..2935b4c99ce 100644
--- a/src/libtest/formatters/pretty.rs
+++ b/src/libtest/formatters/pretty.rs
@@ -3,6 +3,7 @@ use super::*;
 pub(crate) struct PrettyFormatter<T> {
     out: OutputLocation<T>,
     use_color: bool,
+    time_options: Option<TestTimeOptions>,
 
     /// Number of columns to fill when aligning names
     max_name_len: usize,
@@ -16,12 +17,14 @@ impl<T: Write> PrettyFormatter<T> {
         use_color: bool,
         max_name_len: usize,
         is_multithreaded: bool,
+        time_options: Option<TestTimeOptions>,
     ) -> Self {
         PrettyFormatter {
             out,
             use_color,
             max_name_len,
             is_multithreaded,
+            time_options
         }
     }
 
@@ -30,20 +33,24 @@ impl<T: Write> PrettyFormatter<T> {
         &self.out
     }
 
-    pub fn write_ok(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> {
-        self.write_short_result("ok", term::color::GREEN, exec_time)
+    pub fn write_ok(&mut self) -> io::Result<()> {
+        self.write_short_result("ok", term::color::GREEN)
     }
 
-    pub fn write_failed(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> {
-        self.write_short_result("FAILED", term::color::RED, exec_time)
+    pub fn write_failed(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED", term::color::RED)
     }
 
-    pub fn write_ignored(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> {
-        self.write_short_result("ignored", term::color::YELLOW, exec_time)
+    pub fn write_ignored(&mut self) -> io::Result<()> {
+        self.write_short_result("ignored", term::color::YELLOW)
     }
 
-    pub fn write_allowed_fail(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> {
-        self.write_short_result("FAILED (allowed)", term::color::YELLOW, exec_time)
+    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED (allowed)", term::color::YELLOW)
+    }
+
+    pub fn write_time_failed(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED (time limit exceeded)", term::color::RED)
     }
 
     pub fn write_bench(&mut self) -> io::Result<()> {
@@ -54,13 +61,8 @@ impl<T: Write> PrettyFormatter<T> {
         &mut self,
         result: &str,
         color: term::color::Color,
-        exec_time: Option<&TestExecTime>,
     ) -> io::Result<()> {
-        self.write_pretty(result, color)?;
-        if let Some(exec_time) = exec_time {
-            self.write_plain(format!(" {}", exec_time))?;
-        }
-        self.write_plain("\n")
+        self.write_pretty(result, color)
     }
 
     pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
@@ -88,12 +90,48 @@ impl<T: Write> PrettyFormatter<T> {
         self.out.flush()
     }
 
-    pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> {
-        self.write_plain("\nsuccesses:\n")?;
-        let mut successes = Vec::new();
+    fn write_time(
+        &mut self,
+        desc: &TestDesc,
+        exec_time: Option<&TestExecTime>
+    ) -> io::Result<()> {
+        if let (Some(opts), Some(time)) = (self.time_options, exec_time) {
+            let time_str = format!(" <{}>", time);
+
+            let color = if opts.colored {
+                if opts.is_critical(desc, time) {
+                    Some(term::color::RED)
+                } else if opts.is_warn(desc, time) {
+                    Some(term::color::YELLOW)
+                } else {
+                    None
+                }
+            } else {
+                None
+            };
+
+            match color {
+                Some(color) => self.write_pretty(&time_str, color)?,
+                None => self.write_plain(&time_str)?
+            }
+        }
+
+        Ok(())
+    }
+
+    fn write_results(
+        &mut self,
+        inputs: &Vec<(TestDesc, Vec<u8>)>,
+        results_type: &str
+    ) -> io::Result<()> {
+        let results_out_str = format!("\n{}:\n", results_type);
+
+        self.write_plain(&results_out_str)?;
+
+        let mut results = Vec::new();
         let mut stdouts = String::new();
-        for &(ref f, ref stdout) in &state.not_failures {
-            successes.push(f.name.to_string());
+        for &(ref f, ref stdout) in inputs {
+            results.push(f.name.to_string());
             if !stdout.is_empty() {
                 stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
                 let output = String::from_utf8_lossy(stdout);
@@ -106,38 +144,24 @@ impl<T: Write> PrettyFormatter<T> {
             self.write_plain(&stdouts)?;
         }
 
-        self.write_plain("\nsuccesses:\n")?;
-        successes.sort();
-        for name in &successes {
+        self.write_plain(&results_out_str)?;
+        results.sort();
+        for name in &results {
             self.write_plain(&format!("    {}\n", name))?;
         }
         Ok(())
     }
 
+    pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> {
+        self.write_results(&state.not_failures, "successes")
+    }
+
     pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
-        self.write_plain("\nfailures:\n")?;
-        let mut failures = Vec::new();
-        let mut fail_out = String::new();
-        for &(ref f, ref stdout) in &state.failures {
-            failures.push(f.name.to_string());
-            if !stdout.is_empty() {
-                fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
-                let output = String::from_utf8_lossy(stdout);
-                fail_out.push_str(&output);
-                fail_out.push_str("\n");
-            }
-        }
-        if !fail_out.is_empty() {
-            self.write_plain("\n")?;
-            self.write_plain(&fail_out)?;
-        }
+        self.write_results(&state.failures, "failures")
+    }
 
-        self.write_plain("\nfailures:\n")?;
-        failures.sort();
-        for name in &failures {
-            self.write_plain(&format!("    {}\n", name))?;
-        }
-        Ok(())
+    pub fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
+        self.write_results(&state.time_failures, "failures (time limit exceeded)")
     }
 
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
@@ -179,15 +203,19 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
         }
 
         match *result {
-            TrOk => self.write_ok(exec_time),
-            TrFailed | TrFailedMsg(_) => self.write_failed(exec_time),
-            TrIgnored => self.write_ignored(exec_time),
-            TrAllowedFail => self.write_allowed_fail(exec_time),
+            TrOk => self.write_ok()?,
+            TrFailed | TrFailedMsg(_) => self.write_failed()?,
+            TrIgnored => self.write_ignored()?,
+            TrAllowedFail => self.write_allowed_fail()?,
             TrBench(ref bs) => {
                 self.write_bench()?;
-                self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
+                self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
             }
+            TrTimedFail => self.write_time_failed()?,
         }
+
+        self.write_time(desc, exec_time)?;
+        self.write_plain("\n")
     }
 
     fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
@@ -207,7 +235,13 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
         }
         let success = state.failed == 0;
         if !success {
-            self.write_failures(state)?;
+            if !state.failures.is_empty() {
+                self.write_failures(state)?;
+            }
+
+            if !state.time_failures.is_empty() {
+                self.write_time_failures(state)?;
+            }
         }
 
         self.write_plain("\ntest result: ")?;
diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs
index 1812c20904c..8914e7b6b56 100644
--- a/src/libtest/formatters/terse.rs
+++ b/src/libtest/formatters/terse.rs
@@ -180,7 +180,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
     ) -> io::Result<()> {
         match *result {
             TrOk => self.write_ok(),
-            TrFailed | TrFailedMsg(_) => self.write_failed(),
+            TrFailed | TrFailedMsg(_) | TrTimedFail => self.write_failed(),
             TrIgnored => self.write_ignored(),
             TrAllowedFail => self.write_allowed_fail(),
             TrBench(ref bs) => {
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 8b76080fc68..5a77413b2cb 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -56,6 +56,7 @@ use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo};
 use std::path::PathBuf;
 use std::process;
 use std::process::{ExitStatus, Command, Termination};
+use std::str::FromStr;
 use std::sync::mpsc::{channel, Sender};
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -75,13 +76,54 @@ const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE";
 const TR_OK: i32 = 50;
 const TR_FAILED: i32 = 51;
 
+/// This small module contains constants used by `report-time` option.
+/// Those constants values will be used if corresponding environment variables are not set.
+///
+/// To override values for unit-tests, use a constant `RUST_TEST_TIME_UNIT`,
+/// To override values for integration tests, use a constant `RUST_TEST_TIME_INTEGRATION`,
+/// To override values for doctests, use a constant `RUST_TEST_TIME_DOCTEST`.
+///
+/// Example of the expected format is `RUST_TEST_TIME_xxx=100,200`, where 100 means
+/// warn time, and 200 means critical time.
+pub mod time_constants {
+    use std::time::Duration;
+    use super::TEST_WARN_TIMEOUT_S;
+
+    /// Environment variable for overriding default threshold for unit-tests.
+    pub const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT";
+
+    // Unit tests are supposed to be really quick.
+    pub const UNIT_WARN: Duration = Duration::from_millis(50);
+    pub const UNIT_CRITICAL: Duration = Duration::from_millis(100);
+
+    /// Environment variable for overriding default threshold for unit-tests.
+    pub const INTEGRATION_ENV_NAME: &str = "RUST_TEST_TIME_INTEGRATION";
+
+    // Integration tests may have a lot of work, so they can take longer to execute.
+    pub const INTEGRATION_WARN: Duration = Duration::from_millis(500);
+    pub const INTEGRATION_CRITICAL: Duration = Duration::from_millis(1000);
+
+    /// Environment variable for overriding default threshold for unit-tests.
+    pub const DOCTEST_ENV_NAME: &str = "RUST_TEST_TIME_DOCTEST";
+
+    // Doctests are similar to integration tests, because they can include a lot of
+    // initialization code.
+    pub const DOCTEST_WARN: Duration = INTEGRATION_WARN;
+    pub const DOCTEST_CRITICAL: Duration = INTEGRATION_CRITICAL;
+
+    // Do not suppose anything about unknown tests, base limits on the
+    // `TEST_WARN_TIMEOUT_S` constant.
+    pub const UNKNOWN_WARN: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S);
+    pub const UNKNOWN_CRITICAL: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S * 2);
+}
+
 // to be used by rustc to compile tests in libtest
 pub mod test {
     pub use crate::{
         assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
         Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, RunStrategy,
         ShouldPanic, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName,
-        TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk,
+        TestOpts, TestTimeOptions, TestType, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk,
     };
 }
 
@@ -97,6 +139,21 @@ pub enum Concurrent {
     No,
 }
 
+/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html)
+/// conventions.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum TestType {
+    /// Unit-tests are expected to be in the `src` folder of the crate.
+    UnitTest,
+    /// Integration-style tests are expected to be in the `tests` folder of the crate.
+    IntegrationTest,
+    /// Doctests are created by the `librustdoc` manually, so it's a different type of test.
+    DocTest,
+    /// Tests for the sources that don't follow the project layout convention
+    /// (e.g. tests in raw `main.rs` compiled by calling `rustc --test` directly).
+    Unknown,
+}
+
 // The name of a test. By convention this follows the rules for rust
 // paths; i.e., it should be a series of identifiers separated by double
 // colons. This way if some test runner wants to arrange the tests
@@ -232,6 +289,7 @@ pub struct TestDesc {
     pub ignore: bool,
     pub should_panic: ShouldPanic,
     pub allow_fail: bool,
+    pub test_type: TestType,
 }
 
 #[derive(Debug)]
@@ -403,6 +461,141 @@ pub enum RunIgnored {
     Only,
 }
 
+/// Structure denoting time limits for test execution.
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub struct TimeThreshold {
+    pub warn: Duration,
+    pub critical: Duration,
+}
+
+impl TimeThreshold {
+    /// Creates a new `TimeThreshold` instance with provided durations.
+    pub fn new(warn: Duration, critical: Duration) -> Self {
+        Self {
+            warn,
+            critical,
+        }
+    }
+
+    /// Attempts to create a `TimeThreshold` instance with values obtained
+    /// from the environment variable, and returns `None` if the variable
+    /// is not set.
+    /// Environment variable format is expected to match `\d+,\d+`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if variable with provided name is set but contains inappropriate
+    /// value.
+    pub fn from_env_var(env_var_name: &str) -> Option<Self> {
+        let durations_str = env::var(env_var_name).ok()?;
+
+        // Split string into 2 substrings by comma and try to parse numbers.
+        let mut durations = durations_str
+            .splitn(2, ',')
+            .map(|v| {
+                u64::from_str(v).unwrap_or_else(|_| {
+                    panic!(
+                        "Duration value in variable {} is expected to be a number, but got {}",
+                        env_var_name, v
+                    )
+                })
+            });
+
+        // Callback to be called if the environment variable has unexpected structure.
+        let panic_on_incorrect_value = || {
+            panic!(
+                "Duration variable {} expected to have 2 numbers separated by comma, but got {}",
+                env_var_name, durations_str
+            );
+        };
+
+        let (warn, critical) = (
+            durations.next().unwrap_or_else(panic_on_incorrect_value),
+            durations.next().unwrap_or_else(panic_on_incorrect_value)
+        );
+
+        if warn > critical {
+            panic!("Test execution warn time should be less or equal to the critical time");
+        }
+
+        Some(Self::new(Duration::from_millis(warn), Duration::from_millis(critical)))
+    }
+}
+
+/// Structure with parameters for calculating test execution time.
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub struct TestTimeOptions {
+    /// Denotes if the test critical execution time limit excess should be considered
+    /// a test failure.
+    pub error_on_excess: bool,
+    pub colored: bool,
+    pub unit_threshold: TimeThreshold,
+    pub integration_threshold: TimeThreshold,
+    pub doctest_threshold: TimeThreshold,
+}
+
+impl TestTimeOptions {
+    pub fn new_from_env(error_on_excess: bool, colored: bool) -> Self {
+        let unit_threshold =
+            TimeThreshold::from_env_var(time_constants::UNIT_ENV_NAME)
+                .unwrap_or_else(Self::default_unit);
+
+        let integration_threshold =
+            TimeThreshold::from_env_var(time_constants::INTEGRATION_ENV_NAME)
+                .unwrap_or_else(Self::default_integration);
+
+        let doctest_threshold =
+            TimeThreshold::from_env_var(time_constants::DOCTEST_ENV_NAME)
+                .unwrap_or_else(Self::default_doctest);
+
+        Self {
+            error_on_excess,
+            colored,
+            unit_threshold,
+            integration_threshold,
+            doctest_threshold,
+        }
+    }
+
+    pub fn is_warn(&self, test: &TestDesc, exec_time: &TestExecTime) -> bool {
+        exec_time.0 >= self.warn_time(test)
+    }
+
+    pub fn is_critical(&self, test: &TestDesc, exec_time: &TestExecTime) -> bool {
+        exec_time.0 >= self.critical_time(test)
+    }
+
+    fn warn_time(&self, test: &TestDesc) -> Duration {
+        match test.test_type {
+            TestType::UnitTest => self.unit_threshold.warn,
+            TestType::IntegrationTest => self.integration_threshold.warn,
+            TestType::DocTest => self.doctest_threshold.warn,
+            TestType::Unknown => time_constants::UNKNOWN_WARN,
+        }
+    }
+
+    fn critical_time(&self, test: &TestDesc) -> Duration {
+        match test.test_type {
+            TestType::UnitTest => self.unit_threshold.critical,
+            TestType::IntegrationTest => self.integration_threshold.critical,
+            TestType::DocTest => self.doctest_threshold.critical,
+            TestType::Unknown => time_constants::UNKNOWN_CRITICAL,
+        }
+    }
+
+    fn default_unit() -> TimeThreshold {
+        TimeThreshold::new(time_constants::UNIT_WARN, time_constants::UNIT_CRITICAL)
+    }
+
+    fn default_integration() -> TimeThreshold {
+        TimeThreshold::new(time_constants::INTEGRATION_WARN, time_constants::INTEGRATION_CRITICAL)
+    }
+
+    fn default_doctest() -> TimeThreshold {
+        TimeThreshold::new(time_constants::DOCTEST_WARN, time_constants::DOCTEST_CRITICAL)
+    }
+}
+
 #[derive(Debug)]
 pub struct TestOpts {
     pub list: bool,
@@ -418,12 +611,14 @@ pub struct TestOpts {
     pub format: OutputFormat,
     pub test_threads: Option<usize>,
     pub skip: Vec<String>,
-    pub report_time: bool,
+    pub time_options: Option<TestTimeOptions>,
     pub options: Options,
 }
 
 /// Result of parsing the options.
 pub type OptRes = Result<TestOpts, String>;
+/// Result of parsing the option part.
+type OptPartRes<T> = Result<Option<T>, String>;
 
 fn optgroups() -> getopts::Options {
     let mut opts = getopts::Options::new();
@@ -502,10 +697,35 @@ fn optgroups() -> getopts::Options {
             unstable-options = Allow use of experimental features",
             "unstable-options",
         )
-        .optflag(
+        .optflagopt(
             "",
             "report-time",
-            "Show execution time of each test. Not available for --format=terse"
+            "Show execution time of each test. Awailable values:
+            plain   = do not colorize the execution time (default);
+            colored = colorize output according to the `color` parameter value;
+
+            Threshold values for colorized output can be configured via
+            `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and
+            `RUST_TEST_TIME_DOCTEST` environment variables.
+
+            Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+
+            Not available for --format=terse",
+            "plain|colored"
+        )
+        .optflag(
+            "",
+            "ensure-time",
+            "Treat excess of the test execution time limit as error.
+
+            Threshold values for this option can be configured via
+            `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and
+            `RUST_TEST_TIME_DOCTEST` environment variables.
+
+            Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+
+            `CRITICAL_TIME` here means the limit that should not be exceeded by test.
+            "
         );
     return opts;
 }
@@ -554,6 +774,45 @@ fn is_nightly() -> bool {
     bootstrap || !disable_unstable_features
 }
 
+// Gets the option value and checks if unstable features are enabled.
+macro_rules! unstable_optflag {
+    ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{
+        let opt = $matches.opt_present($option_name);
+        if !$allow_unstable && opt {
+            return Some(Err(format!(
+                "The \"{}\" flag is only accepted on the nightly compiler",
+                $option_name
+            )));
+        }
+
+        opt
+    }};
+}
+
+// Gets the CLI options assotiated with `report-time` feature.
+fn get_time_options(
+    matches: &getopts::Matches,
+    allow_unstable: bool)
+-> Option<OptPartRes<TestTimeOptions>> {
+    let report_time = unstable_optflag!(matches, allow_unstable, "report-time");
+    let colored_opt_str = matches.opt_str("report-time");
+    let mut report_time_colored = report_time && colored_opt_str == Some("colored".into());
+    let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-time");
+
+    // If `ensure-test-time` option is provided, time output is enforced,
+    // so user won't be confused if any of tests will silently fail.
+    let options = if report_time || ensure_test_time {
+        if ensure_test_time && !report_time {
+            report_time_colored = true;
+        }
+        Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored))
+    } else {
+        None
+    };
+
+    Some(Ok(options))
+}
+
 // Parses command line arguments into test options
 pub fn parse_opts(args: &[String]) -> Option<OptRes> {
     let mut allow_unstable = false;
@@ -592,26 +851,9 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         None
     };
 
-    let exclude_should_panic = matches.opt_present("exclude-should-panic");
-    if !allow_unstable && exclude_should_panic {
-        return Some(Err(
-            "The \"exclude-should-panic\" flag is only accepted on the nightly compiler".into(),
-        ));
-    }
+    let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic");
 
-    let include_ignored = matches.opt_present("include-ignored");
-    if !allow_unstable && include_ignored {
-        return Some(Err(
-            "The \"include-ignored\" flag is only accepted on the nightly compiler".into(),
-        ));
-    }
-
-    let report_time = matches.opt_present("report-time");
-    if !allow_unstable && report_time {
-        return Some(Err(
-            "The \"report-time\" flag is only accepted on the nightly compiler".into(),
-        ));
-    }
+    let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored");
 
     let run_ignored = match (include_ignored, matches.opt_present("ignored")) {
         (true, true) => {
@@ -641,6 +883,12 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         };
     }
 
+    let time_options = match get_time_options(&matches, allow_unstable) {
+        Some(Ok(val)) => val,
+        Some(Err(e)) => return Some(Err(e)),
+        None => panic!("Unexpected output from `get_time_options`"),
+    };
+
     let test_threads = match matches.opt_str("test-threads") {
         Some(n_str) => match n_str.parse::<usize>() {
             Ok(0) => return Some(Err("argument for --test-threads must not be 0".to_string())),
@@ -706,20 +954,20 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         format,
         test_threads,
         skip: matches.opt_strs("skip"),
-        report_time,
+        time_options,
         options: Options::new().display_output(matches.opt_present("show-output")),
     };
 
     Some(Ok(test_opts))
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct BenchSamples {
     ns_iter_summ: stats::Summary,
     mb_s: usize,
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub enum TestResult {
     TrOk,
     TrFailed,
@@ -727,6 +975,7 @@ pub enum TestResult {
     TrIgnored,
     TrAllowedFail,
     TrBench(BenchSamples),
+    TrTimedFail,
 }
 
 unsafe impl Send for TestResult {}
@@ -774,6 +1023,7 @@ struct ConsoleTestState {
     metrics: MetricMap,
     failures: Vec<(TestDesc, Vec<u8>)>,
     not_failures: Vec<(TestDesc, Vec<u8>)>,
+    time_failures: Vec<(TestDesc, Vec<u8>)>,
     options: Options,
 }
 
@@ -796,6 +1046,7 @@ impl ConsoleTestState {
             metrics: MetricMap::new(),
             failures: Vec::new(),
             not_failures: Vec::new(),
+            time_failures: Vec::new(),
             options: opts.options,
         })
     }
@@ -831,11 +1082,12 @@ impl ConsoleTestState {
                 TrIgnored => "ignored".to_owned(),
                 TrAllowedFail => "failed (allowed)".to_owned(),
                 TrBench(ref bs) => fmt_bench_samples(bs),
+                TrTimedFail => "failed (time limit exceeded)".to_owned(),
             },
             test.name,
         ))?;
         if let Some(exec_time) = exec_time {
-            self.write_log(|| format!(" {}", exec_time))?;
+            self.write_log(|| format!(" <{}>", exec_time))?;
         }
         self.write_log(|| "\n")
     }
@@ -993,6 +1245,10 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
                         stdout.extend_from_slice(format!("note: {}", msg).as_bytes());
                         st.failures.push((test, stdout));
                     }
+                    TrTimedFail => {
+                        st.failed += 1;
+                        st.time_failures.push((test, stdout));
+                    }
                 }
                 Ok(())
             }
@@ -1018,6 +1274,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
             use_color(opts),
             max_name_len,
             is_multithreaded,
+            opts.time_options,
         )),
         OutputFormat::Terse => Box::new(TerseFormatter::new(
             output,
@@ -1487,22 +1744,35 @@ pub fn run_test(
         return;
     }
 
+    struct TestRunOpts {
+        pub strategy: RunStrategy,
+        pub nocapture: bool,
+        pub concurrency: Concurrent,
+        pub time: Option<TestTimeOptions>,
+    }
+
     fn run_test_inner(
         desc: TestDesc,
-        nocapture: bool,
-        report_time: bool,
-        strategy: RunStrategy,
         monitor_ch: Sender<MonitorMsg>,
         testfn: Box<dyn FnOnce() + Send>,
-        concurrency: Concurrent,
+        opts: TestRunOpts,
     ) {
+        let concurrency = opts.concurrency;
         let name = desc.name.clone();
 
         let runtest = move || {
-            match strategy {
+            match opts.strategy {
                 RunStrategy::InProcess =>
-                    run_test_in_process(desc, nocapture, report_time, testfn, monitor_ch),
-                RunStrategy::SpawnPrimary => spawn_test_subprocess(desc, report_time, monitor_ch),
+                    run_test_in_process(
+                        desc,
+                        opts.nocapture,
+                        opts.time.is_some(),
+                        testfn,
+                        monitor_ch,
+                        opts.time
+                    ),
+                RunStrategy::SpawnPrimary =>
+                    spawn_test_subprocess(desc, opts.time.is_some(), monitor_ch, opts.time),
             }
         };
 
@@ -1518,6 +1788,13 @@ pub fn run_test(
         }
     }
 
+    let test_run_opts = TestRunOpts {
+        strategy,
+        nocapture: opts.nocapture,
+        concurrency,
+        time: opts.time_options
+    };
+
     match testfn {
         DynBenchFn(bencher) => {
             // Benchmarks aren't expected to panic, so we run them all in-process.
@@ -1538,22 +1815,16 @@ pub fn run_test(
             };
             run_test_inner(
                 desc,
-                opts.nocapture,
-                opts.report_time,
-                strategy,
                 monitor_ch,
                 Box::new(move || __rust_begin_short_backtrace(f)),
-                concurrency
+                test_run_opts,
             );
         }
         StaticTestFn(f) => run_test_inner(
             desc,
-            opts.nocapture,
-            opts.report_time,
-            strategy,
             monitor_ch,
             Box::new(move || __rust_begin_short_backtrace(f)),
-            concurrency,
+            test_run_opts,
         ),
     }
 }
@@ -1564,10 +1835,13 @@ fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
     f()
 }
 
-fn calc_result<'a>(desc: &TestDesc,
-                   task_result: Result<(), &'a (dyn Any + 'static + Send)>)
--> TestResult {
-    match (&desc.should_panic, task_result) {
+fn calc_result<'a>(
+    desc: &TestDesc,
+    task_result: Result<(), &'a (dyn Any + 'static + Send)>,
+    time_opts: &Option<TestTimeOptions>,
+    exec_time: &Option<TestExecTime>
+) -> TestResult {
+    let result = match (&desc.should_panic, task_result) {
         (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk,
         (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
             if err
@@ -1589,23 +1863,59 @@ fn calc_result<'a>(desc: &TestDesc,
         (&ShouldPanic::Yes, Ok(())) => TrFailedMsg("test did not panic as expected".to_string()),
         _ if desc.allow_fail => TrAllowedFail,
         _ => TrFailed,
+    };
+
+    // If test is already failed (or allowed to fail), do not change the result.
+    if result != TrOk {
+        return result;
     }
+
+    // Check if test is failed due to timeout.
+    if let (Some(opts), Some(time)) = (time_opts, exec_time) {
+        if opts.error_on_excess && opts.is_critical(desc, time) {
+            return TrTimedFail;
+        }
+    }
+
+    result
 }
 
-fn get_result_from_exit_code(desc: &TestDesc, code: i32) -> TestResult {
-    match (desc.allow_fail, code) {
+fn get_result_from_exit_code(
+    desc: &TestDesc,
+    code: i32,
+    time_opts: &Option<TestTimeOptions>,
+    exec_time: &Option<TestExecTime>,
+) -> TestResult {
+    let result = match (desc.allow_fail, code) {
         (_, TR_OK) => TrOk,
         (true, TR_FAILED) => TrAllowedFail,
         (false, TR_FAILED) => TrFailed,
         (_, _) => TrFailedMsg(format!("got unexpected return code {}", code)),
+    };
+
+    // If test is already failed (or allowed to fail), do not change the result.
+    if result != TrOk {
+        return result;
     }
+
+    // Check if test is failed due to timeout.
+    if let (Some(opts), Some(time)) = (time_opts, exec_time) {
+        if opts.error_on_excess && opts.is_critical(desc, time) {
+            return TrTimedFail;
+        }
+    }
+
+    result
 }
 
-fn run_test_in_process(desc: TestDesc,
-                       nocapture: bool,
-                       report_time: bool,
-                       testfn: Box<dyn FnOnce() + Send>,
-                       monitor_ch: Sender<MonitorMsg>) {
+fn run_test_in_process(
+    desc: TestDesc,
+    nocapture: bool,
+    report_time: bool,
+    testfn: Box<dyn FnOnce() + Send>,
+    monitor_ch: Sender<MonitorMsg>,
+    time_opts: Option<TestTimeOptions>,
+) {
     // Buffer for capturing standard I/O
     let data = Arc::new(Mutex::new(Vec::new()));
 
@@ -1635,14 +1945,19 @@ fn run_test_in_process(desc: TestDesc,
     }
 
     let test_result = match result {
-        Ok(()) => calc_result(&desc, Ok(())),
-        Err(e) => calc_result(&desc, Err(e.as_ref())),
+        Ok(()) => calc_result(&desc, Ok(()), &time_opts, &exec_time),
+        Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time),
     };
     let stdout = data.lock().unwrap().to_vec();
     monitor_ch.send((desc.clone(), test_result, exec_time, stdout)).unwrap();
 }
 
-fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender<MonitorMsg>) {
+fn spawn_test_subprocess(
+    desc: TestDesc,
+    report_time: bool,
+    monitor_ch: Sender<MonitorMsg>,
+    time_opts: Option<TestTimeOptions>,
+) {
     let (result, test_output, exec_time) = (|| {
         let args = env::args().collect::<Vec<_>>();
         let current_exe = &args[0];
@@ -1673,7 +1988,7 @@ fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender<M
 
         let result = match (|| -> Result<TestResult, String> {
             let exit_code = get_exit_code(status)?;
-            Ok(get_result_from_exit_code(&desc, exit_code))
+            Ok(get_result_from_exit_code(&desc, exit_code, &time_opts, &exec_time))
         })() {
             Ok(r) => r,
             Err(e) => {
@@ -1688,12 +2003,15 @@ fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender<M
     monitor_ch.send((desc.clone(), result, exec_time, test_output)).unwrap();
 }
 
-fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box<dyn FnOnce() + Send>) -> ! {
+fn run_test_in_spawned_subprocess(
+    desc: TestDesc,
+    testfn: Box<dyn FnOnce() + Send>,
+) -> ! {
     let builtin_panic_hook = panic::take_hook();
     let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
         let test_result = match panic_info {
-            Some(info) => calc_result(&desc, Err(info.payload())),
-            None => calc_result(&desc, Ok(())),
+            Some(info) => calc_result(&desc, Err(info.payload()), &None, &None),
+            None => calc_result(&desc, Ok(()), &None, &None),
         };
 
         // We don't support serializing TrFailedMsg, so just
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
index 6577ec8ad23..aab8d012fdf 100644
--- a/src/libtest/stats.rs
+++ b/src/libtest/stats.rs
@@ -115,7 +115,7 @@ pub trait Stats {
 }
 
 /// Extracted collection of all the summary statistics of a sample set.
-#[derive(Clone, PartialEq, Copy)]
+#[derive(Debug, Clone, PartialEq, Copy)]
 #[allow(missing_docs)]
 pub struct Summary {
     pub sum: f64,
diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs
index b95fb5df710..880d02a28ff 100644
--- a/src/libtest/tests.rs
+++ b/src/libtest/tests.rs
@@ -2,10 +2,11 @@ use super::*;
 
 use crate::test::{
     filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy,
-    ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailedMsg,
-    TrIgnored, TrOk,
+    ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions,
+    TestType, TrFailedMsg, TrIgnored, TrOk,
 };
 use std::sync::mpsc::channel;
+use std::time::Duration;
 
 impl TestOpts {
     fn new() -> TestOpts {
@@ -23,7 +24,7 @@ impl TestOpts {
             format: OutputFormat::Pretty,
             test_threads: None,
             skip: vec![],
-            report_time: false,
+            time_options: None,
             options: Options::new(),
         }
     }
@@ -37,6 +38,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: true,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
+                test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(move || {})),
         },
@@ -46,6 +48,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: false,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
+                test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(move || {})),
         },
@@ -63,6 +66,7 @@ pub fn do_not_run_ignored_tests() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -81,6 +85,7 @@ pub fn ignored_tests_result_in_ignored() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -101,6 +106,7 @@ fn test_should_panic() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -121,6 +127,7 @@ fn test_should_panic_good_message() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage("error message"),
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -143,6 +150,7 @@ fn test_should_panic_bad_message() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -161,6 +169,7 @@ fn test_should_panic_but_succeeds() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -178,11 +187,18 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
     };
+    let time_options = if report_time {
+        Some(TestTimeOptions::default())
+    } else {
+        None
+    };
+
     let test_opts = TestOpts {
-        report_time,
+        time_options,
         ..TestOpts::new()
     };
     let (tx, rx) = channel();
@@ -203,6 +219,97 @@ fn test_should_report_time() {
     assert!(exec_time.is_some());
 }
 
+fn time_test_failure_template(test_type: TestType) -> TestResult {
+    fn f() {}
+    let desc = TestDescAndFn {
+        desc: TestDesc {
+            name: StaticTestName("whatever"),
+            ignore: false,
+            should_panic: ShouldPanic::No,
+            allow_fail: false,
+            test_type
+        },
+        testfn: DynTestFn(Box::new(f)),
+    };
+    // `Default` will initialize all the thresholds to 0 milliseconds.
+    let mut time_options = TestTimeOptions::default();
+    time_options.error_on_excess = true;
+
+    let test_opts = TestOpts {
+        time_options: Some(time_options),
+        ..TestOpts::new()
+    };
+    let (tx, rx) = channel();
+    run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No);
+    let (_, result, _, _) = rx.recv().unwrap();
+
+    result
+}
+
+#[test]
+fn test_error_on_exceed() {
+    let types = [TestType::UnitTest, TestType::IntegrationTest, TestType::DocTest];
+
+    for test_type in types.into_iter() {
+        let result = time_test_failure_template(*test_type);
+
+        assert_eq!(result, TestResult::TrTimedFail);
+    }
+
+    // Check that for unknown tests thresholds aren't applied.
+    let result = time_test_failure_template(TestType::Unknown);
+    assert_eq!(result, TestResult::TrOk);
+}
+
+fn typed_test_desc(test_type: TestType) -> TestDesc {
+    TestDesc {
+        name: StaticTestName("whatever"),
+        ignore: false,
+        should_panic: ShouldPanic::No,
+        allow_fail: false,
+        test_type
+    }
+}
+
+fn test_exec_time(millis: u64) -> TestExecTime {
+    TestExecTime(Duration::from_millis(millis))
+}
+
+#[test]
+fn test_time_options_threshold() {
+    let unit = TimeThreshold::new(Duration::from_millis(50), Duration::from_millis(100));
+    let integration = TimeThreshold::new(Duration::from_millis(500), Duration::from_millis(1000));
+    let doc = TimeThreshold::new(Duration::from_millis(5000), Duration::from_millis(10000));
+
+    let options = TestTimeOptions {
+        error_on_excess: false,
+        colored: false,
+        unit_threshold: unit.clone(),
+        integration_threshold: integration.clone(),
+        doctest_threshold: doc.clone(),
+    };
+
+    let test_vector = [
+        (TestType::UnitTest, unit.warn.as_millis() - 1, false, false),
+        (TestType::UnitTest, unit.warn.as_millis(), true, false),
+        (TestType::UnitTest, unit.critical.as_millis(), true, true),
+        (TestType::IntegrationTest, integration.warn.as_millis() - 1, false, false),
+        (TestType::IntegrationTest, integration.warn.as_millis(), true, false),
+        (TestType::IntegrationTest, integration.critical.as_millis(), true, true),
+        (TestType::DocTest, doc.warn.as_millis() - 1, false, false),
+        (TestType::DocTest, doc.warn.as_millis(), true, false),
+        (TestType::DocTest, doc.critical.as_millis(), true, true),
+    ];
+
+    for (test_type, time, expected_warn, expected_critical) in test_vector.into_iter() {
+        let test_desc = typed_test_desc(*test_type);
+        let exec_time = test_exec_time(*time as u64);
+
+        assert_eq!(options.is_warn(&test_desc, &exec_time), *expected_warn);
+        assert_eq!(options.is_critical(&test_desc, &exec_time), *expected_critical);
+    }
+}
+
 #[test]
 fn parse_ignored_flag() {
     let args = vec![
@@ -284,6 +391,7 @@ pub fn exclude_should_panic_option() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(move || {})),
     });
@@ -305,6 +413,7 @@ pub fn exact_filter_match() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
+                    test_type: TestType::Unknown,
                 },
                 testfn: DynTestFn(Box::new(move || {})),
             })
@@ -416,6 +525,7 @@ pub fn sort_tests() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
+                    test_type: TestType::Unknown,
                 },
                 testfn: DynTestFn(Box::new(testfn)),
             };
@@ -492,6 +602,7 @@ pub fn test_bench_no_iter() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        test_type: TestType::Unknown,
     };
 
     crate::bench::benchmark(desc, tx, true, f);
@@ -511,6 +622,7 @@ pub fn test_bench_iter() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        test_type: TestType::Unknown,
     };
 
     crate::bench::benchmark(desc, tx, true, f);
@@ -524,6 +636,7 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        test_type: TestType::Unknown,
     };
 
     let test_b = TestDesc {
@@ -531,9 +644,10 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        test_type: TestType::Unknown,
     };
 
-    let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false);
+    let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false, None);
 
     let st = ConsoleTestState {
         log_out: None,
@@ -548,6 +662,7 @@ fn should_sort_failures_before_printing_them() {
         failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
         options: Options::new(),
         not_failures: Vec::new(),
+        time_failures: Vec::new(),
     };
 
     out.write_failures(&st).unwrap();
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 8473db5f2af9dc36aaf6f9b053fcc2e0e6ac802
+Subproject 14a3b123074e066d64a99886941473058e52197
diff --git a/src/test/codegen/extern-functions.rs b/src/test/codegen/extern-functions.rs
deleted file mode 100644
index a935d886522..00000000000
--- a/src/test/codegen/extern-functions.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-
-#![crate_type = "lib"]
-#![feature(unwind_attributes)]
-
-extern {
-// CHECK: Function Attrs: nounwind
-// CHECK-NEXT: declare void @extern_fn
-    fn extern_fn();
-// CHECK-NOT: Function Attrs: nounwind
-// CHECK: declare void @unwinding_extern_fn
-    #[unwind(allowed)]
-    fn unwinding_extern_fn();
-}
-
-pub unsafe fn force_declare() {
-    extern_fn();
-    unwinding_extern_fn();
-}
diff --git a/src/test/codegen/non-terminate/infinite-loop-1.rs b/src/test/codegen/non-terminate/infinite-loop-1.rs
new file mode 100644
index 00000000000..56b360e0a7f
--- /dev/null
+++ b/src/test/codegen/non-terminate/infinite-loop-1.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C opt-level=3 -Z insert-sideeffect
+
+#![crate_type = "lib"]
+
+fn infinite_loop() -> u8 {
+    loop {}
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+fn test() -> u8 {
+    // CHECK-NOT: unreachable
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: unreachable
+    let x = infinite_loop();
+    x
+}
diff --git a/src/test/codegen/non-terminate/infinite-loop-2.rs b/src/test/codegen/non-terminate/infinite-loop-2.rs
new file mode 100644
index 00000000000..2921ab6dc04
--- /dev/null
+++ b/src/test/codegen/non-terminate/infinite-loop-2.rs
@@ -0,0 +1,19 @@
+// compile-flags: -C opt-level=3 -Z insert-sideeffect
+
+#![crate_type = "lib"]
+
+fn infinite_loop() -> u8 {
+    let i = 2;
+    while i > 1 {}
+    1
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+fn test() -> u8 {
+    // CHECK-NOT: unreachable
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: unreachable
+    let x = infinite_loop();
+    x
+}
diff --git a/src/test/codegen/non-terminate/infinite-recursion.rs b/src/test/codegen/non-terminate/infinite-recursion.rs
new file mode 100644
index 00000000000..1f292ce379f
--- /dev/null
+++ b/src/test/codegen/non-terminate/infinite-recursion.rs
@@ -0,0 +1,14 @@
+// compile-flags: -C opt-level=3 -Z insert-sideeffect
+
+#![crate_type = "lib"]
+
+#![allow(unconditional_recursion)]
+
+// CHECK-LABEL: @infinite_recursion
+#[no_mangle]
+fn infinite_recursion() -> u8 {
+    // CHECK-NOT: ret i8 undef
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: ret i8 undef
+    infinite_recursion()
+}
diff --git a/src/test/codegen/nounwind-extern.rs b/src/test/codegen/nounwind-extern.rs
deleted file mode 100644
index 54d6a8d2794..00000000000
--- a/src/test/codegen/nounwind-extern.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags: -O
-
-#![crate_type = "lib"]
-
-// CHECK: Function Attrs: norecurse nounwind
-pub extern fn foo() {}
diff --git a/src/test/codegen/unwind-extern-exports.rs b/src/test/codegen/unwind-extern-exports.rs
new file mode 100644
index 00000000000..ddb3a4f6b4d
--- /dev/null
+++ b/src/test/codegen/unwind-extern-exports.rs
@@ -0,0 +1,19 @@
+// compile-flags: -C opt-level=0
+
+#![crate_type = "lib"]
+#![feature(unwind_attributes)]
+
+// Make sure these all do *not* get the attribute.
+// We disable optimizations to prevent LLVM from infering the attribute.
+// CHECK-NOT: nounwind
+
+// "C" ABI
+// pub extern fn foo() {} // FIXME right now we don't abort-on-panic but add `nounwind` nevertheless
+#[unwind(allowed)]
+pub extern fn foo_allowed() {}
+
+// "Rust"
+// (`extern "Rust"` could be removed as all `fn` get it implicitly; we leave it in for clarity.)
+pub extern "Rust" fn bar() {}
+#[unwind(allowed)]
+pub extern "Rust" fn bar_allowed() {}
diff --git a/src/test/codegen/unwind-extern-imports.rs b/src/test/codegen/unwind-extern-imports.rs
new file mode 100644
index 00000000000..485e8bbcd42
--- /dev/null
+++ b/src/test/codegen/unwind-extern-imports.rs
@@ -0,0 +1,41 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(unwind_attributes)]
+
+extern {
+// CHECK: Function Attrs:{{.*}}nounwind
+// CHECK-NEXT: declare void @extern_fn
+    fn extern_fn();
+// CHECK-NOT: Function Attrs:{{.*}}nounwind
+// CHECK: declare void @unwinding_extern_fn
+    #[unwind(allowed)]
+    fn unwinding_extern_fn();
+// CHECK-NOT: nounwind
+// CHECK: declare void @aborting_extern_fn
+    #[unwind(aborts)]
+    fn aborting_extern_fn(); // FIXME: we want to have the attribute here
+}
+
+extern "Rust" {
+// CHECK-NOT: nounwind
+// CHECK: declare void @rust_extern_fn
+    fn rust_extern_fn();
+// CHECK-NOT: nounwind
+// CHECK: declare void @rust_unwinding_extern_fn
+    #[unwind(allowed)]
+    fn rust_unwinding_extern_fn();
+// CHECK-NOT: nounwind
+// CHECK: declare void @rust_aborting_extern_fn
+    #[unwind(aborts)]
+    fn rust_aborting_extern_fn(); // FIXME: we want to have the attribute here
+}
+
+pub unsafe fn force_declare() {
+    extern_fn();
+    unwinding_extern_fn();
+    aborting_extern_fn();
+    rust_extern_fn();
+    rust_unwinding_extern_fn();
+    rust_aborting_extern_fn();
+}
diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index 76098731947..8dc6b73edf6 100644
--- a/src/test/mir-opt/box_expr.rs
+++ b/src/test/mir-opt/box_expr.rs
@@ -41,36 +41,33 @@ impl Drop for S {
 //
 //     bb2: {
 //         _1 = move _2;
-//         drop(_2) -> [return: bb5, unwind: bb4];
+//         drop(_2) -> bb4;
 //     }
 //
 //     bb3 (cleanup): {
 //         drop(_2) -> bb1;
 //     }
 //
-//     bb4 (cleanup): {
-//         drop(_1) -> bb1;
-//     }
-//
-//     bb5: {
+//     bb4: {
 //         StorageDead(_2);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         _4 = move _1;
-//         _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb6, unwind: bb7];
+//         _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
 //     }
 //
-//     bb6: {
+//     bb5: {
 //         StorageDead(_4);
 //         StorageDead(_3);
 //         _0 = ();
 //         drop(_1) -> bb8;
 //     }
-//
+//     bb6 (cleanup): {
+//         drop(_1) -> bb1;
+//     }
 //     bb7 (cleanup): {
-//         drop(_4) -> bb4;
+//         drop(_4) -> bb6;
 //     }
-//
 //     bb8: {
 //         StorageDead(_1);
 //         return;
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
index e9b61690cf8..ad7f195676a 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
@@ -16,7 +16,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(AllocId(0).0x0) : fn();
+//      _3 = const main;
 //      _2 = move _3 as usize (Misc);
 //      ...
 //      _1 = move _2 as *const fn() (Misc);
diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue-62289.rs
index e8dd56cbbae..a3b517e9bca 100644
--- a/src/test/mir-opt/issue-62289.rs
+++ b/src/test/mir-opt/issue-62289.rs
@@ -24,7 +24,7 @@ fn main() {
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         _4 = std::option::Option::<u32>::None;
-//         _3 = const <std::option::Option<u32> as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb4];
+//         _3 = const <std::option::Option<u32> as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3];
 //     }
 //     bb1 (cleanup): {
 //         resume;
@@ -32,63 +32,60 @@ fn main() {
 //     bb2: {
 //         StorageDead(_4);
 //         _5 = discriminant(_3);
-//         switchInt(move _5) -> [0isize: bb11, 1isize: bb6, otherwise: bb5];
+//         switchInt(move _5) -> [0isize: bb10, 1isize: bb5, otherwise: bb4];
 //     }
 //     bb3 (cleanup): {
-//         drop(_0) -> bb1;
+//         drop(_2) -> bb1;
 //     }
-//     bb4 (cleanup): {
-//         drop(_2) -> bb3;
-//     }
-//     bb5: {
+//     bb4: {
 //         unreachable;
 //     }
-//     bb6: {
+//     bb5: {
 //         StorageLive(_6);
 //         _6 = ((_3 as Err).0: std::option::NoneError);
 //         StorageLive(_8);
 //         StorageLive(_9);
 //         _9 = _6;
-//         _8 = const <std::option::NoneError as std::convert::From<std::option::NoneError>>::from(move _9) -> [return: bb8, unwind: bb4];
+//         _8 = const <std::option::NoneError as std::convert::From<std::option::NoneError>>::from(move _9) -> [return: bb7, unwind: bb3];
 //     }
-//     bb7: {
+//     bb6: {
 //         return;
 //     }
-//     bb8: {
+//     bb7: {
 //         StorageDead(_9);
-//         _0 = const <std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error(move _8) -> [return: bb9, unwind: bb4];
+//         _0 = const <std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error(move _8) -> [return: bb8, unwind: bb3];
 //     }
-//     bb9: {
+//     bb8: {
 //         StorageDead(_8);
 //         StorageDead(_6);
-//         drop(_2) -> [return: bb10, unwind: bb3];
+//         drop(_2) -> bb9;
 //     }
-//     bb10: {
+//     bb9: {
 //         StorageDead(_2);
 //         StorageDead(_1);
 //         StorageDead(_3);
-//         goto -> bb7;
+//         goto -> bb6;
 //     }
-//     bb11: {
+//     bb10: {
 //         StorageLive(_10);
 //         _10 = ((_3 as Ok).0: u32);
 //         (*_2) = _10;
 //         StorageDead(_10);
 //         _1 = move _2;
-//         drop(_2) -> [return: bb13, unwind: bb12];
+//         drop(_2) -> [return: bb12, unwind: bb11];
 //     }
-//     bb12 (cleanup): {
-//         drop(_1) -> bb3;
+//     bb11 (cleanup): {
+//         drop(_1) -> bb1;
 //     }
-//     bb13: {
+//     bb12: {
 //         StorageDead(_2);
 //         _0 = std::option::Option::<std::boxed::Box<u32>>::Some(move _1,);
-//         drop(_1) -> [return: bb14, unwind: bb3];
+//         drop(_1) -> bb13;
 //     }
-//     bb14: {
+//     bb13: {
 //         StorageDead(_1);
 //         StorageDead(_3);
-//         goto -> bb7;
+//         goto -> bb6;
 //     }
 // }
 // END rustc.test.ElaborateDrops.before.mir
diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile b/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile
deleted file mode 100644
index b47ce17ec8b..00000000000
--- a/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
--include ../tools.mk
-
-# Make sure we don't ICE if the linker prints a non-UTF-8 error message.
-
-# ignore-windows
-#
-# This does not work in its current form on windows, possibly due to
-# gcc bugs or something about valid Windows paths.  See issue #29151
-# for more information.
-
-# ignore-macos
-#
-# This also does not work on Apple APFS due to the filesystem requiring
-# valid UTF-8 paths.
-
-# The zzz it to allow humans to tab complete or glob this thing.
-bad_dir := $(TMPDIR)/zzz$$'\xff'
-
-all:
-	$(RUSTC) library.rs
-	mkdir $(bad_dir)
-	mv $(TMPDIR)/liblibrary.a $(bad_dir)
-	$(RUSTC) -L $(bad_dir) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined
diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs b/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs
deleted file mode 100644
index 6864018d64e..00000000000
--- a/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#[link(name="library")]
-extern "C" {
-    fn foo();
-}
-
-fn main() { unsafe { foo(); } }
diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs b/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs
deleted file mode 100644
index 6689a82fa2c..00000000000
--- a/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![crate_type = "staticlib"]
-
-extern "C" {
-    fn this_symbol_not_defined();
-}
-
-#[no_mangle]
-pub extern "C" fn foo() {
-    unsafe { this_symbol_not_defined(); }
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile
index 51d8a4a947a..3a377c32993 100644
--- a/src/test/run-make-fulldeps/sanitizer-address/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile
@@ -24,4 +24,7 @@ endif
 
 all:
 	$(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan
+	# Verify that stack buffer overflow is detected:
 	$(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow
+	# Verify that variable name is included in address sanitizer report:
+	$(TMPDIR)/overflow 2>&1 | $(CGREP) "'xs'"
diff --git a/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile
index c2eb4caea26..9868fc1d417 100644
--- a/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile
+++ b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile
@@ -2,4 +2,4 @@
 
 # The target used below doesn't support atomic CAS operations. Verify that's the case
 all:
-	$(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="cas"'
+	$(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="ptr"'
diff --git a/src/test/rustdoc-ui/doc-test-doctest-feature.rs b/src/test/rustdoc-ui/doc-test-doctest-feature.rs
new file mode 100644
index 00000000000..984d49b43ef
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-doctest-feature.rs
@@ -0,0 +1,15 @@
+// build-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+
+#![feature(cfg_doctest)]
+
+// Make sure `cfg(doctest)` is set when finding doctests but not inside
+// the doctests.
+
+/// ```
+/// #![feature(cfg_doctest)]
+/// assert!(!cfg!(doctest));
+/// ```
+#[cfg(doctest)]
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/doc-test-doctest-feature.stdout b/src/test/rustdoc-ui/doc-test-doctest-feature.stdout
new file mode 100644
index 00000000000..75d29fab17d
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-test-doctest-feature.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-test-doctest-feature.rs - Foo (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
index af17ecc86fb..0eb3971d14a 100644
--- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
+++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
@@ -12,7 +12,7 @@ note: generator is returned here
    |
 LL | fn foo() -> Box<impl std::future::Future<Output = u32>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
    |
 LL |     Box::new(async move { x } )
    |                    ^^^^^^^^^^
diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
index a489fb11630..ad20237981c 100644
--- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
@@ -99,5 +99,5 @@ fn main() {
     assert_eq!(12, std::mem::size_of_val(&single_with_noop()));
     assert_eq!(3084, std::mem::size_of_val(&joined()));
     assert_eq!(3084, std::mem::size_of_val(&joined_with_noop()));
-    assert_eq!(3084, std::mem::size_of_val(&join_retval()));
+    assert_eq!(3080, std::mem::size_of_val(&join_retval()));
 }
diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr
index d797f30a2fc..51422fab81f 100644
--- a/src/test/ui/auto-trait-validation.stderr
+++ b/src/test/ui/auto-trait-validation.stderr
@@ -18,5 +18,5 @@ LL | auto trait MyTrait { fn foo() {} }
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0380, E0567.
+Some errors have detailed explanations: E0380, E0567, E0568.
 For more information about an error, try `rustc --explain E0380`.
diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs
new file mode 100644
index 00000000000..84615386d29
--- /dev/null
+++ b/src/test/ui/const-generics/fn-const-param-call.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(const_generics, const_compare_raw_pointers)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn function() -> u32 {
+    17
+}
+
+struct Wrapper<const F: fn() -> u32>;
+
+impl<const F: fn() -> u32> Wrapper<{F}> {
+    fn call() -> u32 {
+        F()
+    }
+}
+
+fn main() {
+    assert_eq!(Wrapper::<{function}>::call(), 17);
+}
diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr
new file mode 100644
index 00000000000..c677d703749
--- /dev/null
+++ b/src/test/ui/const-generics/fn-const-param-call.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/fn-const-param-call.rs:3:12
+   |
+LL | #![feature(const_generics, const_compare_raw_pointers)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs
new file mode 100644
index 00000000000..78fb10e8cb9
--- /dev/null
+++ b/src/test/ui/const-generics/fn-const-param-infer.rs
@@ -0,0 +1,26 @@
+#![feature(const_generics, const_compare_raw_pointers)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Checked<const F: fn(usize) -> bool>;
+
+fn not_one(val: usize) -> bool { val != 1 }
+fn not_two(val: usize) -> bool { val != 2 }
+
+fn generic_arg<T>(val: T) -> bool { true }
+
+fn generic<T>(val: usize) -> bool { val != 1 }
+
+fn main() {
+    let _: Option<Checked<{not_one}>> = None;
+    let _: Checked<{not_one}> = Checked::<{not_one}>;
+    let _: Checked<{not_one}> = Checked::<{not_two}>; //~ mismatched types
+
+    let _ = Checked::<{generic_arg}>;
+    let _ = Checked::<{generic_arg::<usize>}>;
+    let _ = Checked::<{generic_arg::<u32>}>;  //~ mismatched types
+
+    let _ = Checked::<{generic}>; //~ type annotations needed
+    let _ = Checked::<{generic::<u16>}>;
+    let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
+    let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>; //~ mismatched types
+}
diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr
new file mode 100644
index 00000000000..de0916b26bf
--- /dev/null
+++ b/src/test/ui/const-generics/fn-const-param-infer.stderr
@@ -0,0 +1,45 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/fn-const-param-infer.rs:1:12
+   |
+LL | #![feature(const_generics, const_compare_raw_pointers)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/fn-const-param-infer.rs:16:33
+   |
+LL |     let _: Checked<{not_one}> = Checked::<{not_two}>;
+   |                                 ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two`
+   |
+   = note: expected type `Checked<not_one>`
+              found type `Checked<not_two>`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-const-param-infer.rs:20:24
+   |
+LL |     let _ = Checked::<{generic_arg::<u32>}>;
+   |                        ^^^^^^^^^^^^^^^^^^ expected usize, found u32
+   |
+   = note: expected type `fn(usize) -> bool`
+              found type `fn(u32) -> bool {generic_arg::<u32>}`
+
+error[E0282]: type annotations needed
+  --> $DIR/fn-const-param-infer.rs:22:24
+   |
+LL |     let _ = Checked::<{generic}>;
+   |                        ^^^^^^^ cannot infer type for `T`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-const-param-infer.rs:25:40
+   |
+LL |     let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::<u32>`, found `generic::<u16>`
+   |
+   = note: expected type `Checked<generic::<u32>>`
+              found type `Checked<generic::<u16>>`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/issue-60263.rs b/src/test/ui/const-generics/issues/issue-60263.rs
index 70cbc242c41..70cbc242c41 100644
--- a/src/test/ui/const-generics/issue-60263.rs
+++ b/src/test/ui/const-generics/issues/issue-60263.rs
diff --git a/src/test/ui/const-generics/issue-60263.stderr b/src/test/ui/const-generics/issues/issue-60263.stderr
index fe7b6fdb190..fe7b6fdb190 100644
--- a/src/test/ui/const-generics/issue-60263.stderr
+++ b/src/test/ui/const-generics/issues/issue-60263.stderr
diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs
index b810efe7384..b810efe7384 100644
--- a/src/test/ui/const-generics/issue-60818-struct-constructors.rs
+++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs
diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.stderr b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr
index 3e0cd816881..3e0cd816881 100644
--- a/src/test/ui/const-generics/issue-60818-struct-constructors.stderr
+++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr
diff --git a/src/test/ui/const-generics/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs
index 5b5e431bf2f..5b5e431bf2f 100644
--- a/src/test/ui/const-generics/issue-61336-1.rs
+++ b/src/test/ui/const-generics/issues/issue-61336-1.rs
diff --git a/src/test/ui/const-generics/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr
index 949fa896d87..949fa896d87 100644
--- a/src/test/ui/const-generics/issue-61336-1.stderr
+++ b/src/test/ui/const-generics/issues/issue-61336-1.stderr
diff --git a/src/test/ui/const-generics/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs
index 7bb36f41b8f..7bb36f41b8f 100644
--- a/src/test/ui/const-generics/issue-61336-2.rs
+++ b/src/test/ui/const-generics/issues/issue-61336-2.rs
diff --git a/src/test/ui/const-generics/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr
index 63f86c81b1e..63f86c81b1e 100644
--- a/src/test/ui/const-generics/issue-61336-2.stderr
+++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr
diff --git a/src/test/ui/const-generics/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs
index edc012cbb3d..edc012cbb3d 100644
--- a/src/test/ui/const-generics/issue-61336.rs
+++ b/src/test/ui/const-generics/issues/issue-61336.rs
diff --git a/src/test/ui/const-generics/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr
index f96e8e02d4e..f96e8e02d4e 100644
--- a/src/test/ui/const-generics/issue-61336.stderr
+++ b/src/test/ui/const-generics/issues/issue-61336.stderr
diff --git a/src/test/ui/const-generics/issue-61422.rs b/src/test/ui/const-generics/issues/issue-61422.rs
index 45d37b6a2f3..45d37b6a2f3 100644
--- a/src/test/ui/const-generics/issue-61422.rs
+++ b/src/test/ui/const-generics/issues/issue-61422.rs
diff --git a/src/test/ui/const-generics/issue-61422.stderr b/src/test/ui/const-generics/issues/issue-61422.stderr
index 166bd3c2d3b..166bd3c2d3b 100644
--- a/src/test/ui/const-generics/issue-61422.stderr
+++ b/src/test/ui/const-generics/issues/issue-61422.stderr
diff --git a/src/test/ui/const-generics/issue-61432.rs b/src/test/ui/const-generics/issues/issue-61432.rs
index 832095ce542..832095ce542 100644
--- a/src/test/ui/const-generics/issue-61432.rs
+++ b/src/test/ui/const-generics/issues/issue-61432.rs
diff --git a/src/test/ui/const-generics/issue-61432.stderr b/src/test/ui/const-generics/issues/issue-61432.stderr
index 33f77b02810..33f77b02810 100644
--- a/src/test/ui/const-generics/issue-61432.stderr
+++ b/src/test/ui/const-generics/issues/issue-61432.stderr
diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs
new file mode 100644
index 00000000000..4dc46eb0ef6
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+pub trait BitLen: Sized {
+    const BIT_LEN: usize;
+}
+
+impl<const L: usize> BitLen for [u8; L] {
+    const BIT_LEN: usize = 8 * L;
+}
+
+fn main() {
+    let foo = <[u8; 2]>::BIT_LEN;
+}
diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr
new file mode 100644
index 00000000000..20347ac4b7d
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr
@@ -0,0 +1,16 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-62187-encountered-polymorphic-const.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: unused variable: `foo`
+  --> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9
+   |
+LL |     let foo = <[u8; 2]>::BIT_LEN;
+   |         ^^^ help: consider prefixing with an underscore: `_foo`
+   |
+   = note: `#[warn(unused_variables)]` on by default
+
diff --git a/src/test/ui/const-generics/issue-64519.rs b/src/test/ui/const-generics/issues/issue-64519.rs
index 72cce9b4843..72cce9b4843 100644
--- a/src/test/ui/const-generics/issue-64519.rs
+++ b/src/test/ui/const-generics/issues/issue-64519.rs
diff --git a/src/test/ui/const-generics/issue-64519.stderr b/src/test/ui/const-generics/issues/issue-64519.stderr
index d368f39d903..d368f39d903 100644
--- a/src/test/ui/const-generics/issue-64519.stderr
+++ b/src/test/ui/const-generics/issues/issue-64519.stderr
diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs
new file mode 100644
index 00000000000..d26ab8be4c3
--- /dev/null
+++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![feature(const_generics, const_compare_raw_pointers)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+const A: u32 = 3;
+
+struct Const<const P: *const u32>;
+
+impl<const P: *const u32> Const<{P}> {
+    fn get() -> u32 {
+        unsafe {
+            *P
+        }
+    }
+}
+
+fn main() {
+    assert_eq!(Const::<{&A as *const _}>::get(), 3)
+}
diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr
new file mode 100644
index 00000000000..73221596c8e
--- /dev/null
+++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/raw-ptr-const-param-deref.rs:2:12
+   |
+LL | #![feature(const_generics, const_compare_raw_pointers)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs
new file mode 100644
index 00000000000..f69c37fbb8f
--- /dev/null
+++ b/src/test/ui/const-generics/raw-ptr-const-param.rs
@@ -0,0 +1,9 @@
+#![feature(const_generics, const_compare_raw_pointers)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Const<const P: *const u32>;
+
+fn main() {
+    let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types
+    let _: Const<{10 as *const _}> = Const::<{10 as *const _}>;
+}
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr
new file mode 100644
index 00000000000..75b4c0a0a3d
--- /dev/null
+++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/raw-ptr-const-param.rs:1:12
+   |
+LL | #![feature(const_generics, const_compare_raw_pointers)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/raw-ptr-const-param.rs:7:38
+   |
+LL |     let _: Const<{15 as *const _}> = Const::<{10 as *const _}>;
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}`
+   |
+   = note: expected type `Const<{pointer}>`
+              found type `Const<{pointer}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/auxiliary/external_macro.rs b/src/test/ui/consts/auxiliary/external_macro.rs
new file mode 100644
index 00000000000..d260634c996
--- /dev/null
+++ b/src/test/ui/consts/auxiliary/external_macro.rs
@@ -0,0 +1,14 @@
+#![feature(allow_internal_unstable)]
+
+// Macro to help ensure CONST_ERR lint errors
+// are not silenced in external macros.
+// https://github.com/rust-lang/rust/issues/65300
+
+#[macro_export]
+#[allow_internal_unstable(type_ascription)]
+macro_rules! static_assert {
+    ($test:expr) => {
+        #[allow(dead_code)]
+        const _: () = [()][!($test: bool) as usize];
+    }
+}
diff --git a/src/test/ui/consts/const-external-macro-const-err.rs b/src/test/ui/consts/const-external-macro-const-err.rs
new file mode 100644
index 00000000000..616d24f4a7b
--- /dev/null
+++ b/src/test/ui/consts/const-external-macro-const-err.rs
@@ -0,0 +1,13 @@
+// edition:2018
+// aux-build:external_macro.rs
+
+// Ensure that CONST_ERR lint errors
+// are not silenced in external macros.
+// https://github.com/rust-lang/rust/issues/65300
+
+extern crate external_macro;
+use external_macro::static_assert;
+
+fn main() {
+    static_assert!(2 + 2 == 5); //~ ERROR
+}
diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr
new file mode 100644
index 00000000000..237c4d792c9
--- /dev/null
+++ b/src/test/ui/consts/const-external-macro-const-err.stderr
@@ -0,0 +1,11 @@
+error: any use of this value will cause an error
+  --> $DIR/const-external-macro-const-err.rs:12:5
+   |
+LL |     static_assert!(2 + 2 == 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |
+   = note: `#[deny(const_err)]` on by default
+   = 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/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
index 24d2e3ce539..087cc3c86a6 100644
--- a/src/test/ui/consts/const-match-check.eval1.stderr
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1
    |
 LL |     A = { let 0 = 0; 0 },
    |               ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     A = { if let 0 = 0 { /* */ } 0 },
+   |           ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr
index 5d59d06f798..80d9f794bc1 100644
--- a/src/test/ui/consts/const-match-check.eval2.stderr
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1
    |
 LL |     let x: [i32; { let 0 = 0; 0 }] = [];
    |                        ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     let x: [i32; { if let 0 = 0 { /* */ } 0 }] = [];
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr
index 6d74c26f9f7..e6b2f212bb4 100644
--- a/src/test/ui/consts/const-match-check.matchck.stderr
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -3,24 +3,52 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1
    |
 LL | const X: i32 = { let 0 = 0; 0 };
    |                      ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL | const X: i32 = { if let 0 = 0 { /* */ } 0 };
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:8:23
    |
 LL | static Y: i32 = { let 0 = 0; 0 };
    |                       ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 };
+   |                   ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:13:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
    |                          ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     const X: i32 = { if let 0 = 0 { /* */ } 0 };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:19:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
    |                          ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     const X: i32 = { if let 0 = 0 { /* */ } 0 };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs
index ed4055ecdd3..ac771ac81d1 100644
--- a/src/test/ui/deprecation/derive_on_deprecated.rs
+++ b/src/test/ui/deprecation/derive_on_deprecated.rs
@@ -6,4 +6,10 @@
 #[derive(Default)]
 struct X;
 
+#[deprecated(note="Do not use this")]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
+pub struct Step<I> {
+    _skip: Option<I>,
+}
+
 fn main() {}
diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs
index 398bcb7ec0e..91063edf0f6 100644
--- a/src/test/ui/drop/dynamic-drop-async.rs
+++ b/src/test/ui/drop/dynamic-drop-async.rs
@@ -7,7 +7,7 @@
 // edition:2018
 // ignore-wasm32-bare compiled with panic=abort by default
 
-#![feature(slice_patterns, arbitrary_self_types)]
+#![feature(slice_patterns)]
 #![allow(unused)]
 
 use std::{
@@ -45,7 +45,6 @@ impl<T: Unpin> Future for Defer<T> {
 /// The `failing_op`-th operation will panic.
 struct Allocator {
     data: RefCell<Vec<bool>>,
-    name: &'static str,
     failing_op: usize,
     cur_ops: Cell<usize>,
 }
@@ -57,28 +56,23 @@ impl Drop for Allocator {
     fn drop(&mut self) {
         let data = self.data.borrow();
         if data.iter().any(|d| *d) {
-            panic!("missing free in {:?}: {:?}", self.name, data);
+            panic!("missing free: {:?}", data);
         }
     }
 }
 
 impl Allocator {
-    fn new(failing_op: usize, name: &'static str) -> Self {
-        Allocator {
-            failing_op,
-            name,
-            cur_ops: Cell::new(0),
-            data: RefCell::new(vec![]),
-        }
+    fn new(failing_op: usize) -> Self {
+        Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) }
     }
-    fn alloc(self: &Rc<Allocator>) -> impl Future<Output = Ptr> + 'static {
+    fn alloc(&self) -> impl Future<Output = Ptr<'_>> + '_ {
         self.fallible_operation();
 
         let mut data = self.data.borrow_mut();
 
         let addr = data.len();
         data.push(true);
-        Defer { ready: false, value: Some(Ptr(addr, self.clone())) }
+        Defer { ready: false, value: Some(Ptr(addr, self)) }
     }
     fn fallible_operation(&self) {
         self.cur_ops.set(self.cur_ops.get() + 1);
@@ -91,11 +85,11 @@ impl Allocator {
 
 // Type that tracks whether it was dropped and can panic when it's created or
 // destroyed.
-struct Ptr(usize, Rc<Allocator>);
-impl Drop for Ptr {
+struct Ptr<'a>(usize, &'a Allocator);
+impl<'a> Drop for Ptr<'a> {
     fn drop(&mut self) {
         match self.1.data.borrow_mut()[self.0] {
-            false => panic!("double free in {:?} at index {:?}", self.1.name, self.0),
+            false => panic!("double free at index {:?}", self.0),
             ref mut d => *d = false,
         }
 
@@ -119,7 +113,7 @@ async fn dynamic_drop(a: Rc<Allocator>, c: bool) {
     };
 }
 
-struct TwoPtrs(Ptr, Ptr);
+struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>);
 async fn struct_dynamic_drop(a: Rc<Allocator>, c0: bool, c1: bool, c: bool) {
     for i in 0..2 {
         let x;
@@ -234,62 +228,21 @@ async fn subslice_pattern_reassign(a: Rc<Allocator>) {
     a.alloc().await;
 }
 
-async fn panic_after_return(a: Rc<Allocator>, c: bool) -> (Ptr,) {
-    a.alloc().await;
-    let p = a.alloc().await;
-    if c {
-        a.alloc().await;
-        let q = a.alloc().await;
-        // We use a return type that isn't used anywhere else to make sure that
-        // the return place doesn't incorrectly end up in the generator state.
-        return (a.alloc().await,);
-    }
-    (a.alloc().await,)
-}
-
-
-async fn panic_after_init_by_loop(a: Rc<Allocator>) {
-    a.alloc().await;
-    let p = a.alloc().await;
-    let q = loop {
-        a.alloc().await;
-        let r = a.alloc().await;
-        break a.alloc().await;
-    };
-}
-
-async fn panic_after_init_by_match_with_bindings_and_guard(a: Rc<Allocator>, b: bool) {
-    a.alloc().await;
-    let p = a.alloc().await;
-    let q = match a.alloc().await {
-        ref _x if b => {
-            a.alloc().await;
-            let r = a.alloc().await;
-            a.alloc().await
-        }
-        _x => {
-            a.alloc().await;
-            let r = a.alloc().await;
-            a.alloc().await
-        },
-    };
-}
-
-fn run_test<F, G, O>(cx: &mut Context<'_>, ref f: F, name: &'static str)
+fn run_test<F, G>(cx: &mut Context<'_>, ref f: F)
 where
     F: Fn(Rc<Allocator>) -> G,
-    G: Future<Output = O>,
+    G: Future<Output = ()>,
 {
     for polls in 0.. {
         // Run without any panics to find which operations happen after the
         // penultimate `poll`.
-        let first_alloc = Rc::new(Allocator::new(usize::MAX, name));
+        let first_alloc = Rc::new(Allocator::new(usize::MAX));
         let mut fut = Box::pin(f(first_alloc.clone()));
         let mut ops_before_last_poll = 0;
         let mut completed = false;
         for _ in 0..polls {
             ops_before_last_poll = first_alloc.cur_ops.get();
-            if let Poll::Ready(_) = fut.as_mut().poll(cx) {
+            if let Poll::Ready(()) = fut.as_mut().poll(cx) {
                 completed = true;
             }
         }
@@ -298,7 +251,7 @@ where
         // Start at `ops_before_last_poll` so that we will always be able to
         // `poll` the expected number of times.
         for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() {
-            let alloc = Rc::new(Allocator::new(failing_op + 1, name));
+            let alloc = Rc::new(Allocator::new(failing_op + 1));
             let f = &f;
             let cx = &mut *cx;
             let result = panic::catch_unwind(panic::AssertUnwindSafe(move || {
@@ -328,56 +281,46 @@ fn clone_waker(data: *const ()) -> RawWaker {
     RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop))
 }
 
-macro_rules! run_test {
-    ($ctxt:expr, $e:expr) => { run_test($ctxt, $e, stringify!($e)); };
-}
-
 fn main() {
     let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) };
     let context = &mut Context::from_waker(&waker);
 
-    run_test!(context, |a| dynamic_init(a, false));
-    run_test!(context, |a| dynamic_init(a, true));
-    run_test!(context, |a| dynamic_drop(a, false));
-    run_test!(context, |a| dynamic_drop(a, true));
-
-    run_test!(context, |a| assignment(a, false, false));
-    run_test!(context, |a| assignment(a, false, true));
-    run_test!(context, |a| assignment(a, true, false));
-    run_test!(context, |a| assignment(a, true, true));
-
-    run_test!(context, |a| array_simple(a));
-    run_test!(context, |a| vec_simple(a));
-    run_test!(context, |a| vec_unreachable(a));
-
-    run_test!(context, |a| struct_dynamic_drop(a, false, false, false));
-    run_test!(context, |a| struct_dynamic_drop(a, false, false, true));
-    run_test!(context, |a| struct_dynamic_drop(a, false, true, false));
-    run_test!(context, |a| struct_dynamic_drop(a, false, true, true));
-    run_test!(context, |a| struct_dynamic_drop(a, true, false, false));
-    run_test!(context, |a| struct_dynamic_drop(a, true, false, true));
-    run_test!(context, |a| struct_dynamic_drop(a, true, true, false));
-    run_test!(context, |a| struct_dynamic_drop(a, true, true, true));
-
-    run_test!(context, |a| field_assignment(a, false));
-    run_test!(context, |a| field_assignment(a, true));
-
-    run_test!(context, |a| mixed_drop_and_nondrop(a));
-
-    run_test!(context, |a| slice_pattern_one_of(a, 0));
-    run_test!(context, |a| slice_pattern_one_of(a, 1));
-    run_test!(context, |a| slice_pattern_one_of(a, 2));
-    run_test!(context, |a| slice_pattern_one_of(a, 3));
-
-    run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, true));
-    run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, false));
-    run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, true));
-    run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, false));
-    run_test!(context, |a| subslice_pattern_reassign(a));
-
-    run_test!(context, |a| panic_after_return(a, false));
-    run_test!(context, |a| panic_after_return(a, true));
-    run_test!(context, |a| panic_after_init_by_loop(a));
-    run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, false));
-    run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, true));
+    run_test(context, |a| dynamic_init(a, false));
+    run_test(context, |a| dynamic_init(a, true));
+    run_test(context, |a| dynamic_drop(a, false));
+    run_test(context, |a| dynamic_drop(a, true));
+
+    run_test(context, |a| assignment(a, false, false));
+    run_test(context, |a| assignment(a, false, true));
+    run_test(context, |a| assignment(a, true, false));
+    run_test(context, |a| assignment(a, true, true));
+
+    run_test(context, |a| array_simple(a));
+    run_test(context, |a| vec_simple(a));
+    run_test(context, |a| vec_unreachable(a));
+
+    run_test(context, |a| struct_dynamic_drop(a, false, false, false));
+    run_test(context, |a| struct_dynamic_drop(a, false, false, true));
+    run_test(context, |a| struct_dynamic_drop(a, false, true, false));
+    run_test(context, |a| struct_dynamic_drop(a, false, true, true));
+    run_test(context, |a| struct_dynamic_drop(a, true, false, false));
+    run_test(context, |a| struct_dynamic_drop(a, true, false, true));
+    run_test(context, |a| struct_dynamic_drop(a, true, true, false));
+    run_test(context, |a| struct_dynamic_drop(a, true, true, true));
+
+    run_test(context, |a| field_assignment(a, false));
+    run_test(context, |a| field_assignment(a, true));
+
+    run_test(context, |a| mixed_drop_and_nondrop(a));
+
+    run_test(context, |a| slice_pattern_one_of(a, 0));
+    run_test(context, |a| slice_pattern_one_of(a, 1));
+    run_test(context, |a| slice_pattern_one_of(a, 2));
+    run_test(context, |a| slice_pattern_one_of(a, 3));
+
+    run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true));
+    run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false));
+    run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true));
+    run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false));
+    run_test(context, |a| subslice_pattern_reassign(a));
 }
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index 6f9112ae006..8516bc3d964 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -17,7 +17,6 @@ struct InjectedFailure;
 
 struct Allocator {
     data: RefCell<Vec<bool>>,
-    name: &'static str,
     failing_op: usize,
     cur_ops: Cell<usize>,
 }
@@ -29,18 +28,17 @@ impl Drop for Allocator {
     fn drop(&mut self) {
         let data = self.data.borrow();
         if data.iter().any(|d| *d) {
-            panic!("missing free in {:?}: {:?}", self.name, data);
+            panic!("missing free: {:?}", data);
         }
     }
 }
 
 impl Allocator {
-    fn new(failing_op: usize, name: &'static str) -> Self {
+    fn new(failing_op: usize) -> Self {
         Allocator {
             failing_op: failing_op,
             cur_ops: Cell::new(0),
-            data: RefCell::new(vec![]),
-            name,
+            data: RefCell::new(vec![])
         }
     }
     fn alloc(&self) -> Ptr<'_> {
@@ -55,6 +53,20 @@ impl Allocator {
         data.push(true);
         Ptr(addr, self)
     }
+    // FIXME(#47949) Any use of this indicates a bug in rustc: we should never
+    // be leaking values in the cases here.
+    //
+    // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the
+    // `failing_op` is in the list of exception.
+    fn alloc_leaked(&self, exceptions: Vec<usize>) -> Ptr<'_> {
+        let ptr = self.alloc();
+
+        if exceptions.iter().any(|operation| *operation == self.failing_op) {
+            let mut data = self.data.borrow_mut();
+            data[ptr.0] = false;
+        }
+        ptr
+    }
 }
 
 struct Ptr<'a>(usize, &'a Allocator);
@@ -62,7 +74,7 @@ impl<'a> Drop for Ptr<'a> {
     fn drop(&mut self) {
         match self.1.data.borrow_mut()[self.0] {
             false => {
-                panic!("double free in {:?} at index {:?}", self.1.name, self.0)
+                panic!("double free at index {:?}", self.0)
             }
             ref mut d => *d = false
         }
@@ -258,148 +270,79 @@ fn subslice_pattern_reassign(a: &Allocator) {
 }
 
 fn panic_after_return(a: &Allocator) -> Ptr<'_> {
+    // Panic in the drop of `p` or `q` can leak
+    let exceptions = vec![8, 9];
     a.alloc();
     let p = a.alloc();
     {
         a.alloc();
         let p = a.alloc();
-        a.alloc()
+        // FIXME (#47949) We leak values when we panic in a destructor after
+        // evaluating an expression with `rustc_mir::build::Builder::into`.
+        a.alloc_leaked(exceptions)
     }
 }
 
 fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> {
+    // Panic in the drop of `p` or `q` can leak
+    let exceptions = vec![8, 9];
     a.alloc();
     let p = a.alloc();
     {
         a.alloc();
         let q = a.alloc();
-        return a.alloc();
+        // FIXME (#47949)
+        return a.alloc_leaked(exceptions);
     }
 }
 
 fn panic_after_init(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
     a.alloc();
     let p = a.alloc();
     let q = {
         a.alloc();
         let r = a.alloc();
-        a.alloc()
+        // FIXME (#47949)
+        a.alloc_leaked(exceptions)
     };
 }
 
 fn panic_after_init_temp(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
     a.alloc();
     let p = a.alloc();
     {
         a.alloc();
         let r = a.alloc();
-        a.alloc()
+        // FIXME (#47949)
+        a.alloc_leaked(exceptions)
     };
 }
 
 fn panic_after_init_by_loop(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
     a.alloc();
     let p = a.alloc();
     let q = loop {
         a.alloc();
         let r = a.alloc();
-        break a.alloc();
-    };
-}
-
-fn panic_after_init_by_match(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    loop {
-        let q = match b {
-            true => {
-                a.alloc();
-                let r = a.alloc();
-                a.alloc()
-            }
-            false => {
-                a.alloc();
-                let r = a.alloc();
-                break a.alloc();
-            }
-        };
-        return;
-    };
-}
-
-fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = match a.alloc() {
-        _ if b => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        }
-        _ => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        },
-    };
-}
-
-fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = match a.alloc() {
-        _x if b => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        }
-        _x => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        },
-    };
-}
-
-fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = match a.alloc() {
-        ref _x if b => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        }
-        ref _x => {
-            a.alloc();
-            let r = a.alloc();
-            a.alloc()
-        },
-    };
-}
-
-fn panic_after_init_by_break_if(a: &Allocator, b: bool) {
-    a.alloc();
-    let p = a.alloc();
-    let q = loop {
-        let r = a.alloc();
-        break if b {
-            let s = a.alloc();
-            a.alloc()
-        } else {
-            a.alloc()
-        };
+        // FIXME (#47949)
+        break a.alloc_leaked(exceptions);
     };
 }
 
-fn run_test<F>(mut f: F, name: &'static str)
+fn run_test<F>(mut f: F)
     where F: FnMut(&Allocator)
 {
-    let first_alloc = Allocator::new(usize::MAX, name);
+    let first_alloc = Allocator::new(usize::MAX);
     f(&first_alloc);
 
     for failing_op in 1..first_alloc.cur_ops.get()+1 {
-        let alloc = Allocator::new(failing_op, name);
+        let alloc = Allocator::new(failing_op);
         let alloc = &alloc;
         let f = panic::AssertUnwindSafe(&mut f);
         let result = panic::catch_unwind(move || {
@@ -417,91 +360,77 @@ fn run_test<F>(mut f: F, name: &'static str)
     }
 }
 
-fn run_test_nopanic<F>(mut f: F, name: &'static str)
+fn run_test_nopanic<F>(mut f: F)
     where F: FnMut(&Allocator)
 {
-    let first_alloc = Allocator::new(usize::MAX, name);
+    let first_alloc = Allocator::new(usize::MAX);
     f(&first_alloc);
 }
 
-macro_rules! run_test {
-    ($e:expr) => { run_test($e, stringify!($e)); }
-}
-
 fn main() {
-    run_test!(|a| dynamic_init(a, false));
-    run_test!(|a| dynamic_init(a, true));
-    run_test!(|a| dynamic_drop(a, false));
-    run_test!(|a| dynamic_drop(a, true));
-
-    run_test!(|a| assignment2(a, false, false));
-    run_test!(|a| assignment2(a, false, true));
-    run_test!(|a| assignment2(a, true, false));
-    run_test!(|a| assignment2(a, true, true));
-
-    run_test!(|a| assignment1(a, false));
-    run_test!(|a| assignment1(a, true));
-
-    run_test!(|a| array_simple(a));
-    run_test!(|a| vec_simple(a));
-    run_test!(|a| vec_unreachable(a));
-
-    run_test!(|a| struct_dynamic_drop(a, false, false, false));
-    run_test!(|a| struct_dynamic_drop(a, false, false, true));
-    run_test!(|a| struct_dynamic_drop(a, false, true, false));
-    run_test!(|a| struct_dynamic_drop(a, false, true, true));
-    run_test!(|a| struct_dynamic_drop(a, true, false, false));
-    run_test!(|a| struct_dynamic_drop(a, true, false, true));
-    run_test!(|a| struct_dynamic_drop(a, true, true, false));
-    run_test!(|a| struct_dynamic_drop(a, true, true, true));
-
-    run_test!(|a| field_assignment(a, false));
-    run_test!(|a| field_assignment(a, true));
-
-    run_test!(|a| generator(a, 0));
-    run_test!(|a| generator(a, 1));
-    run_test!(|a| generator(a, 2));
-    run_test!(|a| generator(a, 3));
-
-    run_test!(|a| mixed_drop_and_nondrop(a));
-
-    run_test!(|a| slice_pattern_first(a));
-    run_test!(|a| slice_pattern_middle(a));
-    run_test!(|a| slice_pattern_two(a));
-    run_test!(|a| slice_pattern_last(a));
-    run_test!(|a| slice_pattern_one_of(a, 0));
-    run_test!(|a| slice_pattern_one_of(a, 1));
-    run_test!(|a| slice_pattern_one_of(a, 2));
-    run_test!(|a| slice_pattern_one_of(a, 3));
-
-    run_test!(|a| subslice_pattern_from_end(a, true));
-    run_test!(|a| subslice_pattern_from_end(a, false));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true));
-    run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false));
-    run_test!(|a| slice_pattern_reassign(a));
-    run_test!(|a| subslice_pattern_reassign(a));
-
-    run_test!(|a| {
+    run_test(|a| dynamic_init(a, false));
+    run_test(|a| dynamic_init(a, true));
+    run_test(|a| dynamic_drop(a, false));
+    run_test(|a| dynamic_drop(a, true));
+
+    run_test(|a| assignment2(a, false, false));
+    run_test(|a| assignment2(a, false, true));
+    run_test(|a| assignment2(a, true, false));
+    run_test(|a| assignment2(a, true, true));
+
+    run_test(|a| assignment1(a, false));
+    run_test(|a| assignment1(a, true));
+
+    run_test(|a| array_simple(a));
+    run_test(|a| vec_simple(a));
+    run_test(|a| vec_unreachable(a));
+
+    run_test(|a| struct_dynamic_drop(a, false, false, false));
+    run_test(|a| struct_dynamic_drop(a, false, false, true));
+    run_test(|a| struct_dynamic_drop(a, false, true, false));
+    run_test(|a| struct_dynamic_drop(a, false, true, true));
+    run_test(|a| struct_dynamic_drop(a, true, false, false));
+    run_test(|a| struct_dynamic_drop(a, true, false, true));
+    run_test(|a| struct_dynamic_drop(a, true, true, false));
+    run_test(|a| struct_dynamic_drop(a, true, true, true));
+
+    run_test(|a| field_assignment(a, false));
+    run_test(|a| field_assignment(a, true));
+
+    run_test(|a| generator(a, 0));
+    run_test(|a| generator(a, 1));
+    run_test(|a| generator(a, 2));
+    run_test(|a| generator(a, 3));
+
+    run_test(|a| mixed_drop_and_nondrop(a));
+
+    run_test(|a| slice_pattern_first(a));
+    run_test(|a| slice_pattern_middle(a));
+    run_test(|a| slice_pattern_two(a));
+    run_test(|a| slice_pattern_last(a));
+    run_test(|a| slice_pattern_one_of(a, 0));
+    run_test(|a| slice_pattern_one_of(a, 1));
+    run_test(|a| slice_pattern_one_of(a, 2));
+    run_test(|a| slice_pattern_one_of(a, 3));
+
+    run_test(|a| subslice_pattern_from_end(a, true));
+    run_test(|a| subslice_pattern_from_end(a, false));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, true, true));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, true, false));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, false, true));
+    run_test(|a| subslice_pattern_from_end_with_drop(a, false, false));
+    run_test(|a| slice_pattern_reassign(a));
+    run_test(|a| subslice_pattern_reassign(a));
+
+    run_test(|a| {
         panic_after_return(a);
     });
-    run_test!(|a| {
+    run_test(|a| {
         panic_after_return_expr(a);
     });
-    run_test!(|a| panic_after_init(a));
-    run_test!(|a| panic_after_init_temp(a));
-    run_test!(|a| panic_after_init_by_loop(a));
-    run_test!(|a| panic_after_init_by_match(a, false));
-    run_test!(|a| panic_after_init_by_match(a, true));
-    run_test!(|a| panic_after_init_by_match_with_guard(a, false));
-    run_test!(|a| panic_after_init_by_match_with_guard(a, true));
-    run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false));
-    run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true));
-    run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false));
-    run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true));
-    run_test!(|a| panic_after_init_by_break_if(a, false));
-    run_test!(|a| panic_after_init_by_break_if(a, true));
-
-    run_test_nopanic(|a| union1(a), "|a| union1(a)");
+    run_test(|a| panic_after_init(a));
+    run_test(|a| panic_after_init_temp(a));
+    run_test(|a| panic_after_init_by_loop(a));
+
+    run_test_nopanic(|a| union1(a));
 }
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
index 7d59d553d88..d865b59f0b9 100644
--- a/src/test/ui/empty/empty-never-array.stderr
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -11,6 +11,13 @@ LL | | }
 ...
 LL |       let Helper::U(u) = Helper::T(t, []);
    |           ^^^^^^^^^^^^ pattern `T(_, _)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Helper::U(u) = Helper::T(t, []) { /* */ }
+   |
 
 error[E0381]: use of possibly-uninitialized variable: `u`
   --> $DIR/empty-never-array.rs:12:5
diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr
index 56a4bcffc81..577c6e886d5 100644
--- a/src/test/ui/error-codes/E0005.stderr
+++ b/src/test/ui/error-codes/E0005.stderr
@@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `None` not covered
    |
 LL |     let Some(y) = x;
    |         ^^^^^^^ pattern `None` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Some(y) = x { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
new file mode 100644
index 00000000000..ff10d412a11
--- /dev/null
+++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
@@ -0,0 +1,65 @@
+// run-pass
+// ignore-wasm32-bare compiled with panic=abort by default
+// ignore-emscripten no threads support
+
+// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
+// should still run destructors as it unwinds the stack. However,
+// bugs with how the nounwind LLVM attribute was applied led to this
+// simple case being mishandled *if* you had fat LTO turned on.
+
+// Unlike issue-64655-extern-rust-must-allow-unwind.rs, the issue
+// embodied in this test cropped up regardless of optimization level.
+// Therefore it seemed worthy of being enshrined as a dedicated unit
+// test.
+
+// LTO settings cannot be combined with -C prefer-dynamic
+// no-prefer-dynamic
+
+// The revisions just enumerate lto settings (the opt-level appeared irrelevant in practice)
+
+// revisions: no thin fat
+//[no]compile-flags: -C lto=no
+//[thin]compile-flags: -C lto=thin
+//[fat]compile-flags: -C lto=fat
+
+#![feature(core_panic)]
+
+// (For some reason, reproducing the LTO issue requires pulling in std
+// explicitly this way.)
+#![no_std]
+extern crate std;
+
+fn main() {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+    use std::boxed::Box;
+
+    static SHARED: AtomicUsize = AtomicUsize::new(0);
+
+    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0);
+
+    let old_hook = std::panic::take_hook();
+
+    std::panic::set_hook(Box::new(|_| { } )); // no-op on panic.
+
+    let handle = std::thread::spawn(|| {
+        struct Droppable;
+        impl Drop for Droppable {
+            fn drop(&mut self) {
+                SHARED.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+
+        let _guard = Droppable;
+        let s = "issue-64655-allow-unwind-when-calling-panic-directly.rs";
+        core::panicking::panic(&("???", s, 17, 4));
+    });
+
+    let wait = handle.join();
+
+    // Reinstate handler to ease observation of assertion failures.
+    std::panic::set_hook(old_hook);
+
+    assert!(wait.is_err());
+
+    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1);
+}
diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs
new file mode 100644
index 00000000000..bc15fcb0e39
--- /dev/null
+++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs
@@ -0,0 +1,83 @@
+// run-pass
+// ignore-wasm32-bare compiled with panic=abort by default
+// ignore-emscripten no threads support
+
+// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
+// should still run destructors as it unwinds the stack. However,
+// bugs with how the nounwind LLVM attribute was applied led to this
+// simple case being mishandled *if* you had optimization *and* fat
+// LTO turned on.
+
+// This test is the closest thing to a "regression test" we can do
+// without actually spawning subprocesses and comparing stderr
+// results.
+//
+// This test takes the code from the above issue and adapts it to
+// better fit our test infrastructure:
+//
+// * Instead of relying on `println!` to observe whether the destructor
+//   is run, we instead run the code in a spawned thread and
+//   communicate the destructor's operation via a synchronous atomic
+//   in static memory.
+//
+// * To keep the output from confusing a casual user, we override the
+//   panic hook to be a no-op (rather than printing a message to
+//   stderr).
+//
+// (pnkfelix has confirmed by hand that these additions do not mask
+// the underlying bug.)
+
+// LTO settings cannot be combined with -C prefer-dynamic
+// no-prefer-dynamic
+
+// The revisions combine each lto setting with each optimization
+// setting; pnkfelix observed three differing behaviors at opt-levels
+// 0/1/2+3 for this test, so it seems prudent to be thorough.
+
+// revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2  fat3
+
+//[no0]compile-flags: -C opt-level=0 -C lto=no
+//[no1]compile-flags: -C opt-level=1 -C lto=no
+//[no2]compile-flags: -C opt-level=2 -C lto=no
+//[no3]compile-flags: -C opt-level=3 -C lto=no
+//[thin0]compile-flags: -C opt-level=0 -C lto=thin
+//[thin1]compile-flags: -C opt-level=1 -C lto=thin
+//[thin2]compile-flags: -C opt-level=2 -C lto=thin
+//[thin3]compile-flags: -C opt-level=3 -C lto=thin
+//[fat0]compile-flags: -C opt-level=0 -C lto=fat
+//[fat1]compile-flags: -C opt-level=1 -C lto=fat
+//[fat2]compile-flags: -C opt-level=2 -C lto=fat
+//[fat3]compile-flags: -C opt-level=3 -C lto=fat
+
+fn main() {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static SHARED: AtomicUsize = AtomicUsize::new(0);
+
+    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0);
+
+    let old_hook = std::panic::take_hook();
+
+    std::panic::set_hook(Box::new(|_| { } )); // no-op on panic.
+
+    let handle = std::thread::spawn(|| {
+        struct Droppable;
+        impl Drop for Droppable {
+            fn drop(&mut self) {
+                SHARED.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+
+        let _guard = Droppable;
+        None::<()>.expect("???");
+    });
+
+    let wait = handle.join();
+
+    // reinstate handler to ease observation of assertion failures.
+    std::panic::set_hook(old_hook);
+
+    assert!(wait.is_err());
+
+    assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1);
+}
diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs
index afe4dc7d54c..8de390becbe 100644
--- a/src/test/ui/feature-gates/bench.rs
+++ b/src/test/ui/feature-gates/bench.rs
@@ -1,5 +1,9 @@
+// edition:2018
+
 #[bench] //~ ERROR use of unstable library feature 'test'
          //~| WARN this was previously accepted
 fn bench() {}
 
+use bench as _; //~ ERROR use of unstable library feature 'test'
+                //~| WARN this was previously accepted
 fn main() {}
diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr
index b9e24e931d4..168ac925724 100644
--- a/src/test/ui/feature-gates/bench.stderr
+++ b/src/test/ui/feature-gates/bench.stderr
@@ -1,5 +1,5 @@
 error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
-  --> $DIR/bench.rs:1:3
+  --> $DIR/bench.rs:3:3
    |
 LL | #[bench]
    |   ^^^^^
@@ -8,5 +8,14 @@ LL | #[bench]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
 
-error: aborting due to previous error
+error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+  --> $DIR/bench.rs:7:5
+   |
+LL | use bench as _;
+   |     ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs
new file mode 100644
index 00000000000..1ab11ce3b44
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs
@@ -0,0 +1,9 @@
+struct ConstFn<const F: fn()>;
+//~^ ERROR const generics are unstable
+//~^^ ERROR using function pointers as const generic parameters is unstable
+
+struct ConstPtr<const P: *const u32>;
+//~^ ERROR const generics are unstable
+//~^^ ERROR using raw pointers as const generic parameters is unstable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
new file mode 100644
index 00000000000..935f84b9163
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
@@ -0,0 +1,39 @@
+error[E0658]: const generics are unstable
+  --> $DIR/feature-gate-const_generics-ptr.rs:1:22
+   |
+LL | struct ConstFn<const F: fn()>;
+   |                      ^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
+   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+
+error[E0658]: const generics are unstable
+  --> $DIR/feature-gate-const_generics-ptr.rs:5:23
+   |
+LL | struct ConstPtr<const P: *const u32>;
+   |                       ^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
+   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+
+error[E0658]: using function pointers as const generic parameters is unstable
+  --> $DIR/feature-gate-const_generics-ptr.rs:1:25
+   |
+LL | struct ConstFn<const F: fn()>;
+   |                         ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53020
+   = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
+
+error[E0658]: using raw pointers as const generic parameters is unstable
+  --> $DIR/feature-gate-const_generics-ptr.rs:5:26
+   |
+LL | struct ConstPtr<const P: *const u32>;
+   |                          ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53020
+   = help: add `#![feature(const_compare_raw_pointers)]` 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/feature-gates/feature-gate-exhaustive-patterns.nll.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr
new file mode 100644
index 00000000000..d77fbc1e823
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr
@@ -0,0 +1,16 @@
+error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+  --> $DIR/feature-gate-exhaustive-patterns.rs:7:9
+   |
+LL |     let Ok(_x) = foo();
+   |         ^^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Ok(_x) = foo() { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index dd4ca1f67e3..d77fbc1e823 100644
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
    |
 LL |     let Ok(_x) = foo();
    |         ^^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Ok(_x) = foo() { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/auxiliary/issue-57271-lib.rs b/src/test/ui/issues/auxiliary/issue-57271-lib.rs
new file mode 100644
index 00000000000..ff625668a9d
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/issue-57271-lib.rs
@@ -0,0 +1,11 @@
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+pub enum BaseType {
+    Byte,
+    Char,
+    Double,
+    Float,
+    Int,
+    Long,
+    Short,
+    Boolean,
+}
diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr
index 9ec26b024bc..d3c8e876b8a 100644
--- a/src/test/ui/issues/issue-31561.stderr
+++ b/src/test/ui/issues/issue-31561.stderr
@@ -12,6 +12,13 @@ LL | | }
 ...
 LL |       let Thing::Foo(y) = Thing::Foo(1);
    |           ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Thing::Foo(y) = Thing::Foo(1) { /* */ }
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-53912.rs b/src/test/ui/issues/issue-53912.rs
index 4718aea0429..4718aea0429 100644
--- a/src/test/ui/issue-53912.rs
+++ b/src/test/ui/issues/issue-53912.rs
diff --git a/src/test/ui/issues/issue-57271.rs b/src/test/ui/issues/issue-57271.rs
new file mode 100644
index 00000000000..9940fecbeed
--- /dev/null
+++ b/src/test/ui/issues/issue-57271.rs
@@ -0,0 +1,24 @@
+// aux-build:issue-57271-lib.rs
+
+extern crate issue_57271_lib;
+
+use issue_57271_lib::BaseType;
+
+pub enum ObjectType { //~ ERROR recursive type `ObjectType` has infinite size
+    Class(ClassTypeSignature),
+    Array(TypeSignature),
+    TypeVariable(()),
+}
+
+pub struct ClassTypeSignature {
+    pub package: (),
+    pub class: (),
+    pub inner: (),
+}
+
+pub enum TypeSignature { //~ ERROR recursive type `TypeSignature` has infinite size
+    Base(BaseType),
+    Object(ObjectType),
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr
new file mode 100644
index 00000000000..4f164624f7a
--- /dev/null
+++ b/src/test/ui/issues/issue-57271.stderr
@@ -0,0 +1,25 @@
+error[E0072]: recursive type `ObjectType` has infinite size
+  --> $DIR/issue-57271.rs:7:1
+   |
+LL | pub enum ObjectType {
+   | ^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
+LL |     Class(ClassTypeSignature),
+LL |     Array(TypeSignature),
+   |           ------------- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
+
+error[E0072]: recursive type `TypeSignature` has infinite size
+  --> $DIR/issue-57271.rs:19:1
+   |
+LL | pub enum TypeSignature {
+   | ^^^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
+LL |     Base(BaseType),
+LL |     Object(ObjectType),
+   |            ---------- recursive without indirection
+   |
+   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-57399-self-return-impl-trait.rs b/src/test/ui/issues/issue-57399-self-return-impl-trait.rs
new file mode 100644
index 00000000000..23d68263b3a
--- /dev/null
+++ b/src/test/ui/issues/issue-57399-self-return-impl-trait.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+trait T {
+    type T;
+}
+
+impl T for i32 {
+    type T = u32;
+}
+
+struct S<A> {
+    a: A,
+}
+
+
+impl From<u32> for S<<i32 as T>::T> {
+    fn from(a: u32) -> Self {
+        Self { a }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr b/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr
new file mode 100644
index 00000000000..5c71410a827
--- /dev/null
+++ b/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr
@@ -0,0 +1,8 @@
+warning: field is never used: `a`
+  --> $DIR/issue-57399-self-return-impl-trait.rs:12:5
+   |
+LL |     a: A,
+   |     ^^^^
+   |
+   = note: `#[warn(dead_code)]` on by default
+
diff --git a/src/test/ui/issue-59020.rs b/src/test/ui/issues/issue-59020.rs
index e7544934da0..e7544934da0 100644
--- a/src/test/ui/issue-59020.rs
+++ b/src/test/ui/issues/issue-59020.rs
diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs b/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs
new file mode 100644
index 00000000000..7bce57923a5
--- /dev/null
+++ b/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs
@@ -0,0 +1,5 @@
+struct X {}
+
+const Y: X = X("ö"); //~ ERROR expected function, found struct `X`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
new file mode 100644
index 00000000000..ae9025bb041
--- /dev/null
+++ b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
@@ -0,0 +1,15 @@
+error[E0423]: expected function, found struct `X`
+  --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
+   |
+LL | struct X {}
+   | ----------- `X` defined here
+LL | 
+LL | const Y: X = X("ö");
+   |              ^
+   |              |
+   |              did you mean `X { /* fields */ }`?
+   |              help: a constant with a similar name exists: `Y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
new file mode 100644
index 00000000000..e0eaafdfc2f
--- /dev/null
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
@@ -0,0 +1,11 @@
+trait Foo {
+    fn foo(&self);
+}
+
+trait Bar {}
+
+fn do_stuff<T : Bar>(t : T) {
+    t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
new file mode 100644
index 00000000000..24bf60abf6a
--- /dev/null
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `foo` found for type `T` in the current scope
+  --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
+   |
+LL |     t.foo()
+   |       ^^^ method not found in `T`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it:
+   |
+LL | fn do_stuff<T: Foo + Bar>(t : T) {
+   |             ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/match/non-exhaustive-defined-here.stderr b/src/test/ui/match/non-exhaustive-defined-here.stderr
index 25b8bbdab2d..e5f01174ac1 100644
--- a/src/test/ui/match/non-exhaustive-defined-here.stderr
+++ b/src/test/ui/match/non-exhaustive-defined-here.stderr
@@ -41,6 +41,13 @@ LL | | }
 ...
 LL |       let E::A = e;
    |           ^^^^ patterns `B` and `C` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let E::A = e { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:40:11
@@ -85,6 +92,13 @@ LL | | }
 ...
 LL |       let E::A = e;
    |           ^^^^ patterns `&B` and `&C` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let E::A = e { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:48:11
@@ -129,6 +143,13 @@ LL | | }
 ...
 LL |       let E::A = e;
    |           ^^^^ patterns `&&mut &B` and `&&mut &C` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let E::A = e { /* */ }
+   |
 
 error[E0004]: non-exhaustive patterns: `None` not covered
   --> $DIR/non-exhaustive-defined-here.rs:65:11
@@ -163,6 +184,13 @@ LL | | }
 ...
 LL |       let Opt::Some(ref _x) = e;
    |           ^^^^^^^^^^^^^^^^^ pattern `None` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Opt::Some(ref _x) = e { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/nll/issue-63154-normalize.rs b/src/test/ui/nll/issue-63154-normalize.rs
new file mode 100644
index 00000000000..484c12879d3
--- /dev/null
+++ b/src/test/ui/nll/issue-63154-normalize.rs
@@ -0,0 +1,34 @@
+// Regression test for rust-lang/rust#63154
+//
+// Before, we would ICE after failing to normalize the destination type
+// when checking call destinations and also when checking MIR
+// assignment statements.
+
+// check-pass
+
+trait HasAssocType {
+    type Inner;
+}
+
+impl HasAssocType for () {
+    type Inner = ();
+}
+
+trait Tr<I, T>: Fn(I) -> Option<T> {}
+impl<I, T, Q: Fn(I) -> Option<T>> Tr<I, T> for Q {}
+
+fn f<T: HasAssocType>() -> impl Tr<T, T::Inner> {
+    |_| None
+}
+
+fn g<T, Y>(f: impl Tr<T, Y>) -> impl Tr<T, Y> {
+    f
+}
+
+fn h() {
+    g(f())(());
+}
+
+fn main() {
+    h();
+}
diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr
index aa18b923044..2362ccd32de 100644
--- a/src/test/ui/not-panic/not-panic-safe.stderr
+++ b/src/test/ui/not-panic/not-panic-safe.stderr
@@ -8,6 +8,7 @@ LL |     assert::<&mut i32>();
    |     ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
    |
    = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32`
+   = note: `std::panic::UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/abi/abort-on-c-abi.rs b/src/test/ui/panics/abort-on-panic.rs
index 2f08730ec61..c6e8dbf012c 100644
--- a/src/test/ui/abi/abort-on-c-abi.rs
+++ b/src/test/ui/panics/abort-on-panic.rs
@@ -14,11 +14,16 @@ use std::io::prelude::*;
 use std::io;
 use std::process::{Command, Stdio};
 
-#[unwind(aborts)] // FIXME(#58794)
+#[unwind(aborts)] // FIXME(#58794) should work even without the attribute
 extern "C" fn panic_in_ffi() {
     panic!("Test");
 }
 
+#[unwind(aborts)]
+extern "Rust" fn panic_in_rust_abi() {
+    panic!("TestRust");
+}
+
 fn test() {
     let _ = panic::catch_unwind(|| { panic_in_ffi(); });
     // The process should have aborted by now.
@@ -26,15 +31,34 @@ fn test() {
     let _ = io::stdout().flush();
 }
 
+fn testrust() {
+    let _ = panic::catch_unwind(|| { panic_in_rust_abi(); });
+    // The process should have aborted by now.
+    io::stdout().write(b"This should never be printed.\n");
+    let _ = io::stdout().flush();
+}
+
 fn main() {
     let args: Vec<String> = env::args().collect();
-    if args.len() > 1 && args[1] == "test" {
-        return test();
+    if args.len() > 1 {
+        // This is inside the self-executed command.
+        match &*args[1] {
+            "test" => return test(),
+            "testrust" => return testrust(),
+            _ => panic!("bad test"),
+        }
     }
 
+    // These end up calling the self-execution branches above.
     let mut p = Command::new(&args[0])
                         .stdout(Stdio::piped())
                         .stdin(Stdio::piped())
                         .arg("test").spawn().unwrap();
     assert!(!p.wait().unwrap().success());
+
+    let mut p = Command::new(&args[0])
+                        .stdout(Stdio::piped())
+                        .stdin(Stdio::piped())
+                        .arg("testrust").spawn().unwrap();
+    assert!(!p.wait().unwrap().success());
 }
diff --git a/src/test/ui/privacy/privacy5.rs b/src/test/ui/privacy/privacy5.rs
index 741ba0be2c2..3dc26b1955c 100644
--- a/src/test/ui/privacy/privacy5.rs
+++ b/src/test/ui/privacy/privacy5.rs
@@ -48,31 +48,31 @@ mod a {
 }
 
 fn this_crate() {
-    let a = a::A(()); //~ ERROR tuple struct `A` is private
-    let b = a::B(2); //~ ERROR tuple struct `B` is private
-    let c = a::C(2, 3); //~ ERROR tuple struct `C` is private
+    let a = a::A(()); //~ ERROR tuple struct constructor `A` is private
+    let b = a::B(2); //~ ERROR tuple struct constructor `B` is private
+    let c = a::C(2, 3); //~ ERROR tuple struct constructor `C` is private
     let d = a::D(4);
 
-    let a::A(()) = a; //~ ERROR tuple struct `A` is private
-    let a::A(_) = a; //~ ERROR tuple struct `A` is private
-    match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private
-    match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private
-
-    let a::B(_) = b; //~ ERROR tuple struct `B` is private
-    let a::B(_b) = b; //~ ERROR tuple struct `B` is private
-    match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private
-    match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private
-    match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private
-                                            //~^ ERROR tuple struct `B` is private
-
-    let a::C(_, _) = c; //~ ERROR tuple struct `C` is private
-    let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private
-    let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private
-    let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private
-    match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private
-    match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private
-    match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private
-    match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private
+    let a::A(()) = a; //~ ERROR tuple struct constructor `A` is private
+    let a::A(_) = a; //~ ERROR tuple struct constructor `A` is private
+    match a { a::A(()) => {} } //~ ERROR tuple struct constructor `A` is private
+    match a { a::A(_) => {} } //~ ERROR tuple struct constructor `A` is private
+
+    let a::B(_) = b; //~ ERROR tuple struct constructor `B` is private
+    let a::B(_b) = b; //~ ERROR tuple struct constructor `B` is private
+    match b { a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private
+    match b { a::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private
+    match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private
+                                            //~^ ERROR tuple struct constructor `B` is private
+
+    let a::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private
+    let a::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private
+    let a::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private
+    let a::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private
+    match c { a::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private
+    match c { a::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private
+    match c { a::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private
+    match c { a::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private
 
     let a::D(_) = d;
     let a::D(_d) = d;
@@ -80,38 +80,38 @@ fn this_crate() {
     match d { a::D(_d) => {} }
     match d { a::D(1) => {} a::D(_) => {} }
 
-    let a2 = a::A; //~ ERROR tuple struct `A` is private
-    let b2 = a::B; //~ ERROR tuple struct `B` is private
-    let c2 = a::C; //~ ERROR tuple struct `C` is private
+    let a2 = a::A; //~ ERROR tuple struct constructor `A` is private
+    let b2 = a::B; //~ ERROR tuple struct constructor `B` is private
+    let c2 = a::C; //~ ERROR tuple struct constructor `C` is private
     let d2 = a::D;
 }
 
 fn xcrate() {
-    let a = other::A(()); //~ ERROR tuple struct `A` is private
-    let b = other::B(2); //~ ERROR tuple struct `B` is private
-    let c = other::C(2, 3); //~ ERROR tuple struct `C` is private
+    let a = other::A(()); //~ ERROR tuple struct constructor `A` is private
+    let b = other::B(2); //~ ERROR tuple struct constructor `B` is private
+    let c = other::C(2, 3); //~ ERROR tuple struct constructor `C` is private
     let d = other::D(4);
 
-    let other::A(()) = a; //~ ERROR tuple struct `A` is private
-    let other::A(_) = a; //~ ERROR tuple struct `A` is private
-    match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private
-    match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private
-
-    let other::B(_) = b; //~ ERROR tuple struct `B` is private
-    let other::B(_b) = b; //~ ERROR tuple struct `B` is private
-    match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private
-    match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private
-    match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private
-                                                    //~^ ERROR tuple struct `B` is private
-
-    let other::C(_, _) = c; //~ ERROR tuple struct `C` is private
-    let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private
-    let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private
-    let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private
-    match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private
-    match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private
-    match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private
-    match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private
+    let other::A(()) = a; //~ ERROR tuple struct constructor `A` is private
+    let other::A(_) = a; //~ ERROR tuple struct constructor `A` is private
+    match a { other::A(()) => {} } //~ ERROR tuple struct constructor `A` is private
+    match a { other::A(_) => {} } //~ ERROR tuple struct constructor `A` is private
+
+    let other::B(_) = b; //~ ERROR tuple struct constructor `B` is private
+    let other::B(_b) = b; //~ ERROR tuple struct constructor `B` is private
+    match b { other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private
+    match b { other::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private
+    match b { other::B(1) => {}//~ ERROR tuple struct constructor `B` is private
+        other::B(_) => {} }    //~ ERROR tuple struct constructor `B` is private
+
+    let other::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private
+    let other::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private
+    let other::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private
+    let other::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private
+    match c { other::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private
+    match c { other::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private
+    match c { other::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private
+    match c { other::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private
 
     let other::D(_) = d;
     let other::D(_d) = d;
@@ -119,9 +119,9 @@ fn xcrate() {
     match d { other::D(_d) => {} }
     match d { other::D(1) => {} other::D(_) => {} }
 
-    let a2 = other::A; //~ ERROR tuple struct `A` is private
-    let b2 = other::B; //~ ERROR tuple struct `B` is private
-    let c2 = other::C; //~ ERROR tuple struct `C` is private
+    let a2 = other::A; //~ ERROR tuple struct constructor `A` is private
+    let b2 = other::B; //~ ERROR tuple struct constructor `B` is private
+    let c2 = other::C; //~ ERROR tuple struct constructor `C` is private
     let d2 = other::D;
 }
 
diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr
index 532d1ac1e2f..2ee83149b69 100644
--- a/src/test/ui/privacy/privacy5.stderr
+++ b/src/test/ui/privacy/privacy5.stderr
@@ -1,386 +1,482 @@
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:51:16
    |
+LL |     pub struct A(());
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     let a = a::A(());
    |                ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:52:16
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     let b = a::B(2);
    |                ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:53:16
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     let c = a::C(2, 3);
    |                ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:56:12
    |
+LL |     pub struct A(());
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     let a::A(()) = a;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:57:12
    |
+LL |     pub struct A(());
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     let a::A(_) = a;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:58:18
    |
+LL |     pub struct A(());
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     match a { a::A(()) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:59:18
    |
+LL |     pub struct A(());
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     match a { a::A(_) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:61:12
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     let a::B(_) = b;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:62:12
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     let a::B(_b) = b;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:63:18
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     match b { a::B(_) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:64:18
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     match b { a::B(_b) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:18
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:32
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
    |                                ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:68:12
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     let a::C(_, _) = c;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:69:12
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     let a::C(_a, _) = c;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:70:12
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     let a::C(_, _b) = c;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:71:12
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     let a::C(_a, _b) = c;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:72:18
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     match c { a::C(_, _) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:73:18
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     match c { a::C(_a, _) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:74:18
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     match c { a::C(_, _b) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:75:18
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     match c { a::C(_a, _b) => {} }
    |                  ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:83:17
    |
+LL |     pub struct A(());
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     let a2 = a::A;
    |                 ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:84:17
    |
+LL |     pub struct B(isize);
+   |                  ----- a constructor is private if any of the fields is private
+...
 LL |     let b2 = a::B;
    |                 ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:85:17
    |
+LL |     pub struct C(pub isize, isize);
+   |                  ---------------- a constructor is private if any of the fields is private
+...
 LL |     let c2 = a::C;
    |                 ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:90:20
    |
 LL |     let a = other::A(());
    |                    ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct A(());
+   |              -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:91:20
    |
 LL |     let b = other::B(2);
    |                    ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:92:20
    |
 LL |     let c = other::C(2, 3);
    |                    ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:95:16
    |
 LL |     let other::A(()) = a;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct A(());
+   |              -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:96:16
    |
 LL |     let other::A(_) = a;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct A(());
+   |              -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:97:22
    |
 LL |     match a { other::A(()) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct A(());
+   |              -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:98:22
    |
 LL |     match a { other::A(_) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct A(());
+   |              -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:100:16
    |
 LL |     let other::B(_) = b;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:101:16
    |
 LL |     let other::B(_b) = b;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:102:22
    |
 LL |     match b { other::B(_) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:103:22
    |
 LL |     match b { other::B(_b) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:104:22
    |
-LL |     match b { other::B(1) => {} other::B(_) => {} }
+LL |     match b { other::B(1) => {}
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
-  --> $DIR/privacy5.rs:104:40
+error[E0603]: tuple struct constructor `B` is private
+  --> $DIR/privacy5.rs:105:16
    |
-LL |     match b { other::B(1) => {} other::B(_) => {} }
-   |                                        ^
+LL |         other::B(_) => {} }
+   |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:107:16
    |
 LL |     let other::C(_, _) = c;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:108:16
    |
 LL |     let other::C(_a, _) = c;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:109:16
    |
 LL |     let other::C(_, _b) = c;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:110:16
    |
 LL |     let other::C(_a, _b) = c;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:111:22
    |
 LL |     match c { other::C(_, _) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:112:22
    |
 LL |     match c { other::C(_a, _) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:113:22
    |
 LL |     match c { other::C(_, _b) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:114:22
    |
 LL |     match c { other::C(_a, _b) => {} }
    |                      ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `A` is private
+error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:122:21
    |
 LL |     let a2 = other::A;
    |                     ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct A(());
+   |              -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `B` is private
+error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:123:21
    |
 LL |     let b2 = other::B;
    |                     ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct B(isize);
+   |              ----- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `C` is private
+error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:124:21
    |
 LL |     let c2 = other::C;
    |                     ^
+   | 
+  ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct C(pub isize, isize);
+   |              ---------------- a constructor is private if any of the fields is private
 
 error: aborting due to 48 previous errors
 
diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs
new file mode 100644
index 00000000000..a01b8f302ca
--- /dev/null
+++ b/src/test/ui/proc-macro/disappearing-resolution.rs
@@ -0,0 +1,22 @@
+// Regression test for issue #64803 (initial attribute resolution can disappear later).
+
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+mod m {
+    use test_macros::Empty;
+}
+use m::Empty; //~ ERROR derive macro `Empty` is private
+
+// To resolve `empty_helper` we need to resolve `Empty`.
+// During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`,
+// successfully resolve `Empty` from there, and then resolve `empty_helper` as its helper.
+// During validation `use m::Empty` introduces a `Res::Err` stub, so `Empty` resolves to it,
+// and `empty_helper` can no longer be resolved.
+#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
+#[derive(Empty)]
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr
new file mode 100644
index 00000000000..a3377ef515f
--- /dev/null
+++ b/src/test/ui/proc-macro/disappearing-resolution.stderr
@@ -0,0 +1,15 @@
+error: cannot find attribute `empty_helper` in this scope
+  --> $DIR/disappearing-resolution.rs:18:3
+   |
+LL | #[empty_helper]
+   |   ^^^^^^^^^^^^
+
+error[E0603]: derive macro `Empty` is private
+  --> $DIR/disappearing-resolution.rs:11:8
+   |
+LL | use m::Empty;
+   |        ^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index b9385952faf..f9ae75b1831 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
    |
 LL |     let Ok(x) = res;
    |         ^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Ok(x) = res { /* */ }
+   |
 
 error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/recursive-types-are-not-uninhabited.rs:8:5
diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr
index 3b13e25293d..0cf5d9cd5f1 100644
--- a/src/test/ui/refutable-pattern-errors.stderr
+++ b/src/test/ui/refutable-pattern-errors.stderr
@@ -9,6 +9,13 @@ error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` an
    |
 LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
    |         ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ }
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs
index 0b389acf75d..0eecc7f8cc5 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.rs
+++ b/src/test/ui/resolve/privacy-struct-ctor.rs
@@ -16,7 +16,7 @@ mod m {
 
     fn f() {
         n::Z;
-        //~^ ERROR tuple struct `Z` is private
+        //~^ ERROR tuple struct constructor `Z` is private
         Z;
         //~^ ERROR expected value, found struct `Z`
     }
@@ -27,21 +27,21 @@ use m::S2; // OK, only the type is imported
 
 fn main() {
     m::S;
-    //~^ ERROR tuple struct `S` is private
+    //~^ ERROR tuple struct constructor `S` is private
     let _: S = m::S(2);
-    //~^ ERROR tuple struct `S` is private
+    //~^ ERROR tuple struct constructor `S` is private
     S;
     //~^ ERROR expected value, found struct `S`
     m::n::Z;
-    //~^ ERROR tuple struct `Z` is private
+    //~^ ERROR tuple struct constructor `Z` is private
 
     S2;
     //~^ ERROR expected value, found struct `S2`
 
     xcrate::m::S;
-    //~^ ERROR tuple struct `S` is private
+    //~^ ERROR tuple struct constructor `S` is private
     xcrate::S;
     //~^ ERROR expected value, found struct `xcrate::S`
     xcrate::m::n::Z;
-    //~^ ERROR tuple struct `Z` is private
+    //~^ ERROR tuple struct constructor `Z` is private
 }
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index 979367bc623..7d884d3a669 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -34,53 +34,63 @@ help: possible better candidate is found in another module, you can import it in
 LL | use m::S;
    |
 
-error[E0603]: tuple struct `Z` is private
+error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:18:12
    |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |                            --------------- a constructor is private if any of the fields is private
+...
 LL |         n::Z;
    |            ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `S` is private
+error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:29:8
    |
+LL |     pub struct S(u8);
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     m::S;
    |        ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `S` is private
+error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:31:19
    |
+LL |     pub struct S(u8);
+   |                  -- a constructor is private if any of the fields is private
+...
 LL |     let _: S = m::S(2);
    |                   ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `Z` is private
+error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:35:11
    |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |                            --------------- a constructor is private if any of the fields is private
+...
 LL |     m::n::Z;
    |           ^
-   |
-   = note: a tuple struct constructor is private if any of its fields is private
 
-error[E0603]: tuple struct `S` is private
+error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:41:16
    |
 LL |     xcrate::m::S;
    |                ^
+   | 
+  ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL |     pub struct S(u8);
+   |                  -- a constructor is private if any of the fields is private
 
-error[E0603]: tuple struct `Z` is private
+error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:45:19
    |
 LL |     xcrate::m::n::Z;
    |                   ^
+   | 
+  ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |                            --------------- a constructor is private if any of the fields is private
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.rs b/src/test/ui/rfc-2008-non-exhaustive/struct.rs
index 94ac588d240..cf383a260e0 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.rs
@@ -21,7 +21,7 @@ fn main() {
     //~^ ERROR expected function, found struct `TupleStruct` [E0423]
 
     let ts_explicit = structs::TupleStruct(640, 480);
-    //~^ ERROR tuple struct `TupleStruct` is private [E0603]
+    //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]
 
     let TupleStruct { 0: first_field, 1: second_field } = ts;
     //~^ ERROR `..` required with struct marked as non-exhaustive
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
index d75a376286f..d3686a1b869 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -10,13 +10,16 @@ error[E0423]: expected value, found struct `UnitStruct`
 LL |     let us = UnitStruct;
    |              ^^^^^^^^^^ constructor is not visible here due to private fields
 
-error[E0603]: tuple struct `TupleStruct` is private
+error[E0603]: tuple struct constructor `TupleStruct` is private
   --> $DIR/struct.rs:23:32
    |
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^
+   | 
+  ::: $DIR/auxiliary/structs.rs:13:24
    |
-   = note: a tuple struct constructor is private if any of its fields is private
+LL | pub struct TupleStruct(pub u16, pub u16);
+   |                        ---------------- a constructor is private if any of the fields is private
 
 error[E0603]: unit struct `UnitStruct` is private
   --> $DIR/struct.rs:32:32
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
index ac0025ec758..d9d6ea21b8b 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -3,8 +3,6 @@ error[E0603]: tuple variant `Tuple` is private
    |
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
    |                                                ^^^^^
-   |
-   = note: a tuple variant constructor is private if any of its fields is private
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
@@ -23,16 +21,12 @@ error[E0603]: tuple variant `Tuple` is private
    |
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
    |                                ^^^^^
-   |
-   = note: a tuple variant constructor is private if any of its fields is private
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
    |
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
    |                                   ^^^^^
-   |
-   = note: a tuple variant constructor is private if any of its fields is private
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs
new file mode 100644
index 00000000000..22ca6dde45e
--- /dev/null
+++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs
@@ -0,0 +1,14 @@
+trait Trait {}
+
+struct S;
+
+impl<'a> Trait for &'a mut S {}
+
+fn foo<X: Trait>(_: X) {}
+
+
+fn main() {
+  let s = S;
+  foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied
+  foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied
+}
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
new file mode 100644
index 00000000000..ccaceefacd7
--- /dev/null
+++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
@@ -0,0 +1,30 @@
+error[E0277]: the trait bound `&S: Trait` is not satisfied
+  --> $DIR/imm-ref-trait-object-literal.rs:12:7
+   |
+LL | fn foo<X: Trait>(_: X) {}
+   |    ---    ----- required by this bound in `foo`
+...
+LL |   foo(&s);
+   |       -^
+   |       |
+   |       the trait `Trait` is not implemented for `&S`
+   |       help: consider changing this borrow's mutability: `&mut`
+   |
+   = help: the following implementations were found:
+             <&'a mut S as Trait>
+
+error[E0277]: the trait bound `S: Trait` is not satisfied
+  --> $DIR/imm-ref-trait-object-literal.rs:13:7
+   |
+LL | fn foo<X: Trait>(_: X) {}
+   |    ---    ----- required by this bound in `foo`
+...
+LL |   foo(s);
+   |       ^ the trait `Trait` is not implemented for `S`
+   |
+   = help: the following implementations were found:
+             <&'a mut S as Trait>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs
new file mode 100644
index 00000000000..288d6c699f5
--- /dev/null
+++ b/src/test/ui/suggestions/imm-ref-trait-object.rs
@@ -0,0 +1,8 @@
+fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
+     t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object
+}
+
+fn main() {
+     let array = [0u64];
+     test(&mut array.iter());
+}
diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr
new file mode 100644
index 00000000000..9185eaa65c0
--- /dev/null
+++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr
@@ -0,0 +1,10 @@
+error: the `min` method cannot be invoked on a trait object
+  --> $DIR/imm-ref-trait-object.rs:2:8
+   |
+LL |      t.min().unwrap()
+   |        ^^^
+   |
+   = note: you need `&mut dyn std::iter::Iterator<Item = &u64>` instead of `&dyn std::iter::Iterator<Item = &u64>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
index fb3e1096ad5..a1e1f4d1357 100644
--- a/src/test/ui/suggestions/into-str.stderr
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -8,6 +8,7 @@ LL |     foo(String::new());
    |     ^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
    |
    = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix
+   = note: `std::convert::From<std::string::String>` is implemented for `&mut str`, but not for `&str`
    = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`
 
 error: aborting due to previous error
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
new file mode 100644
index 00000000000..dcef2ada63b
--- /dev/null
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
@@ -0,0 +1,23 @@
+use std::env::args;
+use std::fs::File;
+use std::io::{stdout, Write, BufWriter};
+
+fn main() {
+    let mut args = args();
+    let _ = args.next();
+    let dest = args.next();
+
+    let h1; let h2; let h3;
+
+    let fp: &dyn Write = match dest {
+        Some(path) => { h1 = File::create(path).unwrap(); &h1 },
+        None => { h2 = stdout(); h3 = h2.lock(); &h3 }
+    };
+
+    let fp = BufWriter::new(fp);
+    //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+    //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+    //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+
+    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type
+}
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
new file mode 100644
index 00000000000..daa8e1162d1
--- /dev/null
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -0,0 +1,41 @@
+error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+  --> $DIR/mut-borrow-needed-by-trait.rs:17:29
+   |
+LL |     let fp = BufWriter::new(fp);
+   |                             ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |
+   = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
+   = note: required by `std::io::BufWriter::<W>::new`
+
+error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+  --> $DIR/mut-borrow-needed-by-trait.rs:17:14
+   |
+LL |     let fp = BufWriter::new(fp);
+   |              ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |
+   = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
+   = note: required by `std::io::BufWriter`
+
+error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+  --> $DIR/mut-borrow-needed-by-trait.rs:17:14
+   |
+LL |     let fp = BufWriter::new(fp);
+   |              ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |
+   = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
+   = note: required by `std::io::BufWriter`
+
+error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope
+  --> $DIR/mut-borrow-needed-by-trait.rs:22:5
+   |
+LL |     writeln!(fp, "hello world").unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>`
+   |
+   = note: the method `write_fmt` exists but the following trait bounds were not satisfied:
+           `std::io::BufWriter<&dyn std::io::Write> : std::io::Write`
+   = 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 4 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
index 40c2c2e4c9d..63182a6bd95 100644
--- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
@@ -17,4 +17,5 @@ LL |     let (a, b) = copy(NoClone);
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0568.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
index 1184e30749f..8755bcded9d 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
@@ -6,3 +6,4 @@ LL | auto trait Magic : Sized where Option<Self> : Magic {}
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0568`.
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
index 7b45ca07b35..5a388834909 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
@@ -6,3 +6,4 @@ LL | auto trait Magic: Copy {}
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0568`.
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
index 29ff1dc3760..26e1be34ea7 100644
--- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -12,6 +12,13 @@ LL | | }
 ...
 LL |       let Foo::D(_y) = x;
    |           ^^^^^^^^^^ pattern `A(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Foo::D(_y) = x { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 25519ab2d6a..a49344e45ce 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -51,6 +51,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
    |
 LL |     let Ok(x) = x;
    |         ^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Ok(x) = x { /* */ }
+   |
 
 error: aborting due to 7 previous errors
 
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 7cf3cc7663b..4383cd9d5be 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -143,7 +143,7 @@ def issue(
         cc @{}, do you think you would have time to do the follow-up work?
         If so, that would be great!
 
-        cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
+        cc @{}, the PR reviewer, and nominating for compiler team prioritization.
 
         ''').format(
             relevant_pr_number, tool, status_description,
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 8dc9ba96d57c5705b99a18a380d41579e9d2d67
+Subproject a18df16181947edd5eb593ea0f2321e0035448e
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
-Subproject afb1ee1c14594aed5bb4a762b357b01f13c9de1
+Subproject 33e3667085e4c73d4391c6168552458eb47664d