1
Fork 0

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.
This commit is contained in:
Joshua Nelson 2020-07-11 00:28:42 -04:00
parent 2d0e8e2162
commit 02a24c8e2f
6 changed files with 40 additions and 0 deletions

View file

@ -4027,6 +4027,7 @@ name = "rustdoc"
version = "0.0.0"
dependencies = [
"itertools 0.8.0",
"lazy_static",
"minifier",
"pulldown-cmark",
"rustc-rayon",

View file

@ -16,3 +16,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tempfile = "3"
itertools = "0.8"
lazy_static = "1"

View file

@ -364,6 +364,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
..Options::default()
};
lazy_static! {
static ref EMPTY_MAP: FxHashSet<LocalDefId> = 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);
});

View file

@ -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;

View file

@ -0,0 +1,4 @@
enum E {
//~^ ERROR recursive type `E` has infinite size
V(E),
}

View file

@ -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`.