[swift-evolution] [REVIEW] SE-0193 - Cross-module inlining and specialization

Slava Pestov spestov at apple.com
Fri Dec 22 01:29:52 CST 2017

> On Dec 21, 2017, at 12:42 PM, Paul Cantrell <cantrell at pobox.com> wrote:
> 1. Presumably the portions of A inlined into B and C remain sensitive to the version-specific memory layout of A? Or will ABI stability mean that the compiler can magically rearrange memory offsets in already-compiled code when the layout changes? (Apologies if this is a too-obvious question; this part of Swift is all a mystery to me.)

There is not really a notion of memory layout at the level of an entire module. For structs, classes and enums, you pretty much have the same concerns with both inlinable and non-inlinable functions — if the framework author can change the stored property layout of a struct or class (or adds a case to an enum), code that manipulates these data types must not make any compile-time assumptions that might be invalidated at runtime with a newer version of the framework.

This is basically what the upcoming @fixedContents proposal for structs is about — giving framework authors a way to trade future flexibility for performance by allowing the compiler to make assumptions about the layout of a struct as it is written at compile-time. The @exhaustive proposal for enums has a similar implementation angle, but is of course more interesting because it affects the source language as well, with switch statements.

We don’t plan on any kind of resilience opt-out for classes — already in shipping Swift compilers, accesses to stored properties of classes use accessor methods and not direct access across module boundaries.

> 2. Is there some class of statically identifiable breaking changes that the compiler does (or should) detect to flag incompatible inlined code? e.g. some version of A inlined into B references A.foo, then A.foo is deleted in a later version of A, so mixing older B with newer A in a project gives a compile- or link-time error?

This is what an “ABI differ” tool would achieve, but like I said it has not yet been designed.

> 3. Does this need some sort of poison pill feature for other sorts of breaking changes that are not statically detectable? e.g. invariants of a data structure in A change in release 2.0, so the author of A says “it is an error to include A ≥2.0 in any project that inlined any of my code from a version <2.0.” Is this what you were getting at with the mention of @inlinable(2.0) in the proposal? Sounded like that part was about something else, but I didn’t really grasp it tbh.

This is an interesting point and I think it is outside of the scope of these proposals. If the ABI of a library changes in an incompatible manner and previous binaries are no longer compatible with it, you should think of it as shipping a *new* library, either by changing it’s name or bumping the major version number, so that the dynamic linker prevents the client binary from being run in the first place.

> Yes, frameworks+app built simultaneously are clearly the more common case. Though Carthage seems to be champing at the bit to create this problem, since it added a feature to download prebuilt binaries long before ABI stability! I can easily imagining this feature spreading via word of mouth as a “secret go faster switch,” and causing no end of problems in the wild.

Perhaps, but I still think it is strictly better to formalize the feature through a proposal and document the pitfalls carefully — the underscored attribute is already spreading through word of mouth and in the absence of official documentation the potential for abuse is greater.

> It might be safer — and better match the understanding of the typical user — to have @inlinable assume by default that an inlined version of any given method is only valid only for the specific version of the module it was inlined from. The compiler would by default flag any version mixing as an error, and require an explicit statement of compatibility intent for each piece of inlinable code to opt in to the danger zone of mixed versions.

How would this be implemented?


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171221/3232b356/attachment.html>

More information about the swift-evolution mailing list