about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-04 19:08:23 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2025-08-10 12:00:08 +0200
commitd528a49fd7c0447cc51406908fb13fe055d273aa (patch)
treef4a96585e52802f820c4f2227a7086d4f3416af0 /src
parent1a6d6363d090961a1efe513d413f5b51ecd81ab8 (diff)
downloadrust-d528a49fd7c0447cc51406908fb13fe055d273aa.tar.gz
rust-d528a49fd7c0447cc51406908fb13fe055d273aa.zip
Fix panic if an item does not have a body
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/html/render/span_map.rs32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 505797ccc0b..6906e6e30ff 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
 
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor, VisitorExt};
 use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath};
 use rustc_middle::hir::nested_filter;
@@ -201,6 +201,17 @@ impl SpanMapVisitor<'_> {
     }
 }
 
+// This is a reimplementation of `hir_enclosing_body_owner` which allows to fail without
+// panicking.
+fn hir_enclosing_body_owner(tcx: TyCtxt<'_>, hir_id: HirId) -> Option<LocalDefId> {
+    for (_, node) in tcx.hir_parent_iter(hir_id) {
+        if let Some((def_id, _)) = node.associated_body() {
+            return Some(def_id);
+        }
+    }
+    None
+}
+
 impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
     type NestedFilter = nested_filter::All;
 
@@ -221,15 +232,16 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
             QPath::TypeRelative(qself, path) => {
                 if matches!(path.res, Res::Err) {
                     let tcx = self.tcx;
-                    let body_id = tcx.hir_enclosing_body_owner(id);
-                    let typeck_results = tcx.typeck_body(tcx.hir_body_owned_by(body_id).id());
-                    let path = rustc_hir::Path {
-                        // We change the span to not include parens.
-                        span: path.ident.span,
-                        res: typeck_results.qpath_res(qpath, id),
-                        segments: &[],
-                    };
-                    self.handle_path(&path, false);
+                    if let Some(body_id) = hir_enclosing_body_owner(tcx, id) {
+                        let typeck_results = tcx.typeck_body(tcx.hir_body_owned_by(body_id).id());
+                        let path = rustc_hir::Path {
+                            // We change the span to not include parens.
+                            span: path.ident.span,
+                            res: typeck_results.qpath_res(qpath, id),
+                            segments: &[],
+                        };
+                        self.handle_path(&path, false);
+                    }
                 } else {
                     self.infer_id(path.hir_id, Some(id), path.ident.span);
                 }