From 02a24c8e2fd370041a24b7d93e8c3710b7b76015 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 11 Jul 2020 00:28:42 -0400 Subject: [PATCH] Don't ICE on infinitely recursive types `evaluate_obligation` can only be run on types that are already valid. So rustdoc still has to run typeck even though it doesn't care about the result. --- Cargo.lock | 1 + src/librustdoc/Cargo.toml | 1 + src/librustdoc/core.rs | 15 +++++++++++++++ src/librustdoc/lib.rs | 2 ++ src/test/rustdoc-ui/infinite-recursive-type.rs | 4 ++++ .../rustdoc-ui/infinite-recursive-type.stderr | 17 +++++++++++++++++ 6 files changed, 40 insertions(+) create mode 100644 src/test/rustdoc-ui/infinite-recursive-type.rs create mode 100644 src/test/rustdoc-ui/infinite-recursive-type.stderr diff --git a/Cargo.lock b/Cargo.lock index 5309c03ee23..992421dcd7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4027,6 +4027,7 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "itertools 0.8.0", + "lazy_static", "minifier", "pulldown-cmark", "rustc-rayon", diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 4af13e4cd58..baceb13cc61 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -16,3 +16,4 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tempfile = "3" itertools = "0.8" +lazy_static = "1" diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 39c214b1fb4..a77b177bd28 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -364,6 +364,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt ..Options::default() }; + lazy_static! { + static ref EMPTY_MAP: FxHashSet = FxHashSet::default(); + } let config = interface::Config { opts: sessopts, crate_cfg: interface::parse_cfgspecs(cfgs), @@ -378,8 +381,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt lint_caps, register_lints: None, override_queries: Some(|_sess, local_providers, external_providers| { + // Most lints will require typechecking, so just don't run them. local_providers.lint_mod = |_, _| {}; external_providers.lint_mod = |_, _| {}; + local_providers.typeck_item_bodies = |_, _| {}; + // hack so that `used_trait_imports` won't try to call typeck_tables_of + local_providers.used_trait_imports = |_, _| &EMPTY_MAP; + // In case typeck does end up being called, don't ICE in case there were name resolution errors local_providers.typeck_tables_of = move |tcx, def_id| { // Closures' tables come from their outermost function, // as they are part of the same "inference environment". @@ -439,6 +447,13 @@ 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| { + // Some queries require that they only run on valid types: + // https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425 + // Therefore typecheck this crate before running lints. + // NOTE: this does not typeck item 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); }); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4bd6b1260cc..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; 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), + | ^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. -- 2.44.0