From b146000e910ccd60bdcde89363cb6aa14ecc0d95 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Fri, 7 Aug 2020 20:07:07 -0400
Subject: [PATCH] EXTREMELY hacky fix

This runs _just_ enough of typeck that later queries don't panic.
Because this is in the same part of the compiler that errors on `impl
Trait`, this special-cases impl Trait for rustdoc and no one else.
Everything is fine.
---
 src/librustc_privacy/lib.rs                   |  4 +--
 src/librustc_typeck/check/mod.rs              | 12 ++++++--
 src/librustc_typeck/lib.rs                    |  1 +
 src/librustdoc/core.rs                        | 17 +++++++++++
 .../infinite-recursive-type-impl-trait.rs     |  7 +++++
 .../infinite-recursive-type-impl-trait.stderr | 17 +++++++++++
 .../rustdoc-ui/infinite-recursive-type.stderr | 29 +++++++------------
 7 files changed, 63 insertions(+), 24 deletions(-)
 create mode 100644 src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
 create mode 100644 src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr

diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 48d846dfefd..1f418fe7f7f 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -787,9 +787,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     // FIXME: This is some serious pessimization intended to workaround deficiencies
                     // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
                     // reachable if they are returned via `impl Trait`, even from private functions.
-                    let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
+                    let exist_level =
+                        cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
                     self.reach(item.hir_id, exist_level).generics().predicates().ty();
-
                 }
             }
             // Visit everything.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 6cefc99f7b1..9169b5aa58a 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1967,10 +1967,16 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             check_union(tcx, it.hir_id, it.span);
         }
         hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
-            let def_id = tcx.hir().local_def_id(it.hir_id);
+            // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
+            // `async-std` (and `pub async fn` in general).
+            // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
+            // See https://github.com/rust-lang/rust/issues/75100
+            if !tcx.sess.opts.actually_rustdoc {
+                let def_id = tcx.hir().local_def_id(it.hir_id);
 
-            let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
-            check_opaque(tcx, def_id, substs, it.span, &origin);
+                let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                check_opaque(tcx, def_id, substs, it.span, &origin);
+            }
         }
         hir::ItemKind::TyAlias(..) => {
             let def_id = tcx.hir().local_def_id(it.hir_id);
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 9ba2545ba63..bea0f1e1f08 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -356,6 +356,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
         tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
     })?;
 
+    // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
     tcx.sess.time("item_types_checking", || {
         for &module in tcx.hir().krate().modules.keys() {
             tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index eab310ddf89..b13acaae1bf 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -449,6 +449,23 @@ 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| {
+                // 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`)
+
+                // HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
+                // and might break if queries change their assumptions in the future.
+
+                // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
+                tcx.sess.time("item_types_checking", || {
+                    for &module in tcx.hir().krate().modules.keys() {
+                        tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
+                    }
+                });
                 tcx.sess.abort_if_errors();
                 sess.time("missing_docs", || {
                     rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
new file mode 100644
index 00000000000..b3a7ee56313
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -0,0 +1,7 @@
+fn f() -> impl Sized {
+    enum E {
+    //~^ ERROR recursive type `f::E` has infinite size
+        V(E),
+    }
+    unimplemented!()
+}
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
new file mode 100644
index 00000000000..ec1bb786fe5
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `f::E` has infinite size
+  --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
+   |
+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 `f::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-ui/infinite-recursive-type.stderr b/src/test/rustdoc-ui/infinite-recursive-type.stderr
index 8d12392c567..897445f200c 100644
--- a/src/test/rustdoc-ui/infinite-recursive-type.stderr
+++ b/src/test/rustdoc-ui/infinite-recursive-type.stderr
@@ -1,26 +1,17 @@
-error: internal compiler error[E0391]: cycle detected when computing `Sized` constraints for `E`
+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
    |
-   = note: ...which again requires computing `Sized` constraints for `E`, completing the cycle
-   = note: cycle used when evaluating trait selection obligation `E: std::convert::From<E>`
-
-error: internal compiler error: TyKind::Error constructed but no error reported
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E` representable
    |
-   = note: delayed at /home/joshua/rustc/src/librustc_session/session.rs:436:27
+LL |     V(Box<E>),
+   |       ^^^^ ^
 
-thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:366:17
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
-
-note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
-
-note: rustc 1.47.0-dev running on x86_64-unknown-linux-gnu
-
-note: compiler flags: -Z threads=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z unstable-options -C debuginfo=0
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0072`.