From b2f19eac2f139d35d9398ba2e90c2c424e84792b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heath=20Dutton=F0=9F=95=B4=EF=B8=8F?= Date: Wed, 24 Dec 2025 23:41:40 -0500 Subject: [PATCH 1/5] rustdoc: fix duplicate Re-exports sections 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 happened because the code iterated over each ItemType separately and rendered a section header for each, even though both ExternCrate and Import map to the same ItemSection. 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. --- src/librustdoc/html/render/print_item.rs | 39 ++++++++++++++----- .../duplicate-reexports-section-150211.rs | 19 +++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 tests/rustdoc/extern/duplicate-reexports-section-150211.rs diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0b52c0b56b82..ccf6490877d6 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -398,18 +398,34 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i let mut types = not_stripped_items.keys().copied().collect::>(); types.sort_unstable_by(|a, b| reorder(*a).cmp(&reorder(*b))); + let mut last_section: Option = 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 ¬_stripped_items[&type_] { match myitem.kind { @@ -526,6 +542,9 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i } } } + } + // 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 000000000000..41f80cc6ab75 --- /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 . +// 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; From 09f57eb96f8a7652eebae41a870e7af0f3fd65e6 Mon Sep 17 00:00:00 2001 From: BioTomateHP Date: Fri, 26 Dec 2025 18:05:59 +0100 Subject: [PATCH 2/5] Update hir.rs: fix typo, conform to max_width --- compiler/rustc_hir/src/hir.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e176c703b33e..a1fdb81f0ab3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -150,10 +150,13 @@ impl From for LifetimeSyntax { /// `LifetimeSource::OutlivesBound` or `LifetimeSource::PreciseCapturing` /// — there's no way to "elide" these lifetimes. #[derive(Debug, Copy, Clone, HashStable_Generic)] -// Raise the aligement to at least 4 bytes - this is relied on in other parts of the compiler(for pointer tagging): -// https://github.com/rust-lang/rust/blob/ce5fdd7d42aba9a2925692e11af2bd39cf37798a/compiler/rustc_data_structures/src/tagged_ptr.rs#L163 -// Removing this `repr(4)` will cause the compiler to not build on platforms like `m68k` Linux, where the aligement of u32 and usize is only 2. -// Since `repr(align)` may only raise aligement, this has no effect on platforms where the aligement is already sufficient. +// Raise the alignment to at least 4 bytes. +// This is relied on in other parts of the compiler (for pointer tagging): +// +// Removing this `repr(4)` will cause the compiler to not build on platforms +// like `m68k` Linux, where the alignment of u32 and usize is only 2. +// Since `repr(align)` may only raise alignment, this has no effect on +// platforms where the alignment is already sufficient. #[repr(align(4))] pub struct Lifetime { #[stable_hasher(ignore)] From 106e88e0baaa87dfd56c533ca795f484e849e501 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 26 Dec 2025 23:25:32 +0100 Subject: [PATCH 3/5] Document default SOCK_CLOEXEC flag on new UnixStream Currently, the `std::os::unix::net::UnixStream` docs do not specify that the SOCK_CLOEXEC flag is set on new sockets. This commit adds a note clarifying that, in line with the note abuot the `MSG_NOSIGNAL` flag. --- library/std/src/os/unix/net/stream.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 1fed1229d5ae..ed5c434543d9 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -58,6 +58,13 @@ use crate::time::Duration; /// } /// ``` /// +/// # `SOCK_CLOEXEC` +/// +/// On platforms that support it, we pass the close-on-exec flag to atomically create the socket and +/// set it as CLOEXEC. On Linux, this was added in 2.6.27. See [`socket(2)`] for more information. +/// +/// [`socket(2)`](https://www.man7.org/linux/man-pages/man2/socket.2.html#:~:text=SOCK_CLOEXEC) +/// /// # `SIGPIPE` /// /// Writes to the underlying socket in `SOCK_STREAM` mode are made with `MSG_NOSIGNAL` flag. From ee9db304214c6705b7ba2106e50b3eada99ee24c Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 27 Dec 2025 10:59:21 +0100 Subject: [PATCH 4/5] fix late night markdown --- library/std/src/os/unix/net/stream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index ed5c434543d9..c0a8045884a5 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -63,7 +63,7 @@ use crate::time::Duration; /// On platforms that support it, we pass the close-on-exec flag to atomically create the socket and /// set it as CLOEXEC. On Linux, this was added in 2.6.27. See [`socket(2)`] for more information. /// -/// [`socket(2)`](https://www.man7.org/linux/man-pages/man2/socket.2.html#:~:text=SOCK_CLOEXEC) +/// [`socket(2)`]: https://www.man7.org/linux/man-pages/man2/socket.2.html#:~:text=SOCK_CLOEXEC /// /// # `SIGPIPE` /// From 7898df42b99224d7e706ec4d28891f0e8ad6c9e9 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 27 Dec 2025 13:17:28 +0100 Subject: [PATCH 5/5] Improve missing core error for tier 3 targets Tier 3 targets can't be installed via rustup, so don't recommend that. Additionally, do recommend build-std on stable because it's the recommended way to use these targets, people should switch to nightly. --- compiler/rustc_metadata/src/errors.rs | 9 +++++++-- compiler/rustc_metadata/src/locator.rs | 2 ++ tests/ui/crate-loading/missing-std-tier-3.rs | 14 ++++++++++++++ tests/ui/crate-loading/missing-std-tier-3.stderr | 12 ++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/ui/crate-loading/missing-std-tier-3.rs create mode 100644 tests/ui/crate-loading/missing-std-tier-3.stderr diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index abfd078f7462..caca9c2a6c3d 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -466,6 +466,7 @@ pub struct CannotFindCrate { pub profiler_runtime: Symbol, pub locator_triple: TargetTuple, pub is_ui_testing: bool, + pub is_tier_3: bool, } impl Diagnostic<'_, G> for CannotFindCrate { @@ -485,11 +486,13 @@ impl Diagnostic<'_, G> for CannotFindCrate { diag.note(fluent::metadata_target_no_std_support); } + let has_precompiled_std = !self.is_tier_3; + if self.missing_core { if env!("CFG_RELEASE_CHANNEL") == "dev" && !self.is_ui_testing { // Note: Emits the nicer suggestion only for the dev channel. diag.help(fluent::metadata_consider_adding_std); - } else { + } else if has_precompiled_std { // NOTE: this suggests using rustup, even though the user may not have it installed. // That's because they could choose to install it; or this may give them a hint which // target they need to install from their distro. @@ -504,7 +507,9 @@ impl Diagnostic<'_, G> for CannotFindCrate { if !self.missing_core && self.span.is_dummy() { diag.note(fluent::metadata_std_required); } - if self.is_nightly_build { + // Recommend -Zbuild-std even on stable builds for Tier 3 targets because + // it's the recommended way to use the target, the user should switch to nightly. + if self.is_nightly_build || !has_precompiled_std { diag.help(fluent::metadata_consider_building_std); } } else if self.crate_name == self.profiler_runtime { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 9fef22f9558d..df6eb77c178c 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1224,6 +1224,7 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, is_ui_testing: sess.opts.unstable_opts.ui_testing, + is_tier_3: sess.target.metadata.tier == Some(3), }; // The diagnostic for missing core is very good, but it is followed by a lot of // other diagnostics that do not add information. @@ -1249,6 +1250,7 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), is_ui_testing: sess.opts.unstable_opts.ui_testing, + is_tier_3: sess.target.metadata.tier == Some(3), }; // The diagnostic for missing core is very good, but it is followed by a lot of // other diagnostics that do not add information. diff --git a/tests/ui/crate-loading/missing-std-tier-3.rs b/tests/ui/crate-loading/missing-std-tier-3.rs new file mode 100644 index 000000000000..74c7db3db0ab --- /dev/null +++ b/tests/ui/crate-loading/missing-std-tier-3.rs @@ -0,0 +1,14 @@ +// Ensure that we do not recommend rustup installing tier 3 targets. + +//@ compile-flags: --target m68k-unknown-linux-gnu +//@ needs-llvm-components: m68k +//@ rustc-env:CARGO_CRATE_NAME=foo +//@ ignore-backends: gcc +#![feature(no_core)] +#![no_core] +extern crate core; +//~^ ERROR can't find crate for `core` +//~| NOTE can't find crate +//~| NOTE target may not be installed +//~| HELP consider building the standard library from source with `cargo build -Zbuild-std` +fn main() {} diff --git a/tests/ui/crate-loading/missing-std-tier-3.stderr b/tests/ui/crate-loading/missing-std-tier-3.stderr new file mode 100644 index 000000000000..197feeccd9c5 --- /dev/null +++ b/tests/ui/crate-loading/missing-std-tier-3.stderr @@ -0,0 +1,12 @@ +error[E0463]: can't find crate for `core` + --> $DIR/missing-std-tier-3.rs:9:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ can't find crate + | + = note: the `m68k-unknown-linux-gnu` target may not be installed + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0463`.