Change:
I tried this code: I expected to see this happen: Compiles successfully. Instead, this happened: Fails with this error: nightly-2024-06-26 and earlier. nightly-2024-06-27 and later, starting with . See for a discussion of the issue. : cc
To elaborate, the difference is in symbols.o. Here's a dump of symbols.o before the change: And here's after: Spot the difference. Spoiler: is now present.
So is that right or wrong? The static is "used" so marking it exported to ensure it does not get optimized away seems to make sense? I don't understand why this is a problem only on Windows.
Well that's not a problem per se but if we want to do that then we have to do it properly. is defined as a in (on my machine). This is linked directly and not in a lib file. So it's already being included. There's no reason for to include it. The only issue is that is being emitted as a comdat, meaning the linker is still allowed to remove it. We could just not do that (or add a linker directive). But that's a pre-existing issue.
I don't understand any part of that.^^ Should my PR get reverted or is there a better way to fix this regression? If there is a better way, I am afraid I lack the knowledge to implement and test it. I don't understand symbol handling on Linux, let alone on Windows.
I don't know enough about the Rust compiler to say. My complete guess would be that was silently broken before but now it's nosily broken.
Hm, who would understand our Windows linking story? ?
After CGU partitioning, we try to internalize symbols when possible. What is surprising to me is that this process only looks at export level, ignoring used attribute (in the contrast to say the internalization during fat LTO). Consequently we have a situation where synthetic object file references a symbol that is no longer exported (on Linux that does not result in a linking error, even though reference is unresolved). Anyway, if the consequence of would be to export those symbols for no reason, that seems rather counter productive to me.
Ah, the behaviour was working to spec before: So I think I'd agree that is the wrong approach and should be reverted because this currently ends up conflating different things. Maybe changes elsewhere would fix this but I don't want to speculate.
the separate issue you pointed out earlier in is presumably still relevant for ?
Could this explain recent CI flakiness? The failure at and a couple other failed merges (linked on that thread, also the retries) have been msvc linker errors.
That's unfortunate. :/ Our reachable symbol code is such a spaghetti mess... I guess I'll just have to copy-paste more things into Miri then. :shrug: I am traveling right now, I'd appreciate if someone else could do the revert.
The following patch should fix the incorrect internalization I mentioned earlier: As for the question whether those symbols should be exported in the first place, it might be necessary for COFF and . The following code suggests that would not have the desired effect otherwise I don't have access to windows environment at the moment to verify that, so I don't plan to work on this myself.
Ooh this is also the stuff that also broke several ci-runs already ...
Looks like this did not fully fix the ci failures :melting_face:
Makes sense: some CI failures look non-deterministic, while we'd expect this error not to be.
Alternative approach for Miri:

Discussion:
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::bug; <del> use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; </del> <ins> use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; </ins> use rustc_middle::middle::privacy::{self, Level}; use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc}; use rustc_middle::query::Providers;

if !self.any_library { // If we are building an executable, only explicitly extern // types need to be exported. <del> if has_custom_linkage(self.tcx, search_item) { </del> <ins> let codegen_attrs = if self.tcx.def_kind(search_item).has_codegen_attrs() { self.tcx.codegen_fn_attrs(search_item) } else { CodegenFnAttrs::EMPTY }; let is_extern = codegen_attrs.contains_extern_indicator(); let std_internal = codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); if is_extern || std_internal { </ins> self.reachable_symbols.insert(search_item); } } else {

<del> //! Ensure that we call Windows TLS callbacks in the local crate. //@only-target-windows // Calling eprintln in the callback seems to (re-)initialize some thread-local storage // and then leak the memory allocated for that. Let's just ignore these leaks, // that's not what this test is about. //@compile-flags: -Zmiri-ignore-leaks #[link_section = ".CRT$XLB"] #[used] // Miri only considers explicitly `#[used]` statics for `lookup_link_section` pub static CALLBACK: unsafe extern "system" fn(*const (), u32, *const ()) = tls_callback; unsafe extern "system" fn tls_callback(_h: *const (), _dw_reason: u32, _pv: *const ()) { eprintln!("in tls_callback"); } fn main() {} </del>

<ins> // This is a non-regression test for issue #127052 where unreferenced `#[used]` statics couldn't be // removed by the MSVC linker, causing linking errors. //@ build-pass: needs linking //@ only-msvc #[used] static FOO: u32 = 0; fn main() {} </ins>