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

Xiaodi Wu xiaodi.wu at gmail.com
Tue Jan 2 12:52:50 CST 2018


On Fri, Dec 22, 2017 at 11:12 PM, Slava Pestov <spestov at apple.com> wrote:

>
>
> On Dec 22, 2017, at 7:09 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Fri, Dec 22, 2017 at 6:12 PM, Chris Lattner <clattner at nondot.org>
> wrote:
>
>>
>> On Dec 22, 2017, at 1:03 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> 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 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:
>>
>>
>> No rush, no worries, enjoy the holiday!
>>
>> 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?
>>
>>
>> No: availability information kicks in based on what you are *deploying*
>> to, not what you’re compiling on.
>>
>> I expect that this stuff will be extremely rarely used in practice, but
>> here’s an example:
>>
>> iOS15 declares this public:
>>
>> public void foo() {
>>    bar()
>> }
>>
>> iOS16 wants to promote foo to inlinable, but knows that the inlined body
>> doesn’t work with iOS15, because iOS15 needs the call to bar to happen (for
>> whatever reason)
>>
>> @available(inlinable: iOS16)
>> public void foo() {
>>
>> // nothing needed on iOS16 or later.
>>
>> }
>>
>
> Deployment platform makes more sense, but I still can't envision a real
> use case. What sorts of `bar()` would hypothetically be necessary for iOS
> 15 but not 16? Why would a third-party library need to increase its
> inlining availability for an app based on deployment platform?
>
>
> A better example would be if bar() was itself only available in iOS 16:
>
> @available(iOS 15)
> @available(inlinable: iOS 16)
> public func foo() {
>   bar()
> }
>
> @available(iOS 16)
> public func bar() { … }
>
> Suppose your app calls foo() and deploys to iOS 15. Then you cannot inline
> foo(), because bar() does not exist on iOS 15. (Presumably, foo() had a
> different implementation on iOS 15). But if you’re deploying to iOS 16, all
> is well, and you can inline foo(), which results in your app directly
> calling bar().
>
> I'm quite sure that the reason you inverted your "abiPublic" example is
> because of the same issue. Intuitively, you would want to mark something as
> "available" in version N and then maybe some special kind of "available" in
> version N+1 (which @available(inlinable) would be). But
> @available(linkerSymbol), as you spell it, suffers from a similar problem
> to that of @available(unavailable): it's _not_ a special kind of API
> availability, but rather indicates that something is less-than-available.
> That is, you would use it to indicate that something is available as ABI
> but not as API. In that sense, it extends the "mess" we have with
> @available(unavailable).
>
>
> I don’t think it’s quite the same thing as @available(unavailable). An
> @available(abiPublic) symbol would still be declared to have internal
> visibility, so in this case the @available attribute makes it strictly more
> visible than it would be without. We’re not going to spell it as
> ‘@available(abiPublic) public’, which indeed would be confusing because the
> symbol is not actually public at the source level.
>

In Chris's example, it's an annotation of a public API that was once
internal in a previous version:

  @available(apiPublic: iOS 14)
  @available(iOS 15)
  @available(inlinable: iOS 16)
  public func foo() { ... }

This is a sensible use, but it shows how we get to exactly the "indeed
confusing" situation you write about above: here, @available(apiPublic)
elevates the API above internal but below public *even when it annotates a
public API*.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20180102/9be3b01f/attachment.html>


More information about the swift-evolution mailing list