Description
At the moment, all closures get weak_odr linkage, since that allows for easily avoiding symbol conflicts between copies of the same closure in different crates -- something that can happen when a function containing a closure is inlined into another crate.
One problem though with this approach is that the mingw toolchain does not allow for more than 2^15 weak symbols within one binary. Unfortunately, there are codebases out there run into this limit, e.g. servo/servo#12393 (comment).
So, if we want to keep supporting mingw, we need to find a way to avoid symbol conflicts for closures without using weak linkage.
For monomorphizations of generic functions the same issue exists but in that case it has been easier to solve because we could just instantiate them within each codegen unit with "internal" linkage, thus avoiding any conflicts. For closures this is currently not possible because the cross-crate inlining infrastructure does not allow for inlining a closure on demand.
I see a few possible solutions, each with its own set of disadvantages:
- Extend the inlining-infrastructure to better support closures. Then we could handle closures just the same as monomorphizations. The downside is that this would mean an investment into code that will become obsolete once non-MIR-trans is removed.
- Always force MIR-trans for closures from extern crates, then we don't need to inline them. The downside is that MIR-trans might not be ready for that yet and that it's kind of a strange and inconsistent behavior.
- Make sure that the symbol-hash of a closure contains the crate-id of the instantiating crate, thus avoid cross-crate conflicts. The downside is that this makes symbol naming more complicated again, i.e. one can't just call
instance.symbol_name()
and get a nicely predictable result anymore. - Store the set of exported closure instances in crate metadata and never locally instantiate closures that already exist somewhere. The downside is that it means more stuff in metadata.
- Drop support for mingw
:P
cc @rust-lang/compiler