about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-16 19:01:48 +0000
committerbors <bors@rust-lang.org>2020-07-16 19:01:48 +0000
commit5c9e5df3a097e094641f16dab501ab1c4da10e9f (patch)
treeefbe559cc0c2e00c0bb7b690975388002d00f06f /src
parent6ee1b62c811a6eb68d6db6dfb91f66a49956749b (diff)
parentff685f51f4f130d4080ef800e5e041ddbca903dc (diff)
downloadrust-5c9e5df3a097e094641f16dab501ab1c4da10e9f.tar.gz
rust-5c9e5df3a097e094641f16dab501ab1c4da10e9f.zip
Auto merge of #74408 - Manishearth:rollup-9gxn4od, r=Manishearth
Rollup of 21 pull requests

Successful merges:

 - #73566 (Don't run `everybody_loops` for rustdoc; instead ignore resolution errors)
 - #73771 (Don't pollute docs/suggestions with libstd deps)
 - #73794 (Small cleanup for E0705 explanation)
 - #73807 (rustdoc: glue tokens before highlighting)
 - #73835 (Clean up E0710 explanation)
 - #73926 (Ignoring test case: [codegen] repr-transparent-aggregates-1.rs for aarch64)
 - #73981 (Remove some `ignore-stage1` annotations.)
 - #73998 (add regression test for #61216)
 - #74140 (Make hir ProjectionKind more precise)
 - #74148 (Move #[doc(alias)] check in rustc)
 - #74159 (forbid generic params in the type of const params)
 - #74171 (Fix 44056 test with debug on macos.)
 - #74221 (Don't panic if the lhs of a div by zero is not statically known)
 - #74325 (Focus on the current file in the source file sidebar)
 - #74359 (rustdoc: Rename internal API fns to `into_string`)
 - #74370 (Reintroduce spotlight / "important traits" feature)
 - #74390 (Fix typo in std::mem::transmute documentation)
 - #74391 (BtreeMap: superficially refactor root access)
 - #74392 (const generics triage)
 - #74397 (Fix typo in the latest release note)
 - #74406 (Set shell for github actions CI)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/ci/github-actions/ci.yml20
-rw-r--r--src/doc/rustdoc/src/unstable-features.md21
-rw-r--r--src/doc/unstable-book/src/language-features/doc-spotlight.md30
-rw-r--r--src/liballoc/collections/btree/map.rs175
-rw-r--r--src/liballoc/collections/btree/node.rs5
-rw-r--r--src/libcore/future/future.rs1
-rw-r--r--src/libcore/intrinsics.rs2
-rw-r--r--src/libcore/iter/traits/iterator.rs1
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/librustc_ast_passes/feature_gate.rs1
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0671.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0705.md4
-rw-r--r--src/librustc_error_codes/error_codes/E0710.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0770.md15
-rw-r--r--src/librustc_feature/active.rs3
-rw-r--r--src/librustc_hir/hir.rs6
-rw-r--r--src/librustc_interface/passes.rs6
-rw-r--r--src/librustc_mir/transform/const_prop.rs26
-rw-r--r--src/librustc_passes/check_attr.rs30
-rw-r--r--src/librustc_resolve/diagnostics.rs13
-rw-r--r--src/librustc_resolve/late.rs113
-rw-r--r--src/librustc_resolve/lib.rs34
-rw-r--r--src/librustc_span/symbol.rs2
-rw-r--r--src/librustc_typeck/check/method/suggest.rs6
-rw-r--r--src/librustc_typeck/collect.rs61
-rw-r--r--src/librustc_typeck/expr_use_visitor.rs3
-rw-r--r--src/librustc_typeck/mem_categorization.rs170
-rw-r--r--src/librustdoc/clean/inline.rs14
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs29
-rw-r--r--src/librustdoc/core.rs108
-rw-r--r--src/librustdoc/externalfiles.rs4
-rw-r--r--src/librustdoc/html/format.rs12
-rw-r--r--src/librustdoc/html/highlight.rs51
-rw-r--r--src/librustdoc/html/highlight/tests.rs82
-rw-r--r--src/librustdoc/html/markdown.rs14
-rw-r--r--src/librustdoc/html/markdown/tests.rs7
-rw-r--r--src/librustdoc/html/render.rs86
-rw-r--r--src/librustdoc/html/sources.rs11
-rw-r--r--src/librustdoc/html/static/main.js7
-rw-r--r--src/librustdoc/html/static/rustdoc.css74
-rw-r--r--src/librustdoc/html/static/source-script.js5
-rw-r--r--src/librustdoc/html/static/themes/ayu.css5
-rw-r--r--src/librustdoc/html/static/themes/dark.css5
-rw-r--r--src/librustdoc/html/static/themes/light.css5
-rw-r--r--src/librustdoc/lib.rs3
-rw-r--r--src/librustdoc/markdown.rs4
-rw-r--r--src/libstd/io/mod.rs2
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/test/codegen/issue-44056-macos-tls-align.rs5
-rw-r--r--src/test/codegen/repr-transparent-aggregates-1.rs1
-rw-r--r--src/test/compile-fail/asm-src-loc-codegen-units.rs2
-rw-r--r--src/test/run-make-fulldeps/issue-37839/Makefile2
-rw-r--r--src/test/run-make-fulldeps/issue-37893/Makefile2
-rw-r--r--src/test/run-make-fulldeps/rustdoc-determinism/Makefile16
-rw-r--r--src/test/run-make-fulldeps/rustdoc-determinism/bar.rs1
-rw-r--r--src/test/run-make-fulldeps/rustdoc-determinism/foo.rs1
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/README.md7
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/async.rs10
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/async.stderr12
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/closure.rs5
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/closure.stderr12
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs7
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr12
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs6
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr12
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs6
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr12
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs10
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr12
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs10
-rw-r--r--src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr12
-rw-r--r--src/test/rustdoc-ui/impl-fn-nesting.rs49
-rw-r--r--src/test/rustdoc-ui/impl-fn-nesting.stderr66
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type.rs4
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type.stderr17
-rw-r--r--src/test/rustdoc/doc-spotlight.rs36
-rw-r--r--src/test/rustdoc/impl-trait-alias.rs14
-rw-r--r--src/test/rustdoc/macro-in-async-block.rs9
-rw-r--r--src/test/rustdoc/macro-in-closure.rs7
-rw-r--r--src/test/rustdoc/return-impl-trait.rs15
-rw-r--r--src/test/ui/check-doc-alias-attr.rs (renamed from src/test/rustdoc-ui/check-doc-alias-attr.rs)1
-rw-r--r--src/test/ui/check-doc-alias-attr.stderr (renamed from src/test/rustdoc-ui/check-doc-alias-attr.stderr)6
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-const-param.rs15
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr24
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs2
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr16
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.rs11
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr19
-rw-r--r--src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs14
-rw-r--r--src/test/ui/const-generics/issues/issue-68596.rs18
-rw-r--r--src/test/ui/const-generics/issues/issue-71169.rs10
-rw-r--r--src/test/ui/const-generics/issues/issue-71169.stderr17
-rw-r--r--src/test/ui/const-generics/issues/issue-71381.rs2
-rw-r--r--src/test/ui/const-generics/issues/issue-71381.stderr17
-rw-r--r--src/test/ui/const-generics/issues/issue-71611.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue-71611.stderr9
-rw-r--r--src/test/ui/const-generics/issues/issue-73120.rs8
-rw-r--r--src/test/ui/const-generics/issues/issue-73491.rs9
-rw-r--r--src/test/ui/const-generics/issues/issue-73508.rs6
-rw-r--r--src/test/ui/const-generics/issues/issue-73508.stderr17
-rw-r--r--src/test/ui/const-generics/issues/issue-74101.rs9
-rw-r--r--src/test/ui/const-generics/issues/issue-74255.rs18
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-67144-1.rs28
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-67144-2.rs22
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-70217.rs16
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-70586.rs33
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-71348.rs35
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-71805.rs41
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-73730.rs17
-rw-r--r--src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs11
-rw-r--r--src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr14
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_spotlight.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr12
-rw-r--r--src/tools/error_index_generator/main.rs2
116 files changed, 1875 insertions, 286 deletions
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 8545ec15d32..0b3b77f217d 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -95,6 +95,7 @@ x--expand-yaml-anchors--remove:
 
       - name: add extra environment variables
         run: src/ci/scripts/setup-environment.sh
+        shell: bash
         env:
           # Since it's not possible to merge `${{ matrix.env }}` with the other
           # variables in `job.<name>.env`, the variables defined in the matrix
@@ -105,54 +106,67 @@ x--expand-yaml-anchors--remove:
 
       - name: decide whether to skip this job
         run: src/ci/scripts/should-skip-this.sh
+        shell: bash
         <<: *step
 
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
+        shell: bash
         <<: *step
 
       - name: show the current environment
         run: src/ci/scripts/dump-environment.sh
+        shell: bash
         <<: *step
 
       - name: install awscli
         run: src/ci/scripts/install-awscli.sh
+        shell: bash
         <<: *step
 
       - name: install sccache
         run: src/ci/scripts/install-sccache.sh
+        shell: bash
         <<: *step
 
       - name: install clang
         run: src/ci/scripts/install-clang.sh
+        shell: bash
         <<: *step
 
       - name: install WIX
         run: src/ci/scripts/install-wix.sh
+        shell: bash
         <<: *step
 
       - name: ensure the build happens on a partition with enough space
         run: src/ci/scripts/symlink-build-dir.sh
+        shell: bash
         <<: *step
 
       - name: disable git crlf conversion
         run: src/ci/scripts/disable-git-crlf-conversion.sh
+        shell: bash
         <<: *step
 
       - name: install MSYS2
         run: src/ci/scripts/install-msys2.sh
+        shell: bash
         <<: *step
 
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
+        shell: bash
         <<: *step
 
       - name: install ninja
         run: src/ci/scripts/install-ninja.sh
+        shell: bash
         <<: *step
 
       - name: enable ipv6 on Docker
         run: src/ci/scripts/enable-docker-ipv6.sh
+        shell: bash
         <<: *step
 
       # Disable automatic line ending conversion (again). On Windows, when we're
@@ -162,18 +176,22 @@ x--expand-yaml-anchors--remove:
       # appropriate line endings.
       - name: disable git crlf conversion
         run: src/ci/scripts/disable-git-crlf-conversion.sh
+        shell: bash
         <<: *step
 
       - name: checkout submodules
         run: src/ci/scripts/checkout-submodules.sh
+        shell: bash
         <<: *step
 
       - name: ensure line endings are correct
         run: src/ci/scripts/verify-line-endings.sh
+        shell: bash
         <<: *step
 
       - name: run the build
         run: src/ci/scripts/run-build-from-ci.sh
+        shell: bash
         env:
           AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }}
           AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}
@@ -182,6 +200,7 @@ x--expand-yaml-anchors--remove:
 
       - name: upload artifacts to S3
         run: src/ci/scripts/upload-artifacts.sh
+        shell: bash
         env:
           AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}
           AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}
@@ -620,6 +639,7 @@ jobs:
 
       - name: publish toolstate
         run: src/ci/publish_toolstate.sh
+        shell: bash
         env:
           TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}
         <<: *step
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index eea674f2b84..d16c2a9d034 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -150,6 +150,27 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
 [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
 [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
 
+### Adding your trait to the "Important Traits" dialog
+
+Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
+implemented on it. These traits are intended to be the primary interface for their types, and are
+often the only thing available to be documented on their types. For this reason, Rustdoc will track
+when a given type implements one of these traits and call special attention to it when a function
+returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
+to the function, which, when clicked, shows the dialog.
+
+In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
+`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
+special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
+attribute to your own trait to include it in the "Important Traits" dialog in documentation.
+
+The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
+For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
+issue][issue-spotlight].
+
+[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
+[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
+
 ### Exclude certain dependencies from documentation
 
 The standard library uses several dependencies which, in turn, use several types and traits from the
diff --git a/src/doc/unstable-book/src/language-features/doc-spotlight.md b/src/doc/unstable-book/src/language-features/doc-spotlight.md
new file mode 100644
index 00000000000..8117755fef1
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/doc-spotlight.md
@@ -0,0 +1,30 @@
+# `doc_spotlight`
+
+The tracking issue for this feature is: [#45040]
+
+The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
+to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
+attribute to a trait definition will make rustdoc print extra information for functions which return
+a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
+`io::Write` traits in the standard library.
+
+You can do this on your own traits, like this:
+
+```
+#![feature(doc_spotlight)]
+
+#[doc(spotlight)]
+pub trait MyTrait {}
+
+pub struct MyStruct;
+impl MyTrait for MyStruct {}
+
+/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
+/// without having to write that yourself!
+pub fn my_fn() -> MyStruct { MyStruct }
+```
+
+This feature was originally implemented in PR [#45039].
+
+[#45040]: https://github.com/rust-lang/rust/issues/45040
+[#45039]: https://github.com/rust-lang/rust/pull/45039
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index f3781db1cf7..bf5748739d4 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -151,7 +151,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
                     let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
 
                     {
-                        let root = out_tree.root.as_mut().unwrap();
+                        let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped
                         let mut out_node = match root.as_mut().force() {
                             Leaf(leaf) => leaf,
                             Internal(_) => unreachable!(),
@@ -171,14 +171,10 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
                 }
                 Internal(internal) => {
                     let mut out_tree = clone_subtree(internal.first_edge().descend());
-                    out_tree.ensure_root_is_owned();
 
                     {
-                        // Ideally we'd use the return of ensure_root_is_owned
-                        // instead of re-unwrapping here but unfortunately that
-                        // borrows all of out_tree and we need access to the
-                        // length below.
-                        let mut out_node = out_tree.root.as_mut().unwrap().push_level();
+                        let out_root = BTreeMap::ensure_is_owned(&mut out_tree.root);
+                        let mut out_node = out_root.push_level();
                         let mut in_edge = internal.first_edge();
                         while let Ok(kv) = in_edge.right_kv() {
                             let (k, v) = kv.into_kv();
@@ -212,7 +208,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
             // Ord` constraint, which this method lacks.
             BTreeMap { root: None, length: 0 }
         } else {
-            clone_subtree(self.root.as_ref().unwrap().as_ref())
+            clone_subtree(self.root.as_ref().unwrap().as_ref()) // unwrap succeeds because not empty
         }
     }
 }
@@ -243,8 +239,8 @@ where
     }
 
     fn replace(&mut self, key: K) -> Option<K> {
-        self.ensure_root_is_owned();
-        match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut()?.as_mut(), &key) {
+        let root = Self::ensure_is_owned(&mut self.root);
+        match search::search_tree::<marker::Mut<'_>, K, (), K>(root.as_mut(), &key) {
             Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
             GoDown(handle) => {
                 VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
@@ -943,7 +939,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
         // Second, we build a tree from the sorted sequence in linear time.
         self.from_sorted_iter(iter);
-        self.fix_right_edge();
     }
 
     /// Constructs a double-ended iterator over a sub-range of elements in the map.
@@ -1058,8 +1053,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
         // FIXME(@porglezomp) Avoid allocating if we don't insert
-        self.ensure_root_is_owned();
-        match search::search_tree(self.root.as_mut().unwrap().as_mut(), &key) {
+        let root = Self::ensure_is_owned(&mut self.root);
+        match search::search_tree(root.as_mut(), &key) {
             Found(handle) => {
                 Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
             }
@@ -1070,8 +1065,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     }
 
     fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
-        self.ensure_root_is_owned();
-        let mut cur_node = self.root.as_mut().unwrap().as_mut().last_leaf_edge().into_node();
+        let root = Self::ensure_is_owned(&mut self.root);
+        let mut cur_node = root.as_mut().last_leaf_edge().into_node();
         // Iterate through all key-value pairs, pushing them into nodes at the right level.
         for (key, value) in iter {
             // Try to push key-value pair into the current leaf node.
@@ -1116,11 +1111,12 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
             self.length += 1;
         }
+        Self::fix_right_edge(root)
     }
 
-    fn fix_right_edge(&mut self) {
+    fn fix_right_edge(root: &mut node::Root<K, V>) {
         // Handle underfull nodes, start from the top.
-        let mut cur_node = self.root.as_mut().unwrap().as_mut();
+        let mut cur_node = root.as_mut();
         while let Internal(internal) = cur_node.force() {
             // Check if right-most child is underfull.
             let mut last_edge = internal.last_edge();
@@ -1179,16 +1175,17 @@ impl<K: Ord, V> BTreeMap<K, V> {
         }
 
         let total_num = self.len();
+        let left_root = self.root.as_mut().unwrap(); // unwrap succeeds because not empty
 
         let mut right = Self::new();
-        let right_root = right.ensure_root_is_owned();
-        for _ in 0..(self.root.as_ref().unwrap().as_ref().height()) {
+        let right_root = Self::ensure_is_owned(&mut right.root);
+        for _ in 0..left_root.height() {
             right_root.push_level();
         }
 
         {
-            let mut left_node = self.root.as_mut().unwrap().as_mut();
-            let mut right_node = right.root.as_mut().unwrap().as_mut();
+            let mut left_node = left_root.as_mut();
+            let mut right_node = right_root.as_mut();
 
             loop {
                 let mut split_edge = match search::search_node(left_node, key) {
@@ -1214,12 +1211,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
             }
         }
 
-        self.fix_right_border();
-        right.fix_left_border();
+        left_root.fix_right_border();
+        right_root.fix_left_border();
 
-        if self.root.as_ref().unwrap().as_ref().height()
-            < right.root.as_ref().unwrap().as_ref().height()
-        {
+        if left_root.height() < right_root.height() {
             self.recalc_length();
             right.length = total_num - self.len();
         } else {
@@ -1301,69 +1296,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
         self.length = dfs(self.root.as_ref().unwrap().as_ref());
     }
-
-    /// Removes empty levels on the top.
-    fn fix_top(&mut self) {
-        loop {
-            {
-                let node = self.root.as_ref().unwrap().as_ref();
-                if node.height() == 0 || node.len() > 0 {
-                    break;
-                }
-            }
-            self.root.as_mut().unwrap().pop_level();
-        }
-    }
-
-    fn fix_right_border(&mut self) {
-        self.fix_top();
-
-        {
-            let mut cur_node = self.root.as_mut().unwrap().as_mut();
-
-            while let Internal(node) = cur_node.force() {
-                let mut last_kv = node.last_kv();
-
-                if last_kv.can_merge() {
-                    cur_node = last_kv.merge().descend();
-                } else {
-                    let right_len = last_kv.reborrow().right_edge().descend().len();
-                    // `MINLEN + 1` to avoid readjust if merge happens on the next level.
-                    if right_len < node::MIN_LEN + 1 {
-                        last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
-                    }
-                    cur_node = last_kv.right_edge().descend();
-                }
-            }
-        }
-
-        self.fix_top();
-    }
-
-    /// The symmetric clone of `fix_right_border`.
-    fn fix_left_border(&mut self) {
-        self.fix_top();
-
-        {
-            let mut cur_node = self.root.as_mut().unwrap().as_mut();
-
-            while let Internal(node) = cur_node.force() {
-                let mut first_kv = node.first_kv();
-
-                if first_kv.can_merge() {
-                    cur_node = first_kv.merge().descend();
-                } else {
-                    let left_len = first_kv.reborrow().left_edge().descend().len();
-                    if left_len < node::MIN_LEN + 1 {
-                        first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
-                    }
-                    cur_node = first_kv.left_edge().descend();
-                }
-            }
-        }
-
-        self.fix_top();
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2321,9 +2253,9 @@ impl<K, V> BTreeMap<K, V> {
     }
 
     /// If the root node is the empty (non-allocated) root node, allocate our
-    /// own node.
-    fn ensure_root_is_owned(&mut self) -> &mut node::Root<K, V> {
-        self.root.get_or_insert_with(node::Root::new_leaf)
+    /// own node. Is an associated function to avoid borrowing the entire BTreeMap.
+    fn ensure_is_owned(root: &mut Option<node::Root<K, V>>) -> &mut node::Root<K, V> {
+        root.get_or_insert_with(node::Root::new_leaf)
     }
 }
 
@@ -2825,6 +2757,65 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInter
     }
 }
 
+impl<K, V> node::Root<K, V> {
+    /// Removes empty levels on the top, but keep an empty leaf if the entire tree is empty.
+    fn fix_top(&mut self) {
+        while self.height() > 0 && self.as_ref().len() == 0 {
+            self.pop_level();
+        }
+    }
+
+    fn fix_right_border(&mut self) {
+        self.fix_top();
+
+        {
+            let mut cur_node = self.as_mut();
+
+            while let Internal(node) = cur_node.force() {
+                let mut last_kv = node.last_kv();
+
+                if last_kv.can_merge() {
+                    cur_node = last_kv.merge().descend();
+                } else {
+                    let right_len = last_kv.reborrow().right_edge().descend().len();
+                    // `MINLEN + 1` to avoid readjust if merge happens on the next level.
+                    if right_len < node::MIN_LEN + 1 {
+                        last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
+                    }
+                    cur_node = last_kv.right_edge().descend();
+                }
+            }
+        }
+
+        self.fix_top();
+    }
+
+    /// The symmetric clone of `fix_right_border`.
+    fn fix_left_border(&mut self) {
+        self.fix_top();
+
+        {
+            let mut cur_node = self.as_mut();
+
+            while let Internal(node) = cur_node.force() {
+                let mut first_kv = node.first_kv();
+
+                if first_kv.can_merge() {
+                    cur_node = first_kv.merge().descend();
+                } else {
+                    let left_len = first_kv.reborrow().left_edge().descend().len();
+                    if left_len < node::MIN_LEN + 1 {
+                        first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
+                    }
+                    cur_node = first_kv.left_edge().descend();
+                }
+            }
+        }
+
+        self.fix_top();
+    }
+}
+
 enum UnderflowResult<'a, K, V> {
     AtRoot,
     Merged(Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>, bool, usize),
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index ce74d4f8ee6..f7bd64608d6 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -153,6 +153,11 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
 unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
 
 impl<K, V> Root<K, V> {
+    /// Returns the number of levels below the root.
+    pub fn height(&self) -> usize {
+        self.height
+    }
+
     /// Returns a new owned tree, with its own root node that is initially empty.
     pub fn new_leaf() -> Self {
         Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs
index abf461338d8..733ebdc0e97 100644
--- a/src/libcore/future/future.rs
+++ b/src/libcore/future/future.rs
@@ -24,6 +24,7 @@ use crate::task::{Context, Poll};
 /// `.await` the value.
 ///
 /// [`Waker`]: ../task/struct.Waker.html
+#[doc(spotlight)]
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[lang = "future_trait"]
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 540a8cfb290..45b636b0089 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1126,7 +1126,7 @@ extern "rust-intrinsic" {
     ///
     /// // use `u32::from_ne_bytes` instead
     /// let num = u32::from_ne_bytes(raw_bytes);
-    /// // or use `u32::from_le_bytes` or `u32::from_ge_bytes` to specify the endianness
+    /// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness
     /// let num = u32::from_le_bytes(raw_bytes);
     /// assert_eq!(num, 0x12345678);
     /// let num = u32::from_be_bytes(raw_bytes);
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index ce4be973140..692eed80c02 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -92,6 +92,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
     label = "`{Self}` is not an iterator",
     message = "`{Self}` is not an iterator"
 )]
+#[doc(spotlight)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 pub trait Iterator {
     /// The type of the elements being iterated over.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 88991dea7d4..c2dc3e5985f 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -96,6 +96,7 @@
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
+#![cfg_attr(not(bootstrap), feature(doc_spotlight))]
 #![feature(duration_consts_2)]
 #![feature(extern_types)]
 #![feature(fundamental)]
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index a7b0c9cf81b..b424c8afb34 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -253,6 +253,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     include => external_doc
                     cfg => doc_cfg
                     masked => doc_masked
+                    spotlight => doc_spotlight
                     alias => doc_alias
                     keyword => doc_keyword
                 );
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 60aa12b0511..6160450d766 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -452,6 +452,7 @@ E0766: include_str!("./error_codes/E0766.md"),
 E0767: include_str!("./error_codes/E0767.md"),
 E0768: include_str!("./error_codes/E0768.md"),
 E0769: include_str!("./error_codes/E0769.md"),
+E0770: include_str!("./error_codes/E0770.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0671.md b/src/librustc_error_codes/error_codes/E0671.md
index 449fb8ffc89..a993ce826a7 100644
--- a/src/librustc_error_codes/error_codes/E0671.md
+++ b/src/librustc_error_codes/error_codes/E0671.md
@@ -3,7 +3,7 @@
 Const parameters cannot depend on type parameters.
 The following is therefore invalid:
 
-```compile_fail,E0741
+```compile_fail,E0770
 #![feature(const_generics)]
 
 fn const_id<T, const N: T>() -> T { // error
diff --git a/src/librustc_error_codes/error_codes/E0705.md b/src/librustc_error_codes/error_codes/E0705.md
index 8fa09fe8e72..1edd47de4cb 100644
--- a/src/librustc_error_codes/error_codes/E0705.md
+++ b/src/librustc_error_codes/error_codes/E0705.md
@@ -1,5 +1,5 @@
-A `#![feature]` attribute was declared for a feature that is stable in
-the current edition, but not in all editions.
+A `#![feature]` attribute was declared for a feature that is stable in the
+current edition, but not in all editions.
 
 Erroneous code example:
 
diff --git a/src/librustc_error_codes/error_codes/E0710.md b/src/librustc_error_codes/error_codes/E0710.md
index d9cefe2a6da..b7037ea611b 100644
--- a/src/librustc_error_codes/error_codes/E0710.md
+++ b/src/librustc_error_codes/error_codes/E0710.md
@@ -1,4 +1,4 @@
-An unknown tool name found in scoped lint
+An unknown tool name was found in a scoped lint.
 
 Erroneous code examples:
 
diff --git a/src/librustc_error_codes/error_codes/E0770.md b/src/librustc_error_codes/error_codes/E0770.md
new file mode 100644
index 00000000000..278bf9b907b
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0770.md
@@ -0,0 +1,15 @@
+The type of a const parameter references other generic parameters.
+
+Erroneous code example:
+
+```compile_fail,E0770
+#![feature(const_generics)]
+fn foo<T, const N: T>() {} // error!
+```
+
+To fix this error, use a concrete type for the const parameter:
+
+```
+#![feature(const_generics)]
+fn foo<T, const N: usize>() {}
+```
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 0da3693af4f..d7c310a8b4c 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -368,6 +368,9 @@ declare_features! (
     /// Allows `#[doc(masked)]`.
     (active, doc_masked, "1.21.0", Some(44027), None),
 
+    /// Allows `#[doc(spotlight)]`.
+    (active, doc_spotlight, "1.22.0", Some(45040), None),
+
     /// Allows `#[doc(include = "some-file")]`.
     (active, external_doc, "1.22.0", Some(44732), None),
 
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 07b489a7562..9204f778a24 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2687,7 +2687,7 @@ pub enum Node<'hir> {
     Crate(&'hir CrateItem<'hir>),
 }
 
-impl Node<'_> {
+impl<'hir> Node<'hir> {
     pub fn ident(&self) -> Option<Ident> {
         match self {
             Node::TraitItem(TraitItem { ident, .. })
@@ -2698,7 +2698,7 @@ impl Node<'_> {
         }
     }
 
-    pub fn fn_decl(&self) -> Option<&FnDecl<'_>> {
+    pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
         match self {
             Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
@@ -2722,7 +2722,7 @@ impl Node<'_> {
         }
     }
 
-    pub fn generics(&self) -> Option<&Generics<'_>> {
+    pub fn generics(&self) -> Option<&'hir Generics<'hir>> {
         match self {
             Node::TraitItem(TraitItem { generics, .. })
             | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index af4397075bb..f1b9fafc781 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -354,13 +354,7 @@ fn configure_and_expand_inner<'a>(
         )
     });
 
-    // If we're actually rustdoc then there's no need to actually compile
-    // anything, so switch everything to just looping
-    let mut should_loop = sess.opts.actually_rustdoc;
     if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
-        should_loop |= true;
-    }
-    if should_loop {
         log::debug!("replacing bodies with loop {{}}");
         util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
     }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index fbe3377d875..237a5a64f8b 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -484,7 +484,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         lint: &'static lint::Lint,
         source_info: SourceInfo,
         message: &'static str,
-        panic: AssertKind<ConstInt>,
+        panic: AssertKind<impl std::fmt::Debug>,
     ) -> Option<()> {
         let lint_root = self.lint_root(source_info)?;
         self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
@@ -1004,11 +1004,27 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                     let expected = ScalarMaybeUninit::from(Scalar::from_bool(*expected));
                     let value_const = self.ecx.read_scalar(value).unwrap();
                     if expected != value_const {
+                        enum DbgVal<T> {
+                            Val(T),
+                            Underscore,
+                        }
+                        impl<T: std::fmt::Debug> std::fmt::Debug for DbgVal<T> {
+                            fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+                                match self {
+                                    Self::Val(val) => val.fmt(fmt),
+                                    Self::Underscore => fmt.write_str("_"),
+                                }
+                            }
+                        }
                         let mut eval_to_int = |op| {
-                            let op = self
-                                .eval_operand(op, source_info)
-                                .expect("if we got here, it must be const");
-                            self.ecx.read_immediate(op).unwrap().to_const_int()
+                            // This can be `None` if the lhs wasn't const propagated and we just
+                            // triggered the assert on the value of the rhs.
+                            match self.eval_operand(op, source_info) {
+                                Some(op) => {
+                                    DbgVal::Val(self.ecx.read_immediate(op).unwrap().to_const_int())
+                                }
+                                None => DbgVal::Underscore,
+                            }
                         };
                         let msg = match msg {
                             AssertKind::DivisionByZero(op) => {
diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs
index 46aa5a4dcdf..3e63a63d9d0 100644
--- a/src/librustc_passes/check_attr.rs
+++ b/src/librustc_passes/check_attr.rs
@@ -70,6 +70,8 @@ impl CheckAttrVisitor<'tcx> {
                 self.check_target_feature(attr, span, target)
             } else if attr.check_name(sym::track_caller) {
                 self.check_track_caller(&attr.span, attrs, span, target)
+            } else if attr.check_name(sym::doc) {
+                self.check_doc_alias(attr)
             } else {
                 true
             };
@@ -216,6 +218,34 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
+    fn check_doc_alias(&self, attr: &Attribute) -> bool {
+        if let Some(mi) = attr.meta() {
+            if let Some(list) = mi.meta_item_list() {
+                for meta in list {
+                    if meta.check_name(sym::alias) {
+                        if !meta.is_value_str()
+                            || meta
+                                .value_str()
+                                .map(|s| s.to_string())
+                                .unwrap_or_else(String::new)
+                                .is_empty()
+                        {
+                            self.tcx
+                                .sess
+                                .struct_span_err(
+                                    meta.span(),
+                                    "doc alias attribute expects a string: #[doc(alias = \"0\")]",
+                                )
+                                .emit();
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+        true
+    }
+
     /// Checks if the `#[repr]` attributes on `item` are valid.
     fn check_repr(
         &self,
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 4f25b948eb6..575049c6bac 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -442,6 +442,19 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
+            ResolutionError::ParamInTyOfConstArg(name) => {
+                let mut err = struct_span_err!(
+                    self.session,
+                    span,
+                    E0770,
+                    "the type of const parameters must not depend on other generic parameters"
+                );
+                err.span_label(
+                    span,
+                    format!("the type must not depend on the parameter `{}`", name),
+                );
+                err
+            }
             ResolutionError::SelfInTyParamDefault => {
                 let mut err = struct_span_err!(
                     self.session,
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index c165a601408..ed88e549692 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -123,6 +123,10 @@ crate enum RibKind<'a> {
     /// from the default of a type parameter because they're not declared
     /// before said type parameter. Also see the `visit_generics` override.
     ForwardTyParamBanRibKind,
+
+    /// We are inside of the type of a const parameter. Can't refer to any
+    /// parameters.
+    ConstParamTyRibKind,
 }
 
 impl RibKind<'_> {
@@ -135,7 +139,8 @@ impl RibKind<'_> {
             | FnItemRibKind
             | ConstantItemRibKind
             | ModuleRibKind(_)
-            | MacroDefinition(_) => false,
+            | MacroDefinition(_)
+            | ConstParamTyRibKind => false,
             AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true,
         }
     }
@@ -394,13 +399,23 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
 
     /// Fields used to add information to diagnostic errors.
     diagnostic_metadata: DiagnosticMetadata<'ast>,
+
+    /// State used to know whether to ignore resolution errors for function bodies.
+    ///
+    /// In particular, rustdoc uses this to avoid giving errors for `cfg()` items.
+    /// In most cases this will be `None`, in which case errors will always be reported.
+    /// If it is `Some(_)`, then it will be updated when entering a nested function or trait body.
+    in_func_body: bool,
 }
 
 /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
 impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
     fn visit_item(&mut self, item: &'ast Item) {
         let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
+        // Always report errors in items we just entered.
+        let old_ignore = replace(&mut self.in_func_body, false);
         self.resolve_item(item);
+        self.in_func_body = old_ignore;
         self.diagnostic_metadata.current_item = prev;
     }
     fn visit_arm(&mut self, arm: &'ast Arm) {
@@ -497,6 +512,9 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
 
                 visit::walk_fn_ret_ty(this, &declaration.output);
 
+                // Ignore errors in function bodies if this is rustdoc
+                // Be sure not to set this until the function signature has been resolved.
+                let previous_state = replace(&mut this.in_func_body, true);
                 // Resolve the function body, potentially inside the body of an async closure
                 match fn_kind {
                     FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
@@ -504,6 +522,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                 };
 
                 debug!("(resolving function) leaving function");
+                this.in_func_body = previous_state;
             })
         });
         self.diagnostic_metadata.current_function = previous_value;
@@ -562,7 +581,11 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                     for bound in &param.bounds {
                         self.visit_param_bound(bound);
                     }
+                    self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
+                    self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
                     self.visit_ty(ty);
+                    self.ribs[TypeNS].pop().unwrap();
+                    self.ribs[ValueNS].pop().unwrap();
                 }
             }
         }
@@ -644,6 +667,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             label_ribs: Vec::new(),
             current_trait_ref: None,
             diagnostic_metadata: DiagnosticMetadata::default(),
+            // errors at module scope should always be reported
+            in_func_body: false,
         }
     }
 
@@ -757,7 +782,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 return if self.is_label_valid_from_rib(i) {
                     Some(*id)
                 } else {
-                    self.r.report_error(
+                    self.report_error(
                         original_span,
                         ResolutionError::UnreachableLabel {
                             name: label.name,
@@ -775,7 +800,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
         }
 
-        self.r.report_error(
+        self.report_error(
             original_span,
             ResolutionError::UndeclaredLabel { name: label.name, suggestion },
         );
@@ -798,7 +823,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | ItemRibKind(..)
                 | ConstantItemRibKind
                 | ModuleRibKind(..)
-                | ForwardTyParamBanRibKind => {
+                | ForwardTyParamBanRibKind
+                | ConstParamTyRibKind => {
                     return false;
                 }
             }
@@ -833,7 +859,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             };
             let report_error = |this: &Self, ns| {
                 let what = if ns == TypeNS { "type parameters" } else { "local variables" };
-                this.r.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
+                if this.should_report_errs() {
+                    this.r
+                        .session
+                        .span_err(ident.span, &format!("imports cannot refer to {}", what));
+                }
             };
 
             for &ns in nss {
@@ -1008,7 +1038,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             if seen_bindings.contains_key(&ident) {
                 let span = seen_bindings.get(&ident).unwrap();
                 let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, *span);
-                self.r.report_error(param.ident.span, err);
+                self.report_error(param.ident.span, err);
             }
             seen_bindings.entry(ident).or_insert(param.ident.span);
 
@@ -1274,7 +1304,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 .is_err()
             {
                 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
-                self.r.report_error(span, err(ident.name, &path_names_to_string(path)));
+                self.report_error(span, err(ident.name, &path_names_to_string(path)));
             }
         }
     }
@@ -1289,6 +1319,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
     }
 
     fn resolve_local(&mut self, local: &'ast Local) {
+        debug!("resolving local ({:?})", local);
         // Resolve the type.
         walk_list!(self, visit_ty, &local.ty);
 
@@ -1390,7 +1421,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             if inconsistent_vars.contains_key(name) {
                 v.could_be_path = false;
             }
-            self.r.report_error(
+            self.report_error(
                 *v.origin.iter().next().unwrap(),
                 ResolutionError::VariableNotBoundInPattern(v),
             );
@@ -1400,7 +1431,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
         inconsistent_vars.sort();
         for (name, v) in inconsistent_vars {
-            self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
+            self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
         }
 
         // 5) Finally bubble up all the binding maps.
@@ -1550,7 +1581,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 // `Variant(a, a)`:
                 _ => IdentifierBoundMoreThanOnceInSamePattern,
             };
-            self.r.report_error(ident.span, error(ident.name));
+            self.report_error(ident.span, error(ident.name));
         }
 
         // Record as bound if it's valid:
@@ -1624,7 +1655,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 // to something unusable as a pattern (e.g., constructor function),
                 // but we still conservatively report an error, see
                 // issues/33118#issuecomment-233962221 for one reason why.
-                self.r.report_error(
+                self.report_error(
                     ident.span,
                     ResolutionError::BindingShadowsSomethingUnacceptable(
                         pat_src.descr(),
@@ -1677,18 +1708,27 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         source: PathSource<'ast>,
         crate_lint: CrateLint,
     ) -> PartialRes {
+        log::debug!("smart_resolve_path_fragment(id={:?},qself={:?},path={:?}", id, qself, path);
         let ns = source.namespace();
         let is_expected = &|res| source.is_expected(res);
 
         let report_errors = |this: &mut Self, res: Option<Res>| {
-            let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
-
-            let def_id = this.parent_scope.module.normal_ancestor_id;
-            let instead = res.is_some();
-            let suggestion =
-                if res.is_none() { this.report_missing_type_error(path) } else { None };
-
-            this.r.use_injections.push(UseError { err, candidates, def_id, instead, suggestion });
+            if this.should_report_errs() {
+                let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
+
+                let def_id = this.parent_scope.module.normal_ancestor_id;
+                let instead = res.is_some();
+                let suggestion =
+                    if res.is_none() { this.report_missing_type_error(path) } else { None };
+
+                this.r.use_injections.push(UseError {
+                    err,
+                    candidates,
+                    def_id,
+                    instead,
+                    suggestion,
+                });
+            }
 
             PartialRes::new(Res::Err)
         };
@@ -1746,13 +1786,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
             let def_id = this.parent_scope.module.normal_ancestor_id;
 
-            this.r.use_injections.push(UseError {
-                err,
-                candidates,
-                def_id,
-                instead: false,
-                suggestion: None,
-            });
+            if this.should_report_errs() {
+                this.r.use_injections.push(UseError {
+                    err,
+                    candidates,
+                    def_id,
+                    instead: false,
+                    suggestion: None,
+                });
+            } else {
+                err.cancel();
+            }
 
             // We don't return `Some(parent_err)` here, because the error will
             // be already printed as part of the `use` injections
@@ -1809,7 +1853,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
             Err(err) => {
                 if let Some(err) = report_errors_for_call(self, err) {
-                    self.r.report_error(err.span, err.node);
+                    self.report_error(err.span, err.node);
                 }
 
                 PartialRes::new(Res::Err)
@@ -1843,6 +1887,21 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
     }
 
+    /// A wrapper around [`Resolver::report_error`].
+    ///
+    /// This doesn't emit errors for function bodies if this is rustdoc.
+    fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) {
+        if self.should_report_errs() {
+            self.r.report_error(span, resolution_error);
+        }
+    }
+
+    #[inline]
+    /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items.
+    fn should_report_errs(&self) -> bool {
+        !(self.r.session.opts.actually_rustdoc && self.in_func_body)
+    }
+
     // Resolve in alternative namespaces if resolution in the primary namespace fails.
     fn resolve_qpath_anywhere(
         &mut self,
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a265c15c18b..c3686ca4899 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -214,6 +214,8 @@ enum ResolutionError<'a> {
     BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
     /// Error E0128: type parameters with a default cannot use forward-declared identifiers.
     ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
+    /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
+    ParamInTyOfConstArg(Symbol),
     /// Error E0735: type parameters with a default cannot use `Self`
     SelfInTyParamDefault,
     /// Error E0767: use of unreachable label
@@ -2480,6 +2482,12 @@ impl<'a> Resolver<'a> {
                             }
                             return Res::Err;
                         }
+                        ConstParamTyRibKind => {
+                            if record_used {
+                                self.report_error(span, ParamInTyOfConstArg(rib_ident.name));
+                            }
+                            return Res::Err;
+                        }
                     }
                 }
                 if let Some(res_err) = res_err {
@@ -2503,6 +2511,15 @@ impl<'a> Resolver<'a> {
                         // This was an attempt to use a type parameter outside its scope.
                         ItemRibKind(has_generic_params) => has_generic_params,
                         FnItemRibKind => HasGenericParams::Yes,
+                        ConstParamTyRibKind => {
+                            if record_used {
+                                self.report_error(
+                                    span,
+                                    ResolutionError::ParamInTyOfConstArg(rib_ident.name),
+                                );
+                            }
+                            return Res::Err;
+                        }
                     };
 
                     if record_used {
@@ -2527,9 +2544,24 @@ impl<'a> Resolver<'a> {
                 }
                 for rib in ribs {
                     let has_generic_params = match rib.kind {
+                        NormalRibKind
+                        | ClosureOrAsyncRibKind
+                        | AssocItemRibKind
+                        | ModuleRibKind(..)
+                        | MacroDefinition(..)
+                        | ForwardTyParamBanRibKind
+                        | ConstantItemRibKind => continue,
                         ItemRibKind(has_generic_params) => has_generic_params,
                         FnItemRibKind => HasGenericParams::Yes,
-                        _ => continue,
+                        ConstParamTyRibKind => {
+                            if record_used {
+                                self.report_error(
+                                    span,
+                                    ResolutionError::ParamInTyOfConstArg(rib_ident.name),
+                                );
+                            }
+                            return Res::Err;
+                        }
                     };
 
                     // This was an attempt to use a const parameter outside its scope.
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 75f588918a0..ccb6ccb57fa 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -400,6 +400,7 @@ symbols! {
         doc_cfg,
         doc_keyword,
         doc_masked,
+        doc_spotlight,
         doctest,
         document_private_items,
         dotdot_in_tuple_patterns,
@@ -968,6 +969,7 @@ symbols! {
         soft,
         specialization,
         speed,
+        spotlight,
         sqrtf32,
         sqrtf64,
         sse4a_target_feature,
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index b8e26fc4871..f6ebf8b56bd 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -937,6 +937,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // legal to implement.
         let mut candidates = all_traits(self.tcx)
             .into_iter()
+            // Don't issue suggestions for unstable traits since they're
+            // unlikely to be implementable anyway
+            .filter(|info| match self.tcx.lookup_stability(info.def_id) {
+                Some(attr) => attr.level.is_stable(),
+                None => true,
+            })
             .filter(|info| {
                 // We approximate the coherence rules to only suggest
                 // traits that are legal to implement by requiring that
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 4354996614b..17212187e6a 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::weak_lang_items;
-use rustc_hir::{GenericParamKind, Node};
+use rustc_hir::{GenericParamKind, HirId, Node};
 use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -1155,6 +1155,35 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     }
 }
 
+struct AnonConstInParamListDetector {
+    in_param_list: bool,
+    found_anon_const_in_list: bool,
+    ct: HirId,
+}
+
+impl<'v> Visitor<'v> for AnonConstInParamListDetector {
+    type Map = intravisit::ErasedMap<'v>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
+        let prev = self.in_param_list;
+        self.in_param_list = true;
+        intravisit::walk_generic_param(self, p);
+        self.in_param_list = prev;
+    }
+
+    fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
+        if self.in_param_list && self.ct == c.hir_id {
+            self.found_anon_const_in_list = true;
+        } else {
+            intravisit::walk_anon_const(self, c)
+        }
+    }
+}
+
 fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
     use rustc_hir::*;
 
@@ -1176,10 +1205,32 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             let parent_id = tcx.hir().get_parent_item(hir_id);
             let parent_def_id = tcx.hir().local_def_id(parent_id);
 
-            // HACK(eddyb) this provides the correct generics when
-            // `feature(const_generics)` is enabled, so that const expressions
-            // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
-            if tcx.lazy_normalization() {
+            let mut in_param_list = false;
+            for (_parent, node) in tcx.hir().parent_iter(hir_id) {
+                if let Some(generics) = node.generics() {
+                    let mut visitor = AnonConstInParamListDetector {
+                        in_param_list: false,
+                        found_anon_const_in_list: false,
+                        ct: hir_id,
+                    };
+
+                    visitor.visit_generics(generics);
+                    in_param_list = visitor.found_anon_const_in_list;
+                    break;
+                }
+            }
+
+            if in_param_list {
+                // We do not allow generic parameters in anon consts if we are inside
+                // of a param list.
+                //
+                // This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
+                // and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
+                None
+            } else if tcx.lazy_normalization() {
+                // HACK(eddyb) this provides the correct generics when
+                // `feature(const_generics)` is enabled, so that const expressions
+                // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
                 Some(parent_def_id.to_def_id())
             } else {
                 let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs
index 4e5ef4329c2..1be32729b1e 100644
--- a/src/librustc_typeck/expr_use_visitor.rs
+++ b/src/librustc_typeck/expr_use_visitor.rs
@@ -11,8 +11,10 @@ use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::PatKind;
+use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::{self, adjustment, TyCtxt};
+use rustc_target::abi::VariantIdx;
 
 use crate::mem_categorization as mc;
 use rustc_span::Span;
@@ -396,6 +398,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             &*with_expr,
                             with_place.clone(),
                             with_field.ty(self.tcx(), substs),
+                            mc::ProjectionKind::Field(f_index as u32, VariantIdx::new(0)),
                         );
                         self.delegate_consume(&field_place);
                     }
diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs
index ac42ce80689..70fe2c2cda5 100644
--- a/src/librustc_typeck/mem_categorization.rs
+++ b/src/librustc_typeck/mem_categorization.rs
@@ -54,11 +54,14 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
+use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::PatKind;
+use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
+use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::infer::InferCtxtExt;
 
 #[derive(Clone, Debug)]
@@ -77,8 +80,20 @@ pub enum PlaceBase {
 pub enum ProjectionKind {
     /// A dereference of a pointer, reference or `Box<T>` of the given type
     Deref,
-    /// An index or a field
-    Other,
+
+    /// `B.F` where `B` is the base expression and `F` is
+    /// the field. The field is identified by which variant
+    /// it appears in along with a field index. The variant
+    /// is used for enums.
+    Field(u32, VariantIdx),
+
+    /// Some index like `B[x]`, where `B` is the base
+    /// expression. We don't preserve the index `x` because
+    /// we won't need it.
+    Index,
+
+    /// A subslice covering a range of values like `B[x..y]`.
+    Subslice,
 }
 
 #[derive(Clone, Debug)]
@@ -406,7 +421,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             hir::ExprKind::Field(ref base, _) => {
                 let base = self.cat_expr(&base)?;
                 debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base);
-                Ok(self.cat_projection(expr, base, expr_ty))
+
+                let field_idx = self
+                    .tables
+                    .field_indices()
+                    .get(expr.hir_id)
+                    .cloned()
+                    .expect("Field index not found");
+
+                Ok(self.cat_projection(
+                    expr,
+                    base,
+                    expr_ty,
+                    ProjectionKind::Field(field_idx as u32, VariantIdx::new(0)),
+                ))
             }
 
             hir::ExprKind::Index(ref base, _) => {
@@ -419,7 +447,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                     self.cat_overloaded_place(expr, base)
                 } else {
                     let base = self.cat_expr(&base)?;
-                    Ok(self.cat_projection(expr, base, expr_ty))
+                    Ok(self.cat_projection(expr, base, expr_ty, ProjectionKind::Index))
                 }
             }
 
@@ -533,9 +561,10 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         node: &N,
         base_place: PlaceWithHirId<'tcx>,
         ty: Ty<'tcx>,
+        kind: ProjectionKind,
     ) -> PlaceWithHirId<'tcx> {
         let mut projections = base_place.place.projections;
-        projections.push(Projection { kind: ProjectionKind::Other, ty: ty });
+        projections.push(Projection { kind: kind, ty: ty });
         let ret = PlaceWithHirId::new(
             node.hir_id(),
             base_place.place.base_ty,
@@ -609,6 +638,75 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         self.cat_pattern_(place, pat, &mut op)
     }
 
+    /// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
+    /// Here `pat_hir_id` is the HirId of the pattern itself.
+    fn variant_index_for_adt(
+        &self,
+        qpath: &hir::QPath<'_>,
+        pat_hir_id: hir::HirId,
+        span: Span,
+    ) -> McResult<VariantIdx> {
+        let res = self.tables.qpath_res(qpath, pat_hir_id);
+        let ty = self.tables.node_type(pat_hir_id);
+        let adt_def = match ty.kind {
+            ty::Adt(adt_def, _) => adt_def,
+            _ => {
+                self.tcx()
+                    .sess
+                    .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
+                return Err(());
+            }
+        };
+
+        match res {
+            Res::Def(DefKind::Variant, variant_id) => Ok(adt_def.variant_index_with_id(variant_id)),
+            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
+                Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id))
+            }
+            Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
+            | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
+            | Res::SelfCtor(..)
+            | Res::SelfTy(..) => {
+                // Structs and Unions have only have one variant.
+                Ok(VariantIdx::new(0))
+            }
+            _ => bug!("expected ADT path, found={:?}", res),
+        }
+    }
+
+    /// Returns the total number of fields in an ADT variant used within a pattern.
+    /// Here `pat_hir_id` is the HirId of the pattern itself.
+    fn total_fields_in_adt_variant(
+        &self,
+        pat_hir_id: hir::HirId,
+        variant_index: VariantIdx,
+        span: Span,
+    ) -> McResult<usize> {
+        let ty = self.tables.node_type(pat_hir_id);
+        match ty.kind {
+            ty::Adt(adt_def, _) => Ok(adt_def.variants[variant_index].fields.len()),
+            _ => {
+                self.tcx()
+                    .sess
+                    .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
+                return Err(());
+            }
+        }
+    }
+
+    /// Returns the total number of fields in a tuple used within a Tuple pattern.
+    /// Here `pat_hir_id` is the HirId of the pattern itself.
+    fn total_fields_in_tuple(&self, pat_hir_id: hir::HirId, span: Span) -> McResult<usize> {
+        let ty = self.tables.node_type(pat_hir_id);
+        match ty.kind {
+            ty::Tuple(substs) => Ok(substs.len()),
+            _ => {
+                self.tcx().sess.delay_span_bug(span, "tuple pattern not applied to a tuple");
+                return Err(());
+            }
+        }
+    }
+
     // FIXME(#19596) This is a workaround, but there should be a better way to do this
     fn cat_pattern_<F>(
         &self,
@@ -679,20 +777,54 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         op(&place_with_id, pat);
 
         match pat.kind {
-            PatKind::TupleStruct(_, ref subpats, _) | PatKind::Tuple(ref subpats, _) => {
-                // S(p1, ..., pN) or (p1, ..., pN)
-                for subpat in subpats.iter() {
+            PatKind::Tuple(ref subpats, dots_pos) => {
+                // (p1, ..., pN)
+                let total_fields = self.total_fields_in_tuple(pat.hir_id, pat.span)?;
+
+                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
                     let subpat_ty = self.pat_ty_adjusted(&subpat)?;
-                    let sub_place = self.cat_projection(pat, place_with_id.clone(), subpat_ty);
+                    let projection_kind = ProjectionKind::Field(i as u32, VariantIdx::new(0));
+                    let sub_place =
+                        self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
                     self.cat_pattern_(sub_place, &subpat, op)?;
                 }
             }
 
-            PatKind::Struct(_, field_pats, _) => {
+            PatKind::TupleStruct(ref qpath, ref subpats, dots_pos) => {
+                // S(p1, ..., pN)
+                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
+                let total_fields =
+                    self.total_fields_in_adt_variant(pat.hir_id, variant_index, pat.span)?;
+
+                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
+                    let subpat_ty = self.pat_ty_adjusted(&subpat)?;
+                    let projection_kind = ProjectionKind::Field(i as u32, variant_index);
+                    let sub_place =
+                        self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
+                    self.cat_pattern_(sub_place, &subpat, op)?;
+                }
+            }
+
+            PatKind::Struct(ref qpath, field_pats, _) => {
                 // S { f1: p1, ..., fN: pN }
+
+                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
+
                 for fp in field_pats {
                     let field_ty = self.pat_ty_adjusted(&fp.pat)?;
-                    let field_place = self.cat_projection(pat, place_with_id.clone(), field_ty);
+                    let field_index = self
+                        .tables
+                        .field_indices()
+                        .get(fp.hir_id)
+                        .cloned()
+                        .expect("no index for a field");
+
+                    let field_place = self.cat_projection(
+                        pat,
+                        place_with_id.clone(),
+                        field_ty,
+                        ProjectionKind::Field(field_index as u32, variant_index),
+                    );
                     self.cat_pattern_(field_place, &fp.pat, op)?;
                 }
             }
@@ -723,13 +855,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                         return Err(());
                     }
                 };
-                let elt_place = self.cat_projection(pat, place_with_id.clone(), element_ty);
+                let elt_place = self.cat_projection(
+                    pat,
+                    place_with_id.clone(),
+                    element_ty,
+                    ProjectionKind::Index,
+                );
                 for before_pat in before {
                     self.cat_pattern_(elt_place.clone(), &before_pat, op)?;
                 }
                 if let Some(ref slice_pat) = *slice {
                     let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?;
-                    let slice_place = self.cat_projection(pat, place_with_id, slice_pat_ty);
+                    let slice_place = self.cat_projection(
+                        pat,
+                        place_with_id,
+                        slice_pat_ty,
+                        ProjectionKind::Subslice,
+                    );
                     self.cat_pattern_(slice_place, &slice_pat, op)?;
                 }
                 for after_pat in after {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 78628b198a3..491daa80e5c 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -12,7 +12,7 @@ use rustc_metadata::creader::LoadedMacro;
 use rustc_middle::ty;
 use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
 use crate::clean::{self, GetDefId, ToSource, TypeKind};
@@ -194,6 +194,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
     let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
+    let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
     let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         auto: auto_trait,
@@ -201,6 +202,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
         generics,
         items: trait_items,
         bounds: supertrait_bounds,
+        is_spotlight,
         is_auto,
     }
 }
@@ -339,6 +341,16 @@ pub fn build_impl(
                 return;
             }
         }
+
+        // Skip foreign unstable traits from lists of trait implementations and
+        // such. This helps prevent dependencies of the standard library, for
+        // example, from getting documented as "traits `u32` implements" which
+        // isn't really too helpful.
+        if let Some(stab) = cx.tcx.lookup_stability(did) {
+            if stab.level.is_unstable() {
+                return;
+            }
+        }
     }
 
     let for_ = if let Some(did) = did.as_local() {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 03d6853494c..8a4ee91df40 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1007,6 +1007,7 @@ impl Clean<FnRetTy> for hir::FnRetTy<'_> {
 impl Clean<Item> for doctree::Trait<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
+        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
         Item {
             name: Some(self.name.clean(cx)),
             attrs,
@@ -1021,6 +1022,7 @@ impl Clean<Item> for doctree::Trait<'_> {
                 items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
+                is_spotlight,
                 is_auto: self.is_auto.clean(cx),
             }),
         }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index c9ae67ded0a..6a03722cd08 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -486,33 +486,6 @@ impl Attributes {
         })
     }
 
-    /// Enforce the format of attributes inside `#[doc(...)]`.
-    pub fn check_doc_attributes(
-        diagnostic: &::rustc_errors::Handler,
-        mi: &ast::MetaItem,
-    ) -> Option<(String, String)> {
-        mi.meta_item_list().and_then(|list| {
-            for meta in list {
-                if meta.check_name(sym::alias) {
-                    if !meta.is_value_str()
-                        || meta
-                            .value_str()
-                            .map(|s| s.to_string())
-                            .unwrap_or_else(String::new)
-                            .is_empty()
-                    {
-                        diagnostic.span_err(
-                            meta.span(),
-                            "doc alias attribute expects a string: #[doc(alias = \"0\")]",
-                        );
-                    }
-                }
-            }
-
-            None
-        })
-    }
-
     pub fn has_doc_flag(&self, flag: Symbol) -> bool {
         for attr in &self.other_attrs {
             if !attr.check_name(sym::doc) {
@@ -556,7 +529,6 @@ impl Attributes {
                 } else {
                     if attr.check_name(sym::doc) {
                         if let Some(mi) = attr.meta() {
-                            Attributes::check_doc_attributes(&diagnostic, &mi);
                             if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
                                 // Extracted #[doc(cfg(...))]
                                 match Cfg::parse(cfg_mi) {
@@ -995,6 +967,7 @@ pub struct Trait {
     pub items: Vec<Item>,
     pub generics: Generics,
     pub bounds: Vec<GenericBound>,
+    pub is_spotlight: bool,
     pub is_auto: bool,
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a222920c7d2..00315675faf 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -5,10 +5,15 @@ use rustc_driver::abort_on_err;
 use rustc_errors::emitter::{Emitter, EmitterWriter};
 use rustc_errors::json::JsonEmitter;
 use rustc_feature::UnstableFeatures;
-use rustc_hir::def::Namespace::TypeNS;
+use rustc_hir::def::{Namespace::TypeNS, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::HirId;
+use rustc_hir::{
+    intravisit::{self, NestedVisitorMap, Visitor},
+    Path,
+};
 use rustc_interface::interface;
+use rustc_middle::hir::map::Map;
 use rustc_middle::middle::cstore::CrateStore;
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::{Ty, TyCtxt};
@@ -372,7 +377,35 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         crate_name,
         lint_caps,
         register_lints: None,
-        override_queries: None,
+        override_queries: Some(|_sess, providers, _external_providers| {
+            // Most lints will require typechecking, so just don't run them.
+            providers.lint_mod = |_, _| {};
+            // Prevent `rustc_typeck::check_crate` from calling `typeck_tables_of` on all bodies.
+            providers.typeck_item_bodies = |_, _| {};
+            // hack so that `used_trait_imports` won't try to call typeck_tables_of
+            providers.used_trait_imports = |_, _| {
+                lazy_static! {
+                    static ref EMPTY_SET: FxHashSet<LocalDefId> = FxHashSet::default();
+                }
+                &EMPTY_SET
+            };
+            // In case typeck does end up being called, don't ICE in case there were name resolution errors
+            providers.typeck_tables_of = move |tcx, def_id| {
+                // Closures' tables come from their outermost function,
+                // as they are part of the same "inference environment".
+                // This avoids emitting errors for the parent twice (see similar code in `typeck_tables_of_with_fallback`)
+                let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
+                if outer_def_id != def_id {
+                    return tcx.typeck_tables_of(outer_def_id);
+                }
+
+                let hir = tcx.hir();
+                let body = hir.body(hir.body_owned_by(hir.as_local_hir_id(def_id)));
+                debug!("visiting body for {:?}", def_id);
+                EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
+                (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck_tables_of)(tcx, def_id)
+            };
+        }),
         registry: rustc_driver::diagnostics_registry(),
     };
 
@@ -416,10 +449,17 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
             let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
 
             global_ctxt.enter(|tcx| {
-                tcx.analysis(LOCAL_CRATE).ok();
-
-                // Abort if there were any errors so far
-                sess.abort_if_errors();
+                // Certain queries assume that some checks were run elsewhere
+                // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
+                // so type-check everything other than function bodies in this crate before running lints.
+                // NOTE: this does not call `tcx.analysis()` so that we won't
+                // typeck function bodies or run the default rustc lints.
+                // (see `override_queries` in the `config`)
+                let _ = rustc_typeck::check_crate(tcx);
+                tcx.sess.abort_if_errors();
+                sess.time("missing_docs", || {
+                    rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
+                });
 
                 let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
                 // Convert from a HirId set to a DefId set since we don't always have easy access
@@ -570,6 +610,62 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
     })
 }
 
+/// Due to https://github.com/rust-lang/rust/pull/73566,
+/// the name resolution pass may find errors that are never emitted.
+/// If typeck is called after this happens, then we'll get an ICE:
+/// 'Res::Error found but not reported'. To avoid this, emit the errors now.
+struct EmitIgnoredResolutionErrors<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> EmitIgnoredResolutionErrors<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> Self {
+        Self { tcx }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        // We need to recurse into nested closures,
+        // since those will fallback to the parent for type checking.
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
+    }
+
+    fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
+        debug!("visiting path {:?}", path);
+        if path.res == Res::Err {
+            // We have less context here than in rustc_resolve,
+            // so we can only emit the name and span.
+            // However we can give a hint that rustc_resolve will have more info.
+            let label = format!(
+                "could not resolve path `{}`",
+                path.segments
+                    .iter()
+                    .map(|segment| segment.ident.as_str().to_string())
+                    .collect::<Vec<_>>()
+                    .join("::")
+            );
+            let mut err = rustc_errors::struct_span_err!(
+                self.tcx.sess,
+                path.span,
+                E0433,
+                "failed to resolve: {}",
+                label
+            );
+            err.span_label(path.span, label);
+            err.note("this error was originally ignored because you are running `rustdoc`");
+            err.note("try running again with `rustc` or `cargo check` and you may get a more detailed error");
+            err.emit();
+        }
+        // We could have an outer resolution that succeeded,
+        // but with generic parameters that failed.
+        // Recurse into the segments so we catch those too.
+        intravisit::walk_path(self, path);
+    }
+}
+
 /// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
 /// for `impl Trait` in argument position.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 8b5a3a2ba61..c8121d39d0f 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -37,14 +37,14 @@ impl ExternalHtml {
         let bc = format!(
             "{}{}",
             bc,
-            Markdown(&m_bc, &[], id_map, codes, edition, playground).to_string()
+            Markdown(&m_bc, &[], id_map, codes, edition, playground).into_string()
         );
         let ac = load_external_files(after_content, diag)?;
         let m_ac = load_external_files(md_after_content, diag)?;
         let ac = format!(
             "{}{}",
             ac,
-            Markdown(&m_ac, &[], id_map, codes, edition, playground).to_string()
+            Markdown(&m_ac, &[], id_map, codes, edition, playground).into_string()
         );
         Some(ExternalHtml { in_header: ih, before_content: bc, after_content: ac })
     }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index a453a8b3dcb..0d8284029af 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -63,10 +63,22 @@ impl Buffer {
         Buffer { for_html: false, buffer: String::new() }
     }
 
+    crate fn is_empty(&self) -> bool {
+        self.buffer.is_empty()
+    }
+
     crate fn into_inner(self) -> String {
         self.buffer
     }
 
+    crate fn insert_str(&mut self, idx: usize, s: &str) {
+        self.buffer.insert_str(idx, s);
+    }
+
+    crate fn push_str(&mut self, s: &str) {
+        self.buffer.push_str(s);
+    }
+
     // Intended for consumption by write! and writeln! (std::fmt) but without
     // the fmt::Result return type imposed by fmt::Write (and avoiding the trait
     // import).
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index c4bc73770a7..d4302d0cb54 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -12,15 +12,17 @@ use std::io;
 use std::io::prelude::*;
 
 use rustc_ast::token::{self, Token};
+use rustc_data_structures::sync::Lrc;
 use rustc_parse::lexer;
 use rustc_session::parse::ParseSess;
+use rustc_span::hygiene::SyntaxContext;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym};
-use rustc_span::{FileName, Span};
+use rustc_span::{BytePos, FileName, SourceFile, Span};
 
 /// Highlights `src`, returning the HTML output.
 pub fn render_with_highlighting(
-    src: &str,
+    src: String,
     class: Option<&str>,
     playground_button: Option<&str>,
     tooltip: Option<(&str, &str)>,
@@ -38,12 +40,13 @@ pub fn render_with_highlighting(
     }
 
     let sess = ParseSess::with_silent_emitter();
-    let sf = sess
+    let source_file = sess
         .source_map()
-        .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned());
+        .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src);
+
+    let classifier_source_file = Lrc::clone(&source_file);
     let highlight_result = rustc_driver::catch_fatal_errors(|| {
-        let lexer = lexer::StringReader::new(&sess, sf, None);
-        let mut classifier = Classifier::new(lexer, sess.source_map());
+        let mut classifier = Classifier::new(&sess, classifier_source_file);
 
         let mut highlighted_source = vec![];
         if classifier.write_source(&mut highlighted_source).is_err() {
@@ -61,9 +64,17 @@ pub fn render_with_highlighting(
             write_footer(&mut out, playground_button).unwrap();
         }
         Err(()) => {
+            // Get the source back out of the source map to avoid a copy in the happy path.
+            let span =
+                Span::new(BytePos(0), BytePos(source_file.byte_length()), SyntaxContext::root());
+            let src = sess
+                .source_map()
+                .span_to_snippet(span)
+                .expect("could not retrieve snippet from artificial source file");
+
             // If errors are encountered while trying to highlight, just emit
             // the unhighlighted source.
-            write!(out, "<pre><code>{}</code></pre>", Escape(src)).unwrap();
+            write!(out, "<pre><code>{}</code></pre>", Escape(&src)).unwrap();
         }
     }
 
@@ -73,10 +84,10 @@ pub fn render_with_highlighting(
 /// Processes a program (nested in the internal `lexer`), classifying strings of
 /// text by highlighting category (`Class`). Calls out to a `Writer` to write
 /// each span of text in sequence.
-struct Classifier<'a> {
-    lexer: lexer::StringReader<'a>,
+struct Classifier<'sess> {
+    lexer: lexer::StringReader<'sess>,
     peek_token: Option<Token>,
-    source_map: &'a SourceMap,
+    source_map: &'sess SourceMap,
 
     // State of the classifier.
     in_attribute: bool,
@@ -154,6 +165,7 @@ impl<U: Write> Writer for U {
     }
 }
 
+#[derive(Debug)]
 enum HighlightError {
     LexError,
     IoError(io::Error),
@@ -165,12 +177,14 @@ impl From<io::Error> for HighlightError {
     }
 }
 
-impl<'a> Classifier<'a> {
-    fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> {
+impl<'sess> Classifier<'sess> {
+    fn new(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Classifier<'_> {
+        let lexer = lexer::StringReader::new(sess, source_file, None);
+
         Classifier {
             lexer,
             peek_token: None,
-            source_map,
+            source_map: sess.source_map(),
             in_attribute: false,
             in_macro: false,
             in_macro_nonterminal: false,
@@ -209,11 +223,17 @@ impl<'a> Classifier<'a> {
     /// source.
     fn write_source<W: Writer>(&mut self, out: &mut W) -> Result<(), HighlightError> {
         loop {
-            let next = self.try_next_token()?;
+            let mut next = self.try_next_token()?;
             if next == token::Eof {
                 break;
             }
 
+            // Glue any tokens that need to be glued.
+            if let Some(joint) = next.glue(self.peek()?) {
+                next = joint;
+                let _ = self.try_next_token()?;
+            }
+
             self.write_token(out, next)?;
         }
 
@@ -429,3 +449,6 @@ fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> {
 fn write_footer(out: &mut dyn Write, playground_button: Option<&str>) -> io::Result<()> {
     write!(out, "</pre>{}</div>\n", if let Some(button) = playground_button { button } else { "" })
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
new file mode 100644
index 00000000000..01b25fd6be4
--- /dev/null
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -0,0 +1,82 @@
+use rustc_ast::attr::with_session_globals;
+use rustc_session::parse::ParseSess;
+use rustc_span::edition::Edition;
+use rustc_span::FileName;
+
+use super::Classifier;
+
+fn highlight(src: &str) -> String {
+    let mut out = vec![];
+
+    with_session_globals(Edition::Edition2018, || {
+        let sess = ParseSess::with_silent_emitter();
+        let source_file = sess.source_map().new_source_file(
+            FileName::Custom(String::from("rustdoc-highlighting")),
+            src.to_owned(),
+        );
+
+        let mut classifier = Classifier::new(&sess, source_file);
+        classifier.write_source(&mut out).unwrap();
+    });
+
+    String::from_utf8(out).unwrap()
+}
+
+#[test]
+fn function() {
+    assert_eq!(
+        highlight("fn main() {}"),
+        r#"<span class="kw">fn</span> <span class="ident">main</span>() {}"#,
+    );
+}
+
+#[test]
+fn statement() {
+    assert_eq!(
+        highlight("let foo = true;"),
+        concat!(
+            r#"<span class="kw">let</span> <span class="ident">foo</span> "#,
+            r#"<span class="op">=</span> <span class="bool-val">true</span>;"#,
+        ),
+    );
+}
+
+#[test]
+fn inner_attr() {
+    assert_eq!(
+        highlight(r##"#![crate_type = "lib"]"##),
+        concat!(
+            r##"<span class="attribute">#![<span class="ident">crate_type</span> "##,
+            r##"<span class="op">=</span> <span class="string">&quot;lib&quot;</span>]</span>"##,
+        ),
+    );
+}
+
+#[test]
+fn outer_attr() {
+    assert_eq!(
+        highlight(r##"#[cfg(target_os = "linux")]"##),
+        concat!(
+            r##"<span class="attribute">#[<span class="ident">cfg</span>("##,
+            r##"<span class="ident">target_os</span> <span class="op">=</span> "##,
+            r##"<span class="string">&quot;linux&quot;</span>)]</span>"##,
+        ),
+    );
+}
+
+#[test]
+fn mac() {
+    assert_eq!(
+        highlight("mac!(foo bar)"),
+        concat!(
+            r#"<span class="macro">mac</span><span class="macro">!</span>("#,
+            r#"<span class="ident">foo</span> <span class="ident">bar</span>)"#,
+        ),
+    );
+}
+
+// Regression test for #72684
+#[test]
+fn andand() {
+    assert_eq!(highlight("&&"), r#"<span class="op">&amp;&amp;</span>"#);
+}
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index a0f8eb04e2e..4cfd81ffbce 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -13,7 +13,7 @@
 //! let s = "My *markdown* _text_";
 //! let mut id_map = IdMap::new();
 //! let md = Markdown(s, &[], &mut id_map, ErrorCodes::Yes, Edition::Edition2015, &None);
-//! let html = md.to_string();
+//! let html = md.into_string();
 //! // ... something using html
 //! ```
 
@@ -292,7 +292,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
 
         if let Some((s1, s2)) = tooltip {
             s.push_str(&highlight::render_with_highlighting(
-                &text,
+                text,
                 Some(&format!(
                     "rust-example-rendered{}",
                     if ignore != Ignore::None {
@@ -313,7 +313,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
             Some(Event::Html(s.into()))
         } else {
             s.push_str(&highlight::render_with_highlighting(
-                &text,
+                text,
                 Some(&format!(
                     "rust-example-rendered{}",
                     if ignore != Ignore::None {
@@ -848,7 +848,7 @@ impl LangString {
 }
 
 impl Markdown<'_> {
-    pub fn to_string(self) -> String {
+    pub fn into_string(self) -> String {
         let Markdown(md, links, mut ids, codes, edition, playground) = self;
 
         // This is actually common enough to special-case
@@ -878,7 +878,7 @@ impl Markdown<'_> {
 }
 
 impl MarkdownWithToc<'_> {
-    pub fn to_string(self) -> String {
+    pub fn into_string(self) -> String {
         let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
 
         let p = Parser::new_ext(md, opts());
@@ -899,7 +899,7 @@ impl MarkdownWithToc<'_> {
 }
 
 impl MarkdownHtml<'_> {
-    pub fn to_string(self) -> String {
+    pub fn into_string(self) -> String {
         let MarkdownHtml(md, mut ids, codes, edition, playground) = self;
 
         // This is actually common enough to special-case
@@ -926,7 +926,7 @@ impl MarkdownHtml<'_> {
 }
 
 impl MarkdownSummaryLine<'_> {
-    pub fn to_string(self) -> String {
+    pub fn into_string(self) -> String {
         let MarkdownSummaryLine(md, links) = self;
         // This is actually common enough to special-case
         if md.is_empty() {
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index bf0451a1d9d..783977d285d 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -134,7 +134,7 @@ fn test_header() {
     fn t(input: &str, expect: &str) {
         let mut map = IdMap::new();
         let output =
-            Markdown(input, &[], &mut map, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string();
+            Markdown(input, &[], &mut map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
         assert_eq!(output, expect, "original: {}", input);
     }
 
@@ -166,7 +166,8 @@ fn test_header() {
 fn test_header_ids_multiple_blocks() {
     let mut map = IdMap::new();
     fn t(map: &mut IdMap, input: &str, expect: &str) {
-        let output = Markdown(input, &[], map, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string();
+        let output =
+            Markdown(input, &[], map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
         assert_eq!(output, expect, "original: {}", input);
     }
 
@@ -228,7 +229,7 @@ fn test_markdown_html_escape() {
     fn t(input: &str, expect: &str) {
         let mut idmap = IdMap::new();
         let output =
-            MarkdownHtml(input, &mut idmap, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string();
+            MarkdownHtml(input, &mut idmap, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
         assert_eq!(output, expect, "original: {}", input);
     }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 9fa3f6cc396..31e35125dac 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1895,7 +1895,7 @@ fn render_markdown(
             cx.shared.edition,
             &cx.shared.playground
         )
-        .to_string()
+        .into_string()
     )
 }
 
@@ -2185,7 +2185,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
                        </tr>",
                     name = *myitem.name.as_ref().unwrap(),
                     stab_tags = stability_tags(myitem),
-                    docs = MarkdownSummaryLine(doc_value, &myitem.links()).to_string(),
+                    docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
                     class = myitem.type_(),
                     add = add,
                     stab = stab.unwrap_or_else(String::new),
@@ -2278,7 +2278,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
                 cx.shared.edition,
                 &cx.shared.playground,
             );
-            message.push_str(&format!(": {}", html.to_string()));
+            message.push_str(&format!(": {}", html.into_string()));
         }
         stability.push(format!(
             "<div class='stab deprecated'><span class='emoji'>👎</span> {}</div>",
@@ -2332,7 +2332,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
                     cx.shared.edition,
                     &cx.shared.playground,
                 )
-                .to_string()
+                .into_string()
             );
         }
 
@@ -2415,7 +2415,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
     write!(
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
-           {name}{generics}{decl}{where_clause}</pre>",
+           {name}{generics}{decl}{spotlight}{where_clause}</pre>",
         vis = it.visibility.print_with_space(),
         constness = f.header.constness.print_with_space(),
         asyncness = f.header.asyncness.print_with_space(),
@@ -2425,7 +2425,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
         generics = f.generics.print(),
         where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
         decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
-            .print()
+            .print(),
+        spotlight = spotlight_decl(&f.decl),
     );
     document(w, cx, it)
 }
@@ -2612,7 +2613,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         let name = m.name.as_ref().unwrap();
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
-        write!(w, "<h3 id='{id}' class='method'><code>", id = id);
+        write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
         write!(w, "</code>");
         render_stability_since(w, m, t);
@@ -2926,7 +2927,7 @@ fn render_assoc_item(
         write!(
             w,
             "{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
-                   {generics}{decl}{where_clause}",
+                   {generics}{decl}{spotlight}{where_clause}",
             if parent == ItemType::Trait { "    " } else { "" },
             meth.visibility.print_with_space(),
             header.constness.print_with_space(),
@@ -2938,6 +2939,7 @@ fn render_assoc_item(
             name = name,
             generics = g.print(),
             decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }.print(),
+            spotlight = spotlight_decl(&d),
             where_clause = WhereClause { gens: g, indent, end_newline }
         )
     }
@@ -3559,6 +3561,62 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
     }
 }
 
+fn spotlight_decl(decl: &clean::FnDecl) -> String {
+    let mut out = Buffer::html();
+    let mut trait_ = String::new();
+
+    if let Some(did) = decl.output.def_id() {
+        let c = cache();
+        if let Some(impls) = c.impls.get(&did) {
+            for i in impls {
+                let impl_ = i.inner_impl();
+                if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
+                    if out.is_empty() {
+                        out.push_str(&format!(
+                            "<h3 class=\"important\">Important traits for {}</h3>\
+                                      <code class=\"content\">",
+                            impl_.for_.print()
+                        ));
+                        trait_.push_str(&impl_.for_.print().to_string());
+                    }
+
+                    //use the "where" class here to make it small
+                    out.push_str(&format!(
+                        "<span class=\"where fmt-newline\">{}</span>",
+                        impl_.print()
+                    ));
+                    let t_did = impl_.trait_.def_id().unwrap();
+                    for it in &impl_.items {
+                        if let clean::TypedefItem(ref tydef, _) = it.inner {
+                            out.push_str("<span class=\"where fmt-newline\">    ");
+                            assoc_type(
+                                &mut out,
+                                it,
+                                &[],
+                                Some(&tydef.type_),
+                                AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
+                                "",
+                            );
+                            out.push_str(";</span>");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if !out.is_empty() {
+        out.insert_str(
+            0,
+            "<span class=\"important-traits\"><span class=\"important-traits-tooltip\">ⓘ<div class='important-traits-tooltiptext'><span class=\"docblock\">"
+
+        );
+        out.push_str("</code></span></div></span></span>");
+    }
+
+    out.into_inner()
+}
+
 fn render_impl(
     w: &mut Buffer,
     cx: &Context,
@@ -3632,7 +3690,7 @@ fn render_impl(
                     cx.shared.edition,
                     &cx.shared.playground
                 )
-                .to_string()
+                .into_string()
             );
         }
     }
@@ -3670,7 +3728,8 @@ fn render_impl(
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
-                    write!(w, "<h4 id='{}' class=\"{}{}\"><code>", id, item_type, extra_class);
+                    write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
+                    write!(w, "<code>");
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
                     render_stability_since_raw(w, item.stable_since(), outer_version);
@@ -4526,7 +4585,12 @@ fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
 
 fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro) {
     wrap_into_docblock(w, |w| {
-        w.write_str(&highlight::render_with_highlighting(&t.source, Some("macro"), None, None))
+        w.write_str(&highlight::render_with_highlighting(
+            t.source.clone(),
+            Some("macro"),
+            None,
+            None,
+        ))
     });
     document(w, cx, it)
 }
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 03f79b93186..e3215921f12 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -75,7 +75,7 @@ impl<'a> SourceCollector<'a> {
             return Ok(());
         }
 
-        let contents = match fs::read_to_string(&p) {
+        let mut contents = match fs::read_to_string(&p) {
             Ok(contents) => contents,
             Err(e) => {
                 return Err(Error::new(e, &p));
@@ -83,8 +83,9 @@ impl<'a> SourceCollector<'a> {
         };
 
         // Remove the utf-8 BOM if any
-        let contents =
-            if contents.starts_with("\u{feff}") { &contents[3..] } else { &contents[..] };
+        if contents.starts_with("\u{feff}") {
+            contents.drain(..3);
+        }
 
         // Create the intermediate directories
         let mut cur = self.dst.clone();
@@ -122,7 +123,7 @@ impl<'a> SourceCollector<'a> {
             &self.scx.layout,
             &page,
             "",
-            |buf: &mut _| print_src(buf, &contents),
+            |buf: &mut _| print_src(buf, contents),
             &self.scx.style_files,
         );
         self.scx.fs.write(&cur, v.as_bytes())?;
@@ -160,7 +161,7 @@ where
 
 /// Wrapper struct to render the source code of a file. This will do things like
 /// adding line numbers to the left-hand side.
-fn print_src(buf: &mut Buffer, s: &str) {
+fn print_src(buf: &mut Buffer, s: String) {
     let lines = s.lines().count();
     let mut cols = 0;
     let mut tmp = lines;
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 336c691ac1c..082f9cca064 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -2636,6 +2636,13 @@ function defocusSearchBar() {
         });
     }());
 
+    onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
+        e.onclick = function() {
+            this.getElementsByClassName('important-traits-tooltiptext')[0]
+                .classList.toggle("force-tooltip");
+        };
+    });
+
     // In the search display, allows to switch between tabs.
     function printTab(nb) {
         if (nb === 0 || nb === 1 || nb === 2) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 15a0c76ceea..f5551446bf2 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -146,9 +146,12 @@ code, pre, a.test-arrow {
 	border-radius: 3px;
 	padding: 0 0.1em;
 }
-.docblock pre code, .docblock-short pre code {
+.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
 	padding: 0;
 }
+.docblock code.spotlight :last-child {
+	padding-bottom: 0.6em;
+}
 pre {
 	padding: 14px;
 }
@@ -523,7 +526,7 @@ h4 > code, h3 > code, .invisible > code {
 	font-size: 0.8em;
 }
 
-.content .methods > div {
+.content .methods > div:not(.important-traits) {
 	margin-left: 40px;
 	margin-bottom: 15px;
 }
@@ -1079,10 +1082,6 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	font-size: 16px;
 }
 
-.tooltip:hover .tooltiptext {
-	display: inline;
-}
-
 .tooltip .tooltiptext::after {
 	content: " ";
 	position: absolute;
@@ -1098,13 +1097,52 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	font-size: 20px;
 }
 
-.tooltip .tooltiptext {
+.important-traits-tooltip {
+	display: inline-block;
+	cursor: pointer;
+}
+
+.important-traits:hover .important-traits-tooltiptext,
+.important-traits .important-traits-tooltiptext.force-tooltip {
+	display: inline-block;
+}
+
+.important-traits .important-traits-tooltiptext {
+	display: none;
+	padding: 5px 3px 3px 3px;
+	border-radius: 6px;
+	margin-left: 5px;
+	z-index: 10;
+	font-size: 16px;
+	cursor: default;
+	position: absolute;
 	border: 1px solid;
-	font-weight: normal;
 }
 
-pre.rust {
+.important-traits-tooltip::after {
+	/* The margin on the tooltip does not capture hover events,
+	   this extends the area of hover enough so that mouse hover is not
+	   lost when moving the mouse to the tooltip */
+    content: "\00a0\00a0\00a0";
+}
+
+.important-traits .important, .important-traits .docblock {
+	margin: 0;
+}
+
+.important-traits .docblock code.content{
+    margin: 0;
+    padding: 0;
+    font-size: 20px;
+}
+
+/* Example code has the "Run" button that
+   needs to be positioned relative to the pre */
+pre.rust.rust-example-rendered {
 	position: relative;
+}
+
+pre.rust {
 	tab-size: 4;
 	-moz-tab-size: 4;
 }
@@ -1144,6 +1182,18 @@ pre.rust {
 	font-size: 16px;
 }
 
+.important-traits {
+	cursor: pointer;
+	z-index: 2;
+	margin-left: 5px;
+}
+
+h4 > .important-traits {
+	position: absolute;
+	left: -44px;
+	top: 2px;
+}
+
 #all-types {
 	text-align: center;
 	border: 1px solid;
@@ -1370,6 +1420,12 @@ pre.rust {
 		z-index: 1;
 	}
 
+	h4 > .important-traits {
+		position: absolute;
+		left: -22px;
+		top: 24px;
+	}
+
 	#titles > div > div.count {
 		float: left;
 		width: 100%;
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index cfbfe6675f5..6805f2a266f 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -140,4 +140,9 @@ function createSourceSidebar() {
     });
 
     main.insertBefore(sidebar, main.firstChild);
+    // Focus on the current file in the source files sidebar.
+    var selected_elem = sidebar.getElementsByClassName("selected")[0];
+    if (typeof selected_elem !== "undefined") {
+        selected_elem.focus();
+    }
 }
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index bc21c28750f..b436997da58 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -394,6 +394,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent #314559 transparent transparent;
 }
 
+.important-traits-tooltiptext {
+    background-color: #314559;
+    border-color: #5c6773;
+}
+
 #titles > div.selected {
     background-color: #141920 !important;
 	border-bottom: 1px solid #ffb44c !important;
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 41dcb5c2450..f4ca67f8540 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -337,6 +337,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent black transparent transparent;
 }
 
+.important-traits-tooltiptext {
+	background-color: #111;
+	border-color: #777;
+}
+
 #titles > div:not(.selected) {
 	background-color: #252525;
 	border-top-color: #252525;
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 386fe2398e6..b5a0ba4775c 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -331,6 +331,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent black transparent transparent;
 }
 
+.important-traits-tooltiptext {
+	background-color: #eee;
+	border-color: #999;
+}
+
 #titles > div:not(.selected) {
 	background-color: #e6e6e6;
 	border-top-color: #e6e6e6;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 57151e2b200..cbf53d52ef0 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -15,6 +15,8 @@
 #![recursion_limit = "256"]
 
 extern crate env_logger;
+#[macro_use]
+extern crate lazy_static;
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
@@ -94,6 +96,7 @@ pub fn main() {
         32_000_000 // 32MB on other platforms
     };
     rustc_driver::set_sigpipe_handler();
+    rustc_driver::install_ice_hook();
     env_logger::init_from_env("RUSTDOC_LOG");
     let res = std::thread::Builder::new()
         .stack_size(thread_stack_size)
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index e0753bcd70f..89d184e35cb 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -68,9 +68,9 @@ pub fn render<P: AsRef<Path>>(
     let mut ids = IdMap::new();
     let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
     let text = if !options.markdown_no_toc {
-        MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).to_string()
+        MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string()
     } else {
-        Markdown(text, &[], &mut ids, error_codes, edition, &playground).to_string()
+        Markdown(text, &[], &mut ids, error_codes, edition, &playground).into_string()
     };
 
     let err = write!(
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 717d2868abf..d5af4f25102 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -499,6 +499,7 @@ where
 /// [`&str`]: ../../std/primitive.str.html
 /// [slice]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(spotlight)]
 pub trait Read {
     /// Pull some bytes from this source into the specified buffer, returning
     /// how many bytes were read.
@@ -1261,6 +1262,7 @@ impl Initializer {
 ///
 /// [`write_all`]: #method.write_all
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(spotlight)]
 pub trait Write {
     /// Write a buffer into this writer, returning how many bytes were written.
     ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 4fd5e238eea..cbc24009a94 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -261,6 +261,7 @@
 #![feature(doc_cfg)]
 #![feature(doc_keyword)]
 #![feature(doc_masked)]
+#![cfg_attr(not(bootstrap), feature(doc_spotlight))]
 #![feature(dropck_eyepatch)]
 #![feature(duration_constants)]
 #![feature(exact_size_is_empty)]
diff --git a/src/test/codegen/issue-44056-macos-tls-align.rs b/src/test/codegen/issue-44056-macos-tls-align.rs
index eee59be629b..2270eca5014 100644
--- a/src/test/codegen/issue-44056-macos-tls-align.rs
+++ b/src/test/codegen/issue-44056-macos-tls-align.rs
@@ -6,12 +6,13 @@
 #![crate_type = "rlib"]
 #![feature(thread_local)]
 
-// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
+// local_unnamed_addr does not appear when std is built with debug assertions.
+// CHECK: @STATIC_VAR_1 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
 #[no_mangle]
 #[thread_local]
 static mut STATIC_VAR_1: [u32; 8] = [0; 8];
 
-// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
+// CHECK: @STATIC_VAR_2 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
 #[no_mangle]
 #[thread_local]
 static mut STATIC_VAR_2: [u32; 8] = [4; 8];
diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs
index c23c57c8c59..59f29e756fc 100644
--- a/src/test/codegen/repr-transparent-aggregates-1.rs
+++ b/src/test/codegen/repr-transparent-aggregates-1.rs
@@ -3,6 +3,7 @@
 
 // min-system-llvm-version: 9.0
 // ignore-arm
+// ignore-aarch64
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
diff --git a/src/test/compile-fail/asm-src-loc-codegen-units.rs b/src/test/compile-fail/asm-src-loc-codegen-units.rs
index c9415aed930..5b8690c3b98 100644
--- a/src/test/compile-fail/asm-src-loc-codegen-units.rs
+++ b/src/test/compile-fail/asm-src-loc-codegen-units.rs
@@ -1,5 +1,3 @@
-// WONTFIX(#20184) Needs landing pads (not present in stage1) or the compiler hangs.
-// ignore-stage1
 // compile-flags: -C codegen-units=2
 // ignore-emscripten
 
diff --git a/src/test/run-make-fulldeps/issue-37839/Makefile b/src/test/run-make-fulldeps/issue-37839/Makefile
index c405d5c74d7..f17ce537fb8 100644
--- a/src/test/run-make-fulldeps/issue-37839/Makefile
+++ b/src/test/run-make-fulldeps/issue-37839/Makefile
@@ -1,7 +1,5 @@
 -include ../tools.mk
 
-# ignore-stage1
-
 all:
 	$(RUSTC) a.rs && $(RUSTC) b.rs
 	$(BARE_RUSTC) c.rs -L dependency=$(TMPDIR) --extern b=$(TMPDIR)/libb.rlib \
diff --git a/src/test/run-make-fulldeps/issue-37893/Makefile b/src/test/run-make-fulldeps/issue-37893/Makefile
index df58d4f5d94..27b69baf977 100644
--- a/src/test/run-make-fulldeps/issue-37893/Makefile
+++ b/src/test/run-make-fulldeps/issue-37893/Makefile
@@ -1,6 +1,4 @@
 -include ../tools.mk
 
-# ignore-stage1
-
 all:
 	$(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs
diff --git a/src/test/run-make-fulldeps/rustdoc-determinism/Makefile b/src/test/run-make-fulldeps/rustdoc-determinism/Makefile
new file mode 100644
index 00000000000..0534c2c3831
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-determinism/Makefile
@@ -0,0 +1,16 @@
+-include ../tools.mk
+
+# Assert that the search index is generated deterministically, regardless of the
+# order that crates are documented in.
+
+# ignore-windows
+# Uses `diff`.
+
+all:
+	$(RUSTDOC) foo.rs -o $(TMPDIR)/foo_first
+	$(RUSTDOC) bar.rs -o $(TMPDIR)/foo_first
+
+	$(RUSTDOC) bar.rs -o $(TMPDIR)/bar_first
+	$(RUSTDOC) foo.rs -o $(TMPDIR)/bar_first
+
+	diff $(TMPDIR)/foo_first/search-index.js $(TMPDIR)/bar_first/search-index.js
diff --git a/src/test/run-make-fulldeps/rustdoc-determinism/bar.rs b/src/test/run-make-fulldeps/rustdoc-determinism/bar.rs
new file mode 100644
index 00000000000..ca05a6a9076
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-determinism/bar.rs
@@ -0,0 +1 @@
+pub struct Bar;
diff --git a/src/test/run-make-fulldeps/rustdoc-determinism/foo.rs b/src/test/run-make-fulldeps/rustdoc-determinism/foo.rs
new file mode 100644
index 00000000000..4a835673a59
--- /dev/null
+++ b/src/test/run-make-fulldeps/rustdoc-determinism/foo.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/README.md b/src/test/rustdoc-ui/error-in-impl-trait/README.md
new file mode 100644
index 00000000000..1176a4a8c4c
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/README.md
@@ -0,0 +1,7 @@
+Each of these needs to be in a separate file,
+because the `delay_span_bug` ICE in rustdoc won't be triggerred
+if even a single other error was emitted.
+
+However, conceptually they are all testing basically the same thing.
+See https://github.com/rust-lang/rust/pull/73566#issuecomment-653689128
+for more details.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/async.rs b/src/test/rustdoc-ui/error-in-impl-trait/async.rs
new file mode 100644
index 00000000000..112a2c494a5
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/async.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+/// This used to work with ResolveBodyWithLoop.
+/// However now that we ignore type checking instead of modifying the function body,
+/// the return type is seen as `impl Future<Output = u32>`, not a `u32`.
+/// So it no longer allows errors in the function body.
+pub async fn a() -> u32 {
+    error::_in::async_fn()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/async.stderr b/src/test/rustdoc-ui/error-in-impl-trait/async.stderr
new file mode 100644
index 00000000000..086db1be722
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/async.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `error::_in::async_fn`
+  --> $DIR/async.rs:8:5
+   |
+LL |     error::_in::async_fn()
+   |     ^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::async_fn`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/closure.rs
new file mode 100644
index 00000000000..df40c121d57
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/closure.rs
@@ -0,0 +1,5 @@
+// manually desugared version of an `async fn` (but with a closure instead of a generator)
+pub fn a() -> impl Fn() -> u32 {
+    || content::doesnt::matter()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/closure.stderr b/src/test/rustdoc-ui/error-in-impl-trait/closure.stderr
new file mode 100644
index 00000000000..4ee9c4d1f43
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/closure.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `content::doesnt::matter`
+  --> $DIR/closure.rs:3:8
+   |
+LL |     || content::doesnt::matter()
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `content::doesnt::matter`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs
new file mode 100644
index 00000000000..0ccf2e3866f
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs
@@ -0,0 +1,7 @@
+trait ValidTrait {}
+
+/// This has docs
+pub fn f() -> impl ValidTrait {
+    Vec::<DoesNotExist>::new()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr
new file mode 100644
index 00000000000..72716c258dc
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `DoesNotExist`
+  --> $DIR/generic-argument.rs:5:11
+   |
+LL |     Vec::<DoesNotExist>::new()
+   |           ^^^^^^^^^^^^ could not resolve path `DoesNotExist`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs
new file mode 100644
index 00000000000..399fb827517
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs
@@ -0,0 +1,6 @@
+pub trait ValidTrait {}
+/// This returns impl trait
+pub fn g() -> impl ValidTrait {
+    (|| error::_in::impl_trait::alias::nested::closure())()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr
new file mode 100644
index 00000000000..55f9b609a11
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias::nested::closure`
+  --> $DIR/impl-keyword-closure.rs:4:9
+   |
+LL |     (|| error::_in::impl_trait::alias::nested::closure())()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias::nested::closure`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
new file mode 100644
index 00000000000..24b5734dbd0
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
@@ -0,0 +1,6 @@
+pub trait ValidTrait {}
+/// This returns impl trait
+pub fn g() -> impl ValidTrait {
+    error::_in::impl_trait()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr
new file mode 100644
index 00000000000..3257079f942
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait`
+  --> $DIR/impl-keyword.rs:4:5
+   |
+LL |     error::_in::impl_trait()
+   |     ^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs
new file mode 100644
index 00000000000..1498fa4f890
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+pub trait ValidTrait {}
+type ImplTrait = impl ValidTrait;
+
+/// This returns impl trait, but using a type alias
+pub fn h() -> ImplTrait {
+    (|| error::_in::impl_trait::alias::nested::closure())()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr
new file mode 100644
index 00000000000..84b28139dbc
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias::nested::closure`
+  --> $DIR/trait-alias-closure.rs:8:9
+   |
+LL |     (|| error::_in::impl_trait::alias::nested::closure())()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias::nested::closure`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
new file mode 100644
index 00000000000..cf9bc48c7f8
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+pub trait ValidTrait {}
+type ImplTrait = impl ValidTrait;
+
+/// This returns impl trait, but using a type alias
+pub fn h() -> ImplTrait {
+    error::_in::impl_trait::alias()
+    //~^ ERROR failed to resolve
+}
diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr
new file mode 100644
index 00000000000..9be6a3d8d6b
--- /dev/null
+++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr
@@ -0,0 +1,12 @@
+error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias`
+  --> $DIR/trait-alias.rs:8:5
+   |
+LL |     error::_in::impl_trait::alias()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias`
+   |
+   = note: this error was originally ignored because you are running `rustdoc`
+   = note: try running again with `rustc` or `cargo check` and you may get a more detailed error
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc-ui/impl-fn-nesting.rs b/src/test/rustdoc-ui/impl-fn-nesting.rs
new file mode 100644
index 00000000000..a927f6bd799
--- /dev/null
+++ b/src/test/rustdoc-ui/impl-fn-nesting.rs
@@ -0,0 +1,49 @@
+// Ensure that rustdoc gives errors for trait impls inside function bodies that don't resolve.
+// See https://github.com/rust-lang/rust/pull/73566
+pub struct ValidType;
+pub trait ValidTrait {}
+pub trait NeedsBody {
+    type Item;
+    fn f();
+}
+
+/// This function has docs
+pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
+//~^ ERROR cannot find trait `UnknownBound` in this scope
+//~| ERROR cannot find type `UnknownType` in this scope
+    impl UnknownTrait for ValidType {} //~ ERROR cannot find trait `UnknownTrait`
+    impl<T: UnknownBound> UnknownTrait for T {}
+    //~^ ERROR cannot find trait `UnknownBound` in this scope
+    //~| ERROR cannot find trait `UnknownTrait` in this scope
+    impl ValidTrait for UnknownType {}
+    //~^ ERROR cannot find type `UnknownType` in this scope
+    impl ValidTrait for ValidType where ValidTrait: UnknownBound {}
+    //~^ ERROR cannot find trait `UnknownBound` in this scope
+
+    /// This impl has documentation
+    impl NeedsBody for ValidType {
+        type Item = UnknownType;
+        //~^ ERROR cannot find type `UnknownType` in this scope
+
+        /// This function has documentation
+        fn f() {
+            <UnknownTypeShouldBeIgnored>::a();
+            content::shouldnt::matter();
+            unknown_macro!();
+            //~^ ERROR cannot find macro `unknown_macro` in this scope
+
+            /// This is documentation for a macro
+            macro_rules! can_define_macros_here_too {
+                () => {
+                    this::content::should::also::be::ignored()
+                }
+            }
+            can_define_macros_here_too!();
+
+            /// This also is documented.
+            pub fn doubly_nested(c: UnknownType) {
+            //~^ ERROR cannot find type `UnknownType` in this scope
+            }
+        }
+    }
+}
diff --git a/src/test/rustdoc-ui/impl-fn-nesting.stderr b/src/test/rustdoc-ui/impl-fn-nesting.stderr
new file mode 100644
index 00000000000..608749af895
--- /dev/null
+++ b/src/test/rustdoc-ui/impl-fn-nesting.stderr
@@ -0,0 +1,66 @@
+error: cannot find macro `unknown_macro` in this scope
+  --> $DIR/impl-fn-nesting.rs:32:13
+   |
+LL |             unknown_macro!();
+   |             ^^^^^^^^^^^^^
+
+error[E0405]: cannot find trait `UnknownBound` in this scope
+  --> $DIR/impl-fn-nesting.rs:11:13
+   |
+LL | pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
+   |             ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+  --> $DIR/impl-fn-nesting.rs:11:30
+   |
+LL | pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
+   |                              ^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownTrait` in this scope
+  --> $DIR/impl-fn-nesting.rs:14:10
+   |
+LL |     impl UnknownTrait for ValidType {}
+   |          ^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownTrait` in this scope
+  --> $DIR/impl-fn-nesting.rs:15:27
+   |
+LL |     impl<T: UnknownBound> UnknownTrait for T {}
+   |                           ^^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownBound` in this scope
+  --> $DIR/impl-fn-nesting.rs:15:13
+   |
+LL |     impl<T: UnknownBound> UnknownTrait for T {}
+   |             ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+  --> $DIR/impl-fn-nesting.rs:18:25
+   |
+LL |     impl ValidTrait for UnknownType {}
+   |                         ^^^^^^^^^^^ not found in this scope
+
+error[E0405]: cannot find trait `UnknownBound` in this scope
+  --> $DIR/impl-fn-nesting.rs:20:53
+   |
+LL |     impl ValidTrait for ValidType where ValidTrait: UnknownBound {}
+   |                                                     ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+  --> $DIR/impl-fn-nesting.rs:25:21
+   |
+LL |         type Item = UnknownType;
+   |                     ^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `UnknownType` in this scope
+  --> $DIR/impl-fn-nesting.rs:44:37
+   |
+LL |             pub fn doubly_nested(c: UnknownType) {
+   |                                     ^^^^^^^^^^^ not found in this scope
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0405, E0412.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type.rs b/src/test/rustdoc-ui/infinite-recursive-type.rs
new file mode 100644
index 00000000000..32793fc4f76
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type.rs
@@ -0,0 +1,4 @@
+enum E {
+//~^ ERROR recursive type `E` has infinite size
+    V(E),
+}
diff --git a/src/test/rustdoc-ui/infinite-recursive-type.stderr b/src/test/rustdoc-ui/infinite-recursive-type.stderr
new file mode 100644
index 00000000000..897445f200c
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `E` has infinite size
+  --> $DIR/infinite-recursive-type.rs:1:1
+   |
+LL | enum E {
+   | ^^^^^^ recursive type has infinite size
+LL |
+LL |     V(E),
+   |       - recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E` representable
+   |
+LL |     V(Box<E>),
+   |       ^^^^ ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-spotlight.rs
new file mode 100644
index 00000000000..ddd46c3c215
--- /dev/null
+++ b/src/test/rustdoc/doc-spotlight.rs
@@ -0,0 +1,36 @@
+#![feature(doc_spotlight)]
+
+pub struct Wrapper<T> {
+    inner: T,
+}
+
+impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
+
+#[doc(spotlight)]
+pub trait SomeTrait {
+    // @has doc_spotlight/trait.SomeTrait.html
+    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
+    fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
+        Wrapper {
+            inner: self,
+        }
+    }
+}
+
+pub struct SomeStruct;
+impl SomeTrait for SomeStruct {}
+
+impl SomeStruct {
+    // @has doc_spotlight/struct.SomeStruct.html
+    // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
+    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
+    pub fn new() -> SomeStruct {
+        SomeStruct
+    }
+}
+
+// @has doc_spotlight/fn.bare_fn.html
+// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
+pub fn bare_fn() -> SomeStruct {
+    SomeStruct
+}
diff --git a/src/test/rustdoc/impl-trait-alias.rs b/src/test/rustdoc/impl-trait-alias.rs
new file mode 100644
index 00000000000..54c3f856ddb
--- /dev/null
+++ b/src/test/rustdoc/impl-trait-alias.rs
@@ -0,0 +1,14 @@
+#![feature(type_alias_impl_trait)]
+
+trait MyTrait {}
+impl MyTrait for i32 {}
+
+// @has impl_trait_alias/type.Foo.html 'Foo'
+/// debug type
+pub type Foo = impl MyTrait;
+
+// @has impl_trait_alias/fn.foo.html 'foo'
+/// debug function
+pub fn foo() -> Foo {
+    1
+}
diff --git a/src/test/rustdoc/macro-in-async-block.rs b/src/test/rustdoc/macro-in-async-block.rs
new file mode 100644
index 00000000000..b4aaacf7b3d
--- /dev/null
+++ b/src/test/rustdoc/macro-in-async-block.rs
@@ -0,0 +1,9 @@
+// Regression issue for rustdoc ICE encountered in PR #72088.
+// edition:2018
+#![feature(decl_macro)]
+
+fn main() {
+    async {
+        macro m() {}
+    };
+}
diff --git a/src/test/rustdoc/macro-in-closure.rs b/src/test/rustdoc/macro-in-closure.rs
index 298ff601de8..b4411d927e2 100644
--- a/src/test/rustdoc/macro-in-closure.rs
+++ b/src/test/rustdoc/macro-in-closure.rs
@@ -6,4 +6,11 @@ fn main() {
     || {
         macro m() {}
     };
+
+    let _ = || {
+        macro n() {}
+    };
+
+    let cond = true;
+    let _ = || if cond { macro n() {} } else { panic!() };
 }
diff --git a/src/test/rustdoc/return-impl-trait.rs b/src/test/rustdoc/return-impl-trait.rs
new file mode 100644
index 00000000000..1ccf5ac4611
--- /dev/null
+++ b/src/test/rustdoc/return-impl-trait.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+pub trait Backend {}
+
+impl Backend for () {}
+
+pub struct Module<T>(T);
+
+pub type BackendImpl = impl Backend;
+
+// @has return_impl_trait/fn.make_module.html
+/// Documentation
+pub fn make_module() -> Module<BackendImpl> {
+    Module(())
+}
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.rs b/src/test/ui/check-doc-alias-attr.rs
index 2f01099107d..b02cc1a4545 100644
--- a/src/test/rustdoc-ui/check-doc-alias-attr.rs
+++ b/src/test/ui/check-doc-alias-attr.rs
@@ -1,3 +1,4 @@
+#![crate_type = "lib"]
 #![feature(doc_alias)]
 
 #[doc(alias = "foo")] // ok!
diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/ui/check-doc-alias-attr.stderr
index 480acc821aa..268230ab44a 100644
--- a/src/test/rustdoc-ui/check-doc-alias-attr.stderr
+++ b/src/test/ui/check-doc-alias-attr.stderr
@@ -1,17 +1,17 @@
 error: doc alias attribute expects a string: #[doc(alias = "0")]
-  --> $DIR/check-doc-alias-attr.rs:6:7
+  --> $DIR/check-doc-alias-attr.rs:7:7
    |
 LL | #[doc(alias)]
    |       ^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "0")]
-  --> $DIR/check-doc-alias-attr.rs:7:7
+  --> $DIR/check-doc-alias-attr.rs:8:7
    |
 LL | #[doc(alias = 0)]
    |       ^^^^^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "0")]
-  --> $DIR/check-doc-alias-attr.rs:8:7
+  --> $DIR/check-doc-alias-attr.rs:9:7
    |
 LL | #[doc(alias("bar"))]
    |       ^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs
new file mode 100644
index 00000000000..5aa3617d1d7
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs
@@ -0,0 +1,15 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+
+// Currently, const parameters cannot depend on other generic parameters,
+// as our current implementation can't really support this.
+//
+// We may want to lift this restriction in the future.
+
+pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+//~^ ERROR: the type of const parameters must not depend on other generic parameters
+
+pub struct SelfDependent<const N: [u8; N]>;
+//~^ ERROR: the type of const parameters must not depend on other generic parameters
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr
new file mode 100644
index 00000000000..f6606aea726
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr
@@ -0,0 +1,24 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:9:52
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   |                                                    ^ the type must not depend on the parameter `N`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:12:40
+   |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+   |                                        ^ the type must not depend on the parameter `N`
+
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-param-type-depends-on-const-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
index 86ab8075896..db15ececfa4 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
@@ -1,6 +1,6 @@
 use std::marker::PhantomData;
 
 struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
-//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
+//~^ ERROR the type of const parameters must not depend on other generic parameters
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
index 92a7edf96bc..35996e83361 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -1,3 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
+   |
+LL | struct B<T, const N: T>(PhantomData<[T; N]>);
+   |                      ^ the type must not depend on the parameter `T`
+
 error[E0658]: const generics are unstable
   --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
    |
@@ -7,15 +13,7 @@ LL | struct B<T, const N: T>(PhantomData<[T; N]>);
    = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
-error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
-  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
-   |
-LL | struct B<T, const N: T>(PhantomData<[T; N]>);
-   |                      ^ `T` may not derive both `PartialEq` and `Eq`
-   |
-   = note: it is not currently possible to use a type parameter as the type of a const parameter
-
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0658, E0741.
+Some errors have detailed explanations: E0658, E0770.
 For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
index 654e36df37e..7fe04a43412 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
@@ -1,12 +1,13 @@
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete
 
-// Currently, const parameters cannot depend on type parameters, because there is no way to
-// enforce the structural-match property on an arbitrary type parameter. This restriction
-// may be relaxed in the future. See https://github.com/rust-lang/rfcs/pull/2000 for more
-// details.
+// Currently, const parameters cannot depend on other generic parameters,
+// as our current implementation can't really support this.
+//
+// We may want to lift this restriction in the future.
 
 pub struct Dependent<T, const X: T>([(); X]);
-//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
+//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~| ERROR: parameter `T` is never used
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
index ed05264161e..d081dcbbc7a 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
@@ -1,3 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                                  ^ the type must not depend on the parameter `T`
+
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/const-param-type-depends-on-type-param.rs:1:12
    |
@@ -7,14 +13,15 @@ LL | #![feature(const_generics)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
 
-error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
-  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
+error[E0392]: parameter `T` is never used
+  --> $DIR/const-param-type-depends-on-type-param.rs:9:22
    |
 LL | pub struct Dependent<T, const X: T>([(); X]);
-   |                                  ^ `T` may not derive both `PartialEq` and `Eq`
+   |                      ^ unused parameter
    |
-   = note: it is not currently possible to use a type parameter as the type of a const parameter
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0741`.
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs
new file mode 100644
index 00000000000..59a4d345cbc
--- /dev/null
+++ b/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs
@@ -0,0 +1,14 @@
+#![feature(const_generics)]
+
+// All of these three items must be in `lib2` to reproduce the error
+
+pub trait TypeFn {
+    type Output;
+}
+
+pub struct GenericType<const B: i8>;
+
+// Removing the braces around `42` resolves the crash
+impl TypeFn for GenericType<{ 42 }> {
+    type Output = ();
+}
diff --git a/src/test/ui/const-generics/issues/issue-68596.rs b/src/test/ui/const-generics/issues/issue-68596.rs
new file mode 100644
index 00000000000..1f96e7d3b41
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-68596.rs
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+pub struct S(u8);
+
+impl S {
+    pub fn get<const A: u8>(&self) -> &u8 {
+        &self.0
+    }
+}
+
+fn main() {
+    const A: u8 = 5;
+    let s = S(0);
+
+    s.get::<A>();
+}
diff --git a/src/test/ui/const-generics/issues/issue-71169.rs b/src/test/ui/const-generics/issues/issue-71169.rs
new file mode 100644
index 00000000000..943a16cfcd6
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-71169.rs
@@ -0,0 +1,10 @@
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
+//~^ ERROR the type of const parameters must not
+fn main() {
+    const DATA: [u8; 4] = *b"ABCD";
+    foo::<4, DATA>();
+    //~^ ERROR constant expression depends on
+}
diff --git a/src/test/ui/const-generics/issues/issue-71169.stderr b/src/test/ui/const-generics/issues/issue-71169.stderr
new file mode 100644
index 00000000000..6d4cf4027c1
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-71169.stderr
@@ -0,0 +1,17 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71169.rs:4:43
+   |
+LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
+   |                                           ^^^ the type must not depend on the parameter `LEN`
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-71169.rs:8:14
+   |
+LL |     foo::<4, DATA>();
+   |              ^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/issues/issue-71381.rs b/src/test/ui/const-generics/issues/issue-71381.rs
index c32bd2847f8..08f94823942 100644
--- a/src/test/ui/const-generics/issues/issue-71381.rs
+++ b/src/test/ui/const-generics/issues/issue-71381.rs
@@ -12,6 +12,7 @@ unsafe extern "C" fn pass(args: PassArg) {
 impl Test {
     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
         //~^ ERROR: using function pointers as const generic parameters is forbidden
+        //~| ERROR: the type of const parameters must not depend on other generic parameters
         self.0 = Self::trampiline::<Args, IDX, FN> as _
     }
 
@@ -20,6 +21,7 @@ impl Test {
         const IDX: usize,
         const FN: unsafe extern "C" fn(Args),
         //~^ ERROR: using function pointers as const generic parameters is forbidden
+        //~| ERROR: the type of const parameters must not depend on other generic parameters
     >(
         args: Args,
     ) {
diff --git a/src/test/ui/const-generics/issues/issue-71381.stderr b/src/test/ui/const-generics/issues/issue-71381.stderr
index 6bb776fcfc0..fd4ebe3dead 100644
--- a/src/test/ui/const-generics/issues/issue-71381.stderr
+++ b/src/test/ui/const-generics/issues/issue-71381.stderr
@@ -1,3 +1,15 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71381.rs:13:82
+   |
+LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
+   |                                                                                  ^^^^ the type must not depend on the parameter `Args`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71381.rs:22:40
+   |
+LL |         const FN: unsafe extern "C" fn(Args),
+   |                                        ^^^^ the type must not depend on the parameter `Args`
+
 error: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71381.rs:13:61
    |
@@ -5,10 +17,11 @@ LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
    |                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71381.rs:21:19
+  --> $DIR/issue-71381.rs:22:19
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/issues/issue-71611.rs b/src/test/ui/const-generics/issues/issue-71611.rs
index 64a049e743f..06ff38dec66 100644
--- a/src/test/ui/const-generics/issues/issue-71611.rs
+++ b/src/test/ui/const-generics/issues/issue-71611.rs
@@ -3,6 +3,7 @@
 
 fn func<A, const F: fn(inner: A)>(outer: A) {
     //~^ ERROR: using function pointers as const generic parameters is forbidden
+    //~| ERROR: the type of const parameters must not depend on other generic parameters
     F(outer);
 }
 
diff --git a/src/test/ui/const-generics/issues/issue-71611.stderr b/src/test/ui/const-generics/issues/issue-71611.stderr
index 9a7bf1c0a88..e2c9f22361e 100644
--- a/src/test/ui/const-generics/issues/issue-71611.stderr
+++ b/src/test/ui/const-generics/issues/issue-71611.stderr
@@ -1,8 +1,15 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71611.rs:4:31
+   |
+LL | fn func<A, const F: fn(inner: A)>(outer: A) {
+   |                               ^ the type must not depend on the parameter `A`
+
 error: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71611.rs:4:21
    |
 LL | fn func<A, const F: fn(inner: A)>(outer: A) {
    |                     ^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/issues/issue-73120.rs b/src/test/ui/const-generics/issues/issue-73120.rs
new file mode 100644
index 00000000000..aea4de39f79
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-73120.rs
@@ -0,0 +1,8 @@
+// check-pass
+// aux-build:const_generic_issues_lib.rs
+extern crate const_generic_issues_lib as lib2;
+fn unused_function(
+    _: <lib2::GenericType<42> as lib2::TypeFn>::Output
+) {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-73491.rs b/src/test/ui/const-generics/issues/issue-73491.rs
new file mode 100644
index 00000000000..05e1513bb75
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-73491.rs
@@ -0,0 +1,9 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+const LEN: usize = 1024;
+
+fn hoge<const IN: [u32; LEN]>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-73508.rs b/src/test/ui/const-generics/issues/issue-73508.rs
new file mode 100644
index 00000000000..ba2e2a38e74
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-73508.rs
@@ -0,0 +1,6 @@
+#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+
+pub const fn func_name<const X: *const u32>() {}
+//~^ ERROR using raw pointers
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-73508.stderr b/src/test/ui/const-generics/issues/issue-73508.stderr
new file mode 100644
index 00000000000..23ad1818b6f
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-73508.stderr
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-73508.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/issue-73508.rs:3:33
+   |
+LL | pub const fn func_name<const X: *const u32>() {}
+   |                                 ^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/const-generics/issues/issue-74101.rs b/src/test/ui/const-generics/issues/issue-74101.rs
new file mode 100644
index 00000000000..2f427ef3a27
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-74101.rs
@@ -0,0 +1,9 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+fn test<const N: [u8; 1 + 2]>() {}
+
+struct Foo<const N: [u8; 1 + 2]>;
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-74255.rs b/src/test/ui/const-generics/issues/issue-74255.rs
new file mode 100644
index 00000000000..55ccf57dc99
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-74255.rs
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(dead_code, incomplete_features)]
+
+#[derive(PartialEq, Eq)]
+enum IceEnum {
+    Variant
+}
+
+struct IceStruct;
+
+impl IceStruct {
+    fn ice_struct_fn<const I: IceEnum>() {}
+}
+
+fn main() {
+    IceStruct::ice_struct_fn::<{IceEnum::Variant}>();
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-67144-1.rs b/src/test/ui/const-generics/type-dependent/issue-67144-1.rs
new file mode 100644
index 00000000000..a3d05959198
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-67144-1.rs
@@ -0,0 +1,28 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct X;
+
+impl X {
+    pub fn getn<const N: usize>(&self) -> [u8; N] {
+        getn::<N>()
+    }
+}
+
+fn getn<const N: usize>() -> [u8; N] {
+    unsafe {
+        std::mem::zeroed()
+    }
+}
+
+fn main() {
+    // works
+    let [a,b,c] = getn::<3>();
+
+    // cannot pattern-match on an array without a fixed length
+    let [a,b,c] = X.getn::<3>();
+
+    // mismatched types, expected array `[u8; 3]` found array `[u8; _]`
+    let arr: [u8; 3] = X.getn::<3>();
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-67144-2.rs b/src/test/ui/const-generics/type-dependent/issue-67144-2.rs
new file mode 100644
index 00000000000..c53a149fa8d
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-67144-2.rs
@@ -0,0 +1,22 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct A<const N: usize>;
+
+struct X;
+
+impl X {
+    fn inner<const N: usize>() -> A<N> {
+        outer::<N>()
+    }
+}
+
+fn outer<const N: usize>() -> A<N> {
+    A
+}
+
+fn main() {
+    let i: A<3usize> = outer::<3usize>();
+    let o: A<3usize> = X::inner::<3usize>();
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-70217.rs b/src/test/ui/const-generics/type-dependent/issue-70217.rs
new file mode 100644
index 00000000000..caa611cbd79
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-70217.rs
@@ -0,0 +1,16 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct Struct<const N: usize>;
+
+impl<const N: usize> Struct<N> {
+    fn method<const M: usize>(&self) {}
+}
+
+fn test<const N: usize, const M: usize>(x: Struct<N>) {
+    Struct::<N>::method::<M>(&x);
+    x.method::<N>();
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/type-dependent/issue-70586.rs b/src/test/ui/const-generics/type-dependent/issue-70586.rs
new file mode 100644
index 00000000000..5a0888506eb
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-70586.rs
@@ -0,0 +1,33 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+use std::marker::PhantomData;
+
+// This namespace is necessary for the ICE to trigger
+struct Namespace;
+
+impl Namespace {
+    pub fn const_chunks_exact<T, const N: usize>() -> ConstChunksExact<'static, T, N> {
+        ConstChunksExact { inner: PhantomData }
+    }
+}
+
+
+#[derive(Debug)]
+pub struct ConstChunksExact<'a, T, const N: usize> {
+    inner:  PhantomData<&'a T>
+}
+
+impl <'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, { N }> {
+    type Item = &'a [T; N];
+
+    fn next(&mut self) -> Option<Self::Item> {
+        unreachable!()
+    }
+}
+
+fn main() {
+    let mut chunks = Namespace::const_chunks_exact::<i32, 3usize>();
+    let _next: &[i32; 3] = chunks.next().unwrap();
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-71348.rs b/src/test/ui/const-generics/type-dependent/issue-71348.rs
new file mode 100644
index 00000000000..ec22dcdf60b
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-71348.rs
@@ -0,0 +1,35 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct Foo {
+    i: i32,
+}
+
+trait Get<'a, const N: &'static str> {
+    type Target: 'a;
+
+    fn get(&'a self) -> &'a Self::Target;
+}
+
+impl Foo {
+    fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target
+    where
+        Self: Get<'a, N>,
+    {
+        self.get()
+    }
+}
+
+impl<'a> Get<'a, "int"> for Foo {
+    type Target = i32;
+
+    fn get(&'a self) -> &'a Self::Target {
+        &self.i
+    }
+}
+
+fn main() {
+    let foo = Foo { i: 123 };
+    assert_eq!(foo.ask::<"int">(), &123);
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-71805.rs b/src/test/ui/const-generics/type-dependent/issue-71805.rs
new file mode 100644
index 00000000000..6823d780aef
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-71805.rs
@@ -0,0 +1,41 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+use std::mem::MaybeUninit;
+
+trait CollectSlice<'a>: Iterator {
+    fn inner_array<const N: usize>(&mut self) -> [Self::Item; N];
+
+    fn collect_array<const N: usize>(&mut self) -> [Self::Item; N] {
+        let result = self.inner_array();
+        assert!(self.next().is_none());
+        result
+    }
+}
+
+impl<'a, I: ?Sized> CollectSlice<'a> for I
+where
+    I: Iterator,
+{
+    fn inner_array<const N: usize>(&mut self) -> [Self::Item; N] {
+        let mut result: [MaybeUninit<Self::Item>; N] =
+            unsafe { MaybeUninit::uninit().assume_init() };
+
+        let mut count = 0;
+        for (dest, item) in result.iter_mut().zip(self) {
+            *dest = MaybeUninit::new(item);
+            count += 1;
+        }
+
+        assert_eq!(N, count);
+
+        let temp_ptr: *const [MaybeUninit<Self::Item>; N] = &result;
+        unsafe { std::ptr::read(temp_ptr as *const [Self::Item; N]) }
+    }
+}
+
+fn main() {
+    let mut foos = [0u64; 9].iter().cloned();
+    let _bar: [u64; 9] = foos.collect_array::<9_usize>();
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-73730.rs b/src/test/ui/const-generics/type-dependent/issue-73730.rs
new file mode 100644
index 00000000000..d90cc50ddc4
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-73730.rs
@@ -0,0 +1,17 @@
+// check-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait Foo<'a, A>: Iterator<Item=A> {
+    fn bar<const N: usize>(&mut self) -> *const [A; N];
+}
+
+impl<'a, A, I: ?Sized> Foo<'a, A> for I where I: Iterator<Item=A>  {
+    fn bar<const N: usize>(&mut self) -> *const [A; N] {
+        std::ptr::null()
+    }
+}
+
+fn main() {
+    (0_u8 .. 10).bar::<10_usize>();
+}
diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs
index 5f2d5e80243..d19cf00eb9c 100644
--- a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs
+++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs
@@ -1,9 +1,12 @@
 // check-pass
 
+// compile-flags: --crate-type lib
+
+#![warn(unconditional_panic)]
+
 pub struct Fixed64(i64);
 
-pub fn div(f: Fixed64) {
-    f.0 / 0;
+// HACK: this test passes only because this is a const fn that is written to metadata
+pub const fn div(f: Fixed64) {
+    f.0 / 0; //~ WARN will panic at runtime
 }
-
-fn main() {}
diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
new file mode 100644
index 00000000000..e2a3e4db8ab
--- /dev/null
+++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
@@ -0,0 +1,14 @@
+warning: this operation will panic at runtime
+  --> $DIR/ice-assert-fail-div-by-zero.rs:11:5
+   |
+LL |     f.0 / 0;
+   |     ^^^^^^^ attempt to divide _ by zero
+   |
+note: the lint level is defined here
+  --> $DIR/ice-assert-fail-div-by-zero.rs:5:9
+   |
+LL | #![warn(unconditional_panic)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
new file mode 100644
index 00000000000..452b45b3445
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
@@ -0,0 +1,4 @@
+#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental
+trait SomeTrait {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
new file mode 100644
index 00000000000..010d74054a4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `#[doc(spotlight)]` is experimental
+  --> $DIR/feature-gate-doc_spotlight.rs:1:1
+   |
+LL | #[doc(spotlight)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information
+   = help: add `#![feature(doc_spotlight)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 9aea859999c..c4292d041d0 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -127,7 +127,7 @@ impl Formatter for HTMLFormatter {
                         DEFAULT_EDITION,
                         &Some(playground)
                     )
-                    .to_string()
+                    .into_string()
                 )?
             }
             None => write!(output, "<p>No description.</p>\n")?,