Skip to content

Commit 687ac3f

Browse files
Fix panic if an item does not have a body
1 parent 9457a32 commit 687ac3f

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

src/librustdoc/html/render/span_map.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
22

33
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
44
use rustc_hir::def::{DefKind, Res};
5-
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
5+
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
66
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
77
use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath};
88
use rustc_middle::hir::nested_filter;
@@ -201,6 +201,17 @@ impl SpanMapVisitor<'_> {
201201
}
202202
}
203203

204+
// This is a reimplementation of `hir_enclosing_body_owner` which allows to fail without
205+
// panicking.
206+
fn hir_enclosing_body_owner(tcx: TyCtxt<'_>, hir_id: HirId) -> Option<LocalDefId> {
207+
for (_, node) in tcx.hir_parent_iter(hir_id) {
208+
if let Some((def_id, _)) = node.associated_body() {
209+
return Some(def_id);
210+
}
211+
}
212+
None
213+
}
214+
204215
impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
205216
type NestedFilter = nested_filter::All;
206217

@@ -221,15 +232,16 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
221232
QPath::TypeRelative(qself, path) => {
222233
if matches!(path.res, Res::Err) {
223234
let tcx = self.tcx;
224-
let body_id = tcx.hir_enclosing_body_owner(id);
225-
let typeck_results = tcx.typeck_body(tcx.hir_body_owned_by(body_id).id());
226-
let path = rustc_hir::Path {
227-
// We change the span to not include parens.
228-
span: path.ident.span,
229-
res: typeck_results.qpath_res(qpath, id),
230-
segments: &[],
231-
};
232-
self.handle_path(&path, false);
235+
if let Some(body_id) = hir_enclosing_body_owner(tcx, id) {
236+
let typeck_results = tcx.typeck_body(tcx.hir_body_owned_by(body_id).id());
237+
let path = rustc_hir::Path {
238+
// We change the span to not include parens.
239+
span: path.ident.span,
240+
res: typeck_results.qpath_res(qpath, id),
241+
segments: &[],
242+
};
243+
self.handle_path(&path, false);
244+
}
233245
} else {
234246
self.infer_id(path.hir_id, Some(id), path.ident.span);
235247
}

tests/rustdoc/jump-to-def-ice.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// This test ensures that items with no body don't panic when generating
2+
// jump to def links.
3+
4+
//@ compile-flags: -Zunstable-options --generate-link-to-definition
5+
6+
#![crate_name = "foo"]
7+
8+
//@ has 'src/foo/jump-to-def-ice.rs.html'
9+
10+
pub trait A {
11+
type T;
12+
type U;
13+
}
14+
15+
impl A for () {
16+
type T = Self::U;
17+
type U = ();
18+
}
19+
20+
pub trait C {
21+
type X;
22+
}
23+
24+
pub struct F<T: C>(pub T::X);

0 commit comments

Comments
 (0)