Skip to content

Commit 8743ce8

Browse files
committed
rustdoc: prevent B -> C -> B -> C loops from stack overflowing
1 parent 346065f commit 8743ce8

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

src/librustdoc/passes/collect_trait_impls.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
100100
cx: &DocContext<'_>,
101101
map: &FxHashMap<DefId, &Type>,
102102
cleaner: &mut BadImplStripper<'_>,
103+
targets: &mut FxHashSet<DefId>,
103104
type_did: DefId,
104105
) {
105106
if let Some(target) = map.get(&type_did) {
@@ -108,12 +109,12 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
108109
cleaner.prims.insert(target_prim);
109110
} else if let Some(target_did) = target.def_id(&cx.cache) {
110111
// `impl Deref<Target = S> for S`
111-
if target_did == type_did {
112+
if !targets.insert(target_did) {
112113
// Avoid infinite cycles
113114
return;
114115
}
115116
cleaner.items.insert(target_did.into());
116-
add_deref_target(cx, map, cleaner, target_did);
117+
add_deref_target(cx, map, cleaner, targets, target_did);
117118
}
118119
}
119120
}
@@ -143,7 +144,15 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
143144
// `Deref` target type and the impl for type positions, this map of types is keyed by
144145
// `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
145146
if cleaner.keep_impl_with_def_id(for_did.into()) {
146-
add_deref_target(cx, &type_did_to_deref_target, &mut cleaner, for_did);
147+
let mut targets = FxHashSet::default();
148+
targets.insert(for_did);
149+
add_deref_target(
150+
cx,
151+
&type_did_to_deref_target,
152+
&mut cleaner,
153+
&mut targets,
154+
for_did,
155+
);
147156
}
148157
}
149158
}

0 commit comments

Comments
 (0)