Skip to content

Commit 4ee78a6

Browse files
authored
Rollup merge of #98053 - GuillaumeGomez:fix-generic-impl-json-ice, r=notriddle
Fix generic impl rustdoc json output Fixes #97986. The problem in case of generic trait impl is that the trait's items are the same for all the types afterward. But since they're the same, it's safe for rustdoc-json to just ignore them. A little representation of what's going on: ```rust trait T { fn f(); // <- defid 0 } impl<Y> T for Y { fn f() {} // <- defid 1 } struct S; // <- defid 1 (since it matches `impl<Y> T for Y` ``` cc ```@Urgau``` r? ```@CraftSpider```
2 parents 52afa3a + 99cd9ca commit 4ee78a6

File tree

2 files changed

+67
-10
lines changed

2 files changed

+67
-10
lines changed

src/librustdoc/json/mod.rs

+43-10
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,44 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
181181
let name = item.name;
182182
let item_id = item.item_id;
183183
if let Some(mut new_item) = self.convert_item(item) {
184-
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
185-
t.implementations = self.get_trait_implementors(item_id.expect_def_id())
186-
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
187-
s.impls = self.get_impls(item_id.expect_def_id())
188-
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
189-
e.impls = self.get_impls(item_id.expect_def_id())
190-
} else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
191-
u.impls = self.get_impls(item_id.expect_def_id())
192-
}
184+
let can_be_ignored = match new_item.inner {
185+
types::ItemEnum::Trait(ref mut t) => {
186+
t.implementations = self.get_trait_implementors(item_id.expect_def_id());
187+
false
188+
}
189+
types::ItemEnum::Struct(ref mut s) => {
190+
s.impls = self.get_impls(item_id.expect_def_id());
191+
false
192+
}
193+
types::ItemEnum::Enum(ref mut e) => {
194+
e.impls = self.get_impls(item_id.expect_def_id());
195+
false
196+
}
197+
types::ItemEnum::Union(ref mut u) => {
198+
u.impls = self.get_impls(item_id.expect_def_id());
199+
false
200+
}
201+
202+
types::ItemEnum::Method(_)
203+
| types::ItemEnum::AssocConst { .. }
204+
| types::ItemEnum::AssocType { .. } => true,
205+
types::ItemEnum::Module(_)
206+
| types::ItemEnum::ExternCrate { .. }
207+
| types::ItemEnum::Import(_)
208+
| types::ItemEnum::StructField(_)
209+
| types::ItemEnum::Variant(_)
210+
| types::ItemEnum::Function(_)
211+
| types::ItemEnum::TraitAlias(_)
212+
| types::ItemEnum::Impl(_)
213+
| types::ItemEnum::Typedef(_)
214+
| types::ItemEnum::OpaqueTy(_)
215+
| types::ItemEnum::Constant(_)
216+
| types::ItemEnum::Static(_)
217+
| types::ItemEnum::ForeignType
218+
| types::ItemEnum::Macro(_)
219+
| types::ItemEnum::ProcMacro(_)
220+
| types::ItemEnum::PrimitiveType(_) => false,
221+
};
193222
let removed = self
194223
.index
195224
.borrow_mut()
@@ -199,7 +228,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
199228
// to make sure the items are unique. The main place this happens is when an item, is
200229
// reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
201230
if let Some(old_item) = removed {
202-
assert_eq!(old_item, new_item);
231+
// In case of generic implementations (like `impl<T> Trait for T {}`), all the
232+
// inner items will be duplicated so we can ignore if they are slightly different.
233+
if !can_be_ignored {
234+
assert_eq!(old_item, new_item);
235+
}
203236
}
204237
}
205238

src/test/rustdoc-json/generic_impl.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/97986>.
2+
3+
// @has generic_impl.json
4+
// @has - "$.index[*][?(@.name=='f')]"
5+
// @has - "$.index[*][?(@.name=='AssocTy')]"
6+
// @has - "$.index[*][?(@.name=='AssocConst')]"
7+
8+
pub mod m {
9+
pub struct S;
10+
}
11+
12+
pub trait F {
13+
type AssocTy;
14+
const AssocConst: usize;
15+
fn f() -> m::S;
16+
}
17+
18+
impl<T> F for T {
19+
type AssocTy = u32;
20+
const AssocConst: usize = 0;
21+
fn f() -> m::S {
22+
m::S
23+
}
24+
}

0 commit comments

Comments
 (0)