Skip to content

Commit 206b202

Browse files
committed
Fix ICE in rustdoc when impl is nested in a func
1 parent ebe145e commit 206b202

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

src/librustdoc/html/render/span_map.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,13 @@ fn hir_enclosing_body_owner(tcx: TyCtxt<'_>, hir_id: HirId) -> Option<LocalDefId
251251
return None;
252252
} else if let Some((def_id, _)) = node.associated_body() {
253253
return Some(def_id);
254+
// Items don't have bodies.
255+
// If we go any further, we might encounter an enclosing function
256+
// (e.g. if we're inside an impl that's inside of a function).
257+
// This would cause us to erroneously consider this function to be the owner
258+
// of the node and produce invalid `HirId`s later.
259+
} else if matches!(node, Node::Item(_)) {
260+
return None;
254261
}
255262
}
256263
None
@@ -278,13 +285,22 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
278285
let tcx = self.tcx;
279286
if let Some(body_id) = hir_enclosing_body_owner(tcx, id) {
280287
let typeck_results = tcx.typeck_body(tcx.hir_body_owned_by(body_id).id());
288+
let path_res =
289+
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
290+
typeck_results.qpath_res(qpath, id)
291+
})) {
292+
Ok(path_res) => path_res,
293+
Err(panic) => std::panic::resume_unwind(panic),
294+
};
281295
let path = rustc_hir::Path {
282296
// We change the span to not include parens.
283297
span: path.ident.span,
284-
res: typeck_results.qpath_res(qpath, id),
298+
res: path_res,
285299
segments: &[],
286300
};
287301
self.handle_path(&path, false);
302+
} else {
303+
eprintln!("can't find a body for {id:?} :(");
288304
}
289305
} else {
290306
self.infer_id(path.hir_id, Some(id), path.ident.span.into());
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ compile-flags: -Zunstable-options --generate-link-to-definition
2+
3+
// See: https://github.com/rust-lang/rust/issues/147882
4+
5+
#![crate_name = "foo"]
6+
7+
trait Fun {
8+
fn fun();
9+
}
10+
11+
trait Other {}
12+
13+
impl Fun for () {
14+
fn fun() {
15+
impl<E> Other for E
16+
where
17+
E: std::str::FromStr,
18+
E::Err: Send,
19+
{
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)