about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-11-01 03:33:07 +0100
committerGitHub <noreply@github.com>2021-11-01 03:33:07 +0100
commit3730485a24e95db1f77201c6173cd189f403d151 (patch)
treefa05b28a22d3ae938db5788d43313b7819e2b110 /src
parentbb6901d32b21627e39825699d66c171141c14fd7 (diff)
parentb8ecc9fefa4c9c763cf74e9c9659ecc00f30ba3a (diff)
downloadrust-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')
-rw-r--r--src/librustdoc/scrape_examples.rs20
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs2
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs1
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs2
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() {}