diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 81fbfd9fdbd16..13855bf16920b 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -171,8 +171,21 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { /// the hashmap because certain items (traits and types) need to have their mappings for trait /// implementations filled out before they're inserted. fn item(&mut self, item: clean::Item) -> Result<(), Error> { + let local_blanket_impl = match item.def_id { + clean::ItemId::Blanket { impl_id, .. } => impl_id.is_local(), + clean::ItemId::Auto { .. } + | clean::ItemId::DefId(_) + | clean::ItemId::Primitive(_, _) => false, + }; + // Flatten items that recursively store other items - item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap()); + // FIXME(CraftSpider): We skip children of local blanket implementations, as we'll have + // already seen the actual generic impl, and the generated ones don't need documenting. + // This is necessary due to the visibility, return type, and self arg of the generated + // impls not quite matching, and will no longer be necessary when the mismatch is fixed. + if !local_blanket_impl { + item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap()); + } let id = item.def_id; if let Some(mut new_item) = self.convert_item(item) { diff --git a/src/test/rustdoc-json/impls/blanket_with_local.rs b/src/test/rustdoc-json/impls/blanket_with_local.rs new file mode 100644 index 0000000000000..963ea2fe5aea8 --- /dev/null +++ b/src/test/rustdoc-json/impls/blanket_with_local.rs @@ -0,0 +1,14 @@ +// Test for the ICE in rust/83718 +// A blanket impl plus a local type together shouldn't result in mismatched ID issues + +// @has blanket_with_local.json "$.index[*][?(@.name=='Load')]" +pub trait Load { + fn load() {} +} + +impl

Load for P { + fn load() {} +} + +// @has - "$.index[*][?(@.name=='Wrapper')]" +pub struct Wrapper {}