Unrolled build for #150362
Rollup merge of #150362 - heathdutton:fix-rustdoc-duplicate-reexports-150211, r=notriddle

rustdoc: fix duplicate Re-exports sections

Fixes rust-lang/rust#150211

When a module contains both `pub extern crate` and `pub use` items, they were being rendered under two separate "Re-exports" section headers instead of one.

This fix tracks the current section and only renders a new header when the section actually changes, consolidating items that belong to the same section under a single header.
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 0b52c0b..ccf6490 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -398,18 +398,34 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
         let mut types = not_stripped_items.keys().copied().collect::<Vec<_>>();
         types.sort_unstable_by(|a, b| reorder(*a).cmp(&reorder(*b)));
 
+        let mut last_section: Option<super::ItemSection> = None;
+
         for type_ in types {
             let my_section = item_ty_to_section(type_);
-            let tag = if my_section == super::ItemSection::Reexports {
-                REEXPORTS_TABLE_OPEN
-            } else {
-                ITEM_TABLE_OPEN
-            };
-            write!(
-                w,
-                "{}",
-                write_section_heading(my_section.name(), &cx.derive_id(my_section.id()), None, tag)
-            )?;
+
+            // Only render section heading if the section changed
+            if last_section != Some(my_section) {
+                // Close the previous section if there was one
+                if last_section.is_some() {
+                    w.write_str(ITEM_TABLE_CLOSE)?;
+                }
+                let tag = if my_section == super::ItemSection::Reexports {
+                    REEXPORTS_TABLE_OPEN
+                } else {
+                    ITEM_TABLE_OPEN
+                };
+                write!(
+                    w,
+                    "{}",
+                    write_section_heading(
+                        my_section.name(),
+                        &cx.derive_id(my_section.id()),
+                        None,
+                        tag
+                    )
+                )?;
+                last_section = Some(my_section);
+            }
 
             for (_, myitem) in &not_stripped_items[&type_] {
                 match myitem.kind {
@@ -526,6 +542,9 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
                     }
                 }
             }
+        }
+        // Close the final section
+        if last_section.is_some() {
             w.write_str(ITEM_TABLE_CLOSE)?;
         }
 
diff --git a/tests/rustdoc/extern/duplicate-reexports-section-150211.rs b/tests/rustdoc/extern/duplicate-reexports-section-150211.rs
new file mode 100644
index 0000000..41f80cc
--- /dev/null
+++ b/tests/rustdoc/extern/duplicate-reexports-section-150211.rs
@@ -0,0 +1,19 @@
+//@ aux-build:pub-extern-crate.rs
+
+// Regression test for issue <https://github.com/rust-lang/rust/issues/150211>.
+// When a module has both `pub extern crate` and `pub use` items,
+// they should both appear under a single "Re-exports" section,
+// not two separate sections.
+
+//@ has duplicate_reexports_section_150211/index.html
+// Verify there's exactly one Re-exports section header
+//@ count - '//h2[@id="reexports"]' 1
+//@ has - '//h2[@id="reexports"]' 'Re-exports'
+// Verify both the extern crate and the use item are present
+//@ has - '//code' 'pub extern crate inner;'
+//@ has - '//code' 'pub use inner::SomeStruct;'
+
+pub extern crate inner;
+
+#[doc(no_inline)]
+pub use inner::SomeStruct;