about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-07-16 11:18:24 -0700
committerGitHub <noreply@github.com>2020-07-16 11:18:24 -0700
commitc23f045a8b10c92eef5b1fbefea7696065e5977c (patch)
treeb10918087c472959fa36a535ae67fa0a6db1e2c7 /src/test
parent6ee1b62c811a6eb68d6db6dfb91f66a49956749b (diff)
parent631b2b9b722a3333aa5931fbbfa9df8846d48380 (diff)
downloadrust-c23f045a8b10c92eef5b1fbefea7696065e5977c.tar.gz
rust-c23f045a8b10c92eef5b1fbefea7696065e5977c.zip
Rollup merge of #73566 - jyn514:name-resolve-first, r=eddyb
Don't run `everybody_loops` for rustdoc; instead ignore resolution errors

r? @eddyb
cc @petrochenkov, @GuillaumeGomez, @Manishearth, @ecstatic-morse, @marmeladema

~~Blocked on https://github.com/rust-lang/rust/pull/73743~~ Merged.
~~Blocked on crater run.~~ Crater popped up some ICEs ([now fixed](https://github.com/rust-lang/rust/pull/73566#issuecomment-656934851)). See [crater run](https://crater-reports.s3.amazonaws.com/pr-73566/index.html), [ICEs](https://github.com/rust-lang/rust/pull/73566#issuecomment-653619212).
~~Blocked on #74070 so that we don't make typeck_tables_of public when it shouldn't be.~~ Merged.

Closes #71820, closes #71104, closes #65863.

## What is the motivation for this change?

As seen from a lengthy trail of PRs and issues (https://github.com/rust-lang/rust/pull/73532, https://github.com/rust-lang/rust/pull/73103, https://github.com/rust-lang/rust/issues/71820, https://github.com/rust-lang/rust/issues/71104), `everybody_loops` is causing bugs in rustdoc. The main issue is that it does not preserve the validity of the `DefId` tree, meaning that operations on DefIds may unexpectedly fail when called later. This is blocking intra-doc links (see https://github.com/rust-lang/rust/pull/73101).

This PR starts by removing `everybody_loops`, fixing #71104 and #71820. However, that brings back the bugs seen originally in https://github.com/rust-lang/rust/pull/43348: Since libstd documents items for all platforms, the function bodies sometimes do not type check. Here are the errors from documenting `libstd` with `everybody_loops` disabled and no other changes:

```rust
error[E0433]: failed to resolve: could not find `handle` in `sys`
  --> src/libstd/sys/windows/ext/process.rs:13:27
   |
13 |         let handle = sys::handle::Handle::new(handle as *mut _);
   |                           ^^^^^^ could not find `handle` in `sys`

error[E0425]: cannot find function `symlink_inner` in module `sys::fs`
   --> src/libstd/sys/windows/ext/fs.rs:544:14
    |
544 |     sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false)
    |              ^^^^^^^^^^^^^ not found in `sys::fs`

error[E0425]: cannot find function `symlink_inner` in module `sys::fs`
   --> src/libstd/sys/windows/ext/fs.rs:564:14
    |
564 |     sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true)
    |              ^^^^^^^^^^^^^ not found in `sys::fs`
```

## Why does this need changes to `rustc_resolve`?

Normally, this could be avoided by simply not calling the `typeck_item_bodies` pass. However, the errors above happen before type checking, in name resolution itself. Since name resolution is intermingled with macro expansion, and rustdoc needs expansion to happen before it knows all items to be documented, there needs to be someway to ignore _resolution_ errors in function bodies.

An alternative solution suggested by @petrochenkov was to not run `everybody_loops` on anything containing a nested `DefId`. This would solve some of the immediate issues, but isn't bullet-proof: the following functions still could not be documented if the items in the body failed to resolve:

- Functions containing a nested `DefId` (https://github.com/rust-lang/rust/issues/71104)
- ~~Functions returning `impl Trait` (https://github.com/rust-lang/rust/pull/43878)~~ These ended up not resolving anyway with this PR.
- ~~`const fn`, because `loop {}` in `const fn` is unstable (https://github.com/rust-lang/rust/issues/43636)~~ `const_loop` was just stabilized.

This also isn't exactly what rustdoc wants, which is to avoid looking at function bodies in the first place.

## What changes were made?

The hack implemented in this PR is to add an option to ignore all resolution errors in function bodies. This is enabled only for rustdoc. Since resolution errors are ignored, the MIR generated will be invalid, as can be seen in the following ICE:

```rust
error: internal compiler error: broken MIR in DefId(0:11 ~ doc_cfg[8787]::uses_target_feature[0]) ("return type"): bad type [type error]
  --> /home/joshua/src/rust/src/test/rustdoc/doc-cfg.rs:51:1
   |
51 | / pub unsafe fn uses_target_feature() {
52 | |     content::should::be::irrelevant();
53 | | }
   | |_^
```

Fortunately, rustdoc does not need to access MIR in order to generate documentation. Therefore this also removes the call to `analyze()` in `rustdoc::run_core`. This has the side effect of not generating all lints by default. Most lints are safe to ignore (does rustdoc really need to run liveness analysis?) but `missing_docs` in particular is disabled when it should not be. Re-running `missing_docs` specifically does not help, because it causes the typechecking pass to be run, bringing back the errors from #24658:

```
error[E0599]: no method named `into_handle` found for struct `sys::unix::pipe::AnonPipe` in the current scope
  --> src/libstd/sys/windows/ext/process.rs:71:27
   |
71 |         self.into_inner().into_handle().into_raw() as *mut _
   |                           ^^^^^^^^^^^ method not found in `sys::unix::pipe::AnonPipe`
   |
```

Because of #73743, we only run typeck on demand. So this only causes an issue for functions returning `impl Trait`, which were already special cased by `ReplaceFunctionWithBody`. However, it now considers `async fn f() -> T` to be considered `impl Future<Output = T>`, where before it was considered to have a concrete `T` type.

## How will this affect future changes to rustdoc?

- Any new changes to rustdoc will not be able to perform type checking without bringing back resolution errors in function bodies.
    + As a corollary, any new lints cannot require or perform type checking. In some cases this may require refactoring other parts of the compiler to perform type-checking only on-demand, see for example #73743.
    + As a corollary, rustdoc can never again call `tcx.analysis()` unless this PR is reverted altogether.

## Current status

- ~~I am not yet sure how to bring back `missing_docs` without running typeck. @eddyb suggested allowing lints to opt-out of type-checking, which would probably be another rabbit hole.~~ The opt-out was implemented in https://github.com/rust-lang/rust/pull/73743. However, of the rustc lints, now _only_ missing_docs is run and no other lints: https://github.com/rust-lang/rust/pull/73566#issuecomment-650213058. We need a team decision on whether that's an acceptable tradeoff. Note that all rustdoc lints are still run (`intra_doc_link_resolution_failure`, etc). **UPDATE**: This was deemed acceptable in https://github.com/rust-lang/rust/pull/73566#issuecomment-655750237
- ~~The implementation of optional errors in `rustc_resolve` is very brute force, it should probably be moved from `LateResolver` to `Resolver` to avoid duplicating the logic in many places.~~ I'm mostly happy with it now.

- This no longer allows errors in `async fn f() -> T`. This caused breakage in 50 crates out of a full crater run, all of which (that I looked at) didn't compile when run with rustc directly. In other words, it used to be that they could not be compiled but could still be documented; now they can't be documented either. This needs a decision from the rustdoc team on whether this is acceptable breakage. **UPDATE**: This was deemed acceptable in https://github.com/rust-lang/rust/pull/73566#issuecomment-655750237
- ~~This makes `fn typeck_tables_of` in `rustc_typeck` public. This is not desired behavior, but needs the changes from https://github.com/rust-lang/rust/pull/74070 in order to be fixed.~~ Reverted.
Diffstat (limited to 'src/test')
-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/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
23 files changed, 326 insertions, 0 deletions
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/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(())
+}