SE-0193 - Cross-module inlining and specialization

+1 thanks for your response Chris, it seems to me that it addresses the need this PR is trying to address and it does make it so in a scalable way. I would strongly hope your feedback is added to the proposal and shapes the final solution.

···

Sent from my iPhone

On 21 Dec 2017, at 07:14, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

I am hugely supportive of the features that these attributes enable, but I think that the spelling of this is absolutely wrong, and I’m disappointed that the extensive discussion we’ve had for months about this didn’t make it into (at least) the alternatives considered section. Here are my concerns:

Availability Ranges

Both of these attributes will (perhaps not for Swift 5 given the fact that these will be new then, but certainly in 5.1 or 6) need to be qualified by deployment modifiers. We’ll need the ability to specify not just that a declaration is inlinable or abipublic, but in *which versions* of the binary package (that they are defined in) have this property.

For example, while perhaps it will be common for a decl to be “born inlinable” and just need the form of attribute as specified here, it is just as clear that this is not the *only* model we need. It is entirely reasonable (and will be important in the future) to say that something “became ABI public in iOS14, became abiPublic in iOS 15, and became inlinable in iOS16”. The use of this will be relatively rare, but it is important for the model to support this in time.

Because of this, if we accept the spelling as proposed in this proposal, these attributes will need to be generalized to have an availability range, e.g.:

  @abipublic(iOS 15, *)

The concern is that this proposal opens the door to have a family of attributes each of which have availability information on them, and this “family” of attributes will have nothing tying them together into a unified framework.

Pollution of the Attribute Namespace

Furthermore, these two attributes are the tip of the iceberg, and the core team has spent a lot of time recently discussing the fact there are potentially going to be about a dozen attributes similar to these (fixed_contents, global_var_is_directly_addressible, …) that will only be required for binary frameworks. It is possible that @inlinable will be prominent enough to be a global attribute (I personally am not sure if it will be commonly used or not, it depends a lot on how widely used binary frameworks are). That said, it is clear @abiPublic will not be commonly used, and many attributes that follow these will be even more obscure.

This is bad for three reasons:

1) we’re polluting the general attribute namespace with obscure things. Pollution of the attribute namespace may have a marginal impact today, but will start to matter if/when we ever get user defined attributes.

2) The other reason is that this provides no general framework to tie together these things that affect binary frameworks into a unified framework.

3) Furthermore, I don’t like attributes being a dumping ground for weird performance hacks required by binary frameworks. It is a practical necessity that we support these because they are extremely important for narrow cases, but we don’t need to put them into a syntactically prominent spot in the grammar.

The name “ABI”

A minor point, but the specific name “abiPublic” is not great in my opinion, because “ABI” is a term of art for compiler hackers. Most users have no idea what ABI means, and those who think they do often don’t. Very few people really understand what “stable ABI” means for example.

It would be better to go with something like “apiPublic” or “symbolPublic” or “linkableButNotAccessible” or something else long. This will not be commonly used in user code, so being long and descriptive is a good thing.

Counterproposal:

There is a simple way to address the two concerns above: we already have a framework for handling API evolution with binary frameworks, the @available attribute. We can spell these “attributes” as:

  @available(inlinable) // this symbol has been inlinable since it was introduced

which generalizes properly when we add version ranges:

  @available(iOS 14, *) // this was introduced in iOS 14
  @available(linkerSymbol: iOS 15, *) // this decl’s symbol became “abiPublic" in iOS 15
  @available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
  public func foo() {… }

and allows us to bury weird hacks like “abiPublic” and the other even more obscure things that are coming outside of the global attribute namespace:

  @available(global_var_is_directly_accessible: iOS 15, *)
  public var myDispatchOnceToken : ...

Given this unified framework for handling ABI evolution, we can then separately discuss which ones of these proposals are common and important enough to sugar into a top level attribute. For example, given the general model for inlinable above, we could then (possibly as a later proposal) introduce:

  @inlinable // this symbol has been inlinable since it was introduced
  public func foo()

as sugar for:

  @available(inlinable)
  public func foo()

… which means that the sugar forms can be separately debated, and that the sugar forms don’t have to permit the full complexity of the general case (the availability list). It still isn’t clear to me whether @inlinable meets the bar to be a global attribute, I can see both sides of that argument, and it seems valuable to be able to separate the engineering work to introduce the feature from the bikeshed discussion about whether it should be sugared or not.

In short, respectfully request that you at least add this approach to the "alternatives considered” section. I also suggest you strongly consider pursuing this direction. It solves the same problem as your proposal but:

- scales better as we add more “attributes" in the future - which will be of increasingly narrow applicability.
- provides a unifying model for all of the binary framework hints
- puts all the availability markup into the feature we already have for this.
- provides a better naming framework for things like abiPublic, because you can say "@available(linkerSymbol)” to say that this is making the linker symbol available from the binary framework.

-Chris

Is the problem being addressed significant enough to warrant a change to Swift?

Does this proposal fit well with the feel and direction of Swift?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I was going to write up a detailed response to this as well, but Chris did it for me.

In general, I agree that we need the feature.

However, I believe that the name “ABI” is too specific and does not accomplish the primary purpose of naming this thing — which is to allow people to understand what it means by reading it.

I agree that scoping these attributes inside the availability declaration is the best option. As a framework author, the notion of availability is of primary importance, and having things which affect how my clients see my code be part of that general concept makes the most sense. My second choice would be to scope it inside the “public” declaration, as in:

public
public(inlinable)
public(external) // *where we define external to be what abiPublic is now — more bike shedding welcome

- Tony

···

On Dec 20, 2017, at 11:14 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com <mailto:kremenek@apple.com>> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

I am hugely supportive of the features that these attributes enable, but I think that the spelling of this is absolutely wrong, and I’m disappointed that the extensive discussion we’ve had for months about this didn’t make it into (at least) the alternatives considered section. Here are my concerns:

Availability Ranges

Both of these attributes will (perhaps not for Swift 5 given the fact that these will be new then, but certainly in 5.1 or 6) need to be qualified by deployment modifiers. We’ll need the ability to specify not just that a declaration is inlinable or abipublic, but in *which versions* of the binary package (that they are defined in) have this property.

For example, while perhaps it will be common for a decl to be “born inlinable” and just need the form of attribute as specified here, it is just as clear that this is not the *only* model we need. It is entirely reasonable (and will be important in the future) to say that something “became ABI public in iOS14, became abiPublic in iOS 15, and became inlinable in iOS16”. The use of this will be relatively rare, but it is important for the model to support this in time.

Because of this, if we accept the spelling as proposed in this proposal, these attributes will need to be generalized to have an availability range, e.g.:

  @abipublic(iOS 15, *)

The concern is that this proposal opens the door to have a family of attributes each of which have availability information on them, and this “family” of attributes will have nothing tying them together into a unified framework.

Pollution of the Attribute Namespace

Furthermore, these two attributes are the tip of the iceberg, and the core team has spent a lot of time recently discussing the fact there are potentially going to be about a dozen attributes similar to these (fixed_contents, global_var_is_directly_addressible, …) that will only be required for binary frameworks. It is possible that @inlinable will be prominent enough to be a global attribute (I personally am not sure if it will be commonly used or not, it depends a lot on how widely used binary frameworks are). That said, it is clear @abiPublic will not be commonly used, and many attributes that follow these will be even more obscure.

This is bad for three reasons:

1) we’re polluting the general attribute namespace with obscure things. Pollution of the attribute namespace may have a marginal impact today, but will start to matter if/when we ever get user defined attributes.

2) The other reason is that this provides no general framework to tie together these things that affect binary frameworks into a unified framework.

3) Furthermore, I don’t like attributes being a dumping ground for weird performance hacks required by binary frameworks. It is a practical necessity that we support these because they are extremely important for narrow cases, but we don’t need to put them into a syntactically prominent spot in the grammar.

The name “ABI”

A minor point, but the specific name “abiPublic” is not great in my opinion, because “ABI” is a term of art for compiler hackers. Most users have no idea what ABI means, and those who think they do often don’t. Very few people really understand what “stable ABI” means for example.

It would be better to go with something like “apiPublic” or “symbolPublic” or “linkableButNotAccessible” or something else long. This will not be commonly used in user code, so being long and descriptive is a good thing.

Counterproposal:

There is a simple way to address the two concerns above: we already have a framework for handling API evolution with binary frameworks, the @available attribute. We can spell these “attributes” as:

  @available(inlinable) // this symbol has been inlinable since it was introduced

which generalizes properly when we add version ranges:

  @available(iOS 14, *) // this was introduced in iOS 14
  @available(linkerSymbol: iOS 15, *) // this decl’s symbol became “abiPublic" in iOS 15
  @available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
  public func foo() {… }

and allows us to bury weird hacks like “abiPublic” and the other even more obscure things that are coming outside of the global attribute namespace:

  @available(global_var_is_directly_accessible: iOS 15, *)
  public var myDispatchOnceToken : ...

Given this unified framework for handling ABI evolution, we can then separately discuss which ones of these proposals are common and important enough to sugar into a top level attribute. For example, given the general model for inlinable above, we could then (possibly as a later proposal) introduce:

  @inlinable // this symbol has been inlinable since it was introduced
  public func foo()

as sugar for:

  @available(inlinable)
  public func foo()

… which means that the sugar forms can be separately debated, and that the sugar forms don’t have to permit the full complexity of the general case (the availability list). It still isn’t clear to me whether @inlinable meets the bar to be a global attribute, I can see both sides of that argument, and it seems valuable to be able to separate the engineering work to introduce the feature from the bikeshed discussion about whether it should be sugared or not.

In short, respectfully request that you at least add this approach to the "alternatives considered” section. I also suggest you strongly consider pursuing this direction. It solves the same problem as your proposal but:

- scales better as we add more “attributes" in the future - which will be of increasingly narrow applicability.
- provides a unifying model for all of the binary framework hints
- puts all the availability markup into the feature we already have for this.
- provides a better naming framework for things like abiPublic, because you can say "@available(linkerSymbol)” to say that this is making the linker symbol available from the binary framework.

-Chris

Is the problem being addressed significant enough to warrant a change to Swift?

Does this proposal fit well with the feel and direction of Swift?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org <mailto:swift-evolution-announce@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I come from a perspective similar to Johannes, in that: for my work we are interested in the performance improvements of cross-module optimization and specialization but we regularly rebuild frameworks along with apps and explicitly don’t need ABI versioning. Unlike him, I’m not that concerned with littering attributes for inlinability around, but for our purposes the original proposed spelling of @inlinable/@abiPublic or even better, Tony’s proposed public(inlinable) makes for easier understanding when reading the code than Chris’s proposed @available() extensions, which semantically leans much more heavily on the ABI versioning concept that we won’t otherwise need.

And the Tony-style spelling of @abiPublic should _clearly_ be “internal(external)” for its amazingly oxymoronic yet accurate spelling.

  — Greg

···

On Dec 21, 2017, at 8:06 AM, Johannes Weiß via swift-evolution <swift-evolution@swift.org> wrote:

On 21 Dec 2017, at 12:19 am, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?

I'm working on a performance sensitive library and we're sometimes bitten quite hard by not being able to cross-module inline & specialise. Therefore, it's thrilling to see that you're working in this area.

However, I have to admit that I believe this language feature will most likely be grossly abused. The library I'm working on will presumably never have stable ABI as you'd naturally build it with your application. However we also don't want to miss on the cross-module optimisation & specialisation and I suspect there are quite a few (mostly open-source) libraries in the same space. I'm pretty sure everybody would just end up littering their code with @abiPublic/@inlinable (or the @available(...) syntax Chris Lattner proposed) without actually meaning that.

Summing up: I think this feature is crucial but shouldn't come without a compiler "where all declarations become implicitly @inlinable, and all private and internal declarations become @abiPublic". I really don't want to litter the code with attributes that aren't what I mean. (basically `swift build --global-resilience-domain`) Having this compiler mode also makes these attributes IMHO really niche and therefore I can only sympathise with's Chris' sentiment to not litter the global attribute namespace.

  • Is the problem being addressed significant enough to warrant a change to Swift?

see above.

  • Does this proposal fit well with the feel and direction of Swift?

to back up the 'swift' claim, cross-module inlining & specialisation is absolutely necessary. However this should also be achievable with a 'I don't need a stable ABI for this product' mode in the compiler :).

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

C(++) as described in the proposal and Haskell (https://wiki.haskell.org/Inlining_and_Specialisation\), where {-# INLINABLE myFunction #-} (quoting the docs) causes exactly two things to happens.

  • The function's (exact) definition is included in the interface file for the module.
  • The function will be specialised at use sites -- even across modules.
Note that [the Haskell compiler] GHC is no more keen to inline an INLINABLE function than any other.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

read the proposal (and believe to understand it).

-- Johannes

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

i understand that but i also feel like that’s a completely solvable problem
if someone put in some effort to look into it. right now i think
fileprivate is the only problematic keyword with this since i think
changing the name of a private type makes a lot more sense that it would
break abi than renaming a file would. but it’s also the least used so
that’s a plus.

···

On Thu, Dec 21, 2017 at 12:26 AM, Slava Pestov <spestov@apple.com> wrote:

Thanks for the review, Kelvin.

On Dec 20, 2017, at 8:52 PM, Kelvin Ma via swift-evolution < > swift-evolution@swift.org> wrote:

it makes sense to have @abiPublic on private and fileprivate declarations
too and i hope this gets added, because private and fileprivate are tools
for code organization and maintenance,, the compiler with wmo doesn’t care
about private vs internal. but @abiPublic private is bound to cause
confusion and it just reads funny.

From an implementation standpoint, it would be a simple change to allow
@abiPublic on private and fileprivate declarations. However, I think that
introduce some confusion. Recall that the mangling of private symbols
includes the source file name. This would now be part of your framework’s
ABI. If you moved the @abiPublic function to another source file, or rename
the source file, you will break ABI.

Another approach would be to change the mangling so that @abiPublic
private symbols are mangled like internal symbols, with a module name and
no source file name. This makes for a simpler ABI. However this also has a
downside, because now if you define two @abiPublic private functions in
different files that have the same mangling, you will get a linker error
and not a nice compiler diagnostic.

Note that nothing in this proposal precludes @abiPublic from being applied
to private and fileprivate symbols though. If we figure out a nice solution
to the above problems, we could generalize @abiPublic without any issues.

Slava

Thanks for the answers, Slava. More inline below.

Hi Paul,

Thanks for reviewing the proposal!

A concern: how would a library author reason about, and check for bugs in, the combinatorial explosion of old and new implementations that could exist simultaneously with this feature in use?

I don’t have a simple answer to this unfortunately, other than the author being really careful, perhaps keeping around build artifacts that were compiled against older versions of the library and testing those.

That last paragraph gives a relatively trivial example, but the implications are daunting! If I understand correctly, anything in a library that uses any @inlinable or @abiPublic code must be prepared to deal with every possible combination of every past published implementation of that code. And that “every possible combination” is not per function, but per…call site?

Suppose we have this:

    // Module A

    @inlineable func bar() { ... }

    // Module B

    @inlineable func foo() {
        if whatever {
            bar(0) // compiler decides to inline this...
        } else {
            bar(1) // ...but not this, for whatever reason
        }
    }

    // Module C

    func baz() {
        foo()
    }

…and suppose B was compiled against A v1.0 but C was compiled against A v2.0. Then, if I’m following, it’s possible for bar(0) to use the 1.0 implementation but bar(1) to use the 2.0 impl. Do I have that right? It seems to be what the hash value example is getting at.

That is correct. Another example is if module A publishes an inlinable function, and module B and C depend on A, but B and C were compiled with different versions of A. Then a fourth module D that depends on B and C might see two different published versions of this function.

I am … horrified and intrigued! I suppose C++ headers have always had exactly the same problems, but never having been the maintainer of a C++ library, I never had to worry about it.

More follow-up “huh” questions:

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.)

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?

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.

Or is this not as dangerous as I’m imagining it to be?

It *is* pretty dangerous, which is why I hope this feature is used judiciously by third-party binary frameworks. With source frameworks that are built together with an app and always recompiled, this is less of a concern.

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.

Per this and my questions above, a proposal:

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.

Then inlinable code could opt in by specifying some sort of past and future compatibility contract, e.g. “inline-compatible with version 2.x of this module,” perhaps using syntax along the lines of the @available stuff Chris proposed elsewhere in this thread. IOW, my #3 just above would be necessary for the compiler to allow any version mixing whatsoever.

This would have the advantage of making the default behavior of inlinable much more foolproof, and also of nipping in the bud problems of “oh god there are still modules out there that inlined our version 1.0, we can never alter this class.”

Does all that make sense? I’m more than a little out of my depth here.

Also we are using this feature extensively in the standard library, so as the standard library evolves we will learn and develop best practices, hopefully without too many hiccups :)

I am very curious to see how that develops!

Cheers, P

···

On Dec 21, 2017, at 12:30 AM, Slava Pestov <spestov@apple.com> wrote:

On Dec 20, 2017, at 9:21 PM, Paul Cantrell <cantrell@pobox.com <mailto:cantrell@pobox.com>> wrote:

Slava

Cheers, P

On Dec 20, 2017, at 6:19 PM, Ted Kremenek via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

Is the problem being addressed significant enough to warrant a change to Swift?

Does this proposal fit well with the feel and direction of Swift?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?

I'm working on a performance sensitive library and we're sometimes bitten quite hard by not being able to cross-module inline & specialise. Therefore, it's thrilling to see that you're working in this area.

However, I have to admit that I believe this language feature will most likely be grossly abused. The library I'm working on will presumably never have stable ABI as you'd naturally build it with your application. However we also don't want to miss on the cross-module optimisation & specialisation and I suspect there are quite a few (mostly open-source) libraries in the same space. I'm pretty sure everybody would just end up littering their code with @abiPublic/@inlinable (or the @available(...) syntax Chris Lattner proposed) without actually meaning that.

Summing up: I think this feature is crucial but shouldn't come without a compiler "where all declarations become implicitly @inlinable, and all private and internal declarations become @abiPublic". I really don't want to litter the code with attributes that aren't what I mean. (basically `swift build --global-resilience-domain`) Having this compiler mode also makes these attributes IMHO really niche and therefore I can only sympathise with's Chris' sentiment to not litter the global attribute namespace.

  • Is the problem being addressed significant enough to warrant a change to Swift?

see above.

  • Does this proposal fit well with the feel and direction of Swift?

to back up the 'swift' claim, cross-module inlining & specialisation is absolutely necessary. However this should also be achievable with a 'I don't need a stable ABI for this product' mode in the compiler :).

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

C(++) as described in the proposal and Haskell (https://wiki.haskell.org/Inlining_and_Specialisation\), where {-# INLINABLE myFunction #-} (quoting the docs) causes exactly two things to happens.

  • The function's (exact) definition is included in the interface file for the module.
  • The function will be specialised at use sites -- even across modules.
Note that [the Haskell compiler] GHC is no more keen to inline an INLINABLE function than any other.

forgot to mention GHC's -fspecialise-aggressively which is its way of saying, just specialise things across modules even without '{-# INLINABLE ... #-}' which is basically the compilation mode I'm asking for :).

···

On 21 Dec 2017, at 4:06 pm, Johannes Weiß via swift-evolution <swift-evolution@swift.org> wrote:

On 21 Dec 2017, at 12:19 am, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

read the proposal (and believe to understand it).

-- Johannes

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hi Chris,

Thanks for reviewing the proposal!

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

I am hugely supportive of the features that these attributes enable, but I think that the spelling of this is absolutely wrong, and I’m disappointed that the extensive discussion we’ve had for months about this didn’t make it into (at least) the alternatives considered section. Here are my concerns:

I’m totally aware of your earlier e-mail thread about tying this in with availability and I briefly mentioned it in the ‘future directions’ section. I don’t have any objections to your approach and I’d be open to changing the proposal if there’s some consensus that this is the right way to go.

Do you think exhaustive enums should be spelled as @available(exhaustive) (or @available(exhaustive: …)), also?

Furthermore, these two attributes are the tip of the iceberg, and the core team has spent a lot of time recently discussing the fact there are potentially going to be about a dozen attributes similar to these (fixed_contents, global_var_is_directly_addressible, …) that will only be required for binary frameworks.

Hopefully not a dozen! But yes, there will probably be more than just the three currently under discussion.

A minor point, but the specific name “abiPublic” is not great in my opinion, because “ABI” is a term of art for compiler hackers. Most users have no idea what ABI means, and those who think they do often don’t. Very few people really understand what “stable ABI” means for example.

It would be better to go with something like “apiPublic” or “symbolPublic” or “linkableButNotAccessible” or something else long. This will not be commonly used in user code, so being long and descriptive is a good thing.

Several other people in the thread also objected to the name abiPublic. I’m not attached to it and I would be open to changing it to something better. We just don’t have a clear winner yet...

which generalizes properly when we add version ranges:

  @available(iOS 14, *) // this was introduced in iOS 14
  @available(linkerSymbol: iOS 15, *) // this decl’s symbol became “abiPublic" in iOS 15
  @available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
  public func foo() {… }

Minor nitpick: public implies ABI-public, so you probably meant the other way around, where a symbol became ABI public in iOS 14, then public in iOS 15. This is certainly something we need to support and my understanding is the equivalent already happens all the time in Objective-C land, where SPI becomes API.

In short, respectfully request that you at least add this approach to the "alternatives considered” section.

So, does anyone have any strong objections to Chris’s proposal?

From an implementation standpoint, reworking the parser to parse @available(inlinable) and @available(fixedContents) or whatever would be straightforward. I would still like to punt the version range part of this to a future proposal, though.

Slava

···

On Dec 20, 2017, at 11:14 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com <mailto:kremenek@apple.com>> wrote:

Hi Johannes,

Thanks for reviewing this proposal!

The library I'm working on will presumably never have stable ABI as you'd naturally build it with your application. However we also don't want to miss on the cross-module optimisation & specialisation and I suspect there are quite a few (mostly open-source) libraries in the same space. I'm pretty sure everybody would just end up littering their code with @abiPublic/@inlinable (or the @available(...) syntax Chris Lattner proposed) without actually meaning that.

Summing up: I think this feature is crucial but shouldn't come without a compiler "where all declarations become implicitly @inlinable, and all private and internal declarations become @abiPublic". I really don't want to litter the code with attributes that aren't what I mean. (basically `swift build --global-resilience-domain`) Having this compiler mode also makes these attributes IMHO really niche and therefore I can only sympathise with's Chris' sentiment to not litter the global attribute namespace.

I agree that a ‘completely non-resilient’ compiler mode would be great when building libraries that are always shipped together, and I hope Swift gains such a feature one day, possibly built on top of the very infrastructure used to implement this proposal!

However, the goal of this proposal is to formalize some language features that already exist and are used by the standard library. Clearly making everything fragile is a non-starter for the standard library in an ABI-stable world.

I do hope that this attribute is not abused in the manner in which you describe, but I’m not sure the potential for abuse is reason enough to not run the proposal — people are already using the underscored attribute today, risking source breakage and bugs due to insufficient test coverage in the future.

C(++) as described in the proposal and Haskell (https://wiki.haskell.org/Inlining_and_Specialisation\), where {-# INLINABLE myFunction #-} (quoting the docs) causes exactly two things to happens.

  • The function's (exact) definition is included in the interface file for the module.
  • The function will be specialised at use sites -- even across modules.
Note that [the Haskell compiler] GHC is no more keen to inline an INLINABLE function than any other.

Note that Swift’s compiler is the same — @inlinable does not influence optimizer decisions to inline or not.

Also currently the proposal is implemented by binary serialization of the SIL IR, but nothing in it precludes serializing inlinable function bodies as source code in the future — in fact we are likely to go in that direction if we implement the proposed textual ‘stable’ module format.

Slava

···

On Dec 21, 2017, at 8:06 AM, Johannes Weiß via swift-evolution <swift-evolution@swift.org> wrote:

I come from a perspective similar to Johannes, in that: for my work we are interested in the performance improvements of cross-module optimization and specialization but we regularly rebuild frameworks along with apps and explicitly don’t need ABI versioning. Unlike him, I’m not that concerned with littering attributes for inlinability around, but for our purposes the original proposed spelling of @inlinable/@abiPublic or even better, Tony’s proposed public(inlinable) makes for easier understanding when reading the code than Chris’s proposed @available() extensions, which semantically leans much more heavily on the ABI versioning concept that we won’t otherwise need.

Yeah, the main downside I can think of with Chris’s approach is that for developers publishing source-only packages, version number ranges are probably overkill. I believe Jordan had a similar objection at some point in our internal discussions. However, treating @inlinable as shorthand for @available(inlinable) might be sufficient.

And the Tony-style spelling of @abiPublic should _clearly_ be “internal(external)” for its amazingly oxymoronic yet accurate spelling.

If oxymoronic spelling discourages abuse of these features, I’m all for it ;-)

Slava

···

On Dec 21, 2017, at 11:05 AM, Greg Titus via swift-evolution <swift-evolution@swift.org> wrote:

  — Greg

On Dec 21, 2017, at 8:06 AM, Johannes Weiß via swift-evolution <swift-evolution@swift.org> wrote:

On 21 Dec 2017, at 12:19 am, Ted Kremenek via swift-evolution <swift-evolution@swift.org> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
Reviews are an important part of the Swift evolution process. All review feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager.

When replying, please try to keep the proposal link at the top of the message:

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
...
Reply text
...
Other replies
What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?

I'm working on a performance sensitive library and we're sometimes bitten quite hard by not being able to cross-module inline & specialise. Therefore, it's thrilling to see that you're working in this area.

However, I have to admit that I believe this language feature will most likely be grossly abused. The library I'm working on will presumably never have stable ABI as you'd naturally build it with your application. However we also don't want to miss on the cross-module optimisation & specialisation and I suspect there are quite a few (mostly open-source) libraries in the same space. I'm pretty sure everybody would just end up littering their code with @abiPublic/@inlinable (or the @available(...) syntax Chris Lattner proposed) without actually meaning that.

Summing up: I think this feature is crucial but shouldn't come without a compiler "where all declarations become implicitly @inlinable, and all private and internal declarations become @abiPublic". I really don't want to litter the code with attributes that aren't what I mean. (basically `swift build --global-resilience-domain`) Having this compiler mode also makes these attributes IMHO really niche and therefore I can only sympathise with's Chris' sentiment to not litter the global attribute namespace.

  • Is the problem being addressed significant enough to warrant a change to Swift?

see above.

  • Does this proposal fit well with the feel and direction of Swift?

to back up the 'swift' claim, cross-module inlining & specialisation is absolutely necessary. However this should also be achievable with a 'I don't need a stable ABI for this product' mode in the compiler :).

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

C(++) as described in the proposal and Haskell (https://wiki.haskell.org/Inlining_and_Specialisation\), where {-# INLINABLE myFunction #-} (quoting the docs) causes exactly two things to happens.

  • The function's (exact) definition is included in the interface file for the module.
  • The function will be specialised at use sites -- even across modules.
Note that [the Haskell compiler] GHC is no more keen to inline an INLINABLE function than any other.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

read the proposal (and believe to understand it).

-- Johannes

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Thanks for this reply, Chris. It addresses most of my concerns with the current design - scalability (with the attributes), confusion (over the meaning of ABI) and changes in declarations as things change.

I think your approach is a far better solution.

···

On 21 Dec 2017, at 6:14 pm, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

I am hugely supportive of the features that these attributes enable, but I think that the spelling of this is absolutely wrong, and I’m disappointed that the extensive discussion we’ve had for months about this didn’t make it into (at least) the alternatives considered section. Here are my concerns:

Availability Ranges

Both of these attributes will (perhaps not for Swift 5 given the fact that these will be new then, but certainly in 5.1 or 6) need to be qualified by deployment modifiers. We’ll need the ability to specify not just that a declaration is inlinable or abipublic, but in *which versions* of the binary package (that they are defined in) have this property.

For example, while perhaps it will be common for a decl to be “born inlinable” and just need the form of attribute as specified here, it is just as clear that this is not the *only* model we need. It is entirely reasonable (and will be important in the future) to say that something “became ABI public in iOS14, became abiPublic in iOS 15, and became inlinable in iOS16”. The use of this will be relatively rare, but it is important for the model to support this in time.

Because of this, if we accept the spelling as proposed in this proposal, these attributes will need to be generalized to have an availability range, e.g.:

  @abipublic(iOS 15, *)

The concern is that this proposal opens the door to have a family of attributes each of which have availability information on them, and this “family” of attributes will have nothing tying them together into a unified framework.

Pollution of the Attribute Namespace

Furthermore, these two attributes are the tip of the iceberg, and the core team has spent a lot of time recently discussing the fact there are potentially going to be about a dozen attributes similar to these (fixed_contents, global_var_is_directly_addressible, …) that will only be required for binary frameworks. It is possible that @inlinable will be prominent enough to be a global attribute (I personally am not sure if it will be commonly used or not, it depends a lot on how widely used binary frameworks are). That said, it is clear @abiPublic will not be commonly used, and many attributes that follow these will be even more obscure.

This is bad for three reasons:

1) we’re polluting the general attribute namespace with obscure things. Pollution of the attribute namespace may have a marginal impact today, but will start to matter if/when we ever get user defined attributes.

2) The other reason is that this provides no general framework to tie together these things that affect binary frameworks into a unified framework.

3) Furthermore, I don’t like attributes being a dumping ground for weird performance hacks required by binary frameworks. It is a practical necessity that we support these because they are extremely important for narrow cases, but we don’t need to put them into a syntactically prominent spot in the grammar.

The name “ABI”

A minor point, but the specific name “abiPublic” is not great in my opinion, because “ABI” is a term of art for compiler hackers. Most users have no idea what ABI means, and those who think they do often don’t. Very few people really understand what “stable ABI” means for example.

It would be better to go with something like “apiPublic” or “symbolPublic” or “linkableButNotAccessible” or something else long. This will not be commonly used in user code, so being long and descriptive is a good thing.

Counterproposal:

There is a simple way to address the two concerns above: we already have a framework for handling API evolution with binary frameworks, the @available attribute. We can spell these “attributes” as:

  @available(inlinable) // this symbol has been inlinable since it was introduced

which generalizes properly when we add version ranges:

  @available(iOS 14, *) // this was introduced in iOS 14
  @available(linkerSymbol: iOS 15, *) // this decl’s symbol became “abiPublic" in iOS 15
  @available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
  public func foo() {… }

and allows us to bury weird hacks like “abiPublic” and the other even more obscure things that are coming outside of the global attribute namespace:

  @available(global_var_is_directly_accessible: iOS 15, *)
  public var myDispatchOnceToken : ...

Given this unified framework for handling ABI evolution, we can then separately discuss which ones of these proposals are common and important enough to sugar into a top level attribute. For example, given the general model for inlinable above, we could then (possibly as a later proposal) introduce:

  @inlinable // this symbol has been inlinable since it was introduced
  public func foo()

as sugar for:

  @available(inlinable)
  public func foo()

… which means that the sugar forms can be separately debated, and that the sugar forms don’t have to permit the full complexity of the general case (the availability list). It still isn’t clear to me whether @inlinable meets the bar to be a global attribute, I can see both sides of that argument, and it seems valuable to be able to separate the engineering work to introduce the feature from the bikeshed discussion about whether it should be sugared or not.

In short, respectfully request that you at least add this approach to the "alternatives considered” section. I also suggest you strongly consider pursuing this direction. It solves the same problem as your proposal but:

- scales better as we add more “attributes" in the future - which will be of increasingly narrow applicability.
- provides a unifying model for all of the binary framework hints
- puts all the availability markup into the feature we already have for this.
- provides a better naming framework for things like abiPublic, because you can say "@available(linkerSymbol)” to say that this is making the linker symbol available from the binary framework.

-Chris

Is the problem being addressed significant enough to warrant a change to Swift?

Does this proposal fit well with the feel and direction of Swift?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Proposal link: https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
What is your evaluation of the proposal <x-apple-data-detectors://7>?

-1

The proposal puts all the emphasis on the programmer. It is better for the compiler to decide if something is to be inclined both across modules and within modules.

If something is made public then it should be fixed for a given major version number. No need for extra annotation.

A module system that allows versioning is a better solution.

Can you explain your proposed solution in more detail?

No, cluttering up declarations is completely against the clarity of Swift. For example who other than people on this group will understand @inline(never) @inlinable.

We don’t expect this attribute to be used frequently in third-party frameworks. @inline(never) @inlinable is a weird combination, but I hope that @inline(never) is used even less frequently. In fact other than debugging it probably doesn’t have much purpose at all, and it would be nice to deprecate it some day.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Yes C and C++ and found the equivalent of these annotations problematic. In Java they eliminated all this and let the compiler do the work. In practice this works much better.

The Java approach works because there’s no separate compilation — having a JIT means the optimizer is free to inline across module boundaries without any resilience considerations. This doesn’t fit with Swift’s compilation model though.

Slava

···

On Dec 24, 2017, at 3:04 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

why can’t we just remove inlineable functions from ABI altogether? if the
argument is that app code won’t be able to take advantage of improved
implementations in future library versions i don’t think that makes sense
at all i would assume client code gets recompiled much more often than
library code and their updates are much more likely to be downloaded by
users than library updates.

···

On Sun, Dec 24, 2017 at 6:04 PM, Howard Lovatt via swift-evolution < swift-evolution@swift.org> wrote:

Proposal link: https://github.com/apple/swift-evolution/blob/
master/proposals/0193-cross-module-inlining-and-specialization.md

   -

   What is your evaluation of the proposal?

   -1

   The proposal puts all the emphasis on the programmer. It is better for
   the compiler to decide if something is to be inclined both across modules
   and within modules.

   If something is made public then it should be fixed for a given major
   version number. No need for extra annotation.

   A module system that allows versioning is a better solution.
   -

   Is the problem being addressed significant enough to warrant a change
   to Swift?

   Yes significant but wrong solution
   -

   Does this proposal fit well with the feel and direction of Swift?

   No, cluttering up declarations is completely against the clarity of
   Swift. For example who other than people on this group will understand
   @inline(never) @inlinable.
   -

   If you have used other languages or libraries with a similar feature,
   how do you feel that this proposal compares to those?

   Yes C and C++ and found the equivalent of these annotations
   problematic. In Java they eliminated all this and let the compiler do the
   work. In practice this works much better.

   Perhaps the compiler should publish the SIL or LLVM for all public
   functions. Analogous to Java’s class files. This sort of system works
   really will, much better than C and C++.
   -

   How much effort did you put into your review? A glance, a quick
   reading, or an in-depth study?
   Followed the discussions and read the proposal. The proposal doesn’t
   seem to encompass all the discussions. It would be nice if the proposal had
   a much more extensive summary of alternatives suggested.

-- Howard.

On 20 Dec 2017, at 7:19 pm, Ted Kremenek via swift-evolution < > swift-evolution@swift.org> wrote:

The proposal is available here:

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0193-cross-module-inlining-and-specialization.md

Reviews are an important part of the Swift evolution process. All review
feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the
review manager.

When replying, please try to keep the proposal link at the top of the
message:

Proposal link: GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0193-cross-module-inlining-and-specialization.md
...
Reply text
...
Other replies

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift.

When reviewing a proposal, here are some questions to consider:

   -

   What is your evaluation of the proposal?
   -

   Is the problem being addressed significant enough to warrant a change
   to Swift?
   -

   Does this proposal fit well with the feel and direction of Swift?
   -

   If you have used other languages or libraries with a similar feature,
   how do you feel that this proposal compares to those?
   -

   How much effort did you put into your review? A glance, a quick
   reading, or an in-depth study?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m hugely in favor of a path forward that involves extending existing
language constructs instead of introducing new ones or throwing around a
bunchannotations. I want to say that I like extending `@available`
(because I do), but it kind of breaks my mental model of the flags to
`@available` establishing a sort of “lifecycle” for an entity
(born/introduced foo, deprecated bar, died/removed baz). I know that’s
not official reasoning, but it's helped me explain it to others. (As a
side concern, ABI flags feel too easily forgotten in the expanded form
of `@available` where you are specifying multiple combos for multiple
platforms.)
Maybe there’s opportunity here for clustering together the purpose of
these ABI features more generally? Others have mentioned parameterizing
the access control keywords, which I personally think aligns well and
will also align well if/when versioning is added to those.
Alternatively, bucketing them together under something like
`@stability(inlinable: foo)` and making sure SourceKit gets autocomplete
for the parameters could be neat. I mention this kind of thing over in
the closed enums thread as deserving a more holistic look as we add a
new axis of syntax features to the language.
Sincerely,
  Zachary Waldowski
  zach@waldowski.me

On Thu, Dec 21, 2017, at 2:14 AM, Chris Lattner via swift-evolution wrote:>> On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com> wrote:>>

···

The review of "SE-0193 - Cross-module inlining and specialization"
begins now and runs through *January 5, 2018*.>> The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md&gt;&gt; When reviewing a proposal, here are some questions to consider:

* What is your evaluation of the proposal?> I am hugely supportive of the features that these attributes enable,

but I think that the spelling of this is absolutely wrong, and I’m
disappointed that the extensive discussion we’ve had for months about
this didn’t make it into (at least) the alternatives considered
section. Here are my concerns:>
*Availability Ranges*

Both of these attributes will (perhaps not for Swift 5 given the fact
that these will be new then, but certainly in 5.1 or 6) need to be
qualified by deployment modifiers. We’ll need the ability to specify
not just that a declaration is inlinable or abipublic, but in *which
versions* of the binary package (that they are defined in) have this
property.>
For example, while perhaps it will be common for a decl to be “born
inlinable” and just need the form of attribute as specified here, it
is just as clear that this is not the *only* model we need. It is
entirely reasonable (and will be important in the future) to say that
something “became ABI public in iOS14, became abiPublic in iOS 15, and
became inlinable in iOS16”. The use of this will be relatively rare,
but it is important for the model to support this in time.>
Because of this, if we accept the spelling as proposed in this
proposal, these attributes will need to be generalized to have an
availability range, e.g.:>
@abipublic(iOS 15, *)

The concern is that this proposal opens the door to have a family of
attributes each of which have availability information on them, and
this “family” of attributes will have nothing tying them together into
a unified framework.> **
**
*Pollution of the Attribute Namespace*

Furthermore, these two attributes are the tip of the iceberg, and the
core team has spent a lot of time recently discussing the fact there
are potentially going to be about a dozen attributes similar to these
(fixed_contents, global_var_is_directly_addressible, …) that will
only be required for binary frameworks. It is possible that
@inlinable will be prominent enough to be a global attribute (I
personally am not sure if it will be commonly used or not, it depends
a lot on how widely used binary frameworks are). That said, it is
clear @abiPublic will not be commonly used, and many attributes that
follow these will be even more obscure.>
This is bad for three reasons:

1) we’re polluting the general attribute namespace with obscure
   things. Pollution of the attribute namespace may have a marginal
   impact today, but will start to matter if/when we ever get user
   defined attributes.>
2) The other reason is that this provides no general framework to tie
   together these things that affect binary frameworks into a unified
   framework.>
3) Furthermore, I don’t like attributes being a dumping ground for
   weird performance hacks required by binary frameworks. It is a
   practical necessity that we support these because they are
   extremely important for narrow cases, but we don’t need to put them
   into a syntactically prominent spot in the grammar.>
*The name “ABI”*

A minor point, but the specific name “abiPublic” is not great in my
opinion, because “ABI” is a term of art for compiler hackers. Most
users have no idea what ABI means, and those who think they do often
don’t. Very few people really understand what “stable ABI” means for
example.>
It would be better to go with something like “apiPublic” or
“symbolPublic” or “linkableButNotAccessible” or something else long.
This will not be commonly used in user code, so being long and
descriptive is a good thing.>

*Counterproposal:*

There is a simple way to address the two concerns above: we already
have a framework for handling API evolution with binary frameworks,
the @available attribute. We can spell these “attributes” as:>
@available(inlinable) // this symbol has been inlinable since it was
>
which generalizes properly when we add version ranges:

@available(iOS 14, *) // this was introduced in iOS 14
@available(linkerSymbol: iOS 15, *) // this decl’s symbol became
“abiPublic" in iOS 15> @available(inlinable: iOS 16, *) // this decl became inlinable
in iOS 16> public func foo() {… }

and allows us to bury weird hacks like “abiPublic” and the other even
more obscure things that are coming outside of the global attribute
namespace:>
@available(global_var_is_directly_accessible: iOS 15, *)
public var myDispatchOnceToken : ...

Given this unified framework for handling ABI evolution, we can then
separately discuss which ones of these proposals are common and
important enough to sugar into a top level attribute. For example,
given the general model for inlinable above, we could then (possibly
as a later proposal) introduce:>
@inlinable // this symbol has been inlinable since it was
> public func foo()

as sugar for:

@available(inlinable)
public func foo()

… which means that the sugar forms can be separately debated, and that
the sugar forms don’t have to permit the full complexity of the
general case (the availability list). It still isn’t clear to me
whether @inlinable meets the bar to be a global attribute, I can see
both sides of that argument, and it seems valuable to be able to
separate the engineering work to introduce the feature from the
bikeshed discussion about whether it should be sugared or not.>

In short, respectfully request that you at least add this approach to
the "alternatives considered” section. I also suggest you strongly
consider pursuing this direction. It solves the same problem as your
proposal but:>
- scales better as we add more “attributes" in the future - which will
  be of increasingly narrow applicability.> - provides a unifying model for all of the binary framework hints
- puts all the availability markup into the feature we already have
  for this.> - provides a better naming framework for things like abiPublic,
  because you can say "@available(linkerSymbol)” to say that this is
  making the linker symbol available from the binary framework.>
-Chris

*
* Is the problem being addressed significant enough to warrant a
   change to Swift?

* Does this proposal fit well with the feel and direction of Swift?

* If you have used other languages or libraries with a similar
   feature, how do you feel that this proposal compares to those?

* How much effort did you put into your review? A glance, a quick
   reading, or an in-depth study?>> Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

_________________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

that’s why i keep saying we should separate human-facing encapsulation
concepts from compiler-facing abi visibility concepts. i’ve always been
advocating for something like

internal(visible)
fileprivate(visible)
private(visible)

in the same spelling we currently use for stuff like private(set). we might
have to disallow it for fileprivate because of the name mangling issue that
Slava mentioned but it’s an elegant spelling and extensible if someone
comes up with a good unique mangling scheme for private declarations.

···

On Fri, Dec 29, 2017 at 10:35 AM, Félix Cloutier via swift-evolution < swift-evolution@swift.org> wrote:

I agree with the common theme that `@abiPublic` is weird. I imagine that
not a lot of `@abiPublic` symbols actually want to be internal: they'll
almost all be implementation details that really want to be `private` or
`fileprivate` but that have to be `internal` to satisfy what (I believe)
most people would consider to be a leaky abstraction provided by the Swift
language. So why not go all the way and force @inlinable code to only
reference public declarations?

What do we get in exchange of subverting the thus-far clear meaning of
`internal`? Why is it better to have a special kind of internal that is not
internal, instead of a special kind of public that is not listed, or even
just no special kind of public?

That detail aside, having the ability to do cross-module inlining and
specializing is valuable and exciting.

Félix

Le 20 déc. 2017 à 19:19, Ted Kremenek via swift-evolution < > swift-evolution@swift.org> a écrit :

The review of "SE-0193 - Cross-module inlining and specialization" begins
now and runs through *January 5, 2018*.

The proposal is available here:

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0193-cross-module-inlining-and-specialization.md

Reviews are an important part of the Swift evolution process. All review
feedback should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the
review manager.

When replying, please try to keep the proposal link at the top of the
message:

Proposal link: GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0193-cross-module-inlining-and-specialization.md
...
Reply text
...
Other replies

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift.

When reviewing a proposal, here are some questions to consider:

   -

   What is your evaluation of the proposal?
   -

   Is the problem being addressed significant enough to warrant a change
   to Swift?
   -

   Does this proposal fit well with the feel and direction of Swift?
   -

   If you have used other languages or libraries with a similar feature,
   how do you feel that this proposal compares to those?
   -

   How much effort did you put into your review? A glance, a quick
   reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Perhaps an “unused symbol checker” could skip @abiPublic declarations that have been marked as deprecated or unavailable.

Slava

···

On Dec 20, 2017, at 10:34 PM, Slava Pestov via swift-evolution <swift-evolution@swift.org> wrote:

Perhaps a diagnostic like this would cause problems if you started with an @inlinable function that called an @abiPublic function and then in a subsequent version of your module you modified the @inlinable function such that it no longer calls the @abiPublic function. You would still need to keep that @abiPublic function to support clients that had inlined the old version, right?

This is correct; you may well end up with newer versions of a library that carry @abiPublic symbols only for compatibility reasons.

public
public(inlinable)
public(external) // *where we define external to be what abiPublic is now — more bike shedding welcome

I think the downside is that public(external) or whatever @abiPublic becomes actually behaves like ‘internal’ as far as name lookup is concerned — a user might be confused if they see a public(external) declaration in a source file that they cannot actually call.

Also, @inlinable @abiPublic is a totally legit combination; here is an example:

@inlinable @abiPublic func foo() -> Int {
  return 42
}

@inlinable public func bar() -> Int {
  return foo()
}

A client module can call bar() (and inline and specialize it, which in turn might inline or specialize foo()). However, it cannot directly call foo(), since foo() is not visible in the source language.

To reiterate I’m totally open to alternate spellings for both attributes — I’m just not entirely sold on tying it in with the ‘public’ keyword.

Also tying this in with access control still has the problem Chris pointed out, where once version ranges are introduced, we have several completely different syntaxes and keywords that all take version ranges.

A final data point is that we already have a precedent for <<access modifier>>(<<more stuff>>) — the private(set) and internal(set) syntax for properties and subscripts. But here the syntax is used to denote something completely different, and it might be confusing to overload it further.

Slava

···

On Dec 21, 2017, at 9:33 AM, Tony Parker via swift-evolution <swift-evolution@swift.org> wrote:

- Tony

On Dec 20, 2017, at 11:14 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com <mailto:kremenek@apple.com>> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins now and runs through January 5, 2018.

The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
When reviewing a proposal, here are some questions to consider:

What is your evaluation of the proposal?

I am hugely supportive of the features that these attributes enable, but I think that the spelling of this is absolutely wrong, and I’m disappointed that the extensive discussion we’ve had for months about this didn’t make it into (at least) the alternatives considered section. Here are my concerns:

Availability Ranges

Both of these attributes will (perhaps not for Swift 5 given the fact that these will be new then, but certainly in 5.1 or 6) need to be qualified by deployment modifiers. We’ll need the ability to specify not just that a declaration is inlinable or abipublic, but in *which versions* of the binary package (that they are defined in) have this property.

For example, while perhaps it will be common for a decl to be “born inlinable” and just need the form of attribute as specified here, it is just as clear that this is not the *only* model we need. It is entirely reasonable (and will be important in the future) to say that something “became ABI public in iOS14, became abiPublic in iOS 15, and became inlinable in iOS16”. The use of this will be relatively rare, but it is important for the model to support this in time.

Because of this, if we accept the spelling as proposed in this proposal, these attributes will need to be generalized to have an availability range, e.g.:

  @abipublic(iOS 15, *)

The concern is that this proposal opens the door to have a family of attributes each of which have availability information on them, and this “family” of attributes will have nothing tying them together into a unified framework.

Pollution of the Attribute Namespace

Furthermore, these two attributes are the tip of the iceberg, and the core team has spent a lot of time recently discussing the fact there are potentially going to be about a dozen attributes similar to these (fixed_contents, global_var_is_directly_addressible, …) that will only be required for binary frameworks. It is possible that @inlinable will be prominent enough to be a global attribute (I personally am not sure if it will be commonly used or not, it depends a lot on how widely used binary frameworks are). That said, it is clear @abiPublic will not be commonly used, and many attributes that follow these will be even more obscure.

This is bad for three reasons:

1) we’re polluting the general attribute namespace with obscure things. Pollution of the attribute namespace may have a marginal impact today, but will start to matter if/when we ever get user defined attributes.

2) The other reason is that this provides no general framework to tie together these things that affect binary frameworks into a unified framework.

3) Furthermore, I don’t like attributes being a dumping ground for weird performance hacks required by binary frameworks. It is a practical necessity that we support these because they are extremely important for narrow cases, but we don’t need to put them into a syntactically prominent spot in the grammar.

The name “ABI”

A minor point, but the specific name “abiPublic” is not great in my opinion, because “ABI” is a term of art for compiler hackers. Most users have no idea what ABI means, and those who think they do often don’t. Very few people really understand what “stable ABI” means for example.

It would be better to go with something like “apiPublic” or “symbolPublic” or “linkableButNotAccessible” or something else long. This will not be commonly used in user code, so being long and descriptive is a good thing.

Counterproposal:

There is a simple way to address the two concerns above: we already have a framework for handling API evolution with binary frameworks, the @available attribute. We can spell these “attributes” as:

  @available(inlinable) // this symbol has been inlinable since it was introduced

which generalizes properly when we add version ranges:

  @available(iOS 14, *) // this was introduced in iOS 14
  @available(linkerSymbol: iOS 15, *) // this decl’s symbol became “abiPublic" in iOS 15
  @available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
  public func foo() {… }

and allows us to bury weird hacks like “abiPublic” and the other even more obscure things that are coming outside of the global attribute namespace:

  @available(global_var_is_directly_accessible: iOS 15, *)
  public var myDispatchOnceToken : ...

Given this unified framework for handling ABI evolution, we can then separately discuss which ones of these proposals are common and important enough to sugar into a top level attribute. For example, given the general model for inlinable above, we could then (possibly as a later proposal) introduce:

  @inlinable // this symbol has been inlinable since it was introduced
  public func foo()

as sugar for:

  @available(inlinable)
  public func foo()

… which means that the sugar forms can be separately debated, and that the sugar forms don’t have to permit the full complexity of the general case (the availability list). It still isn’t clear to me whether @inlinable meets the bar to be a global attribute, I can see both sides of that argument, and it seems valuable to be able to separate the engineering work to introduce the feature from the bikeshed discussion about whether it should be sugared or not.

In short, respectfully request that you at least add this approach to the "alternatives considered” section. I also suggest you strongly consider pursuing this direction. It solves the same problem as your proposal but:

- scales better as we add more “attributes" in the future - which will be of increasingly narrow applicability.
- provides a unifying model for all of the binary framework hints
- puts all the availability markup into the feature we already have for this.
- provides a better naming framework for things like abiPublic, because you can say "@available(linkerSymbol)” to say that this is making the linker symbol available from the binary framework.

-Chris

Is the problem being addressed significant enough to warrant a change to Swift?

Does this proposal fit well with the feel and direction of Swift?

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ted Kremenek
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org <mailto:swift-evolution-announce@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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?

Slava

···

On Dec 21, 2017, at 12:42 PM, Paul Cantrell <cantrell@pobox.com> wrote:

Hi Slava,

Hi Johannes,

Thanks for reviewing this proposal!

The library I'm working on will presumably never have stable ABI as you'd naturally build it with your application. However we also don't want to miss on the cross-module optimisation & specialisation and I suspect there are quite a few (mostly open-source) libraries in the same space. I'm pretty sure everybody would just end up littering their code with @abiPublic/@inlinable (or the @available(...) syntax Chris Lattner proposed) without actually meaning that.

Summing up: I think this feature is crucial but shouldn't come without a compiler "where all declarations become implicitly @inlinable, and all private and internal declarations become @abiPublic". I really don't want to litter the code with attributes that aren't what I mean. (basically `swift build --global-resilience-domain`) Having this compiler mode also makes these attributes IMHO really niche and therefore I can only sympathise with's Chris' sentiment to not litter the global attribute namespace.

I agree that a ‘completely non-resilient’ compiler mode would be great when building libraries that are always shipped together, and I hope Swift gains such a feature one day, possibly built on top of the very infrastructure used to implement this proposal!

Cool. I just meant that the compiler mode and the public (as in non-underscored) attributes should go hand in hand to not tempt people into littering their code without thinking.

However, the goal of this proposal is to formalize some language features that already exist and are used by the standard library. Clearly making everything fragile is a non-starter for the standard library in an ABI-stable world.

totally agree that these attributes are necessary, they should be in Swift as soon as we bike shedded the right name. But to prevent them from being placed everywhere without thinking I propose to introduce a compiler mode at the same time.
Performance testing is hard and takes time. So I'm pretty sure that as soon as one @abiPublic/@inlinable has proven to improve performance, library authors will just start putting them anywhere as there's no downside besides making the code harder to read.

What is the downside of bringing the attributes and the compiler mode at the same time. Am I massively underestimating the amount of work required for such mode?

I do hope that this attribute is not abused in the manner in which you describe, but I’m not sure the potential for abuse is reason enough to not run the proposal — people are already using the underscored attribute today, risking source breakage and bugs due to insufficient test coverage in the future.

C(++) as described in the proposal and Haskell (https://wiki.haskell.org/Inlining_and_Specialisation\), where {-# INLINABLE myFunction #-} (quoting the docs) causes exactly two things to happens.

  • The function's (exact) definition is included in the interface file for the module.
  • The function will be specialised at use sites -- even across modules.
Note that [the Haskell compiler] GHC is no more keen to inline an INLINABLE function than any other.

Note that Swift’s compiler is the same — @inlinable does not influence optimizer decisions to inline or not.

Cool, that's what I suspected. Good to know that the Swift & GHC attributes are the same and even the name is :).
So we just need -fspecialise-aggressively :nerd_face:.

Also currently the proposal is implemented by binary serialization of the SIL IR, but nothing in it precludes serializing inlinable function bodies as source code in the future — in fact we are likely to go in that direction if we implement the proposed textual ‘stable’ module format.

Cool. Just to be sure I understand you correctly: Assuming your proposal gets implemented as proposed, a function that does _not_ have the @inlinable attribute it won't be specialised across modules, ever. Correct?

-- Johannes

···

On 22 Dec 2017, at 7:13 am, Slava Pestov <spestov@apple.com> wrote:

On Dec 21, 2017, at 8:06 AM, Johannes Weiß via swift-evolution <swift-evolution@swift.org> wrote:

Slava

I am hugely supportive of the features that these attributes enable, but I think that the spelling of this is absolutely wrong, and I’m disappointed that the extensive discussion we’ve had for months about this didn’t make it into (at least) the alternatives considered section. Here are my concerns:

I’m totally aware of your earlier e-mail thread about tying this in with availability and I briefly mentioned it in the ‘future directions’ section. I don’t have any objections to your approach and I’d be open to changing the proposal if there’s some consensus that this is the right way to go.

Do you think exhaustive enums should be spelled as @available(exhaustive) (or @available(exhaustive: …)), also?

When and if we add private cases to enums, we’ll need to be able to associate an availability range with an “exhaustive” marker. When/if that happens, then yes, we should do so through @available(exhaustive: iOS41, *). The @exhaustive attribute will become sugar for “born exhaustive”, because in the absence of private cases the availability range doesn’t matter (AFAIK).

Furthermore, these two attributes are the tip of the iceberg, and the core team has spent a lot of time recently discussing the fact there are potentially going to be about a dozen attributes similar to these (fixed_contents, global_var_is_directly_addressible, …) that will only be required for binary frameworks.

Hopefully not a dozen! But yes, there will probably be more than just the three currently under discussion.

This is the sort of thing that will creep over the years: lots of sorts of people care about performance, and different sorts of people have different requirements. Specific narrow features can have a huge impact on specific cases, and we should support those needs.

Look at how many obscure attributes GCC has accreted and what a mess it is, we don’t want Swift to look like that in 15 years.

which generalizes properly when we add version ranges:

  @available(iOS 14, *) // this was introduced in iOS 14
  @available(linkerSymbol: iOS 15, *) // this decl’s symbol became “abiPublic" in iOS 15
  @available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
  public func foo() {… }

Minor nitpick: public implies ABI-public, so you probably meant the other way around, where a symbol became ABI public in iOS 14, then public in iOS 15.

You’re right, I got the order backward. The point stands though :-)

This is certainly something we need to support and my understanding is the equivalent already happens all the time in Objective-C land, where SPI becomes API.

In short, respectfully request that you at least add this approach to the "alternatives considered” section.

So, does anyone have any strong objections to Chris’s proposal?

From an implementation standpoint, reworking the parser to parse @available(inlinable) and @available(fixedContents) or whatever would be straightforward. I would still like to punt the version range part of this to a future proposal, though.

I agree. I’m only concerned that we have a direction that supports the availability ranges in a coherent way, I don’t see any urgency to actually implement them today.

-Chris

···

On Dec 21, 2017, at 11:08 PM, Slava Pestov <spestov@apple.com> wrote:

I wish I had more time to compose a fully thought-out reply, but that's not
going to happen in a little while because of outside constraints, so I'll
spill a few thoughts here:

I'm not a great fan of the @available(inlinable) notation.

For one, I have a hard time reasoning how Swift would behave when
inlinability is tied to OS version. In this example, if the *app* (as
opposed to the library) is compiled (as opposed to run) on iOS 16+, then
the *library method* would potentially be emitted into the app, but if
compiled on iOS 15 it wouldn't? Huh?

Second--and perhaps this is not a common opinion--I've always thought that
the @available notation was disastrous in terms of readability, especially
when it comes to @available(unavailable) and the meaning of the asterisk.
Every time, I have to run and look up whether it means the method is in
fact available or unavailable for non-listed platforms. Again, with the
understanding that this is not a fully formed thought, I have to say that I
feel this is taking a readable and fairly straightforward concept
(@inlinable) and adding on too many layers of baggage. That it was easy for
Swift's creator to inadvertently invert the intended annotations in his
initial example is, to me, a pretty good demonstration that the notation is
not at all user-friendly.

···

On Fri, Dec 22, 2017 at 2:08 AM, Slava Pestov via swift-evolution < swift-evolution@swift.org> wrote:

Hi Chris,

Thanks for reviewing the proposal!

On Dec 20, 2017, at 11:14 PM, Chris Lattner via swift-evolution < > swift-evolution@swift.org> wrote:

On Dec 20, 2017, at 4:19 PM, Ted Kremenek <kremenek@apple.com> wrote:

The review of "SE-0193 - Cross-module inlining and specialization" begins
now and runs through *January 5, 2018*.

The proposal is available here:

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0193-cross-module-inlining-and-specialization.md

When reviewing a proposal, here are some questions to consider:

   -

   What is your evaluation of the proposal?

I am hugely supportive of the features that these attributes enable, but I
think that the spelling of this is absolutely wrong, and I’m disappointed
that the extensive discussion we’ve had for months about this didn’t make
it into (at least) the alternatives considered section. Here are my
concerns:

I’m totally aware of your earlier e-mail thread about tying this in with
availability and I briefly mentioned it in the ‘future directions’ section.
I don’t have any objections to your approach and I’d be open to changing
the proposal if there’s some consensus that this is the right way to go.

Do you think exhaustive enums should be spelled as @available(exhaustive)
(or @available(exhaustive: …)), also?

Furthermore, these two attributes are the tip of the iceberg, and the core
team has spent a lot of time recently discussing the fact there are
potentially going to be about a dozen attributes similar to these
(fixed_contents, global_var_is_directly_addressible, …) that will only
be required for binary frameworks.

Hopefully not a dozen! But yes, there will probably be more than just the
three currently under discussion.

A minor point, but the specific name “abiPublic” is not great in my
opinion, because “ABI” is a term of art for compiler hackers. Most users
have no idea what ABI means, and those who think they do often don’t. Very
few people really understand what “stable ABI” means for example.

It would be better to go with something like “apiPublic” or “symbolPublic”
or “linkableButNotAccessible” or something else long. This will not be
commonly used in user code, so being long and descriptive is a good thing.

Several other people in the thread also objected to the name abiPublic.
I’m not attached to it and I would be open to changing it to something
better. We just don’t have a clear winner yet...

which generalizes properly when we add version ranges:

@available(iOS 14, *) // this was introduced in iOS 14
@available(linkerSymbol: iOS 15, *) // this decl’s symbol became
“abiPublic" in iOS 15
@available(inlinable: iOS 16, *) // this decl became inlinable in iOS 16
public func foo() {… }

Minor nitpick: public implies ABI-public, so you probably meant the other
way around, where a symbol became ABI public in iOS 14, then public in iOS
15. This is certainly something we need to support and my understanding is
the equivalent already happens all the time in Objective-C land, where SPI
becomes API.

In short, respectfully request that you at least add this approach to the
"alternatives considered” section.

So, does anyone have any strong objections to Chris’s proposal?

From an implementation standpoint, reworking the parser to parse
@available(inlinable) and @available(fixedContents) or whatever would be
straightforward. I would still like to punt the version range part of this
to a future proposal, though.