Please, pretty please, my compilation times are dying because of transitive module parsing...
Wasn't this already released as part of Swift 6? We have been using internal import ... for a while now.
Correct—the replacement for @_implementationOnly is either internal import or private import depending on how narrowly-scoped you can make the dependency.
There's a subtle difference: internal and private imports don't prune dependencies in non-resilient builds like @_implementationOnly does (with the usual caveats about unsupported attributes), so they're not an exact substitute for the latter if your goal is to reduce the overhead of transitive module loading.
That being said, are you sure that module loading is the culprit for your compile times? We have projects with some very deep dependency trees and module loading isn't among the bottlenecks we've seen in builds. (Unless you're talking about transitive Clang modules, in which case the work done recently around explicit modules should help a lot there.)
If you can provide more context, it might point to something else that could be tweaked in your build.
internalandprivateimports don't prune dependencies in non-resilient builds like@_implementationOnlydoes
Isn't this the crucial reason why @_implementationOnly is unsafe for non-resilient libraries?
To my understanding, to produce correct code, those transitive modules must be parsed.
Hence the parenthetical immediately after the part you quoted: (with the usual caveats about unsupported attributes)
The compiler does a better job at preventing some unsafe things these days involving @_implementationOnly than it used to. For example, a struct can't have even a private stored property whose type comes from an @_implementationOnly imported module because the compiler needs that module to determine the layout of the property so that it can determine the layout of the whole struct. Several versions ago the compiler didn't diagnose that, but now it does IIRC. (To get around it, you can add a level of indirection by boxing the property inside an Any.)
So the reasons the attribute hasn't been made stable are a combination of limitations like the one above being too onerous for a production-quality feature (it would be better to abstract out the layout so that the entire module isn't required to manipulate it), and because there are probably other subtle bugs that need to be fixed as well.
Yes, you are right!
I should have quoted your words, instead of replying to you ![]()
Yeah, I have a module that accidentally has to parse 110 transitive dependencies while containing 1 file with 1 public class with one function (it's a Swinject assembly). 1 direct dependency, 110 transitive.
I mean, of course, maybe I can rearrange my module tree so that this burden is, say, split between separate assemblies... But - there would be no reason to do that in a world where fully private imports in non-resilient modules didn't cause memory layout issues.
Yeah, import ACLs don't prevent the need for transitive module parsing unfortunately...
Still working on this, however slowly:
Like @allevato mentioned:
but we still see some of these details leaking through and I even had a weird edge case with a class' v-table being invisible to a descendant class and not clearly related to implementationOnly imports anyway. The problem was not minimally-reproducible but the fix was adding final to some private methods of the base class. As v-table layout (in fragile builds, resilient is at runtime) happens before devirturalization this was an acceptable fix at the time but we weren't able to diagnose the problem further. If anyone else is working on this actively, please reach out.