diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2021-11-01 03:33:07 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-01 03:33:07 +0100 |
| commit | 3730485a24e95db1f77201c6173cd189f403d151 (patch) | |
| tree | fa05b28a22d3ae938db5788d43313b7819e2b110 /src | |
| parent | bb6901d32b21627e39825699d66c171141c14fd7 (diff) | |
| parent | b8ecc9fefa4c9c763cf74e9c9659ecc00f30ba3a (diff) | |
| download | rust-3730485a24e95db1f77201c6173cd189f403d151.tar.gz rust-3730485a24e95db1f77201c6173cd189f403d151.zip | |
Rollup merge of #90349 - willcrichton:example-analyzer, r=jyn514
Fix rare ICE during typeck in rustdoc scrape_examples While testing the `--scrape-examples` extension on the [wasmtime](https://github.com/bytecodealliance/wasmtime) repository, I found some additional edge cases. Specifically, when asking to typecheck a body containing a function call, I would sometimes get an ICE if: * The body doesn't exist * The function's HIR node didn't have a type This adds checks for both of those conditions. (Also this updates a test to check that the sources of a reverse-dependency are correctly generated and linked.) r? `@jyn514`
Diffstat (limited to 'src')
5 files changed, 28 insertions, 2 deletions
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index fc54e55b876..05e746573f4 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -132,12 +132,28 @@ where fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { intravisit::walk_expr(self, ex); - // Get type of function if expression is a function call let tcx = self.tcx; + + // If we visit an item that contains an expression outside a function body, + // then we need to exit before calling typeck (which will panic). See + // test/run-make/rustdoc-scrape-examples-invalid-expr for an example. + let hir = tcx.hir(); + let owner = hir.local_def_id_to_hir_id(ex.hir_id.owner); + if hir.maybe_body_owned_by(owner).is_none() { + return; + } + + // Get type of function if expression is a function call let (ty, span) = match ex.kind { hir::ExprKind::Call(f, _) => { let types = tcx.typeck(ex.hir_id.owner); - (types.node_type(f.hir_id), ex.span) + + match types.node_type_opt(f.hir_id) { + Some(ty) => (ty, ex.span), + None => { + return; + } + } } hir::ExprKind::MethodCall(_, _, _, span) => { let types = tcx.typeck(ex.hir_id.owner); diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile new file mode 100644 index 00000000000..dce8b83eefe --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile @@ -0,0 +1,5 @@ +deps := ex + +-include ../rustdoc-scrape-examples-multiple/scrape.mk + +all: scrape diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs new file mode 100644 index 00000000000..b342b5b0aae --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs @@ -0,0 +1,2 @@ +pub struct Foo([usize; foobar::f()]); +fn main() {} diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs new file mode 100644 index 00000000000..c30c99dec60 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs @@ -0,0 +1 @@ +pub const fn f() -> usize { 5 } diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs index bd59584bbbf..bdfeda92d79 100644 --- a/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs +++ b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs @@ -1,4 +1,6 @@ // @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' '' // @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' '' +// @has src/ex/ex.rs.html +// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' '' pub fn ok() {} |
