diff options
| author | Yuki Okushi <jtitor@2k36.org> | 2022-06-16 07:24:40 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-16 07:24:40 +0900 |
| commit | 4ee78a686facf95eb640fc00d5b92d4e9281e81c (patch) | |
| tree | ba451d17fb0ed0b8beba3ff15aee2fc49b4de334 /src | |
| parent | 52afa3a70c2f5fad0c61f06497b13b66490b97a8 (diff) | |
| parent | 99cd9cae10fd7c9db35f3047a7f376bdb2d13f66 (diff) | |
| download | rust-4ee78a686facf95eb640fc00d5b92d4e9281e81c.tar.gz rust-4ee78a686facf95eb640fc00d5b92d4e9281e81c.zip | |
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```
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustdoc/json/mod.rs | 53 | ||||
| -rw-r--r-- | src/test/rustdoc-json/generic_impl.rs | 24 |
2 files changed, 67 insertions, 10 deletions
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index f338050bee0..0964b757e74 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -181,15 +181,44 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let name = item.name; let item_id = item.item_id; if let Some(mut new_item) = self.convert_item(item) { - if let types::ItemEnum::Trait(ref mut t) = new_item.inner { - t.implementations = self.get_trait_implementors(item_id.expect_def_id()) - } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner { - s.impls = self.get_impls(item_id.expect_def_id()) - } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner { - e.impls = self.get_impls(item_id.expect_def_id()) - } else if let types::ItemEnum::Union(ref mut u) = new_item.inner { - u.impls = self.get_impls(item_id.expect_def_id()) - } + let can_be_ignored = match new_item.inner { + types::ItemEnum::Trait(ref mut t) => { + t.implementations = self.get_trait_implementors(item_id.expect_def_id()); + false + } + types::ItemEnum::Struct(ref mut s) => { + s.impls = self.get_impls(item_id.expect_def_id()); + false + } + types::ItemEnum::Enum(ref mut e) => { + e.impls = self.get_impls(item_id.expect_def_id()); + false + } + types::ItemEnum::Union(ref mut u) => { + u.impls = self.get_impls(item_id.expect_def_id()); + false + } + + types::ItemEnum::Method(_) + | types::ItemEnum::AssocConst { .. } + | types::ItemEnum::AssocType { .. } => true, + types::ItemEnum::Module(_) + | types::ItemEnum::ExternCrate { .. } + | types::ItemEnum::Import(_) + | types::ItemEnum::StructField(_) + | types::ItemEnum::Variant(_) + | types::ItemEnum::Function(_) + | types::ItemEnum::TraitAlias(_) + | types::ItemEnum::Impl(_) + | types::ItemEnum::Typedef(_) + | types::ItemEnum::OpaqueTy(_) + | types::ItemEnum::Constant(_) + | types::ItemEnum::Static(_) + | types::ItemEnum::ForeignType + | types::ItemEnum::Macro(_) + | types::ItemEnum::ProcMacro(_) + | types::ItemEnum::PrimitiveType(_) => false, + }; let removed = self .index .borrow_mut() @@ -199,7 +228,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { // to make sure the items are unique. The main place this happens is when an item, is // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod` if let Some(old_item) = removed { - assert_eq!(old_item, new_item); + // In case of generic implementations (like `impl<T> Trait for T {}`), all the + // inner items will be duplicated so we can ignore if they are slightly different. + if !can_be_ignored { + assert_eq!(old_item, new_item); + } } } diff --git a/src/test/rustdoc-json/generic_impl.rs b/src/test/rustdoc-json/generic_impl.rs new file mode 100644 index 00000000000..ac68ba578b6 --- /dev/null +++ b/src/test/rustdoc-json/generic_impl.rs @@ -0,0 +1,24 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/97986>. + +// @has generic_impl.json +// @has - "$.index[*][?(@.name=='f')]" +// @has - "$.index[*][?(@.name=='AssocTy')]" +// @has - "$.index[*][?(@.name=='AssocConst')]" + +pub mod m { + pub struct S; +} + +pub trait F { + type AssocTy; + const AssocConst: usize; + fn f() -> m::S; +} + +impl<T> F for T { + type AssocTy = u32; + const AssocConst: usize = 0; + fn f() -> m::S { + m::S + } +} |
