Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-07 Thread Chris Lattner via swift-evolution
On Oct 5, 2017, at 1:30 PM, Joe Groff  wrote:
>> On Oct 4, 2017, at 9:24 PM, Chris Lattner  wrote:
>> On Oct 4, 2017, at 9:44 AM, Joe Groff  wrote:
 I disagree.  The semantics being proposed perfectly overlap with the 
 transitional plan for overlays (which matters for the next few years), but 
 they are the wrong default for anything other than overlays and the wrong 
 thing for long term API evolution over the next 20 years.
>>> 
>>> I disagree with this. 'inline' functions in C and C++ have to be backed by 
>>> a symbol in the binary in order to guarantee function pointer identity, but 
>>> we don't have that constraint. Without that constraint, there's almost no 
>>> way that having a fallback definition in the binary is better:
>>> 
>>> - It becomes an ABI compatibility liability that has to be preserved 
>>> forever. 
>> 
>> This seems like a marginal win at all.  Saying that you want to publish a 
>> symbol as public API but not have it be ABI is a bit odd.  What is the 
>> usecase (other than the Swift 3/4/5 transition period)?
> 
> I think it's a bigger win than you give it credit. If the function only 
> exists in client code, then the library can much more aggressively deprecate 
> and remove or replace the API, since it only has to worry about source 
> compatibility and not deployed binary compatibility. If introducing 
> `@inlinable` later further requires new clients to emit-into-client from that 
> point on, so that the in-dylib entry point only exists for backward 
> compatibility, then you get a free "linked-on-or-after" boundary where you 
> can fix quirks or shed compatibility behavior in the inlinable version while 
> preserving it in the binary.

I recognize the points you’re trying to make, but I’m not aware of sufficient 
experience with the model that makes me have any faith that it is the right 
default.  Consider:

1) Objective-C is widely known and proven for maintaining long-lived stable 
ABIs.  It worries (almost) equally about source and binary compatibility, 
because one without the other is odd.

2) C++ is widely known for both terrible source and binary compatibility, as 
well as for extensive code bloat.  It uses the model you’re describing.

Are you familiar with any system that uses the model you’re describing that 
provides good source/binary stability across api evolutions, and that does not 
inflict massive code bloat?


>>> - It increases binary size for a function that's rarely used, and which is 
>>> often much larger as an outlined generic function than the simple operation 
>>> that can be inlined into client code. Inlining makes the most sense when 
>>> the inlined operation is smaller than a function call, so in many cases the 
>>> net dylib + executable size would increase.
>> 
>> I can see this argument, but you’re basically saying that a sufficiently 
>> smart programmer can optimize code size based on (near) perfect knowledge of 
>> the symbol and all clients.  I don’t think this is realistic for a number of 
>> reasons.  In general, an API vendor has no way to know:
>> 
>> 1) how many clients it will have, potentially in multiple modules that get 
>> linked into a single app.
>> 2) on which types a generic function will be used with.
>> 3) what the code size tradeoffs ARE, e.g. if you have a large function that 
>> doesn’t use the archetype much, there is low bloat.
>> 
>> Furthermore, we have evidence from the C++ community that people are very 
>> eager to mark lots of things inlinable regardless of the cost of doing so.  
>> Swift may end up being different, but programmers still have no general way 
>> to reason about code size given their declaration and without perfect 
>> knowledge of the clients.
>> 
>> The code of the approach I’m advocating is one *single* implementation gets 
>> generated in the module that defines the decl.  This can lead the N 
>> instantiations of exactly the same unspecialized code (consider the currying 
>> and other cases) in N different modules that end up in an app.  This seems 
>> like the right tradeoff.
> 
> If we're talking about inlinable functions, then we're already talking about 
> functions generally on the small end of the scale,

What?  Programmers can and will mark tons of things inlinable.  This is well 
known from the C++ community.  I see nothing in your design that would lead to 
the conclusion that “only small functions” would get marked inlinable.

Even if we were dealing with disciplined programmers, it is a pretty 
meaningless and bad heuristic to make them decide about inlinability (in the 
sense you describe) since the profitability of inlining a function body depends 
on a ton of things.  This includes target processor architecture, but even more 
so the detailed behavior of the function body, and also the contextual 
information at specific calls sites (e.g. constant parameters).  Programmers 
will not be able to judge this 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-07 Thread Chris Lattner via swift-evolution

> On Oct 5, 2017, at 9:32 AM, Joe Groff  wrote:
> 
>>> 
>>> The suggestion to have this semantics was originally my fault, I believe, 
>>> and it arose from the observation that if we have 'inlinable' backed by a 
>>> symbol in the binary, then we'd also want the 'must be emitted by client' 
>>> attribute. I think 'must be emitted by client' is going to almost always be 
>>> preferable for an inlinable function, though, so it's better to have the 
>>> single attribute with this behavior, only constrained by backward 
>>> deployment.
>> 
>> What is the use case of “must be emitted by client” attribute?  If I imagine 
>> that the Swift 5 standard library is shipped in the OS, I can see cases 
>> where deprecated/legacy shims for Swift3/4 compatibility would be emitted 
>> into the client but not shipped in the OS.  Those seem relatively obscure 
>> though.
> 
> You could just as easily pose the opposite question—what's the use case for a 
> symbol in the dylib when the definition is visible to clients? Evaluating the 
> tradeoffs, we feel like it's better not to unless backward compatibility 
> demands it.

The behavior I’m proposing dovetails with the overall design of swift 
resilience progressive disclosure:

1) You can be fast and loose with a symbol, so long as you don’t define it as 
public.
2) Making it public allows you to be fast and loose within your module, but you 
have to opt into guarantees for other modules.
3) You can ship your symbol as public, then grant additional guarantees 
(overridability/subclassability or inlinability) in a subsequent release after 
you gain experience with it.

I think it is hugely problematic that transitioning from “public” to “inlinable 
public” would be an ABI break with your approach.

I would much rather see a model where “public” can graduate to “inlinable 
public” in an ABI compatible way, but that there were a “alwaysinlined public” 
concept (with a sufficiently scary name) for power users that want the 
semantics that you’re arguing for.

-Chris


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-06 Thread Slava Pestov via swift-evolution
Hi all,

Summarizing the thread so far, I see there were three main points of discussion:

- The name itself, @inlinable, is causing some confusion. Chris suggested a 
more general name, like @fragile. A few other possible names were discussed. I 
don’t think we’ve decided on the best name yet so I’m open to suggestions here. 
I personally like the name @fragile if nobody has objections to it, at the very 
least because it does not mislead the reader into thinking inlining is going to 
take place.

- Several people would like to see @_versioned be formalized (with a better 
name) and added to the proposal. My preference would be to do this in a 
separate proposal soon after, but I’d be willing to entertain the possibility 
of rolling it into this one.

- The core point is whether inlinable functions should retain a public entry 
point in the original module, or if the compiler should always be required to 
emit a copy (whether inlined or not) into the client module. Joe Groff made a 
number of good arguments in favor of the latter.

Jordan Rose also pointed out offline that we should not allow @inlinable to be 
applied to dynamic methods, since there’s no way for a client to devirtualize 
across an objc_msgSend boundary, so the attribute would have no effect in this 
case. I don’t expect this change to be controversial.

I’d like to get the proposal into a form suitable for publishing as a draft 
pull request against the evolution repository. Do we have some general 
agreement on resolving the above issues, or does anyone still have concerns or 
further suggestions?

Slava

> On Oct 2, 2017, at 1:31 PM, Slava Pestov  wrote:
> 
> Hi all,
> 
> Here is a draft proposal that makes public a feature we’ve had for a while. 
> Let me know what you think!
> 
> Cross-module inlining and specialization ("@inlinable")
> Proposal: SE- 
> Authors: Slava Pestov , Jordan Rose 
> 
> Review Manager: TBD
> Status: Initial pitch
> Implementation: Already implemented as an underscored attribute @_inlineable
> Introduction
> We propose introducing an @inlinable attribute which exports the body of a 
> function as part of a module's interface, making it available to the 
> optimizer when referenced from other modules.
> 
> Motivation
> One of the top priorities of the Swift 5 release is a design and 
> implementation of the Swift ABI. This effort consists of three major tasks:
> 
> Finalizing the low-level function calling convention, layout of data types, 
> and various runtime data structures. The goal here is to maintain 
> compatibility across compiler versions, ensuring that we can continue to make 
> improvements to the Swift compiler without breaking binaries built with an 
> older version of the compiler.
> 
> Implementing support for library evolution, or the ability to make certain 
> source-compatible changes, without breaking binary compatibility. Examples of 
> source-compatible changes we are considering include adding new stored 
> properties to structs and classes, removing private stored properties from 
> structs and classes, adding new public methods to a class, or adding new 
> protocol requirements that have a default implementation. The goal here is to 
> maintain compatibility across framework versions, ensuring that framework 
> authors can evolve their API without breaking binaries built against an older 
> version of the framework. For more information about the resilience model, 
> see the library evolution document 
>  in the 
> Swift repository.
> 
> Stabilizing the API of the standard library. The goal here is to ensure that 
> the standard library can be deployed separately from client binaries and 
> frameworks, without forcing recompilation of existing code.
> 
> All existing language features of Swift were designed with these goals in 
> mind. In particular, the implementation of generic types and functions relies 
> on runtime reified types to allow separate compilation and type checking of 
> generic code.
> 
> Within the scope of a single module, the Swift compiler performs very 
> aggressive optimization, including full and partial specialization of generic 
> functions, inlining, and various forms of interprocedural analysis.
> 
> On the other hand, across module boundaries, runtime generics introduce 
> unavoidable overhead, as reified type metadata must be passed between 
> functions, and various indirect access patterns must be used to manipulate 
> values of generic type. We believe that for most applications, this overhead 
> is negligible compared to the actual work performed by the code itself.
> 
> However, for some advanced use cases, and in particular for the standard 
> library, the overhead of runtime generics can dominate any useful work 
> performed by the library. Examples include the various algorithms defined in 
> 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Joe Groff via swift-evolution


> On Oct 4, 2017, at 9:24 PM, Chris Lattner  wrote:
> 
> On Oct 4, 2017, at 9:44 AM, Joe Groff  wrote:
>>> I disagree.  The semantics being proposed perfectly overlap with the 
>>> transitional plan for overlays (which matters for the next few years), but 
>>> they are the wrong default for anything other than overlays and the wrong 
>>> thing for long term API evolution over the next 20 years.
>> 
>> I disagree with this. 'inline' functions in C and C++ have to be backed by a 
>> symbol in the binary in order to guarantee function pointer identity, but we 
>> don't have that constraint. Without that constraint, there's almost no way 
>> that having a fallback definition in the binary is better:
>> 
>> - It becomes an ABI compatibility liability that has to be preserved 
>> forever. 
> 
> This seems like a marginal win at all.  Saying that you want to publish a 
> symbol as public API but not have it be ABI is a bit odd.  What is the 
> usecase (other than the Swift 3/4/5 transition period)?

I think it's a bigger win than you give it credit. If the function only exists 
in client code, then the library can much more aggressively deprecate and 
remove or replace the API, since it only has to worry about source 
compatibility and not deployed binary compatibility. If introducing 
`@inlinable` later further requires new clients to emit-into-client from that 
point on, so that the in-dylib entry point only exists for backward 
compatibility, then you get a free "linked-on-or-after" boundary where you can 
fix quirks or shed compatibility behavior in the inlinable version while 
preserving it in the binary.

>> - It increases binary size for a function that's rarely used, and which is 
>> often much larger as an outlined generic function than the simple operation 
>> that can be inlined into client code. Inlining makes the most sense when the 
>> inlined operation is smaller than a function call, so in many cases the net 
>> dylib + executable size would increase.
> 
> I can see this argument, but you’re basically saying that a sufficiently 
> smart programmer can optimize code size based on (near) perfect knowledge of 
> the symbol and all clients.  I don’t think this is realistic for a number of 
> reasons.  In general, an API vendor has no way to know:
> 
> 1) how many clients it will have, potentially in multiple modules that get 
> linked into a single app.
> 2) on which types a generic function will be used with.
> 3) what the code size tradeoffs ARE, e.g. if you have a large function that 
> doesn’t use the archetype much, there is low bloat.
> 
> Furthermore, we have evidence from the C++ community that people are very 
> eager to mark lots of things inlinable regardless of the cost of doing so.  
> Swift may end up being different, but programmers still have no general way 
> to reason about code size given their declaration and without perfect 
> knowledge of the clients.
> 
> The code of the approach I’m advocating is one *single* implementation gets 
> generated in the module that defines the decl.  This can lead the N 
> instantiations of exactly the same unspecialized code (consider the currying 
> and other cases) in N different modules that end up in an app.  This seems 
> like the right tradeoff.

If we're talking about inlinable functions, then we're already talking about 
functions generally on the small end of the scale, so duplication is less of an 
issue. Furthermore, the duplication hazard only exists at dylib boundaries, 
since among static libraries we can still instantiate all the different 
instantiations of the function as ODR and let the linker fold them. For most 
apps there aren't going to be that many of those boundaries.

>> - It increases the uncertainty of the behavior client code sees. If an 
>> inlinable function must always be emitted in the client, then client code 
>> *always* gets the current definition. If an inlinable function calls into 
>> the dylib when the compiler chooses not to inline it, then you may get the 
>> current definition, or you may get an older definition from any published 
>> version of the dylib. Ideally these all behave the same if the function is 
>> inlinable, but quirks are going to be inevitable.
> 
> You’re saying that “if an API author incorrectly changes the behavior of 
> their inlinable function” that your approach papers over the bug a little bit 
> better.  I don’t see this as something that is important to design around.  
> Not least of which because it will produce other inconsistencies: what if a 
> binary module A is built against the old version of that inlinable function 
> and you app builds against a newer version?  Then you have the two 
> inconsistent versions in your app again.
> 
> More generally though, an API vendor who does this has broken the 
> fragile/inlinable contract, and they therefore invoked undefined behavior - 
> c'est la vie.

The contract doesn't need to be nearly 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Slava Pestov via swift-evolution

> On Oct 5, 2017, at 1:17 PM, Michael Ilseman via swift-evolution 
>  wrote:
> 
> Another benefit of the always-emit-into-client-and-omit-from-libary-binary is 
> cross-call consistency. A function foo could change in a way such that *all* 
> calls using either the new or old version is fine, but some interleaving of 
> calls to new and old versions is invalid. Having to reason about and test 
> interleaving is very difficult. This further extends to groups of functions 
> that want to maintain a cross-function-group call consistency (e.g. multiple 
> methods on a struct).

This is not true though, because any calls to the inlinable function from 
inside its defining module will always use the ‘latest’ definition.

Or imagine if you link multiple frameworks that all inline different versions 
of an inlinable function. I don’t think there’s a way to make the guarantee you 
described.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Michael Ilseman via swift-evolution
Another benefit of the always-emit-into-client-and-omit-from-libary-binary is 
cross-call consistency. A function foo could change in a way such that *all* 
calls using either the new or old version is fine, but some interleaving of 
calls to new and old versions is invalid. Having to reason about and test 
interleaving is very difficult. This further extends to groups of functions 
that want to maintain a cross-function-group call consistency (e.g. multiple 
methods on a struct).



> On Oct 5, 2017, at 9:32 AM, Joe Groff via swift-evolution 
>  wrote:
> 
> 
> 
>> On Oct 4, 2017, at 9:15 PM, Chris Lattner > > wrote:
>> 
>> 
>>> On Oct 4, 2017, at 9:36 AM, Joe Groff >> > wrote:
>>> 
>> It wouldn't avoid the complexity, because we want the "non-ABI, 
>> always-emit-into-client" behavior for the standard library. For the 
>> soon-to-be-ABI-stable libraries where @inlinable even matters, such as 
>> the standard library and Apple SDK overlays, there's pretty much perfect 
>> overlap between things we want to inline and things we don't want to 
>> take up binary space and ABI surface in binaries, so the behavior Slava 
>> proposes seems like the right default. 
> 
> I disagree.  The semantics being proposed perfectly overlap with the 
> transitional plan for overlays (which matters for the next few years), 
> but they are the wrong default for anything other than overlays and the 
> wrong thing for long term API evolution over the next 20 years.
 
 Can you elaborate on this? If inlinable functions have public entry 
 points, the version in the framework may or may not be called… because of 
 SIL serialization and inlining. Since the existence of the public entry 
 point doesn’t offer much of a guarantee, it seems desirable to not have 
 the public entry point. For example if the inlinable function is not used 
 elsewhere in the framework, we wouldn’t have to emit it at all. This might 
 make the standard library smaller for instance.
 
 However I’m still waiting for Dave or Jordan to chime in with the original 
 justification for the ‘always emit into client’ behavior. IIRC there was a 
 resilience-related argument too, but I don’t remember what it is now.
>>> 
>>> The suggestion to have this semantics was originally my fault, I believe, 
>>> and it arose from the observation that if we have 'inlinable' backed by a 
>>> symbol in the binary, then we'd also want the 'must be emitted by client' 
>>> attribute. I think 'must be emitted by client' is going to almost always be 
>>> preferable for an inlinable function, though, so it's better to have the 
>>> single attribute with this behavior, only constrained by backward 
>>> deployment.
>> 
>> What is the use case of “must be emitted by client” attribute?  If I imagine 
>> that the Swift 5 standard library is shipped in the OS, I can see cases 
>> where deprecated/legacy shims for Swift3/4 compatibility would be emitted 
>> into the client but not shipped in the OS.  Those seem relatively obscure 
>> though.
> 
> You could just as easily pose the opposite question—what's the use case for a 
> symbol in the dylib when the definition is visible to clients? Evaluating the 
> tradeoffs, we feel like it's better not to unless backward compatibility 
> demands it.
> 
> -Joe
> 
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Roman Levenstein via swift-evolution

> On Oct 5, 2017, at 12:01 AM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Oh right. @_specialize modifies the original entry point to do runtime 
> dispatch among the possible specializations. So the overhead comes from the 
> unnecessary checks. I guess ideally we would have two versions of 
> @_specialize, one adds the runtime dispatch whereas the other one just 
> publishes static specializations which can be deserialized and used as needed.

The support for publishing static specializations is envisioned in the current 
implementation of @_specialize already, though it is not well tested yet.

If you use the "exported: true" parameter with @_specialize, the body of the 
produced specialization would not be SIL serialized, but it will emitted into 
the object file of the defining module and the specialized function will be 
made available as a public symbol in the object file, so that the clients can 
link against it and invoke it directly. Since clients can refer to this symbol 
now, it cannot be removed in the future versions of the library as it would 
break all such clients linked against it.

@_specialize(exported: true, where K == Int, V == Int)
func foo(dict: Dictionary) {
}

We could also allow for making those exported specializations @inlinable if 
required by the user.

-Roman

> 
> Since @_specialize is not an officially supported attribute though, I would 
> suggest punting this discussion until someone decides to push through an 
> evolution proposal for it. For all intents and purposes, @inlinable is a 
> superset of @_specialized because it defers the specialization decisions to 
> the client.
> 
> Slava
> 
>> On Oct 4, 2017, at 11:47 PM, Taylor Swift > > wrote:
>> 
>> See the thread 
>> 
>>  from july over generic trig functions, where @_specialize() + @_inlineable 
>> had a small but consistent performance penalty relative to @_inlineable 
>> alone.
>> 
>> On Thu, Oct 5, 2017 at 1:32 AM, Slava Pestov > > wrote:
>> 
>> 
>>> On Oct 4, 2017, at 11:04 PM, Taylor Swift >> > wrote:
>>> 
>>> 
>>> 
>>> On Oct 5, 2017, at 12:52 AM, Slava Pestov >> > wrote:
>>> 
 
 
> On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution 
> > wrote:
> 
> i’m just tryna follow along here && this is probably a dumb question, but 
> is it possible for a generic function to be emitted as a set of 
> specialized functions into the client, but not inlined everywhere? It can 
> be the case where a large generic function gets slowed down by the large 
> number of generic operations inside it but it doesn’t make sense for it 
> to be inlined completely.
 
 This is already possible. The optimizer doesn’t have to inline an 
 @_inlineable function at its call site; it can emit a call to a 
 specialized version instead.
 
 Slava
>>> 
>>> Is there a reason using @_specialize() and @_inlineable together is slower 
>>> than using @_inlineable by itself?
>> 
>> By specialization, I mean the optimizer pass which takes a function body and 
>> substitutes generic parameters with statically-known types.
>> 
>> I’m not sure what your question means though. Adding a @_specialize 
>> attribute should never make anything slower. Rather it makes the optimizer 
>> eagerly emit specializations of a function in the defining module. You can 
>> think of @_specialize and @inlinable as mostly mutually exclusive; either 
>> you publish the complete function body for clients to optimize as they 
>> please, or you publish a fixed set of specializations.
>> 
>> You might prefer the latter for secrecy (serialized SIL is much closer to 
>> source code than machine code), but the the former enables more general 
>> optimizations.
>> 
>> Slava
>> 
> 
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Joe Groff via swift-evolution


> On Oct 5, 2017, at 10:46 AM, Taylor Swift  wrote:
> 
> why is runtime dispatch even necessary? Why can’t the client just call the 
> specialized version directly?

Runtime dispatch on the callee side keeps the exact set of specializations open 
to change, since it isn't ABI, and in theory shouldn't be all that expensive, 
since you're "just" checking type identity.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Taylor Swift via swift-evolution
why is runtime dispatch even necessary? Why can’t the client just call the
specialized version directly?

On Thu, Oct 5, 2017 at 2:01 AM, Slava Pestov  wrote:

> Oh right. @_specialize modifies the original entry point to do runtime
> dispatch among the possible specializations. So the overhead comes from the
> unnecessary checks. I guess ideally we would have two versions of
> @_specialize, one adds the runtime dispatch whereas the other one just
> publishes static specializations which can be deserialized and used as
> needed.
>
> Since @_specialize is not an officially supported attribute though, I
> would suggest punting this discussion until someone decides to push through
> an evolution proposal for it. For all intents and purposes, @inlinable is a
> superset of @_specialized because it defers the specialization decisions to
> the client.
>
> Slava
>
>
> On Oct 4, 2017, at 11:47 PM, Taylor Swift  wrote:
>
> See the thread
> 
> from july over generic trig functions, where @_specialize() + @_inlineable
> had a small but consistent performance penalty relative to @_inlineable
> alone.
>
> On Thu, Oct 5, 2017 at 1:32 AM, Slava Pestov  wrote:
>
>>
>>
>> On Oct 4, 2017, at 11:04 PM, Taylor Swift  wrote:
>>
>>
>>
>> On Oct 5, 2017, at 12:52 AM, Slava Pestov  wrote:
>>
>>
>>
>> On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> i’m just tryna follow along here && this is probably a dumb question, but
>> is it possible for a generic function to be emitted as a set of specialized
>> functions into the client, but not inlined everywhere? It can be the case
>> where a large generic function gets slowed down by the large number of
>> generic operations inside it but it doesn’t make sense for it to be inlined
>> completely.
>>
>>
>> This is already possible. The optimizer doesn’t have to inline an
>> @_inlineable function at its call site; it can emit a call to a specialized
>> version instead.
>>
>> Slava
>>
>>
>> Is there a reason using @_specialize() and @_inlineable together is
>> slower than using @_inlineable by itself?
>>
>>
>> By specialization, I mean the optimizer pass which takes a function body
>> and substitutes generic parameters with statically-known types.
>>
>> I’m not sure what your question means though. Adding a @_specialize
>> attribute should never make anything slower. Rather it makes the optimizer
>> eagerly emit specializations of a function in the defining module. You can
>> think of @_specialize and @inlinable as mostly mutually exclusive; either
>> you publish the complete function body for clients to optimize as they
>> please, or you publish a fixed set of specializations.
>>
>> You might prefer the latter for secrecy (serialized SIL is much closer to
>> source code than machine code), but the the former enables more general
>> optimizations.
>>
>> Slava
>>
>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Ben Langmuir via swift-evolution
Hi Slava,

What is the impact on debugging?  Will we emit a non-inline version of the 
function into the client at Onone? Will it be impossible to call from a 
debugger with optimization enabled?  I've been burned by this in C++.

Ben

> On Oct 2, 2017, at 1:31 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Hi all,
> 
> Here is a draft proposal that makes public a feature we’ve had for a while. 
> Let me know what you think!
> 
> Cross-module inlining and specialization ("@inlinable")
> Proposal: SE- 
> Authors: Slava Pestov , Jordan Rose 
> 
> Review Manager: TBD
> Status: Initial pitch
> Implementation: Already implemented as an underscored attribute @_inlineable
> Introduction
> We propose introducing an @inlinable attribute which exports the body of a 
> function as part of a module's interface, making it available to the 
> optimizer when referenced from other modules.
> 
> Motivation
> One of the top priorities of the Swift 5 release is a design and 
> implementation of the Swift ABI. This effort consists of three major tasks:
> 
> Finalizing the low-level function calling convention, layout of data types, 
> and various runtime data structures. The goal here is to maintain 
> compatibility across compiler versions, ensuring that we can continue to make 
> improvements to the Swift compiler without breaking binaries built with an 
> older version of the compiler.
> 
> Implementing support for library evolution, or the ability to make certain 
> source-compatible changes, without breaking binary compatibility. Examples of 
> source-compatible changes we are considering include adding new stored 
> properties to structs and classes, removing private stored properties from 
> structs and classes, adding new public methods to a class, or adding new 
> protocol requirements that have a default implementation. The goal here is to 
> maintain compatibility across framework versions, ensuring that framework 
> authors can evolve their API without breaking binaries built against an older 
> version of the framework. For more information about the resilience model, 
> see the library evolution document 
>  in the 
> Swift repository.
> 
> Stabilizing the API of the standard library. The goal here is to ensure that 
> the standard library can be deployed separately from client binaries and 
> frameworks, without forcing recompilation of existing code.
> 
> All existing language features of Swift were designed with these goals in 
> mind. In particular, the implementation of generic types and functions relies 
> on runtime reified types to allow separate compilation and type checking of 
> generic code.
> 
> Within the scope of a single module, the Swift compiler performs very 
> aggressive optimization, including full and partial specialization of generic 
> functions, inlining, and various forms of interprocedural analysis.
> 
> On the other hand, across module boundaries, runtime generics introduce 
> unavoidable overhead, as reified type metadata must be passed between 
> functions, and various indirect access patterns must be used to manipulate 
> values of generic type. We believe that for most applications, this overhead 
> is negligible compared to the actual work performed by the code itself.
> 
> However, for some advanced use cases, and in particular for the standard 
> library, the overhead of runtime generics can dominate any useful work 
> performed by the library. Examples include the various algorithms defined in 
> protocol extensions of Sequence and Collection, for instance the mapmethod of 
> the Sequence protocol. Here the algorithm is very simple and spends most of 
> its time manipulating generic values and calling to a user-supplied closure; 
> specialization and inlining can completely eliminate the algorithm of the 
> higher-order function call and generate equivalent code to a hand-written 
> loop manipulating concrete types.
> 
> We would like to annotate such functions with the @inlinable attribute. This 
> will make their bodies available to the optimizer when building client code; 
> on the other hand, calling such a function will cause it to be emitted into 
> the client binary, meaning that if a library were to change the definition of 
> such a function, only binaries built against the newer version of library 
> will use the new definition.
> 
> Proposed solution
> The @inlinable attribute causes the body of a function to be emitted as part 
> of the module interface. For example, a framework can define a rather 
> impractical implementation of an algorithm which returns true if all elements 
> of a sequence are equal or if the sequence is empty, and falseotherwise:
> 
> @inlinable public func allEqual(_ seq: T) -> Bool
> where T : Sequence, T.Element : Equatable {
>   var iter = seq.makeIterator()
>   

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Joe Groff via swift-evolution


> On Oct 4, 2017, at 9:15 PM, Chris Lattner  wrote:
> 
> 
>> On Oct 4, 2017, at 9:36 AM, Joe Groff > > wrote:
>> 
> It wouldn't avoid the complexity, because we want the "non-ABI, 
> always-emit-into-client" behavior for the standard library. For the 
> soon-to-be-ABI-stable libraries where @inlinable even matters, such as 
> the standard library and Apple SDK overlays, there's pretty much perfect 
> overlap between things we want to inline and things we don't want to take 
> up binary space and ABI surface in binaries, so the behavior Slava 
> proposes seems like the right default. 
 
 I disagree.  The semantics being proposed perfectly overlap with the 
 transitional plan for overlays (which matters for the next few years), but 
 they are the wrong default for anything other than overlays and the wrong 
 thing for long term API evolution over the next 20 years.
>>> 
>>> Can you elaborate on this? If inlinable functions have public entry points, 
>>> the version in the framework may or may not be called… because of SIL 
>>> serialization and inlining. Since the existence of the public entry point 
>>> doesn’t offer much of a guarantee, it seems desirable to not have the 
>>> public entry point. For example if the inlinable function is not used 
>>> elsewhere in the framework, we wouldn’t have to emit it at all. This might 
>>> make the standard library smaller for instance.
>>> 
>>> However I’m still waiting for Dave or Jordan to chime in with the original 
>>> justification for the ‘always emit into client’ behavior. IIRC there was a 
>>> resilience-related argument too, but I don’t remember what it is now.
>> 
>> The suggestion to have this semantics was originally my fault, I believe, 
>> and it arose from the observation that if we have 'inlinable' backed by a 
>> symbol in the binary, then we'd also want the 'must be emitted by client' 
>> attribute. I think 'must be emitted by client' is going to almost always be 
>> preferable for an inlinable function, though, so it's better to have the 
>> single attribute with this behavior, only constrained by backward deployment.
> 
> What is the use case of “must be emitted by client” attribute?  If I imagine 
> that the Swift 5 standard library is shipped in the OS, I can see cases where 
> deprecated/legacy shims for Swift3/4 compatibility would be emitted into the 
> client but not shipped in the OS.  Those seem relatively obscure though.

You could just as easily pose the opposite question—what's the use case for a 
symbol in the dylib when the definition is visible to clients? Evaluating the 
tradeoffs, we feel like it's better not to unless backward compatibility 
demands it.

-Joe

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Slava Pestov via swift-evolution
Oh right. @_specialize modifies the original entry point to do runtime dispatch 
among the possible specializations. So the overhead comes from the unnecessary 
checks. I guess ideally we would have two versions of @_specialize, one adds 
the runtime dispatch whereas the other one just publishes static 
specializations which can be deserialized and used as needed.

Since @_specialize is not an officially supported attribute though, I would 
suggest punting this discussion until someone decides to push through an 
evolution proposal for it. For all intents and purposes, @inlinable is a 
superset of @_specialized because it defers the specialization decisions to the 
client.

Slava

> On Oct 4, 2017, at 11:47 PM, Taylor Swift  wrote:
> 
> See the thread 
> 
>  from july over generic trig functions, where @_specialize() + @_inlineable 
> had a small but consistent performance penalty relative to @_inlineable alone.
> 
> On Thu, Oct 5, 2017 at 1:32 AM, Slava Pestov  > wrote:
> 
> 
>> On Oct 4, 2017, at 11:04 PM, Taylor Swift > > wrote:
>> 
>> 
>> 
>> On Oct 5, 2017, at 12:52 AM, Slava Pestov > > wrote:
>> 
>>> 
>>> 
 On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution 
 > wrote:
 
 i’m just tryna follow along here && this is probably a dumb question, but 
 is it possible for a generic function to be emitted as a set of 
 specialized functions into the client, but not inlined everywhere? It can 
 be the case where a large generic function gets slowed down by the large 
 number of generic operations inside it but it doesn’t make sense for it to 
 be inlined completely.
>>> 
>>> This is already possible. The optimizer doesn’t have to inline an 
>>> @_inlineable function at its call site; it can emit a call to a specialized 
>>> version instead.
>>> 
>>> Slava
>> 
>> Is there a reason using @_specialize() and @_inlineable together is slower 
>> than using @_inlineable by itself?
> 
> By specialization, I mean the optimizer pass which takes a function body and 
> substitutes generic parameters with statically-known types.
> 
> I’m not sure what your question means though. Adding a @_specialize attribute 
> should never make anything slower. Rather it makes the optimizer eagerly emit 
> specializations of a function in the defining module. You can think of 
> @_specialize and @inlinable as mostly mutually exclusive; either you publish 
> the complete function body for clients to optimize as they please, or you 
> publish a fixed set of specializations.
> 
> You might prefer the latter for secrecy (serialized SIL is much closer to 
> source code than machine code), but the the former enables more general 
> optimizations.
> 
> Slava
> 

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Taylor Swift via swift-evolution
See the thread

from july over generic trig functions, where @_specialize() + @_inlineable
had a small but consistent performance penalty relative to @_inlineable
alone.

On Thu, Oct 5, 2017 at 1:32 AM, Slava Pestov  wrote:

>
>
> On Oct 4, 2017, at 11:04 PM, Taylor Swift  wrote:
>
>
>
> On Oct 5, 2017, at 12:52 AM, Slava Pestov  wrote:
>
>
>
> On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> i’m just tryna follow along here && this is probably a dumb question, but
> is it possible for a generic function to be emitted as a set of specialized
> functions into the client, but not inlined everywhere? It can be the case
> where a large generic function gets slowed down by the large number of
> generic operations inside it but it doesn’t make sense for it to be inlined
> completely.
>
>
> This is already possible. The optimizer doesn’t have to inline an
> @_inlineable function at its call site; it can emit a call to a specialized
> version instead.
>
> Slava
>
>
> Is there a reason using @_specialize() and @_inlineable together is slower
> than using @_inlineable by itself?
>
>
> By specialization, I mean the optimizer pass which takes a function body
> and substitutes generic parameters with statically-known types.
>
> I’m not sure what your question means though. Adding a @_specialize
> attribute should never make anything slower. Rather it makes the optimizer
> eagerly emit specializations of a function in the defining module. You can
> think of @_specialize and @inlinable as mostly mutually exclusive; either
> you publish the complete function body for clients to optimize as they
> please, or you publish a fixed set of specializations.
>
> You might prefer the latter for secrecy (serialized SIL is much closer to
> source code than machine code), but the the former enables more general
> optimizations.
>
> Slava
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Slava Pestov via swift-evolution


> On Oct 4, 2017, at 11:04 PM, Taylor Swift  wrote:
> 
> 
> 
> On Oct 5, 2017, at 12:52 AM, Slava Pestov  > wrote:
> 
>> 
>> 
>>> On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution 
>>> > wrote:
>>> 
>>> i’m just tryna follow along here && this is probably a dumb question, but 
>>> is it possible for a generic function to be emitted as a set of specialized 
>>> functions into the client, but not inlined everywhere? It can be the case 
>>> where a large generic function gets slowed down by the large number of 
>>> generic operations inside it but it doesn’t make sense for it to be inlined 
>>> completely.
>> 
>> This is already possible. The optimizer doesn’t have to inline an 
>> @_inlineable function at its call site; it can emit a call to a specialized 
>> version instead.
>> 
>> Slava
> 
> Is there a reason using @_specialize() and @_inlineable together is slower 
> than using @_inlineable by itself?

By specialization, I mean the optimizer pass which takes a function body and 
substitutes generic parameters with statically-known types.

I’m not sure what your question means though. Adding a @_specialize attribute 
should never make anything slower. Rather it makes the optimizer eagerly emit 
specializations of a function in the defining module. You can think of 
@_specialize and @inlinable as mostly mutually exclusive; either you publish 
the complete function body for clients to optimize as they please, or you 
publish a fixed set of specializations.

You might prefer the latter for secrecy (serialized SIL is much closer to 
source code than machine code), but the the former enables more general 
optimizations.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-05 Thread Taylor Swift via swift-evolution


> On Oct 5, 2017, at 12:52 AM, Slava Pestov  wrote:
> 
> 
> 
>> On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution 
>>  wrote:
>> 
>> i’m just tryna follow along here && this is probably a dumb question, but is 
>> it possible for a generic function to be emitted as a set of specialized 
>> functions into the client, but not inlined everywhere? It can be the case 
>> where a large generic function gets slowed down by the large number of 
>> generic operations inside it but it doesn’t make sense for it to be inlined 
>> completely.
> 
> This is already possible. The optimizer doesn’t have to inline an 
> @_inlineable function at its call site; it can emit a call to a specialized 
> version instead.
> 
> Slava

Is there a reason using @_specialize() and @_inlineable together is slower than 
using @_inlineable by itself?___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Slava Pestov via swift-evolution


> On Oct 4, 2017, at 9:40 PM, Taylor Swift via swift-evolution 
>  wrote:
> 
> i’m just tryna follow along here && this is probably a dumb question, but is 
> it possible for a generic function to be emitted as a set of specialized 
> functions into the client, but not inlined everywhere? It can be the case 
> where a large generic function gets slowed down by the large number of 
> generic operations inside it but it doesn’t make sense for it to be inlined 
> completely.

This is already possible. The optimizer doesn’t have to inline an @_inlineable 
function at its call site; it can emit a call to a specialized version instead.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Chris Lattner via swift-evolution

> On Oct 4, 2017, at 9:40 PM, Taylor Swift  wrote:
> 
> 
> - It becomes an ABI compatibility liability that has to be preserved forever. 
> - It increases binary size for a function that's rarely used, and which is 
> often much larger as an outlined generic function than the simple operation 
> that can be inlined into client code. Inlining makes the most sense when the 
> inlined operation is smaller than a function call, so in many cases the net 
> dylib + executable size would increase.
> - It increases the uncertainty of the behavior client code sees. If an 
> inlinable function must always be emitted in the client, then client code 
> *always* gets the current definition. If an inlinable function calls into the 
> dylib when the compiler chooses not to inline it, then you may get the 
> current definition, or you may get an older definition from any published 
> version of the dylib. Ideally these all behave the same if the function is 
> inlinable, but quirks are going to be inevitable.
>  
> i’m just tryna follow along here && this is probably a dumb question, but is 
> it possible for a generic function to be emitted as a set of specialized 
> functions into the client, but not inlined everywhere? It can be the case 
> where a large generic function gets slowed down by the large number of 
> generic operations inside it but it doesn’t make sense for it to be inlined 
> completely.

Yep, something like that would definitely be possible by a sufficiently smart 
compiler, it is compatible with both approaches.

-Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Taylor Swift via swift-evolution
On Wed, Oct 4, 2017 at 11:44 AM, Joe Groff via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Oct 3, 2017, at 9:56 PM, Chris Lattner  wrote:
>
>
> On Oct 3, 2017, at 9:50 AM, Joe Groff  wrote:
>
>
>
> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> We have discussed adding a "versioned @inlinable" variant that preserves
> the public entry point for older clients, while making the declaration
> inlinable for newer clients. This will likely be a separate proposal and
> discussion.
>
> 5) It eliminates this complexity.
>
>
> It wouldn't avoid the complexity, because we want the "non-ABI,
> always-emit-into-client" behavior for the standard library. For the
> soon-to-be-ABI-stable libraries where @inlinable even matters, such as the
> standard library and Apple SDK overlays, there's pretty much perfect
> overlap between things we want to inline and things we don't want to take
> up binary space and ABI surface in binaries, so the behavior Slava proposes
> seems like the right default.
>
>
> I disagree.  The semantics being proposed perfectly overlap with the
> transitional plan for overlays (which matters for the next few years), but
> they are the wrong default for anything other than overlays and the wrong
> thing for long term API evolution over the next 20 years.
>
>
> I disagree with this. 'inline' functions in C and C++ have to be backed by
> a symbol in the binary in order to guarantee function pointer identity, but
> we don't have that constraint. Without that constraint, there's almost no
> way that having a fallback definition in the binary is better:
>
> - It becomes an ABI compatibility liability that has to be preserved
> forever.
> - It increases binary size for a function that's rarely used, and which is
> often much larger as an outlined generic function than the simple operation
> that can be inlined into client code. Inlining makes the most sense when
> the inlined operation is smaller than a function call, so in many cases the
> net dylib + executable size would increase.
> - It increases the uncertainty of the behavior client code sees. If an
> inlinable function must always be emitted in the client, then client code
> *always* gets the current definition. If an inlinable function calls into
> the dylib when the compiler chooses not to inline it, then you may get the
> current definition, or you may get an older definition from any published
> version of the dylib. Ideally these all behave the same if the function is
> inlinable, but quirks are going to be inevitable.
>
> -Joe
>
>
> -Chris
>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
i’m just tryna follow along here && this is probably a dumb question, but
is it possible for a generic function to be emitted as a set of specialized
functions into the client, but not inlined everywhere? It can be the case
where a large generic function gets slowed down by the large number of
generic operations inside it but it doesn’t make sense for it to be inlined
completely.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Chris Lattner via swift-evolution

> On Oct 4, 2017, at 9:24 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> 
>> - It increases binary size for a function that's rarely used, and which is 
>> often much larger as an outlined generic function than the simple operation 
>> that can be inlined into client code. Inlining makes the most sense when the 
>> inlined operation is smaller than a function call, so in many cases the net 
>> dylib + executable size would increase.
> 
> I can see this argument, but you’re basically saying that a sufficiently 
> smart programmer can optimize code size based on (near) perfect knowledge of 
> the symbol and all clients.  I don’t think this is realistic for a number of 
> reasons.  In general, an API vendor has no way to know:
> 
> 1) how many clients it will have, potentially in multiple modules that get 
> linked into a single app.
> 2) on which types a generic function will be used with.
> 3) what the code size tradeoffs ARE, e.g. if you have a large function that 
> doesn’t use the archetype much, there is low bloat.
> 
> Furthermore, we have evidence from the C++ community that people are very 
> eager to mark lots of things inlinable regardless of the cost of doing so.  
> Swift may end up being different, but programmers still have no general way 
> to reason about code size given their declaration and without perfect 
> knowledge of the clients.
> 
> The code of the approach I’m advocating is one *single* implementation gets 
> generated in the module that defines the decl.  This can lead the N 
> instantiations of exactly the same unspecialized code (consider the currying 
> and other cases) in N different modules that end up in an app.  This seems 
> like the right tradeoff.

Also, not all inlinable functions are generic.  There are perfectly rationale 
reasons to inline non-generic functions as well, and they don’t benefit from 
the specialization benefits you’re indicating.

Finally, even if a symbol is generic, it isn’t certain that the client will be 
able to specialize.  The calls may be from unspecialized code after all.

-Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Chris Lattner via swift-evolution
On Oct 4, 2017, at 9:44 AM, Joe Groff  wrote:
>> I disagree.  The semantics being proposed perfectly overlap with the 
>> transitional plan for overlays (which matters for the next few years), but 
>> they are the wrong default for anything other than overlays and the wrong 
>> thing for long term API evolution over the next 20 years.
> 
> I disagree with this. 'inline' functions in C and C++ have to be backed by a 
> symbol in the binary in order to guarantee function pointer identity, but we 
> don't have that constraint. Without that constraint, there's almost no way 
> that having a fallback definition in the binary is better:
> 
> - It becomes an ABI compatibility liability that has to be preserved forever. 

This seems like a marginal win at all.  Saying that you want to publish a 
symbol as public API but not have it be ABI is a bit odd.  What is the usecase 
(other than the Swift 3/4/5 transition period)?

> - It increases binary size for a function that's rarely used, and which is 
> often much larger as an outlined generic function than the simple operation 
> that can be inlined into client code. Inlining makes the most sense when the 
> inlined operation is smaller than a function call, so in many cases the net 
> dylib + executable size would increase.

I can see this argument, but you’re basically saying that a sufficiently smart 
programmer can optimize code size based on (near) perfect knowledge of the 
symbol and all clients.  I don’t think this is realistic for a number of 
reasons.  In general, an API vendor has no way to know:

1) how many clients it will have, potentially in multiple modules that get 
linked into a single app.
2) on which types a generic function will be used with.
3) what the code size tradeoffs ARE, e.g. if you have a large function that 
doesn’t use the archetype much, there is low bloat.

Furthermore, we have evidence from the C++ community that people are very eager 
to mark lots of things inlinable regardless of the cost of doing so.  Swift may 
end up being different, but programmers still have no general way to reason 
about code size given their declaration and without perfect knowledge of the 
clients.

The code of the approach I’m advocating is one *single* implementation gets 
generated in the module that defines the decl.  This can lead the N 
instantiations of exactly the same unspecialized code (consider the currying 
and other cases) in N different modules that end up in an app.  This seems like 
the right tradeoff.

> - It increases the uncertainty of the behavior client code sees. If an 
> inlinable function must always be emitted in the client, then client code 
> *always* gets the current definition. If an inlinable function calls into the 
> dylib when the compiler chooses not to inline it, then you may get the 
> current definition, or you may get an older definition from any published 
> version of the dylib. Ideally these all behave the same if the function is 
> inlinable, but quirks are going to be inevitable.

You’re saying that “if an API author incorrectly changes the behavior of their 
inlinable function” that your approach papers over the bug a little bit better. 
 I don’t see this as something that is important to design around.  Not least 
of which because it will produce other inconsistencies: what if a binary module 
A is built against the old version of that inlinable function and you app 
builds against a newer version?  Then you have the two inconsistent versions in 
your app again.

More generally though, an API vendor who does this has broken the 
fragile/inlinable contract, and they therefore invoked undefined behavior - 
c'est la vie.

-Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Chris Lattner via swift-evolution

> On Oct 4, 2017, at 9:36 AM, Joe Groff  wrote:
> 
 It wouldn't avoid the complexity, because we want the "non-ABI, 
 always-emit-into-client" behavior for the standard library. For the 
 soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
 standard library and Apple SDK overlays, there's pretty much perfect 
 overlap between things we want to inline and things we don't want to take 
 up binary space and ABI surface in binaries, so the behavior Slava 
 proposes seems like the right default. 
>>> 
>>> I disagree.  The semantics being proposed perfectly overlap with the 
>>> transitional plan for overlays (which matters for the next few years), but 
>>> they are the wrong default for anything other than overlays and the wrong 
>>> thing for long term API evolution over the next 20 years.
>> 
>> Can you elaborate on this? If inlinable functions have public entry points, 
>> the version in the framework may or may not be called… because of SIL 
>> serialization and inlining. Since the existence of the public entry point 
>> doesn’t offer much of a guarantee, it seems desirable to not have the public 
>> entry point. For example if the inlinable function is not used elsewhere in 
>> the framework, we wouldn’t have to emit it at all. This might make the 
>> standard library smaller for instance.
>> 
>> However I’m still waiting for Dave or Jordan to chime in with the original 
>> justification for the ‘always emit into client’ behavior. IIRC there was a 
>> resilience-related argument too, but I don’t remember what it is now.
> 
> The suggestion to have this semantics was originally my fault, I believe, and 
> it arose from the observation that if we have 'inlinable' backed by a symbol 
> in the binary, then we'd also want the 'must be emitted by client' attribute. 
> I think 'must be emitted by client' is going to almost always be preferable 
> for an inlinable function, though, so it's better to have the single 
> attribute with this behavior, only constrained by backward deployment.

What is the use case of “must be emitted by client” attribute?  If I imagine 
that the Swift 5 standard library is shipped in the OS, I can see cases where 
deprecated/legacy shims for Swift3/4 compatibility would be emitted into the 
client but not shipped in the OS.  Those seem relatively obscure though.

The other issue is that if/when the stdlib and overlays start shipping in the 
OS, that backward deployment will require them to be statically linked into the 
app (optionally with an arclite style dynamic fallback approach).  This problem 
seems orthogonal to the discussion though.

-Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Nevin Brackett-Rozinsky via swift-evolution
On Mon, Oct 2, 2017 at 5:45 PM, Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

> This is unduly restrictive; @_versioned (despite being the wrong spelling)
> is what we want here. To be callable from an inlinable function, internal
> things need only be visible in terms of public ABI, not necessarily
> inlinable, just as public things need only be public and not necessarily
> inlinable.
>

Unduly restrictive is fine for now, we don’t need to make @_versioned ready
for primetime just to roll out @inlinable. We can begin with the semantics
that @inlinable functions can only call things which are themselves either
@inlinable or public, and then subsequently in the future we can expand it
to “…or whatever-we-end-up-calling-@_versioned”.

That way the scope of this proposal can stay narrow and self-contained.

Nevin



> On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  wrote:
>>
>>> Thanks for taking a look!
>>>
>>> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
>>> nevin.brackettrozin...@gmail.com> wrote:
>>> > 3. Even though @inlinable will have no effect on declarations which
>>> are not public, we should still allow it to be placed there. That way when
>>> the access level is later changed to be public, the attribute is already
>>> where it should be. This is similar to why we permit, eg., members of an
>>> internal type to be declared public, which was discussed and decided
>>> previously on Swift Evolution.
>>>
>>> This is an interesting point. Do you think the attribute should be
>>> completely ignored, or should the restrictions on references to non-public
>>> things, etc still be enforced?
>>>
>>
>>  Hmm, good question!
>>
>> I rather like the idea Greg Parker put forth, where non-public @inlinable
>> items can be used by public @inlinable ones, which implies that the
>> restrictions should indeed still apply—something @inlinable can only
>> reference public or @inlinable things.
>>
>> Nevin
>> ___
>> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Joe Groff via swift-evolution


> On Oct 4, 2017, at 9:46 AM, Joe Groff via swift-evolution 
>  wrote:
> 
> 
> 
> On Oct 3, 2017, at 10:03 PM, Chris Lattner  wrote:
> 
>> 
>>> On Oct 3, 2017, at 10:04 AM, Joe Groff  wrote:
>>> 
>>> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
>>>  wrote:
 
 The major question I have is “why yet another attribute”.  The thread 
 about exhaustive/extensible enums is similarly proposing introducing 
 another one-off way to be enums fragile, and this is directly related just 
 for function-like things.
 
 I’d love to see rationale in the proposal for why you’re not taking this 
 in one of these directions:
 
 1) Why not another level of access control?  There is a reasonable 
 argument that what you’re doing is making something “more public than 
 public” or that you’re making the “body also public”.  I’m not strongly in 
 favor of this design approach, but if you agree, the doc should explain 
 why you’re not in favor of it.
 
 2) Why can’t we have a single Swift-wide concept that unifies all of the 
 resilience ideas under a single umbrella like “fragile” - which indicates 
 that the body of a declaration is knowable to clients?  There is a very 
 reasonable holistic design where “fragile public func” makes its body 
 inlinable, and “fragile enum” similarly makes the cases knowable to the 
 client (thus making exhaustive switching a possibility).  I am strongly in 
 favor of this approach.
>>> 
>>> I'm of two minds on this. So far, it has seemingly been the case that, for 
>>> every kind of declaration, there's been exactly one resilience-related 
>>> attribute, and with blurry enough vision you could say they're all really 
>>> doing the same thing, "expose this declaration body directly to clients", 
>>> which only makes sense as a concept for public API. If these properties 
>>> hold, then sure, it might make sense to consider these all as one 
>>> "extra-public" concept. On the other hand, we don't know yet whether these 
>>> properties will hold in the long term as we're actively designing the 
>>> facilities we need for ABI stability and resilience. From an incremental, 
>>> iterative design perspective, I think it's wiser to keep them all separate 
>>> attributes, even if it's a bit messy in the short term. Once the design 
>>> stabilizes, we can look at whether it makes sense to fold related concepts 
>>> together. It's easier to fold different things together after the fact then 
>>> to try to separate things after they've been mixed together.
>> 
>> As I said above, I pretty strongly disagree with this approach.  It 
>> encourages a “one attribute/declmodifier/keyword per decl kind” approach, 
>> which is user hostile.  It doesn’t make sense for “exhaustive" to apply to 
>> enums, "@inlinable” to apply to function-like things, something else to 
>> apply to structs, something else to apply to classes, etc.
> 
> Premature abstraction is user-hostile too. These things all have subtly 
> different impacts on language semantics, some of which we're still 
> discovering as we develop their designs.

These are also ultimately all "power user" features that only a handful of 
first and second parties shipping binary frameworks need to think about. Apps 
don't need to care about this at all, and most packages outside the OS can be 
shipped as source or as fragile binaries, for which these sorts of attributes 
are unnecessary for the build system to (eventually) provide the desired 
performance.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Ole Begemann via swift-evolution
How does @inlinable relate to the @_specialize attribute described in 
https://github.com/apple/swift/pull/6797 (original swift-evolution post 
about it: 
https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20160314/001449.html)?


Here's how I understand it:

@_specialize emits the specialized generic code (for the types specified 
in the @_specialize declaration) in the module binary (module A). The 
downside is that the author of module A has to decide for which types 
they want to emit specialized code. Clients of module A that need 
specialization for other types are out of luck.


@inlinable enables the optimizer to emit specialized code in the 
binaries that import module A. It shifts the decision what to specialize 
where it belongs (and where it can be made).


Is this understanding correct? Will @inlinable cover everything we'd 
need @_specialize for, or is the plan to make @_specialize public as 
well in the future?


Ole

On 02.10.17 22:31, Slava Pestov via swift-evolution wrote:

Hi all,

Here is a draft proposal that makes public a feature we’ve had for a 
while. Let me know what you think!



  Cross-module inlining and specialization ("@inlinable")

  * Proposal: SE- 
  * Authors: Slava Pestov , Jordan
Rose 
  * Review Manager: TBD
  * Status: *Initial pitch*
  * Implementation: Already implemented as an underscored attribute
|@_inlineable|


Introduction

We propose introducing an |@inlinable| attribute which exports the 
body of a function as part of a module's interface, making it 
available to the optimizer when referenced from other modules.



Motivation

One of the top priorities of the Swift 5 release is a design and 
implementation of /the Swift ABI/. This effort consists of three major 
tasks:


 *

Finalizing the low-level function calling convention, layout of
data types, and various runtime data structures. The goal here is
to maintain compatibility across compiler versions, ensuring that
we can continue to make improvements to the Swift compiler without
breaking binaries built with an older version of the compiler.

 *

Implementing support for /library evolution/, or the ability to
make certain source-compatible changes, without breaking binary
compatibility. Examples of source-compatible changes we are
considering include adding new stored properties to structs and
classes, removing private stored properties from structs and
classes, adding new public methods to a class, or adding new
protocol requirements that have a default implementation. The goal
here is to maintain compatibility across framework versions,
ensuring that framework authors can evolve their API without
breaking binaries built against an older version of the framework.
For more information about the resilience model, see the library
evolution document
 in
the Swift repository.

 *

Stabilizing the API of the standard library. The goal here is to
ensure that the standard library can be deployed separately from
client binaries and frameworks, without forcing recompilation of
existing code.

All existing language features of Swift were designed with these goals 
in mind. In particular, the implementation of generic types and 
functions relies on runtime reified types to allow separate 
compilation and type checking of generic code.


Within the scope of a single module, the Swift compiler performs very 
aggressive optimization, including full and partial specialization of 
generic functions, inlining, and various forms of interprocedural 
analysis.


On the other hand, across module boundaries, runtime generics 
introduce unavoidable overhead, as reified type metadata must be 
passed between functions, and various indirect access patterns must be 
used to manipulate values of generic type. We believe that for most 
applications, this overhead is negligible compared to the actual work 
performed by the code itself.


However, for some advanced use cases, and in particular for the 
standard library, the overhead of runtime generics can dominate any 
useful work performed by the library. Examples include the various 
algorithms defined in protocol extensions of |Sequence| and 
|Collection|, for instance the |map|method of the |Sequence| protocol. 
Here the algorithm is very simple and spends most of its time 
manipulating generic values and calling to a user-supplied closure; 
specialization and inlining can completely eliminate the algorithm of 
the higher-order function call and generate equivalent code to a 
hand-written loop manipulating concrete types.


We would like to annotate such functions with the 
|@inlinable| attribute. This will make their bodies available to the 
optimizer when building client code; on the other hand, calling such a 
function will cause 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Joe Groff via swift-evolution


> On Oct 3, 2017, at 10:03 PM, Chris Lattner  wrote:
> 
> 
>> On Oct 3, 2017, at 10:04 AM, Joe Groff  wrote:
>> 
>>> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
>>>  wrote:
>>> 
>>> The major question I have is “why yet another attribute”.  The thread about 
>>> exhaustive/extensible enums is similarly proposing introducing another 
>>> one-off way to be enums fragile, and this is directly related just for 
>>> function-like things.
>>> 
>>> I’d love to see rationale in the proposal for why you’re not taking this in 
>>> one of these directions:
>>> 
>>> 1) Why not another level of access control?  There is a reasonable argument 
>>> that what you’re doing is making something “more public than public” or 
>>> that you’re making the “body also public”.  I’m not strongly in favor of 
>>> this design approach, but if you agree, the doc should explain why you’re 
>>> not in favor of it.
>>> 
>>> 2) Why can’t we have a single Swift-wide concept that unifies all of the 
>>> resilience ideas under a single umbrella like “fragile” - which indicates 
>>> that the body of a declaration is knowable to clients?  There is a very 
>>> reasonable holistic design where “fragile public func” makes its body 
>>> inlinable, and “fragile enum” similarly makes the cases knowable to the 
>>> client (thus making exhaustive switching a possibility).  I am strongly in 
>>> favor of this approach.
>> 
>> I'm of two minds on this. So far, it has seemingly been the case that, for 
>> every kind of declaration, there's been exactly one resilience-related 
>> attribute, and with blurry enough vision you could say they're all really 
>> doing the same thing, "expose this declaration body directly to clients", 
>> which only makes sense as a concept for public API. If these properties 
>> hold, then sure, it might make sense to consider these all as one 
>> "extra-public" concept. On the other hand, we don't know yet whether these 
>> properties will hold in the long term as we're actively designing the 
>> facilities we need for ABI stability and resilience. From an incremental, 
>> iterative design perspective, I think it's wiser to keep them all separate 
>> attributes, even if it's a bit messy in the short term. Once the design 
>> stabilizes, we can look at whether it makes sense to fold related concepts 
>> together. It's easier to fold different things together after the fact then 
>> to try to separate things after they've been mixed together.
> 
> As I said above, I pretty strongly disagree with this approach.  It 
> encourages a “one attribute/declmodifier/keyword per decl kind” approach, 
> which is user hostile.  It doesn’t make sense for “exhaustive" to apply to 
> enums, "@inlinable” to apply to function-like things, something else to apply 
> to structs, something else to apply to classes, etc.

Premature abstraction is user-hostile too. These things all have subtly 
different impacts on language semantics, some of which we're still discovering 
as we develop their designs.

-Joe

> 
> I’d rather that we define one “thing” which can be parameterized.  I’d 
> propose that that be named “fragile” because it appropriately carries 
> negative connotations.  If some declaration has multiple levels of fragility 
> that we want to support, we can allow it to be parameterized, e.g.:
> 
> /// C style fragility, all things about the decl are fragile.
> fragile struct Foo { … }
> 
> /// Just layout is fragile, but not other things (whatever they would be?)
> fragile(layout) struct Foo { … }
> 
> I pretty strongly believe that we should start with the default of having a 
> unifying principle that ties together all resilience concerns under a single 
> umbrella, and fission those concerns when we’re faced with something that 
> forces it.  Starting with them split and hoping that we’ll come around to 
> merging them someday is the wrong side of optimism IMO.
> 
> We’ve been talking about this approach for years, which is why I’m somewhat 
> surprised to see the new direction these things are taking.
> 
> -Chris
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Joe Groff via swift-evolution


> On Oct 3, 2017, at 9:56 PM, Chris Lattner  wrote:
> 
> 
>> On Oct 3, 2017, at 9:50 AM, Joe Groff  wrote:
>> 
>> 
>> 
 On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
  wrote:
 
 We have discussed adding a "versioned @inlinable" variant that preserves 
 the public entry point for older clients, while making the declaration 
 inlinable for newer clients. This will likely be a separate proposal and 
 discussion.
 
>>> 5) It eliminates this complexity.
>> 
>> It wouldn't avoid the complexity, because we want the "non-ABI, 
>> always-emit-into-client" behavior for the standard library. For the 
>> soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
>> standard library and Apple SDK overlays, there's pretty much perfect overlap 
>> between things we want to inline and things we don't want to take up binary 
>> space and ABI surface in binaries, so the behavior Slava proposes seems like 
>> the right default. 
> 
> I disagree.  The semantics being proposed perfectly overlap with the 
> transitional plan for overlays (which matters for the next few years), but 
> they are the wrong default for anything other than overlays and the wrong 
> thing for long term API evolution over the next 20 years.

I disagree with this. 'inline' functions in C and C++ have to be backed by a 
symbol in the binary in order to guarantee function pointer identity, but we 
don't have that constraint. Without that constraint, there's almost no way that 
having a fallback definition in the binary is better:

- It becomes an ABI compatibility liability that has to be preserved forever. 
- It increases binary size for a function that's rarely used, and which is 
often much larger as an outlined generic function than the simple operation 
that can be inlined into client code. Inlining makes the most sense when the 
inlined operation is smaller than a function call, so in many cases the net 
dylib + executable size would increase.
- It increases the uncertainty of the behavior client code sees. If an 
inlinable function must always be emitted in the client, then client code 
*always* gets the current definition. If an inlinable function calls into the 
dylib when the compiler chooses not to inline it, then you may get the current 
definition, or you may get an older definition from any published version of 
the dylib. Ideally these all behave the same if the function is inlinable, but 
quirks are going to be inevitable.

-Joe 

> 
> -Chris
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Joe Groff via swift-evolution


> On Oct 3, 2017, at 9:59 PM, Slava Pestov  wrote:
> 
> 
> 
>>> On Oct 3, 2017, at 9:56 PM, Chris Lattner  wrote:
>>> 
>>> 
 On Oct 3, 2017, at 9:50 AM, Joe Groff  wrote:
 
 
 
> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> We have discussed adding a "versioned @inlinable" variant that preserves 
> the public entry point for older clients, while making the declaration 
> inlinable for newer clients. This will likely be a separate proposal and 
> discussion.
> 
 5) It eliminates this complexity.
>>> 
>>> It wouldn't avoid the complexity, because we want the "non-ABI, 
>>> always-emit-into-client" behavior for the standard library. For the 
>>> soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
>>> standard library and Apple SDK overlays, there's pretty much perfect 
>>> overlap between things we want to inline and things we don't want to take 
>>> up binary space and ABI surface in binaries, so the behavior Slava proposes 
>>> seems like the right default. 
>> 
>> I disagree.  The semantics being proposed perfectly overlap with the 
>> transitional plan for overlays (which matters for the next few years), but 
>> they are the wrong default for anything other than overlays and the wrong 
>> thing for long term API evolution over the next 20 years.
> 
> Can you elaborate on this? If inlinable functions have public entry points, 
> the version in the framework may or may not be called… because of SIL 
> serialization and inlining. Since the existence of the public entry point 
> doesn’t offer much of a guarantee, it seems desirable to not have the public 
> entry point. For example if the inlinable function is not used elsewhere in 
> the framework, we wouldn’t have to emit it at all. This might make the 
> standard library smaller for instance.
> 
> However I’m still waiting for Dave or Jordan to chime in with the original 
> justification for the ‘always emit into client’ behavior. IIRC there was a 
> resilience-related argument too, but I don’t remember what it is now.

The suggestion to have this semantics was originally my fault, I believe, and 
it arose from the observation that if we have 'inlinable' backed by a symbol in 
the binary, then we'd also want the 'must be emitted by client' attribute. I 
think 'must be emitted by client' is going to almost always be preferable for 
an inlinable function, though, so it's better to have the single attribute with 
this behavior, only constrained by backward deployment.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Elia Cereda via swift-evolution

>> 
>> Anyway, for my use case mentioned earlier (shipping a release version of my 
>> app bundle), that doesn’t really matter. I’d just like a compiler switch 
>> that made the whole module not having an ABI, essentially making all all 
>> methods and types @inlinable and @_versioned, using the terminology in your 
>> example.
> 
> Yes, that would be a nice feature to have but it is outside the scope of this 
> proposal. First, we want to tackle shipping resilient modules — then we can 
> discuss generalizing the notion of a “resilience domain” to encompass 
> multiple modules. I realize the latter is more useful to third party 
> developers though, and I apologize that in this particular case our 
> priorities are at odds…

If a framework is only ever used by a single client in the app bundle, as it is 
in the majority of cases, I think the objective should be to link it 
statically. The dynamic linking overhead is useless in this case. Would this 
allow the compiler to optimize across module boundaries? (Are the current 
capabilities of Xcode 9 in this regard described anywhere?) 

Elia Cereda

> Il giorno 04 ott 2017, alle ore 08:09, Slava Pestov via swift-evolution 
>  ha scritto:
> 
> 
> 
>> On Oct 3, 2017, at 11:05 PM, Jonas B > > wrote:
>> 
>> 
>>> On 4 Oct 2017, at 14:33, Slava Pestov >> > wrote:
>>> 
>>> @_versioned makes a symbol visible externally without making it visible 
>>> from the language. There is no requirement that a @_versioned thing is 
>>> @inlinable. It is used when you want to reference an internal function from 
>>> an inlinable function. Eg,
>>> 
>>> internal func myImplDetail() { … }
>>> 
>>> @inlinable public func myPublicFunction() { myImplDetail() } // error!
>>> 
>>> —
>>> 
>>> @_versioned internal func myImplDetail() { … }
>>> 
>>> @inlinable public func myPublicFunction() { myImplDetail() } // OK
>>> 
>>> Slava
>> 
>> 
>> From my language user point of view it would be more understandable if that 
>> was written with a single keyword, eg:
>> @nonABI internal func myImplDetail() { }
>> @nonABI public func myPublicFunction() { myImplDetail() }  // OK
> 
> The two attributes are different though. myImplDetail() is _not_ inlined into 
> client code here, but myPublicFunction() is. So they need different 
> attributes to express this intent.
> 
>> 
>> Anyway, for my use case mentioned earlier (shipping a release version of my 
>> app bundle), that doesn’t really matter. I’d just like a compiler switch 
>> that made the whole module not having an ABI, essentially making all all 
>> methods and types @inlinable and @_versioned, using the terminology in your 
>> example.
> 
> Yes, that would be a nice feature to have but it is outside the scope of this 
> proposal. First, we want to tackle shipping resilient modules — then we can 
> discuss generalizing the notion of a “resilience domain” to encompass 
> multiple modules. I realize the latter is more useful to third party 
> developers though, and I apologize that in this particular case our 
> priorities are at odds…
> 
>> 
>> My other observation is that no matter how great the ergonomics, and no 
>> matter the naming of these attributes, very few people outside the compiler 
>> team is going to be able to successfully ship a versioned library without 
>> the “Checking Binary Compatibility” tool mentioned in 
>> https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#checking-binary-compatibility
>>  
>> .
> 
> I agree — even for members of the compiler team this tool would be very 
> useful, both as a way of encoding our assumptions for sanity-checking, and 
> making sure we don’t make a silly mistake with a future update to the 
> standard library.
> 
> Slava
> 
>> 
>> /Jonas
>> 
> 
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 11:05 PM, Jonas B  wrote:
> 
> 
>> On 4 Oct 2017, at 14:33, Slava Pestov > > wrote:
>> 
>> @_versioned makes a symbol visible externally without making it visible from 
>> the language. There is no requirement that a @_versioned thing is 
>> @inlinable. It is used when you want to reference an internal function from 
>> an inlinable function. Eg,
>> 
>> internal func myImplDetail() { … }
>> 
>> @inlinable public func myPublicFunction() { myImplDetail() } // error!
>> 
>> —
>> 
>> @_versioned internal func myImplDetail() { … }
>> 
>> @inlinable public func myPublicFunction() { myImplDetail() } // OK
>> 
>> Slava
> 
> 
> From my language user point of view it would be more understandable if that 
> was written with a single keyword, eg:
> @nonABI internal func myImplDetail() { }
> @nonABI public func myPublicFunction() { myImplDetail() }  // OK

The two attributes are different though. myImplDetail() is _not_ inlined into 
client code here, but myPublicFunction() is. So they need different attributes 
to express this intent.

> 
> Anyway, for my use case mentioned earlier (shipping a release version of my 
> app bundle), that doesn’t really matter. I’d just like a compiler switch that 
> made the whole module not having an ABI, essentially making all all methods 
> and types @inlinable and @_versioned, using the terminology in your example.

Yes, that would be a nice feature to have but it is outside the scope of this 
proposal. First, we want to tackle shipping resilient modules — then we can 
discuss generalizing the notion of a “resilience domain” to encompass multiple 
modules. I realize the latter is more useful to third party developers though, 
and I apologize that in this particular case our priorities are at odds…

> 
> My other observation is that no matter how great the ergonomics, and no 
> matter the naming of these attributes, very few people outside the compiler 
> team is going to be able to successfully ship a versioned library without the 
> “Checking Binary Compatibility” tool mentioned in 
> https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#checking-binary-compatibility
>  
> .

I agree — even for members of the compiler team this tool would be very useful, 
both as a way of encoding our assumptions for sanity-checking, and making sure 
we don’t make a silly mistake with a future update to the standard library.

Slava

> 
> /Jonas
> 

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-04 Thread Jonas B via swift-evolution

> On 4 Oct 2017, at 14:33, Slava Pestov  wrote:
> 
> @_versioned makes a symbol visible externally without making it visible from 
> the language. There is no requirement that a @_versioned thing is @inlinable. 
> It is used when you want to reference an internal function from an inlinable 
> function. Eg,
> 
> internal func myImplDetail() { … }
> 
> @inlinable public func myPublicFunction() { myImplDetail() } // error!
> 
> —
> 
> @_versioned internal func myImplDetail() { … }
> 
> @inlinable public func myPublicFunction() { myImplDetail() } // OK
> 
> Slava


>From my language user point of view it would be more understandable if that 
>was written with a single keyword, eg:
@nonABI internal func myImplDetail() { }
@nonABI public func myPublicFunction() { myImplDetail() }  // OK

Anyway, for my use case mentioned earlier (shipping a release version of my app 
bundle), that doesn’t really matter. I’d just like a compiler switch that made 
the whole module not having an ABI, essentially making all all methods and 
types @inlinable and @_versioned, using the terminology in your example.

My other observation is that no matter how great the ergonomics, and no matter 
the naming of these attributes, very few people outside the compiler team is 
going to be able to successfully ship a versioned library without the “Checking 
Binary Compatibility” tool mentioned in 
https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#checking-binary-compatibility
 
.

/Jonas

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread David Hart via swift-evolution

> On 4 Oct 2017, at 07:16, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Oct 3, 2017, at 10:11 PM, Slava Pestov > > wrote:
>> 
 However I’m still waiting for Dave or Jordan to chime in with the original 
 justification for the ‘always emit into client’ behavior. IIRC there was a 
 resilience-related argument too, but I don’t remember what it is now.
>>> 
>>> The only argument I can imagine is the “If it gets inlined, you’re 
>>> guaranteed to get the version of the symbol you build against”.  The 
>>> concern is that some instances are inlined and some are not, and if the 
>>> inline and out of line versions diverge then you can have exciting problems.
>>> 
>>> My view on that is that you’ve already lost if you’d done this.  If you 
>>> mark a declaration as fragile (allowing it to be inlined) you’ve 
>>> specifically guaranteed that you’re not going to be changing the observable 
>>> semantics of the function.  Introducing new performance optimizations is 
>>> fine of course.
>> 
>> I understand your reasoning here, but note that in Jordan’s proposal, he’s 
>> adding two new keywords, exhaustive and nonexhaustive. If exhaustive becomes 
>> @fragile, does nonexhaustive still make sense?
> 
> Independently of how exhaustive is spelled, nonexhaustive doesn’t make sense 
> to me.  It should be the default.  Swift doesn’t have keywords to redundantly 
> specify the default unless there is a specific reason to be able to do that.  
> 
> The example often cited is “nonmutating”, but it isn’t there to cover the 
> default: it is specifically required because setters default to mutating so 
> it must exist to be change that default.

Happy to see I’m not the only one with this opinion.

> -Chris
> 
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread David Hart via swift-evolution

> On 4 Oct 2017, at 07:11, Slava Pestov via swift-evolution 
>  wrote:
> 
> 
> 
>> On Oct 3, 2017, at 10:09 PM, Chris Lattner > > wrote:
>> 
>> On Oct 3, 2017, at 9:59 PM, Slava Pestov > > wrote:
> It wouldn't avoid the complexity, because we want the "non-ABI, 
> always-emit-into-client" behavior for the standard library. For the 
> soon-to-be-ABI-stable libraries where @inlinable even matters, such as 
> the standard library and Apple SDK overlays, there's pretty much perfect 
> overlap between things we want to inline and things we don't want to take 
> up binary space and ABI surface in binaries, so the behavior Slava 
> proposes seems like the right default. 
 
 I disagree.  The semantics being proposed perfectly overlap with the 
 transitional plan for overlays (which matters for the next few years), but 
 they are the wrong default for anything other than overlays and the wrong 
 thing for long term API evolution over the next 20 years.
>>> 
>>> Can you elaborate on this? If inlinable functions have public entry points, 
>>> the version in the framework may or may not be called… because of SIL 
>>> serialization and inlining. Since the existence of the public entry point 
>>> doesn’t offer much of a guarantee, it seems desirable to not have the 
>>> public entry point. For example if the inlinable function is not used 
>>> elsewhere in the framework, we wouldn’t have to emit it at all. This might 
>>> make the standard library smaller for instance.
>> 
>> Sure, let me explain the same thing a different way: because the symbol is 
>> known to be present, clients are not *forced* to inline the body of the 
>> function if it is not profitable.  They know that there is always a single 
>> canonical implementation of the function, so they aren’t forced to replicate 
>> it N times for N clients.
>> 
>> Remember also that there are times where the body of a symbol isn’t the 
>> thing that is useful.  If you curry a method for example, you want its 
>> address.  With the proposed inlining semantics, this forces a copy of the 
>> body to be emitted in every module that uses it, because you don’t have a 
>> canonical name for the thing.
>> 
>>> However I’m still waiting for Dave or Jordan to chime in with the original 
>>> justification for the ‘always emit into client’ behavior. IIRC there was a 
>>> resilience-related argument too, but I don’t remember what it is now.
>> 
>> The only argument I can imagine is the “If it gets inlined, you’re 
>> guaranteed to get the version of the symbol you build against”.  The concern 
>> is that some instances are inlined and some are not, and if the inline and 
>> out of line versions diverge then you can have exciting problems.
>> 
>> My view on that is that you’ve already lost if you’d done this.  If you mark 
>> a declaration as fragile (allowing it to be inlined) you’ve specifically 
>> guaranteed that you’re not going to be changing the observable semantics of 
>> the function.  Introducing new performance optimizations is fine of course.
> 
> I understand your reasoning here, but note that in Jordan’s proposal, he’s 
> adding two new keywords, exhaustive and nonexhaustive. If exhaustive becomes 
> @fragile, does nonexhaustive still make sense?

I’ve already made this argument in the corresponding thread: I’m against 
nonexhaustive because it is the default behaviour (for the same reason we don’t 
have/need non-final). Therefore, I wouldn’t feel bad about seeing it go.

> Slava
> 
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 10:32 PM, Jonas B  wrote:
> 
> 
>> On 4 Oct 2017, at 13:36, Slava Pestov > > wrote:
>> 
>>> On Oct 3, 2017, at 9:14 PM, Jonas B via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> Now I understand that this use-case is deferred for a later separate 
>>> discussion, but my point here is that the name and the semantics of this 
>>> attribute should be somewhat “forward-compatilble” with this use-case. “ 
>>> inlinable” does not sound appropriate, because we don’t want to “inline” 
>>> (in the C/C++ meaning) declarations into each usage site.
>>> Instead we want to compile the annotated parts of -all linked modules- as 
>>> one unit. Basically, for those parts, the module name would just function 
>>> like a C++ namespace - an input to the symbol name mangling, and then the 
>>> whole thing could be whole-module-optimized together.
>> 
>> Yeah, @inlinable does not actually force any kind of inlining to be 
>> performed — it declared that the SIL for the function body should be 
>> serialized as part of the module.
>> 
>>> 
>>> This touches upon another comment someone made previously in this 
>>> discussion - that access level and compiler visibility should be separate 
>>> concepts. Because not just public methods, also private methods should be 
>>> subject to this. 
>> 
>> The undocumented @_versioned attribute is currently used to make something 
>> visible to the compiler without making it visible in the language. It sounds 
>> like there’s some interest in documenting this attribute too — can someone 
>> suggest a better name than @_versioned? If we converge on a design here I 
>> can incorporate that into the proposal, relaxing the restriction that 
>> @inlinable functions can only reference other public functions.
>> 
>> Slava
> 
> 
> It’s not totally clear to me what @_versioned is supposed to do. Well, it’s 
> kind of clear that if something less-than-public in module A is declared 
> @_versioned then it’s visible to the compiler when compiling module B (which 
> imports module A). But does @_versioned imply @inlineable? If not, what’s the 
> use case for declaring something @_versioned but not @inlineable? Giving some 
> more information to the optimiser without introducing ABI fragility? Why not 
> always do that then?
> 

@_versioned makes a symbol visible externally without making it visible from 
the language. There is no requirement that a @_versioned thing is @inlinable. 
It is used when you want to reference an internal function from an inlinable 
function. Eg,

internal func myImplDetail() { … }

@inlinable public func myPublicFunction() { myImplDetail() } // error!

—

@_versioned internal func myImplDetail() { … }

@inlinable public func myPublicFunction() { myImplDetail() } // OK

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Jonas B via swift-evolution

> On 4 Oct 2017, at 13:36, Slava Pestov  wrote:
> 
>> On Oct 3, 2017, at 9:14 PM, Jonas B via swift-evolution 
>> > wrote:
>> 
>> 
>> Now I understand that this use-case is deferred for a later separate 
>> discussion, but my point here is that the name and the semantics of this 
>> attribute should be somewhat “forward-compatilble” with this use-case. “ 
>> inlinable” does not sound appropriate, because we don’t want to “inline” (in 
>> the C/C++ meaning) declarations into each usage site.
>> Instead we want to compile the annotated parts of -all linked modules- as 
>> one unit. Basically, for those parts, the module name would just function 
>> like a C++ namespace - an input to the symbol name mangling, and then the 
>> whole thing could be whole-module-optimized together.
> 
> Yeah, @inlinable does not actually force any kind of inlining to be performed 
> — it declared that the SIL for the function body should be serialized as part 
> of the module.
> 
>> 
>> This touches upon another comment someone made previously in this discussion 
>> - that access level and compiler visibility should be separate concepts. 
>> Because not just public methods, also private methods should be subject to 
>> this. 
> 
> The undocumented @_versioned attribute is currently used to make something 
> visible to the compiler without making it visible in the language. It sounds 
> like there’s some interest in documenting this attribute too — can someone 
> suggest a better name than @_versioned? If we converge on a design here I can 
> incorporate that into the proposal, relaxing the restriction that @inlinable 
> functions can only reference other public functions.
> 
> Slava


It’s not totally clear to me what @_versioned is supposed to do. Well, it’s 
kind of clear that if something less-than-public in module A is declared 
@_versioned then it’s visible to the compiler when compiling module B (which 
imports module A). But does @_versioned imply @inlineable? If not, what’s the 
use case for declaring something @_versioned but not @inlineable? Giving some 
more information to the optimiser without introducing ABI fragility? Why not 
always do that then?

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 3, 2017, at 10:16 PM, Chris Lattner  wrote:
> 
> 
>> On Oct 3, 2017, at 10:11 PM, Slava Pestov > > wrote:
>> 
 However I’m still waiting for Dave or Jordan to chime in with the original 
 justification for the ‘always emit into client’ behavior. IIRC there was a 
 resilience-related argument too, but I don’t remember what it is now.
>>> 
>>> The only argument I can imagine is the “If it gets inlined, you’re 
>>> guaranteed to get the version of the symbol you build against”.  The 
>>> concern is that some instances are inlined and some are not, and if the 
>>> inline and out of line versions diverge then you can have exciting problems.
>>> 
>>> My view on that is that you’ve already lost if you’d done this.  If you 
>>> mark a declaration as fragile (allowing it to be inlined) you’ve 
>>> specifically guaranteed that you’re not going to be changing the observable 
>>> semantics of the function.  Introducing new performance optimizations is 
>>> fine of course.
>> 
>> I understand your reasoning here, but note that in Jordan’s proposal, he’s 
>> adding two new keywords, exhaustive and nonexhaustive. If exhaustive becomes 
>> @fragile, does nonexhaustive still make sense?
> 
> Independently of how exhaustive is spelled, nonexhaustive doesn’t make sense 
> to me.  It should be the default.  Swift doesn’t have keywords to redundantly 
> specify the default unless there is a specific reason to be able to do that.  
> 
> The example often cited is “nonmutating”, but it isn’t there to cover the 
> default: it is specifically required because setters default to mutating so 
> it must exist to be change that default.

To elaborate on this point, Swift does not include keywords to be able to spell 
the default for lots of things.  If we did, we would have to have things like 
“nonfinal”, “strong”, etc.  Adding these would not make the language better.

As I pointed out on the enum discussion upthread, the interesting thing is to 
add a *clang* attribute for nonexhaustive, which I thought already exists, but 
I don’t see in the clang language extensions documentation at 
https://clang.llvm.org/docs/LanguageExtensions.html

-Chris
 

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 10:21 PM, Jonas B  wrote:
> 
> 
>> 
>> Yeah, but the compiler could handle NSObject as a special case. Are there 
>> enough other special cases that it is worth documenting and exposing a 
>> fragile attribute on classes to the user?
>> 
> 
> Pitching in here.. currently if you do something remotely complex with 
> protocols and generics you need a bunch of classes for type erasure.
> 
> I don’t want to think about what happens if you annotate a class with the 
> "open” access modifier as @fragile/@inlineable though. Would @fragile become 
> transitive? :)

I don’t think it would be transitive. For instance NSObject is “fragile” 
because the compiler can assume it has a known size, but certainly that is not 
true for most subclasses of NSObject.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Jonas B via swift-evolution

> 
> Yeah, but the compiler could handle NSObject as a special case. Are there 
> enough other special cases that it is worth documenting and exposing a 
> fragile attribute on classes to the user?
> 

Pitching in here.. currently if you do something remotely complex with 
protocols and generics you need a bunch of classes for type erasure.

I don’t want to think about what happens if you annotate a class with the 
"open” access modifier as @fragile/@inlineable though. Would @fragile become 
transitive? :)___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 3, 2017, at 10:18 PM, Slava Pestov  wrote:
> 
> 
> 
>> On Oct 3, 2017, at 10:17 PM, Chris Lattner > > wrote:
>> 
>>> 
>>> On Oct 3, 2017, at 10:15 PM, Slava Pestov >> > wrote:
>>> 
>>> 
>>> 
 On Oct 3, 2017, at 10:14 PM, Chris Lattner > wrote:
 
 On Oct 2, 2017, at 11:11 PM, Slava Pestov > wrote:
>> In any case, even if you’re opposed to these approaches, I’d love for 
>> the “alternatives considered” section to indicate what the objection is. 
>>  I am really very concerned that you’re causing a keyword/attribute 
>> explosion and conceptual complexity by adding too many small things to 
>> individual parts of the language.  We would ideally have a simple and 
>> holistic solution to resilience.
> 
> I agree with that keyword/attribute explosion is a concern. We also plan 
> on submitting a proposal to add a @fixedContents attribute for structs 
> (currently implemented as @_fixed_layout) which enables more efficient 
> access patterns in resilient code, for example direct access of stored 
> properties, at the cost of preventing new stored properties from being 
> added in a binary-compatible manner. So we would have ‘nonexhaustive’ 
> enums, @fixedContents structs, and @inlinable 
> functions/properties/initializers.
 
 Yes, and then we’ll need something else for classes as well (*head 
 explodes*).
>>> 
>>> FWIW, I was hoping we wouldn’t need to expose any such attribute for 
>>> classes (or protocols) at all, because classes are already “slow” and 
>>> anything we do to make them resilient doesn’t make things much “slower”. 
>>> But that could change, of course.
>> 
>> But everyone knows that NSObject is fixed size, right?
> 
> Yeah, but the compiler could handle NSObject as a special case. Are there 
> enough other special cases that it is worth documenting and exposing a 
> fragile attribute on classes to the user?

My point is that NSObject isn’t a special case.  It is simply a very commonly 
known case right now.  While I agree that we can ignore this concern in the 
short term, in the long term evolution of Swift, the exact same concept will 
pop up at some point.  It is a really really high value optimization for things 
that are at a low level of the stack.

-Chris



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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 10:17 PM, Chris Lattner  wrote:
> 
>> 
>> On Oct 3, 2017, at 10:15 PM, Slava Pestov  wrote:
>> 
>> 
>> 
>>> On Oct 3, 2017, at 10:14 PM, Chris Lattner  wrote:
>>> 
>>> On Oct 2, 2017, at 11:11 PM, Slava Pestov  wrote:
> In any case, even if you’re opposed to these approaches, I’d love for the 
> “alternatives considered” section to indicate what the objection is.  I 
> am really very concerned that you’re causing a keyword/attribute 
> explosion and conceptual complexity by adding too many small things to 
> individual parts of the language.  We would ideally have a simple and 
> holistic solution to resilience.
 
 I agree with that keyword/attribute explosion is a concern. We also plan 
 on submitting a proposal to add a @fixedContents attribute for structs 
 (currently implemented as @_fixed_layout) which enables more efficient 
 access patterns in resilient code, for example direct access of stored 
 properties, at the cost of preventing new stored properties from being 
 added in a binary-compatible manner. So we would have ‘nonexhaustive’ 
 enums, @fixedContents structs, and @inlinable 
 functions/properties/initializers.
>>> 
>>> Yes, and then we’ll need something else for classes as well (*head 
>>> explodes*).
>> 
>> FWIW, I was hoping we wouldn’t need to expose any such attribute for classes 
>> (or protocols) at all, because classes are already “slow” and anything we do 
>> to make them resilient doesn’t make things much “slower”. But that could 
>> change, of course.
> 
> But everyone knows that NSObject is fixed size, right?

Yeah, but the compiler could handle NSObject as a special case. Are there 
enough other special cases that it is worth documenting and exposing a fragile 
attribute on classes to the user?

Slava

> 
> -Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 3, 2017, at 10:15 PM, Slava Pestov  wrote:
> 
> 
> 
>> On Oct 3, 2017, at 10:14 PM, Chris Lattner  wrote:
>> 
>> On Oct 2, 2017, at 11:11 PM, Slava Pestov  wrote:
 In any case, even if you’re opposed to these approaches, I’d love for the 
 “alternatives considered” section to indicate what the objection is.  I am 
 really very concerned that you’re causing a keyword/attribute explosion 
 and conceptual complexity by adding too many small things to individual 
 parts of the language.  We would ideally have a simple and holistic 
 solution to resilience.
>>> 
>>> I agree with that keyword/attribute explosion is a concern. We also plan on 
>>> submitting a proposal to add a @fixedContents attribute for structs 
>>> (currently implemented as @_fixed_layout) which enables more efficient 
>>> access patterns in resilient code, for example direct access of stored 
>>> properties, at the cost of preventing new stored properties from being 
>>> added in a binary-compatible manner. So we would have ‘nonexhaustive’ 
>>> enums, @fixedContents structs, and @inlinable 
>>> functions/properties/initializers.
>> 
>> Yes, and then we’ll need something else for classes as well (*head 
>> explodes*).
> 
> FWIW, I was hoping we wouldn’t need to expose any such attribute for classes 
> (or protocols) at all, because classes are already “slow” and anything we do 
> to make them resilient doesn’t make things much “slower”. But that could 
> change, of course.

But everyone knows that NSObject is fixed size, right?

-Chris


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 3, 2017, at 10:11 PM, Slava Pestov  wrote:
> 
>>> However I’m still waiting for Dave or Jordan to chime in with the original 
>>> justification for the ‘always emit into client’ behavior. IIRC there was a 
>>> resilience-related argument too, but I don’t remember what it is now.
>> 
>> The only argument I can imagine is the “If it gets inlined, you’re 
>> guaranteed to get the version of the symbol you build against”.  The concern 
>> is that some instances are inlined and some are not, and if the inline and 
>> out of line versions diverge then you can have exciting problems.
>> 
>> My view on that is that you’ve already lost if you’d done this.  If you mark 
>> a declaration as fragile (allowing it to be inlined) you’ve specifically 
>> guaranteed that you’re not going to be changing the observable semantics of 
>> the function.  Introducing new performance optimizations is fine of course.
> 
> I understand your reasoning here, but note that in Jordan’s proposal, he’s 
> adding two new keywords, exhaustive and nonexhaustive. If exhaustive becomes 
> @fragile, does nonexhaustive still make sense?

Independently of how exhaustive is spelled, nonexhaustive doesn’t make sense to 
me.  It should be the default.  Swift doesn’t have keywords to redundantly 
specify the default unless there is a specific reason to be able to do that.  

The example often cited is “nonmutating”, but it isn’t there to cover the 
default: it is specifically required because setters default to mutating so it 
must exist to be change that default.

-Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 10:14 PM, Chris Lattner  wrote:
> 
> On Oct 2, 2017, at 11:11 PM, Slava Pestov  wrote:
>>> In any case, even if you’re opposed to these approaches, I’d love for the 
>>> “alternatives considered” section to indicate what the objection is.  I am 
>>> really very concerned that you’re causing a keyword/attribute explosion and 
>>> conceptual complexity by adding too many small things to individual parts 
>>> of the language.  We would ideally have a simple and holistic solution to 
>>> resilience.
>> 
>> I agree with that keyword/attribute explosion is a concern. We also plan on 
>> submitting a proposal to add a @fixedContents attribute for structs 
>> (currently implemented as @_fixed_layout) which enables more efficient 
>> access patterns in resilient code, for example direct access of stored 
>> properties, at the cost of preventing new stored properties from being added 
>> in a binary-compatible manner. So we would have ‘nonexhaustive’ enums, 
>> @fixedContents structs, and @inlinable functions/properties/initializers.
> 
> Yes, and then we’ll need something else for classes as well (*head explodes*).

FWIW, I was hoping we wouldn’t need to expose any such attribute for classes 
(or protocols) at all, because classes are already “slow” and anything we do to 
make them resilient doesn’t make things much “slower”. But that could change, 
of course.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution
On Oct 2, 2017, at 11:11 PM, Slava Pestov  wrote:
>> In any case, even if you’re opposed to these approaches, I’d love for the 
>> “alternatives considered” section to indicate what the objection is.  I am 
>> really very concerned that you’re causing a keyword/attribute explosion and 
>> conceptual complexity by adding too many small things to individual parts of 
>> the language.  We would ideally have a simple and holistic solution to 
>> resilience.
> 
> I agree with that keyword/attribute explosion is a concern. We also plan on 
> submitting a proposal to add a @fixedContents attribute for structs 
> (currently implemented as @_fixed_layout) which enables more efficient access 
> patterns in resilient code, for example direct access of stored properties, 
> at the cost of preventing new stored properties from being added in a 
> binary-compatible manner. So we would have ‘nonexhaustive’ enums, 
> @fixedContents structs, and @inlinable functions/properties/initializers.

Yes, and then we’ll need something else for classes as well (*head explodes*).

I really prefer having a single “fragile” concept, and allowing it to be 
parameterized for declarations that can be fragile in different ways: 
"fragile(storage) class Foo” or whatever.

> Perhaps it makes sense to have a single ‘fragile’ keyword replace 
> @fixedContents and @inlinable. For enums, ‘nonexhaustive’ does “feel” a bit 
> different, so perhaps it makes sense for it to be its own thing.

The core team discussed enums about a year ago and my recollection was that we 
came to the decision that there was “c style fragility” and “non-fragility” 
that were the only interesting points on the spectrum.  Intermediate points 
like saying that "the list of members can be fixed, but their enum values were 
not” was deemed to be only of academic curiosity.  If we ever had a compelling 
use-case for such a thing, we could parameterize fragile to support it.

> From an implementation perspective it doesn’t really matter if we have 
> multiple attributes or one, so of course I’d prefer to go with the approach 
> that makes the most sense to people language design-wise.

Yes, I’m only concerned with the user visible design here.  Internally 
implementing these things as a matrix of capabilities is entirely sensible, but 
not the purview of swift-evolution.

>> This semantic doesn’t make sense to me, and I think we need to change it.  I 
>> think we are better served with the semantics of “the body may be inlined, 
>> but doesn’t have to.”
> 
> That is the effect it has today. The decision to inline or not is made by the 
> optimizer, and @inlinable doesn’t change anything here; it makes the body 
> available if the optimizer chooses to do so.

If I read the proposal correctly, it is saying that the body has to be inlined 
into the modules that use it, because there is no symbol published from the 
module that defines it.  That’s the concept of inlining that I’m objecting to.

-Chris


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 10:09 PM, Chris Lattner  wrote:
> 
> On Oct 3, 2017, at 9:59 PM, Slava Pestov  > wrote:
 It wouldn't avoid the complexity, because we want the "non-ABI, 
 always-emit-into-client" behavior for the standard library. For the 
 soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
 standard library and Apple SDK overlays, there's pretty much perfect 
 overlap between things we want to inline and things we don't want to take 
 up binary space and ABI surface in binaries, so the behavior Slava 
 proposes seems like the right default. 
>>> 
>>> I disagree.  The semantics being proposed perfectly overlap with the 
>>> transitional plan for overlays (which matters for the next few years), but 
>>> they are the wrong default for anything other than overlays and the wrong 
>>> thing for long term API evolution over the next 20 years.
>> 
>> Can you elaborate on this? If inlinable functions have public entry points, 
>> the version in the framework may or may not be called… because of SIL 
>> serialization and inlining. Since the existence of the public entry point 
>> doesn’t offer much of a guarantee, it seems desirable to not have the public 
>> entry point. For example if the inlinable function is not used elsewhere in 
>> the framework, we wouldn’t have to emit it at all. This might make the 
>> standard library smaller for instance.
> 
> Sure, let me explain the same thing a different way: because the symbol is 
> known to be present, clients are not *forced* to inline the body of the 
> function if it is not profitable.  They know that there is always a single 
> canonical implementation of the function, so they aren’t forced to replicate 
> it N times for N clients.
> 
> Remember also that there are times where the body of a symbol isn’t the thing 
> that is useful.  If you curry a method for example, you want its address.  
> With the proposed inlining semantics, this forces a copy of the body to be 
> emitted in every module that uses it, because you don’t have a canonical name 
> for the thing.
> 
>> However I’m still waiting for Dave or Jordan to chime in with the original 
>> justification for the ‘always emit into client’ behavior. IIRC there was a 
>> resilience-related argument too, but I don’t remember what it is now.
> 
> The only argument I can imagine is the “If it gets inlined, you’re guaranteed 
> to get the version of the symbol you build against”.  The concern is that 
> some instances are inlined and some are not, and if the inline and out of 
> line versions diverge then you can have exciting problems.
> 
> My view on that is that you’ve already lost if you’d done this.  If you mark 
> a declaration as fragile (allowing it to be inlined) you’ve specifically 
> guaranteed that you’re not going to be changing the observable semantics of 
> the function.  Introducing new performance optimizations is fine of course.

I understand your reasoning here, but note that in Jordan’s proposal, he’s 
adding two new keywords, exhaustive and nonexhaustive. If exhaustive becomes 
@fragile, does nonexhaustive still make sense?

Slava

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution
On Oct 3, 2017, at 9:59 PM, Slava Pestov  wrote:
>>> It wouldn't avoid the complexity, because we want the "non-ABI, 
>>> always-emit-into-client" behavior for the standard library. For the 
>>> soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
>>> standard library and Apple SDK overlays, there's pretty much perfect 
>>> overlap between things we want to inline and things we don't want to take 
>>> up binary space and ABI surface in binaries, so the behavior Slava proposes 
>>> seems like the right default. 
>> 
>> I disagree.  The semantics being proposed perfectly overlap with the 
>> transitional plan for overlays (which matters for the next few years), but 
>> they are the wrong default for anything other than overlays and the wrong 
>> thing for long term API evolution over the next 20 years.
> 
> Can you elaborate on this? If inlinable functions have public entry points, 
> the version in the framework may or may not be called… because of SIL 
> serialization and inlining. Since the existence of the public entry point 
> doesn’t offer much of a guarantee, it seems desirable to not have the public 
> entry point. For example if the inlinable function is not used elsewhere in 
> the framework, we wouldn’t have to emit it at all. This might make the 
> standard library smaller for instance.

Sure, let me explain the same thing a different way: because the symbol is 
known to be present, clients are not *forced* to inline the body of the 
function if it is not profitable.  They know that there is always a single 
canonical implementation of the function, so they aren’t forced to replicate it 
N times for N clients.

Remember also that there are times where the body of a symbol isn’t the thing 
that is useful.  If you curry a method for example, you want its address.  With 
the proposed inlining semantics, this forces a copy of the body to be emitted 
in every module that uses it, because you don’t have a canonical name for the 
thing.

> However I’m still waiting for Dave or Jordan to chime in with the original 
> justification for the ‘always emit into client’ behavior. IIRC there was a 
> resilience-related argument too, but I don’t remember what it is now.

The only argument I can imagine is the “If it gets inlined, you’re guaranteed 
to get the version of the symbol you build against”.  The concern is that some 
instances are inlined and some are not, and if the inline and out of line 
versions diverge then you can have exciting problems.

My view on that is that you’ve already lost if you’d done this.  If you mark a 
declaration as fragile (allowing it to be inlined) you’ve specifically 
guaranteed that you’re not going to be changing the observable semantics of the 
function.  Introducing new performance optimizations is fine of course.

-Chris


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 3, 2017, at 10:04 AM, Joe Groff  wrote:
> 
> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
> > wrote:
>> 
>> The major question I have is “why yet another attribute”.  The thread about 
>> exhaustive/extensible enums is similarly proposing introducing another 
>> one-off way to be enums fragile, and this is directly related just for 
>> function-like things.
>> 
>> I’d love to see rationale in the proposal for why you’re not taking this in 
>> one of these directions:
>> 
>> 1) Why not another level of access control?  There is a reasonable argument 
>> that what you’re doing is making something “more public than public” or that 
>> you’re making the “body also public”.  I’m not strongly in favor of this 
>> design approach, but if you agree, the doc should explain why you’re not in 
>> favor of it.
>> 
>> 2) Why can’t we have a single Swift-wide concept that unifies all of the 
>> resilience ideas under a single umbrella like “fragile” - which indicates 
>> that the body of a declaration is knowable to clients?  There is a very 
>> reasonable holistic design where “fragile public func” makes its body 
>> inlinable, and “fragile enum” similarly makes the cases knowable to the 
>> client (thus making exhaustive switching a possibility).  I am strongly in 
>> favor of this approach.
> 
> I'm of two minds on this. So far, it has seemingly been the case that, for 
> every kind of declaration, there's been exactly one resilience-related 
> attribute, and with blurry enough vision you could say they're all really 
> doing the same thing, "expose this declaration body directly to clients", 
> which only makes sense as a concept for public API. If these properties hold, 
> then sure, it might make sense to consider these all as one "extra-public" 
> concept. On the other hand, we don't know yet whether these properties will 
> hold in the long term as we're actively designing the facilities we need for 
> ABI stability and resilience. From an incremental, iterative design 
> perspective, I think it's wiser to keep them all separate attributes, even if 
> it's a bit messy in the short term. Once the design stabilizes, we can look 
> at whether it makes sense to fold related concepts together. It's easier to 
> fold different things together after the fact then to try to separate things 
> after they've been mixed together.

As I said above, I pretty strongly disagree with this approach.  It encourages 
a “one attribute/declmodifier/keyword per decl kind” approach, which is user 
hostile.  It doesn’t make sense for “exhaustive" to apply to enums, 
"@inlinable” to apply to function-like things, something else to apply to 
structs, something else to apply to classes, etc.

I’d rather that we define one “thing” which can be parameterized.  I’d propose 
that that be named “fragile” because it appropriately carries negative 
connotations.  If some declaration has multiple levels of fragility that we 
want to support, we can allow it to be parameterized, e.g.:

/// C style fragility, all things about the decl are fragile.
fragile struct Foo { … }

/// Just layout is fragile, but not other things (whatever they would be?)
fragile(layout) struct Foo { … }

I pretty strongly believe that we should start with the default of having a 
unifying principle that ties together all resilience concerns under a single 
umbrella, and fission those concerns when we’re faced with something that 
forces it.  Starting with them split and hoping that we’ll come around to 
merging them someday is the wrong side of optimism IMO.

We’ve been talking about this approach for years, which is why I’m somewhat 
surprised to see the new direction these things are taking.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 9:56 PM, Chris Lattner  wrote:
> 
>> 
>> On Oct 3, 2017, at 9:50 AM, Joe Groff > > wrote:
>> 
>> 
>> 
>>> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
>>> > wrote:
>>> 
 We have discussed adding a "versioned @inlinable" variant that preserves 
 the public entry point for older clients, while making the declaration 
 inlinable for newer clients. This will likely be a separate proposal and 
 discussion.
 
>>> 5) It eliminates this complexity.
>> 
>> It wouldn't avoid the complexity, because we want the "non-ABI, 
>> always-emit-into-client" behavior for the standard library. For the 
>> soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
>> standard library and Apple SDK overlays, there's pretty much perfect overlap 
>> between things we want to inline and things we don't want to take up binary 
>> space and ABI surface in binaries, so the behavior Slava proposes seems like 
>> the right default. 
> 
> I disagree.  The semantics being proposed perfectly overlap with the 
> transitional plan for overlays (which matters for the next few years), but 
> they are the wrong default for anything other than overlays and the wrong 
> thing for long term API evolution over the next 20 years.

Can you elaborate on this? If inlinable functions have public entry points, the 
version in the framework may or may not be called… because of SIL serialization 
and inlining. Since the existence of the public entry point doesn’t offer much 
of a guarantee, it seems desirable to not have the public entry point. For 
example if the inlinable function is not used elsewhere in the framework, we 
wouldn’t have to emit it at all. This might make the standard library smaller 
for instance.

However I’m still waiting for Dave or Jordan to chime in with the original 
justification for the ‘always emit into client’ behavior. IIRC there was a 
resilience-related argument too, but I don’t remember what it is now.

Slava

> 
> -Chris

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 3, 2017, at 9:50 AM, Joe Groff  wrote:
> 
> 
> 
>> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
>> > wrote:
>> 
>>> We have discussed adding a "versioned @inlinable" variant that preserves 
>>> the public entry point for older clients, while making the declaration 
>>> inlinable for newer clients. This will likely be a separate proposal and 
>>> discussion.
>>> 
>> 5) It eliminates this complexity.
> 
> It wouldn't avoid the complexity, because we want the "non-ABI, 
> always-emit-into-client" behavior for the standard library. For the 
> soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
> standard library and Apple SDK overlays, there's pretty much perfect overlap 
> between things we want to inline and things we don't want to take up binary 
> space and ABI surface in binaries, so the behavior Slava proposes seems like 
> the right default. 

I disagree.  The semantics being proposed perfectly overlap with the 
transitional plan for overlays (which matters for the next few years), but they 
are the wrong default for anything other than overlays and the wrong thing for 
long term API evolution over the next 20 years.

-Chris


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 2, 2017, at 11:27 PM, Slava Pestov  wrote:
> 
> 
>> On Oct 2, 2017, at 10:57 PM, Chris Lattner > > wrote:
>> 
>> 1) Why not another level of access control?  There is a reasonable argument 
>> that what you’re doing is making something “more public than public” or that 
>> you’re making the “body also public”.  I’m not strongly in favor of this 
>> design approach, but if you agree, the doc should explain why you’re not in 
>> favor of it.
> 
> Oh, I forgot to address this point. I’m against this because even though this 
> proposal says inlinable requires public, it is really orthogonal to public, 
> because eventually we will have something like the current @_versioned 
> attribute, where internal (or even private, as some have suggested) functions 
> can be “public ABI”. For example,

I’m also against it, because it should theoretically be orthogonal to 
open/public.  While we could define “fragile” as being “more permissive than 
open and public”, that is weird and access control is already too complicated.  
:-)

-Chris


> 
> @_versioned func myInternalDetails() {
>   // …
> }
> 
> @inlinable
> public func myPublicFunction() {
>   myInternalDetails() // I can reference this from an inlinable function, but 
> users can’t call it directly
> }
> 
> Slava

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Chris Lattner via swift-evolution

> On Oct 2, 2017, at 11:20 PM, Slava Pestov  wrote:
> 
> 
>> On Oct 2, 2017, at 11:11 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> 
>>> This semantic doesn’t make sense to me, and I think we need to change it.  
>>> I think we are better served with the semantics of “the body may be 
>>> inlined, but doesn’t have to.”
>> 
>> That is the effect it has today. The decision to inline or not is made by 
>> the optimizer, and @inlinable doesn’t change anything here; it makes the 
>> body available if the optimizer chooses to do so.
> 
> Also remember we have the @inline(never) attribute. It’s not underscored so 
> I’m assuming it’s an “official” part of the language. And "@inline(never) 
> @inlinable" is a perfectly valid combination — it serializes the SIL for the 
> function body, and while inlining it is prohibited, it is still subject to 
> specialization, function signature optimizations, etc.

Despite the underscore, I don’t think that this was officially ever “design 
reviewed”, and I don’t think it is widely used.  If we need to change or 
restrict or add requirements to @inline(never), we can do so IMO.  We can 
design adequate upgrade paths and keep the old behavior around for 
compatibility if necessary.  Lets focus on what the right long term model is.

-Chris


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution


> On Oct 3, 2017, at 9:14 PM, Jonas B via swift-evolution 
>  wrote:
> 
> 
> Now I understand that this use-case is deferred for a later separate 
> discussion, but my point here is that the name and the semantics of this 
> attribute should be somewhat “forward-compatilble” with this use-case. “ 
> inlinable” does not sound appropriate, because we don’t want to “inline” (in 
> the C/C++ meaning) declarations into each usage site.
> Instead we want to compile the annotated parts of -all linked modules- as one 
> unit. Basically, for those parts, the module name would just function like a 
> C++ namespace - an input to the symbol name mangling, and then the whole 
> thing could be whole-module-optimized together.

Yeah, @inlinable does not actually force any kind of inlining to be performed — 
it declared that the SIL for the function body should be serialized as part of 
the module.

> 
> This touches upon another comment someone made previously in this discussion 
> - that access level and compiler visibility should be separate concepts. 
> Because not just public methods, also private methods should be subject to 
> this. 

The undocumented @_versioned attribute is currently used to make something 
visible to the compiler without making it visible in the language. It sounds 
like there’s some interest in documenting this attribute too — can someone 
suggest a better name than @_versioned? If we converge on a design here I can 
incorporate that into the proposal, relaxing the restriction that @inlinable 
functions can only reference other public functions.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Jonas B via swift-evolution
I find the following points in the proposal interesting:

> Within the scope of a single module, the Swift compiler performs very 
> aggressive optimization, including full and partial specialization of generic 
> functions, inlining, and various forms of interprocedural analysis.
> On the other hand, across module boundaries, runtime generics introduce 
> unavoidable overhead
...
> The attribute can only be applied to public declarations. This is because the 
> attribute only has an effect when the declaration is used from outside of the 
> module.

If your company name is not Apple, looking at how your code base using Swift is 
typically going to be deployed - it’s very often going to end up in a iOS or 
macOS app bundle. Those bundles are deployed as one unit.
Now, in our code base (I suspect similar to many other users of swift), we have 
various frameworks that are not frameworks for the purpose of providing a 
stable ABI but rather:
* A reusable unit with a somewhat stable API, that can be shared between apps 
and with the wider open source community
* A mechanism for namespacing

Now I understand that this use-case is deferred for a later separate 
discussion, but my point here is that the name and the semantics of this 
attribute should be somewhat “forward-compatilble” with this use-case. “ 
inlinable” does not sound appropriate, because we don’t want to “inline” (in 
the C/C++ meaning) declarations into each usage site.
Instead we want to compile the annotated parts of -all linked modules- as one 
unit. Basically, for those parts, the module name would just function like a 
C++ namespace - an input to the symbol name mangling, and then the whole thing 
could be whole-module-optimized together.

This touches upon another comment someone made previously in this discussion - 
that access level and compiler visibility should be separate concepts. Because 
not just public methods, also private methods should be subject to this. 

Jonas

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Joe Groff via swift-evolution
On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
 wrote:
> 
> The major question I have is “why yet another attribute”.  The thread about 
> exhaustive/extensible enums is similarly proposing introducing another 
> one-off way to be enums fragile, and this is directly related just for 
> function-like things.
> 
> I’d love to see rationale in the proposal for why you’re not taking this in 
> one of these directions:
> 
> 1) Why not another level of access control?  There is a reasonable argument 
> that what you’re doing is making something “more public than public” or that 
> you’re making the “body also public”.  I’m not strongly in favor of this 
> design approach, but if you agree, the doc should explain why you’re not in 
> favor of it.
> 
> 2) Why can’t we have a single Swift-wide concept that unifies all of the 
> resilience ideas under a single umbrella like “fragile” - which indicates 
> that the body of a declaration is knowable to clients?  There is a very 
> reasonable holistic design where “fragile public func” makes its body 
> inlinable, and “fragile enum” similarly makes the cases knowable to the 
> client (thus making exhaustive switching a possibility).  I am strongly in 
> favor of this approach.

I'm of two minds on this. So far, it has seemingly been the case that, for 
every kind of declaration, there's been exactly one resilience-related 
attribute, and with blurry enough vision you could say they're all really doing 
the same thing, "expose this declaration body directly to clients", which only 
makes sense as a concept for public API. If these properties hold, then sure, 
it might make sense to consider these all as one "extra-public" concept. On the 
other hand, we don't know yet whether these properties will hold in the long 
term as we're actively designing the facilities we need for ABI stability and 
resilience. From an incremental, iterative design perspective, I think it's 
wiser to keep them all separate attributes, even if it's a bit messy in the 
short term. Once the design stabilizes, we can look at whether it makes sense 
to fold related concepts together. It's easier to fold different things 
together after the fact then to try to separate things after they've been mixed 
together.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Joe Groff via swift-evolution


> On Oct 2, 2017, at 10:58 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> We have discussed adding a "versioned @inlinable" variant that preserves the 
>> public entry point for older clients, while making the declaration inlinable 
>> for newer clients. This will likely be a separate proposal and discussion.
>> 
> 5) It eliminates this complexity.

It wouldn't avoid the complexity, because we want the "non-ABI, 
always-emit-into-client" behavior for the standard library. For the 
soon-to-be-ABI-stable libraries where @inlinable even matters, such as the 
standard library and Apple SDK overlays, there's pretty much perfect overlap 
between things we want to inline and things we don't want to take up binary 
space and ABI surface in binaries, so the behavior Slava proposes seems like 
the right default. With these semantics, the only time an inlinable declaration 
needs an exported symbol is for backward deployment, and we're inevitably going 
to need "versioned" as a general backward deployment concept for other things.

-Joe

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Michael Gottesman via swift-evolution

> On Oct 3, 2017, at 12:28 AM, Andrew Trick via swift-evolution 
>  wrote:
> 
> 
> 
>> On Oct 2, 2017, at 11:20 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Oct 2, 2017, at 11:11 PM, Slava Pestov via swift-evolution 
>>> > wrote:
>>> 
 This semantic doesn’t make sense to me, and I think we need to change it.  
 I think we are better served with the semantics of “the body may be 
 inlined, but doesn’t have to.”
>>> 
>>> That is the effect it has today. The decision to inline or not is made by 
>>> the optimizer, and @inlinable doesn’t change anything here; it makes the 
>>> body available if the optimizer chooses to do so.
>> 
>> Also remember we have the @inline(never) attribute. It’s not underscored so 
>> I’m assuming it’s an “official” part of the language. And "@inline(never) 
>> @inlinable" is a perfectly valid combination — it serializes the SIL for the 
>> function body, and while inlining it is prohibited, it is still subject to 
>> specialization, function signature optimizations, etc.
>> 
>> Slava
> 
> FWIW, the @inlinable name has always confused me. Methods not marked 
> @inlinable are still internally inlinable. "Inlining" is already a term of 
> art with specific semantics in other languages, and even in Swift is it's own 
> thing to be controlled independently from resilience. The real issue I have 
> with the name is that it says nothing about resilience. I’ll never forget 
> that fragility is the opposite of resilience. I can't see how a @fragile 
> attribute would ever be misconstrued.

+1. This is exactly how I feel.

> 
> As for the various shades of fragility of data types, I don't see why that 
> can't be handled as qualifiers or additional optional attributes for expert 
> developers. It’s just a matter of picking a reasonable default.
> 
> -Andy
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Andrew Trick via swift-evolution


> On Oct 2, 2017, at 11:20 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> 
>> On Oct 2, 2017, at 11:11 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> 
>>> This semantic doesn’t make sense to me, and I think we need to change it.  
>>> I think we are better served with the semantics of “the body may be 
>>> inlined, but doesn’t have to.”
>> 
>> That is the effect it has today. The decision to inline or not is made by 
>> the optimizer, and @inlinable doesn’t change anything here; it makes the 
>> body available if the optimizer chooses to do so.
> 
> Also remember we have the @inline(never) attribute. It’s not underscored so 
> I’m assuming it’s an “official” part of the language. And "@inline(never) 
> @inlinable" is a perfectly valid combination — it serializes the SIL for the 
> function body, and while inlining it is prohibited, it is still subject to 
> specialization, function signature optimizations, etc.
> 
> Slava

FWIW, the @inlinable name has always confused me. Methods not marked @inlinable 
are still internally inlinable. "Inlining" is already a term of art with 
specific semantics in other languages, and even in Swift is it's own thing to 
be controlled independently from resilience. The real issue I have with the 
name is that it says nothing about resilience. I’ll never forget that fragility 
is the opposite of resilience. I can't see how a @fragile attribute would ever 
be misconstrued.

As for the various shades of fragility of data types, I don't see why that 
can't be handled as qualifiers or additional optional attributes for expert 
developers. It’s just a matter of picking a reasonable default.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution

> On Oct 2, 2017, at 10:57 PM, Chris Lattner  wrote:
> 
> 1) Why not another level of access control?  There is a reasonable argument 
> that what you’re doing is making something “more public than public” or that 
> you’re making the “body also public”.  I’m not strongly in favor of this 
> design approach, but if you agree, the doc should explain why you’re not in 
> favor of it.

Oh, I forgot to address this point. I’m against this because even though this 
proposal says inlinable requires public, it is really orthogonal to public, 
because eventually we will have something like the current @_versioned 
attribute, where internal (or even private, as some have suggested) functions 
can be “public ABI”. For example,

@_versioned func myInternalDetails() {
  // …
}

@inlinable
public func myPublicFunction() {
  myInternalDetails() // I can reference this from an inlinable function, but 
users can’t call it directly
}

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution

> On Oct 2, 2017, at 11:11 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
>> This semantic doesn’t make sense to me, and I think we need to change it.  I 
>> think we are better served with the semantics of “the body may be inlined, 
>> but doesn’t have to.”
> 
> That is the effect it has today. The decision to inline or not is made by the 
> optimizer, and @inlinable doesn’t change anything here; it makes the body 
> available if the optimizer chooses to do so.

Also remember we have the @inline(never) attribute. It’s not underscored so I’m 
assuming it’s an “official” part of the language. And "@inline(never) 
@inlinable" is a perfectly valid combination — it serializes the SIL for the 
function body, and while inlining it is prohibited, it is still subject to 
specialization, function signature optimizations, etc.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-03 Thread Slava Pestov via swift-evolution
Thanks for the review!

> On Oct 2, 2017, at 10:57 PM, Chris Lattner  wrote:
> 
> This is a great proposal, I’m a strong supporter, but have one question and 
> one strong push back:
> 
>> On Oct 2, 2017, at 1:31 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> Introduction
>> We propose introducing an @inlinable attribute which exports the body of a 
>> function as part of a module's interface, making it available to the 
>> optimizer when referenced from other modules.
>> 
> The major question I have is “why yet another attribute”.  The thread about 
> exhaustive/extensible enums is similarly proposing introducing another 
> one-off way to be enums fragile, and this is directly related just for 
> function-like things.
> 
> I’d love to see rationale in the proposal for why you’re not taking this in 
> one of these directions:
> 
> 1) Why not another level of access control?  There is a reasonable argument 
> that what you’re doing is making something “more public than public” or that 
> you’re making the “body also public”.  I’m not strongly in favor of this 
> design approach, but if you agree, the doc should explain why you’re not in 
> favor of it.
> 
> 2) Why can’t we have a single Swift-wide concept that unifies all of the 
> resilience ideas under a single umbrella like “fragile” - which indicates 
> that the body of a declaration is knowable to clients?  There is a very 
> reasonable holistic design where “fragile public func” makes its body 
> inlinable, and “fragile enum” similarly makes the cases knowable to the 
> client (thus making exhaustive switching a possibility).  I am strongly in 
> favor of this approach.  
> 
> 
> In any case, even if you’re opposed to these approaches, I’d love for the 
> “alternatives considered” section to indicate what the objection is.  I am 
> really very concerned that you’re causing a keyword/attribute explosion and 
> conceptual complexity by adding too many small things to individual parts of 
> the language.  We would ideally have a simple and holistic solution to 
> resilience.

I agree with that keyword/attribute explosion is a concern. We also plan on 
submitting a proposal to add a @fixedContents attribute for structs (currently 
implemented as @_fixed_layout) which enables more efficient access patterns in 
resilient code, for example direct access of stored properties, at the cost of 
preventing new stored properties from being added in a binary-compatible 
manner. So we would have ‘nonexhaustive’ enums, @fixedContents structs, and 
@inlinable functions/properties/initializers.

Perhaps it makes sense to have a single ‘fragile’ keyword replace 
@fixedContents and @inlinable. For enums, ‘nonexhaustive’ does “feel” a bit 
different, so perhaps it makes sense for it to be its own thing. From an 
implementation perspective it doesn’t really matter if we have multiple 
attributes or one, so of course I’d prefer to go with the approach that makes 
the most sense to people language design-wise.

> This semantic doesn’t make sense to me, and I think we need to change it.  I 
> think we are better served with the semantics of “the body may be inlined, 
> but doesn’t have to.”

That is the effect it has today. The decision to inline or not is made by the 
optimizer, and @inlinable doesn’t change anything here; it makes the body 
available if the optimizer chooses to do so.

> 2) there are lots of reasons why the compiler may not *want* to inline the 
> body of a declaration, including wanting fast debug builds, “optimizing for 
> size” builds, or cost heuristics that lead the compiler to believe that there 
> is no gain for inlining the body of a function in some context.

Right.

> 3) If the symbol is always guaranteed to be present, adding @inlinable is an 
> ABI preserving change.  I think that this is also really important because it 
> reflects a natural evolution of code: in R1 of a module’s public release, a 
> symbol my be public, but after numerous releases, it may be decided that it 
> is stable enough to make “inlinable”.
> 
> 4) Certain declarations *have* to be emitted anyway, e.g. an @inlinable open 
> method on a class can’t actually be inlined in most cases, because the call 
> is dynamicly dispatched.

Yes. The function is still emitted into the library, but the symbol does not 
have public linkage. If we make the change to give the attribute ‘always emit 
into client’ semantics, a client can still reference the function without 
inlining it, for whatever reason, either because it cannot be (you’re using the 
function as a value) or the optimizer decides that it is not profitable to 
inline it. However the client binary would have to emit its own copy of the 
function (again, with non-public linkage).

>> We have discussed adding a "versioned @inlinable" variant that preserves the 
>> public entry point for older clients, while making the declaration 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Chris Lattner via swift-evolution
This is a great proposal, I’m a strong supporter, but have one question and one 
strong push back:

> On Oct 2, 2017, at 1:31 PM, Slava Pestov via swift-evolution 
>  wrote:
> Introduction
> We propose introducing an @inlinable attribute which exports the body of a 
> function as part of a module's interface, making it available to the 
> optimizer when referenced from other modules.
> 
The major question I have is “why yet another attribute”.  The thread about 
exhaustive/extensible enums is similarly proposing introducing another one-off 
way to be enums fragile, and this is directly related just for function-like 
things.

I’d love to see rationale in the proposal for why you’re not taking this in one 
of these directions:

1) Why not another level of access control?  There is a reasonable argument 
that what you’re doing is making something “more public than public” or that 
you’re making the “body also public”.  I’m not strongly in favor of this design 
approach, but if you agree, the doc should explain why you’re not in favor of 
it.

2) Why can’t we have a single Swift-wide concept that unifies all of the 
resilience ideas under a single umbrella like “fragile” - which indicates that 
the body of a declaration is knowable to clients?  There is a very reasonable 
holistic design where “fragile public func” makes its body inlinable, and 
“fragile enum” similarly makes the cases knowable to the client (thus making 
exhaustive switching a possibility).  I am strongly in favor of this approach.  


In any case, even if you’re opposed to these approaches, I’d love for the 
“alternatives considered” section to indicate what the objection is.  I am 
really very concerned that you’re causing a keyword/attribute explosion and 
conceptual complexity by adding too many small things to individual parts of 
the language.  We would ideally have a simple and holistic solution to 
resilience.

> Effect on ABI stability
> 
> The introduction of the @inlinable attribute does not change the ABI of 
> existing declarations. However, adding @inlinable to an existing declaration 
> changes ABI, because the declaration will no longer have a public entry point 
> in the generated library. Removing @inlinable from an existing declaration 
> does not change ABI, because it merely introduces a new public symbol in the 
> generated library.
> 
This semantic doesn’t make sense to me, and I think we need to change it.  I 
think we are better served with the semantics of “the body may be inlined, but 
doesn’t have to.”  This corresponds to available_externally linkage in LLVM, 
 and is provided by GNU89 
"extern inline".

Here are 5 reasons:

1) the current spelling: "@inlinable” implies that the body “may” be inlined, 
not that it “must” be inlined.

2) there are lots of reasons why the compiler may not *want* to inline the body 
of a declaration, including wanting fast debug builds, “optimizing for size” 
builds, or cost heuristics that lead the compiler to believe that there is no 
gain for inlining the body of a function in some context.

3) If the symbol is always guaranteed to be present, adding @inlinable is an 
ABI preserving change.  I think that this is also really important because it 
reflects a natural evolution of code: in R1 of a module’s public release, a 
symbol my be public, but after numerous releases, it may be decided that it is 
stable enough to make “inlinable”.

4) Certain declarations *have* to be emitted anyway, e.g. an @inlinable open 
method on a class can’t actually be inlined in most cases, because the call is 
dynamicly dispatched.
> We have discussed adding a "versioned @inlinable" variant that preserves the 
> public entry point for older clients, while making the declaration inlinable 
> for newer clients. This will likely be a separate proposal and discussion.
> 
5) It eliminates this complexity.


> Comparison with other languages
> The closest language feature to the @inlinable attribute is found in C and 
> C++. In C and C++, the concept of a header file is similar to Swift's binary 
> swiftmodule files, except they are written by hand and not generated by the 
> compiler. Swift's public declarations are roughly analogous to declarations 
> whose prototypes appear in a header file.
> 
> Header files mostly contain declarations without bodies, but can also declare 
> static inlinefunctions with bodies. Such functions are not part of the binary 
> interface of the library, and are instead emitted into client code when 
> referenced. As with @inlinable declarations, static inlinefunctions can only 
> reference other "public" declarations, that is, those that are defined in 
> other header files.
> 
The writing should be clarified, because there are multiple concepts going on 
here, including GNU89’s notion of inline, C99’s notion of inline (aka extern 
inline), and static inline, each with overlapping but and confusingly 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Taylor Swift via swift-evolution
again, i should reiterate, most users aren’t compiler engineers and so most
people use access modifiers as a means of code organization. being able to
diagnose when a “private” symbol is being referenced from somewhere it
shouldn’t be is very important; the linking and mangling details should be
handled by the compiler underneath all of that.

On Mon, Oct 2, 2017 at 11:45 PM, Slava Pestov  wrote:

>
> On Oct 2, 2017, at 9:15 PM, Xiaodi Wu  wrote:
>
>
> On Mon, Oct 2, 2017 at 22:23 Slava Pestov  wrote:
>
>> On Oct 2, 2017, at 8:06 PM, Xiaodi Wu  wrote:
>>
>> On Mon, Oct 2, 2017 at 9:55 PM, Slava Pestov  wrote:
>>
>>>
>>> On Oct 2, 2017, at 7:52 PM, Kelvin Ma  wrote:
>>>
>>> Is this only a problem with fileprivate or does it extend to private
>>> members too? I feel like this would be a very valuable feature to support.
>>>
>>>
>>> Private members too. Consider this example,
>>>
>>> struct S {
>>>   private func f() {}
>>> }
>>>
>>> The member S.f mangles as _T06struct1SV1f33_
>>> AB643CAAAE0894CD0BC8584D7CA3AD23LLyyF. In this case, I suppose we won’t
>>> need the private discriminator because there can only be one S.f that’s
>>> directly a member of S, and not an extension. However imagine if two
>>> different source files both defined extensions of S, with a private member
>>> f. You would need to disambiguate them somehow.
>>>
>>
>> The simple-minded way to do this would be to require @_versioned
>> annotations on private and fileprivate members to supply an internally
>> unique alternative name to be used for mangling-as-though-internal (i.e.
>> `@_versioned(my_extension_f)`). Such a function becoming public in an
>> ABI-compatible way would require renaming the "actual" name to the unique
>> @_versioned name.
>>
>>
>> We have _silgen_name for that, but we really don’t want to expose this
>> more generally because people have been abusing it to make things visible
>> to C, and they should be using @_cdecl instead.
>>
>
> The difference here would be that the "@_versioned name" would be subject
> to mangling. It's essentially equivalent to a way of specifying a custom
> discriminator to be hashed so that the source file name is omitted and not
> ABI. Not that I think it'd be elegant, but it would not be abusable like
> _silgen_name.
>
>
> That wouldn’t solve the problem where removing @_versioned(name) and
> adding public would change the symbol’s name.
>
> However, your idea of mangling versioned private symbols like internal and
> diagnosing conflicts might be workable.
>
> Slava
>
>
>
>> A more elegant refinement could be to have @_versioned private and
>> fileprivate members mangled as though internal, erroring if two or more
>> members with the same name are both @_versioned--would that work?
>>
>>
>> If you’re going to do that what is the value in having the capability at
>> all?
>>
>
> Solely to have some way of preventing members in one file from calling
> members in another file at compile time.
>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution

> On Oct 2, 2017, at 9:15 PM, Xiaodi Wu  wrote:
> 
> 
> On Mon, Oct 2, 2017 at 22:23 Slava Pestov  > wrote:
>> On Oct 2, 2017, at 8:06 PM, Xiaodi Wu > > wrote:
>> 
>> On Mon, Oct 2, 2017 at 9:55 PM, Slava Pestov > > wrote:
>> 
>>> On Oct 2, 2017, at 7:52 PM, Kelvin Ma >> > wrote:
>>> 
>>> Is this only a problem with fileprivate or does it extend to private 
>>> members too? I feel like this would be a very valuable feature to support.
>> 
>> Private members too. Consider this example,
>> 
>> struct S {
>>   private func f() {}
>> }
>> 
>> The member S.f mangles as 
>> _T06struct1SV1f33_AB643CAAAE0894CD0BC8584D7CA3AD23LLyyF. In this case, I 
>> suppose we won’t need the private discriminator because there can only be 
>> one S.f that’s directly a member of S, and not an extension. However imagine 
>> if two different source files both defined extensions of S, with a private 
>> member f. You would need to disambiguate them somehow.
>> 
>> The simple-minded way to do this would be to require @_versioned annotations 
>> on private and fileprivate members to supply an internally unique 
>> alternative name to be used for mangling-as-though-internal (i.e. 
>> `@_versioned(my_extension_f)`). Such a function becoming public in an 
>> ABI-compatible way would require renaming the "actual" name to the unique 
>> @_versioned name.
> 
> We have _silgen_name for that, but we really don’t want to expose this more 
> generally because people have been abusing it to make things visible to C, 
> and they should be using @_cdecl instead.
> 
> The difference here would be that the "@_versioned name" would be subject to 
> mangling. It's essentially equivalent to a way of specifying a custom 
> discriminator to be hashed so that the source file name is omitted and not 
> ABI. Not that I think it'd be elegant, but it would not be abusable like 
> _silgen_name.

That wouldn’t solve the problem where removing @_versioned(name) and adding 
public would change the symbol’s name.

However, your idea of mangling versioned private symbols like internal and 
diagnosing conflicts might be workable.

Slava

> 
>> 
>> A more elegant refinement could be to have @_versioned private and 
>> fileprivate members mangled as though internal, erroring if two or more 
>> members with the same name are both @_versioned--would that work?
>> 
> 
> If you’re going to do that what is the value in having the capability at all?
> 
> Solely to have some way of preventing members in one file from calling 
> members in another file at compile time.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Xiaodi Wu via swift-evolution
On Mon, Oct 2, 2017 at 22:23 Slava Pestov  wrote:

> On Oct 2, 2017, at 8:06 PM, Xiaodi Wu  wrote:
>
> On Mon, Oct 2, 2017 at 9:55 PM, Slava Pestov  wrote:
>
>>
>> On Oct 2, 2017, at 7:52 PM, Kelvin Ma  wrote:
>>
>> Is this only a problem with fileprivate or does it extend to private
>> members too? I feel like this would be a very valuable feature to support.
>>
>>
>> Private members too. Consider this example,
>>
>> struct S {
>>   private func f() {}
>> }
>>
>> The member S.f mangles
>> as _T06struct1SV1f33_AB643CAAAE0894CD0BC8584D7CA3AD23LLyyF. In this case, I
>> suppose we won’t need the private discriminator because there can only be
>> one S.f that’s directly a member of S, and not an extension. However
>> imagine if two different source files both defined extensions of S, with a
>> private member f. You would need to disambiguate them somehow.
>>
>
> The simple-minded way to do this would be to require @_versioned
> annotations on private and fileprivate members to supply an internally
> unique alternative name to be used for mangling-as-though-internal (i.e.
> `@_versioned(my_extension_f)`). Such a function becoming public in an
> ABI-compatible way would require renaming the "actual" name to the unique
> @_versioned name.
>
>
> We have _silgen_name for that, but we really don’t want to expose this
> more generally because people have been abusing it to make things visible
> to C, and they should be using @_cdecl instead.
>

The difference here would be that the "@_versioned name" would be subject
to mangling. It's essentially equivalent to a way of specifying a custom
discriminator to be hashed so that the source file name is omitted and not
ABI. Not that I think it'd be elegant, but it would not be abusable like
_silgen_name.


> A more elegant refinement could be to have @_versioned private and
> fileprivate members mangled as though internal, erroring if two or more
> members with the same name are both @_versioned--would that work?
>
>
> If you’re going to do that what is the value in having the capability at
> all?
>

Solely to have some way of preventing members in one file from calling
members in another file at compile time.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution

> On Oct 2, 2017, at 8:06 PM, Xiaodi Wu  wrote:
> 
> On Mon, Oct 2, 2017 at 9:55 PM, Slava Pestov  > wrote:
> 
>> On Oct 2, 2017, at 7:52 PM, Kelvin Ma > > wrote:
>> 
>> Is this only a problem with fileprivate or does it extend to private members 
>> too? I feel like this would be a very valuable feature to support.
> 
> Private members too. Consider this example,
> 
> struct S {
>   private func f() {}
> }
> 
> The member S.f mangles as 
> _T06struct1SV1f33_AB643CAAAE0894CD0BC8584D7CA3AD23LLyyF. In this case, I 
> suppose we won’t need the private discriminator because there can only be one 
> S.f that’s directly a member of S, and not an extension. However imagine if 
> two different source files both defined extensions of S, with a private 
> member f. You would need to disambiguate them somehow.
> 
> The simple-minded way to do this would be to require @_versioned annotations 
> on private and fileprivate members to supply an internally unique alternative 
> name to be used for mangling-as-though-internal (i.e. 
> `@_versioned(my_extension_f)`). Such a function becoming public in an 
> ABI-compatible way would require renaming the "actual" name to the unique 
> @_versioned name.

We have _silgen_name for that, but we really don’t want to expose this more 
generally because people have been abusing it to make things visible to C, and 
they should be using @_cdecl instead.

> 
> A more elegant refinement could be to have @_versioned private and 
> fileprivate members mangled as though internal, erroring if two or more 
> members with the same name are both @_versioned--would that work?
> 

If you’re going to do that what is the value in having the capability at all?

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Xiaodi Wu via swift-evolution
On Mon, Oct 2, 2017 at 9:55 PM, Slava Pestov  wrote:

>
> On Oct 2, 2017, at 7:52 PM, Kelvin Ma  wrote:
>
> Is this only a problem with fileprivate or does it extend to private
> members too? I feel like this would be a very valuable feature to support.
>
>
> Private members too. Consider this example,
>
> struct S {
>   private func f() {}
> }
>
> The member S.f mangles as 
> _T06struct1SV1f33_AB643CAAAE0894CD0BC8584D7CA3AD23LLyyF.
> In this case, I suppose we won’t need the private discriminator because
> there can only be one S.f that’s directly a member of S, and not an
> extension. However imagine if two different source files both defined
> extensions of S, with a private member f. You would need to disambiguate
> them somehow.
>

The simple-minded way to do this would be to require @_versioned
annotations on private and fileprivate members to supply an internally
unique alternative name to be used for mangling-as-though-internal (i.e.
`@_versioned(my_extension_f)`). Such a function becoming public in an
ABI-compatible way would require renaming the "actual" name to the unique
@_versioned name.

A more elegant refinement could be to have @_versioned private and
fileprivate members mangled as though internal, erroring if two or more
members with the same name are both @_versioned--would that work?
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution

> On Oct 2, 2017, at 7:52 PM, Kelvin Ma  wrote:
> 
> Is this only a problem with fileprivate or does it extend to private members 
> too? I feel like this would be a very valuable feature to support.

Private members too. Consider this example,

struct S {
  private func f() {}
}

The member S.f mangles as 
_T06struct1SV1f33_AB643CAAAE0894CD0BC8584D7CA3AD23LLyyF. In this case, I 
suppose we won’t need the private discriminator because there can only be one 
S.f that’s directly a member of S, and not an extension. However imagine if two 
different source files both defined extensions of S, with a private member f. 
You would need to disambiguate them somehow.

Slava

> 
> On Mon, Oct 2, 2017 at 9:43 PM, Slava Pestov  > wrote:
> It would be a trivial change to allow @_versioned on private and fileprivate 
> declarations, but there are two pitfalls to keep in mind:
> 
> - Private symbols are mangled with a ‘discriminator’ which is basically a 
> hash of the file name. So now it would be part of the ABI, which seems 
> fragile — you can’t move the private function to another source file, or 
> rename the source file.
> 
> - Similarly, right now a @_versioned function becoming public is an ABI 
> compatible change. This would no longer work if you could have private 
> @_versioned functions, because the symbol name would change if it became 
> public.
> 
> For these reasons we decided against “private versioned” as a concept. I feel 
> like internal is enough here.
> 
> Slava
>  
>> On Oct 2, 2017, at 4:54 PM, Taylor Swift > > wrote:
>> 
>> Right now @_versioned is only for internal declarations. We should have 
>> something similar for private and fileprivate declarations. I think most 
>> people use those modifiers for code organization, not binary resilience, so 
>> we would do well to make the two intents separate and explicit.
>> 
>> On Mon, Oct 2, 2017 at 6:42 PM, Xiaodi Wu > > wrote:
>> 
>> On Mon, Oct 2, 2017 at 17:41 Taylor Swift > > wrote:
>> I think we should try to separate visibility from access control. In other 
>> words, the compiler should be able to see more than the user. I want to be 
>> able to write private and internal code that cannot be called explicitly in 
>> source, but can still be inlined by the compiler. Right now people are doing 
>> this with underscored methods and variable names but I don’t think that’s a 
>> good convention to use. We should have something at the language level that 
>> enforces that something shouldn’t be referenced by name outside of its 
>> scope, but is public for all compilation and ABI purposes. Maybe an 
>> attribute like @visible or a new keyword or something.
>> 
>> Right, that’s @_versioned, essentially.
>> 
>> 
>> On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> This is unduly restrictive; @_versioned (despite being the wrong spelling) 
>> is what we want here. To be callable from an inlinable function, internal 
>> things need only be visible in terms of public ABI, not necessarily 
>> inlinable, just as public things need only be public and not necessarily 
>> inlinable.
>> On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution 
>> > wrote:
>> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov > > wrote:
>> Thanks for taking a look!
>> 
>> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky 
>> > > > > wrote:
>> > 3. Even though @inlinable will have no effect on declarations which are 
>> > not public, we should still allow it to be placed there. That way when the 
>> > access level is later changed to be public, the attribute is already where 
>> > it should be. This is similar to why we permit, eg., members of an 
>> > internal type to be declared public, which was discussed and decided 
>> > previously on Swift Evolution.
>> 
>> This is an interesting point. Do you think the attribute should be 
>> completely ignored, or should the restrictions on references to non-public 
>> things, etc still be enforced?
>> 
>>  Hmm, good question!
>> 
>> I rather like the idea Greg Parker put forth, where non-public @inlinable 
>> items can be used by public @inlinable ones, which implies that the 
>> restrictions should indeed still apply—something @inlinable can only 
>> reference public or @inlinable things.
>> 
>> Nevin
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Kelvin Ma via swift-evolution
Is this only a problem with fileprivate or does it extend to private
members too? I feel like this would be a very valuable feature to support.

On Mon, Oct 2, 2017 at 9:43 PM, Slava Pestov  wrote:

> It would be a trivial change to allow @_versioned on private and
> fileprivate declarations, but there are two pitfalls to keep in mind:
>
> - Private symbols are mangled with a ‘discriminator’ which is basically a
> hash of the file name. So now it would be part of the ABI, which seems
> fragile — you can’t move the private function to another source file, or
> rename the source file.
>
> - Similarly, right now a @_versioned function becoming public is an ABI
> compatible change. This would no longer work if you could have private
> @_versioned functions, because the symbol name would change if it became
> public.
>
> For these reasons we decided against “private versioned” as a concept. I
> feel like internal is enough here.
>
> Slava
>
>
> On Oct 2, 2017, at 4:54 PM, Taylor Swift  wrote:
>
> Right now @_versioned is only for internal declarations. We should have
> something similar for private and fileprivate declarations. I think most
> people use those modifiers for code organization, not binary resilience, so
> we would do well to make the two intents separate and explicit.
>
> On Mon, Oct 2, 2017 at 6:42 PM, Xiaodi Wu  wrote:
>
>>
>> On Mon, Oct 2, 2017 at 17:41 Taylor Swift  wrote:
>>
>>> I think we should try to separate visibility from access control. In
>>> other words, the compiler should be able to see more than the user. I want
>>> to be able to write private and internal code that cannot be called
>>> explicitly in source, but can still be inlined by the compiler. Right now
>>> people are doing this with underscored methods and variable names but I
>>> don’t think that’s a good convention to use. We should have something at
>>> the language level that enforces that something shouldn’t be referenced by
>>> name outside of its scope, but is public for all compilation and ABI
>>> purposes. Maybe an attribute like @visible or a new keyword or something.
>>>
>>
>> Right, that’s @_versioned, essentially.
>>
>>
>> On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
 This is unduly restrictive; @_versioned (despite being the wrong
 spelling) is what we want here. To be callable from an inlinable function,
 internal things need only be visible in terms of public ABI, not
 necessarily inlinable, just as public things need only be public and not
 necessarily inlinable.
 On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via
 swift-evolution  wrote:

> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov 
> wrote:
>
>> Thanks for taking a look!
>>
>> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
>> nevin.brackettrozin...@gmail.com> wrote:
>> > 3. Even though @inlinable will have no effect on declarations which
>> are not public, we should still allow it to be placed there. That way 
>> when
>> the access level is later changed to be public, the attribute is already
>> where it should be. This is similar to why we permit, eg., members of an
>> internal type to be declared public, which was discussed and decided
>> previously on Swift Evolution.
>>
>> This is an interesting point. Do you think the attribute should be
>> completely ignored, or should the restrictions on references to 
>> non-public
>> things, etc still be enforced?
>>
>
>  Hmm, good question!
>
> I rather like the idea Greg Parker put forth, where non-public
> @inlinable items can be used by public @inlinable ones, which implies that
> the restrictions should indeed still apply—something @inlinable can only
> reference public or @inlinable things.
>
> Nevin
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution
It would be a trivial change to allow @_versioned on private and fileprivate 
declarations, but there are two pitfalls to keep in mind:

- Private symbols are mangled with a ‘discriminator’ which is basically a hash 
of the file name. So now it would be part of the ABI, which seems fragile — you 
can’t move the private function to another source file, or rename the source 
file.

- Similarly, right now a @_versioned function becoming public is an ABI 
compatible change. This would no longer work if you could have private 
@_versioned functions, because the symbol name would change if it became public.

For these reasons we decided against “private versioned” as a concept. I feel 
like internal is enough here.

Slava
 
> On Oct 2, 2017, at 4:54 PM, Taylor Swift  wrote:
> 
> Right now @_versioned is only for internal declarations. We should have 
> something similar for private and fileprivate declarations. I think most 
> people use those modifiers for code organization, not binary resilience, so 
> we would do well to make the two intents separate and explicit.
> 
> On Mon, Oct 2, 2017 at 6:42 PM, Xiaodi Wu  > wrote:
> 
> On Mon, Oct 2, 2017 at 17:41 Taylor Swift  > wrote:
> I think we should try to separate visibility from access control. In other 
> words, the compiler should be able to see more than the user. I want to be 
> able to write private and internal code that cannot be called explicitly in 
> source, but can still be inlined by the compiler. Right now people are doing 
> this with underscored methods and variable names but I don’t think that’s a 
> good convention to use. We should have something at the language level that 
> enforces that something shouldn’t be referenced by name outside of its scope, 
> but is public for all compilation and ABI purposes. Maybe an attribute like 
> @visible or a new keyword or something.
> 
> Right, that’s @_versioned, essentially.
> 
> 
> On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution 
> > wrote:
> This is unduly restrictive; @_versioned (despite being the wrong spelling) is 
> what we want here. To be callable from an inlinable function, internal things 
> need only be visible in terms of public ABI, not necessarily inlinable, just 
> as public things need only be public and not necessarily inlinable.
> On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution 
> > wrote:
> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  > wrote:
> Thanks for taking a look!
> 
> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky 
> >  > > wrote:
> > 3. Even though @inlinable will have no effect on declarations which are not 
> > public, we should still allow it to be placed there. That way when the 
> > access level is later changed to be public, the attribute is already where 
> > it should be. This is similar to why we permit, eg., members of an internal 
> > type to be declared public, which was discussed and decided previously on 
> > Swift Evolution.
> 
> This is an interesting point. Do you think the attribute should be completely 
> ignored, or should the restrictions on references to non-public things, etc 
> still be enforced?
> 
>  Hmm, good question!
> 
> I rather like the idea Greg Parker put forth, where non-public @inlinable 
> items can be used by public @inlinable ones, which implies that the 
> restrictions should indeed still apply—something @inlinable can only 
> reference public or @inlinable things.
> 
> Nevin
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Xiaodi Wu via swift-evolution
Sounds reasonable to me.


On Mon, Oct 2, 2017 at 18:54 Taylor Swift  wrote:

> Right now @_versioned is only for internal declarations. We should have
> something similar for private and fileprivate declarations. I think most
> people use those modifiers for code organization, not binary resilience, so
> we would do well to make the two intents separate and explicit.
>
> On Mon, Oct 2, 2017 at 6:42 PM, Xiaodi Wu  wrote:
>
>>
>> On Mon, Oct 2, 2017 at 17:41 Taylor Swift  wrote:
>>
>>> I think we should try to separate visibility from access control. In
>>> other words, the compiler should be able to see more than the user. I want
>>> to be able to write private and internal code that cannot be called
>>> explicitly in source, but can still be inlined by the compiler. Right now
>>> people are doing this with underscored methods and variable names but I
>>> don’t think that’s a good convention to use. We should have something at
>>> the language level that enforces that something shouldn’t be referenced by
>>> name outside of its scope, but is public for all compilation and ABI
>>> purposes. Maybe an attribute like @visible or a new keyword or something.
>>>
>>
>> Right, that’s @_versioned, essentially.
>>
>>
>> On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
 This is unduly restrictive; @_versioned (despite being the wrong
 spelling) is what we want here. To be callable from an inlinable function,
 internal things need only be visible in terms of public ABI, not
 necessarily inlinable, just as public things need only be public and not
 necessarily inlinable.
 On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via
 swift-evolution  wrote:

> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov 
> wrote:
>
>> Thanks for taking a look!
>>
>> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
>> nevin.brackettrozin...@gmail.com> wrote:
>> > 3. Even though @inlinable will have no effect on declarations which
>> are not public, we should still allow it to be placed there. That way 
>> when
>> the access level is later changed to be public, the attribute is already
>> where it should be. This is similar to why we permit, eg., members of an
>> internal type to be declared public, which was discussed and decided
>> previously on Swift Evolution.
>>
>> This is an interesting point. Do you think the attribute should be
>> completely ignored, or should the restrictions on references to 
>> non-public
>> things, etc still be enforced?
>>
>
>  Hmm, good question!
>
> I rather like the idea Greg Parker put forth, where non-public
> @inlinable items can be used by public @inlinable ones, which implies that
> the restrictions should indeed still apply—something @inlinable can only
> reference public or @inlinable things.
>
> Nevin
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Taylor Swift via swift-evolution
Right now @_versioned is only for internal declarations. We should have
something similar for private and fileprivate declarations. I think most
people use those modifiers for code organization, not binary resilience, so
we would do well to make the two intents separate and explicit.

On Mon, Oct 2, 2017 at 6:42 PM, Xiaodi Wu  wrote:

>
> On Mon, Oct 2, 2017 at 17:41 Taylor Swift  wrote:
>
>> I think we should try to separate visibility from access control. In
>> other words, the compiler should be able to see more than the user. I want
>> to be able to write private and internal code that cannot be called
>> explicitly in source, but can still be inlined by the compiler. Right now
>> people are doing this with underscored methods and variable names but I
>> don’t think that’s a good convention to use. We should have something at
>> the language level that enforces that something shouldn’t be referenced by
>> name outside of its scope, but is public for all compilation and ABI
>> purposes. Maybe an attribute like @visible or a new keyword or something.
>>
>
> Right, that’s @_versioned, essentially.
>
>
> On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> This is unduly restrictive; @_versioned (despite being the wrong
>>> spelling) is what we want here. To be callable from an inlinable function,
>>> internal things need only be visible in terms of public ABI, not
>>> necessarily inlinable, just as public things need only be public and not
>>> necessarily inlinable.
>>> On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution
>>>  wrote:
>>>
 On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  wrote:

> Thanks for taking a look!
>
> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
> nevin.brackettrozin...@gmail.com> wrote:
> > 3. Even though @inlinable will have no effect on declarations which
> are not public, we should still allow it to be placed there. That way when
> the access level is later changed to be public, the attribute is already
> where it should be. This is similar to why we permit, eg., members of an
> internal type to be declared public, which was discussed and decided
> previously on Swift Evolution.
>
> This is an interesting point. Do you think the attribute should be
> completely ignored, or should the restrictions on references to non-public
> things, etc still be enforced?
>

  Hmm, good question!

 I rather like the idea Greg Parker put forth, where non-public
 @inlinable items can be used by public @inlinable ones, which implies that
 the restrictions should indeed still apply—something @inlinable can only
 reference public or @inlinable things.

 Nevin
 ___
 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Xiaodi Wu via swift-evolution
On Mon, Oct 2, 2017 at 17:41 Taylor Swift  wrote:

> I think we should try to separate visibility from access control. In other
> words, the compiler should be able to see more than the user. I want to be
> able to write private and internal code that cannot be called explicitly in
> source, but can still be inlined by the compiler. Right now people are
> doing this with underscored methods and variable names but I don’t think
> that’s a good convention to use. We should have something at the language
> level that enforces that something shouldn’t be referenced by name outside
> of its scope, but is public for all compilation and ABI purposes. Maybe an
> attribute like @visible or a new keyword or something.
>

Right, that’s @_versioned, essentially.


On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> This is unduly restrictive; @_versioned (despite being the wrong
>> spelling) is what we want here. To be callable from an inlinable function,
>> internal things need only be visible in terms of public ABI, not
>> necessarily inlinable, just as public things need only be public and not
>> necessarily inlinable.
>> On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  wrote:
>>>
 Thanks for taking a look!

 > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
 nevin.brackettrozin...@gmail.com> wrote:
 > 3. Even though @inlinable will have no effect on declarations which
 are not public, we should still allow it to be placed there. That way when
 the access level is later changed to be public, the attribute is already
 where it should be. This is similar to why we permit, eg., members of an
 internal type to be declared public, which was discussed and decided
 previously on Swift Evolution.

 This is an interesting point. Do you think the attribute should be
 completely ignored, or should the restrictions on references to non-public
 things, etc still be enforced?

>>>
>>>  Hmm, good question!
>>>
>>> I rather like the idea Greg Parker put forth, where non-public
>>> @inlinable items can be used by public @inlinable ones, which implies that
>>> the restrictions should indeed still apply—something @inlinable can only
>>> reference public or @inlinable things.
>>>
>>> Nevin
>>> ___
>>> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Taylor Swift via swift-evolution
This is something I’ve been waiting for for a long time and I’m glad this
is finally becoming a reality. This is a big step forward for anyone
interested in seeing Swift get core “almost-stdlib” libraries.

On Mon, Oct 2, 2017 at 3:31 PM, Slava Pestov via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi all,
>
> Here is a draft proposal that makes public a feature we’ve had for a
> while. Let me know what you think!
>
> Cross-module inlining and specialization ("@inlinable")
>
>- Proposal: SE-
>- Authors: Slava Pestov , Jordan Rose
>
>- Review Manager: TBD
>- Status: *Initial pitch*
>- Implementation: Already implemented as an underscored attribute
>@_inlineable
>
> Introduction
>
> We propose introducing an @inlinable attribute which exports the body of
> a function as part of a module's interface, making it available to the
> optimizer when referenced from other modules.
> Motivation
>
> One of the top priorities of the Swift 5 release is a design and
> implementation of *the Swift ABI*. This effort consists of three major
> tasks:
>
>-
>
>Finalizing the low-level function calling convention, layout of data
>types, and various runtime data structures. The goal here is to maintain
>compatibility across compiler versions, ensuring that we can continue to
>make improvements to the Swift compiler without breaking binaries built
>with an older version of the compiler.
>-
>
>Implementing support for *library evolution*, or the ability to make
>certain source-compatible changes, without breaking binary compatibility.
>Examples of source-compatible changes we are considering include adding new
>stored properties to structs and classes, removing private stored
>properties from structs and classes, adding new public methods to a class,
>or adding new protocol requirements that have a default implementation. The
>goal here is to maintain compatibility across framework versions, ensuring
>that framework authors can evolve their API without breaking binaries built
>against an older version of the framework. For more information about the
>resilience model, see the library evolution document
> in
>the Swift repository.
>-
>
>Stabilizing the API of the standard library. The goal here is to
>ensure that the standard library can be deployed separately from client
>binaries and frameworks, without forcing recompilation of existing code.
>
> All existing language features of Swift were designed with these goals in
> mind. In particular, the implementation of generic types and functions
> relies on runtime reified types to allow separate compilation and type
> checking of generic code.
>
> Within the scope of a single module, the Swift compiler performs very
> aggressive optimization, including full and partial specialization of
> generic functions, inlining, and various forms of interprocedural analysis.
>
> On the other hand, across module boundaries, runtime generics introduce
> unavoidable overhead, as reified type metadata must be passed between
> functions, and various indirect access patterns must be used to manipulate
> values of generic type. We believe that for most applications, this
> overhead is negligible compared to the actual work performed by the code
> itself.
>
> However, for some advanced use cases, and in particular for the standard
> library, the overhead of runtime generics can dominate any useful work
> performed by the library. Examples include the various algorithms defined
> in protocol extensions of Sequence and Collection, for instance the mapmethod
> of the Sequence protocol. Here the algorithm is very simple and spends
> most of its time manipulating generic values and calling to a user-supplied
> closure; specialization and inlining can completely eliminate the algorithm
> of the higher-order function call and generate equivalent code to a
> hand-written loop manipulating concrete types.
>
> We would like to annotate such functions with the @inlinable attribute.
> This will make their bodies available to the optimizer when building client
> code; on the other hand, calling such a function will cause it to be
> emitted into the client binary, meaning that if a library were to change
> the definition of such a function, only binaries built against the newer
> version of library will use the new definition.
> Proposed solution
>
> The @inlinable attribute causes the body of a function to be emitted as
> part of the module interface. For example, a framework can define a rather
> impractical implementation of an algorithm which returns true if all
> elements of a sequence are equal or if the sequence is empty, and false
> otherwise:
>
> @inlinable public func allEqual(_ seq: T) -> Bool
> where T : Sequence, T.Element : Equatable 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Taylor Swift via swift-evolution
I think we should try to separate visibility from access control. In other
words, the compiler should be able to see more than the user. I want to be
able to write private and internal code that cannot be called explicitly in
source, but can still be inlined by the compiler. Right now people are
doing this with underscored methods and variable names but I don’t think
that’s a good convention to use. We should have something at the language
level that enforces that something shouldn’t be referenced by name outside
of its scope, but is public for all compilation and ABI purposes. Maybe an
attribute like @visible or a new keyword or something.

On Mon, Oct 2, 2017 at 4:45 PM, Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

> This is unduly restrictive; @_versioned (despite being the wrong spelling)
> is what we want here. To be callable from an inlinable function, internal
> things need only be visible in terms of public ABI, not necessarily
> inlinable, just as public things need only be public and not necessarily
> inlinable.
> On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  wrote:
>>
>>> Thanks for taking a look!
>>>
>>> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
>>> nevin.brackettrozin...@gmail.com> wrote:
>>> > 3. Even though @inlinable will have no effect on declarations which
>>> are not public, we should still allow it to be placed there. That way when
>>> the access level is later changed to be public, the attribute is already
>>> where it should be. This is similar to why we permit, eg., members of an
>>> internal type to be declared public, which was discussed and decided
>>> previously on Swift Evolution.
>>>
>>> This is an interesting point. Do you think the attribute should be
>>> completely ignored, or should the restrictions on references to non-public
>>> things, etc still be enforced?
>>>
>>
>>  Hmm, good question!
>>
>> I rather like the idea Greg Parker put forth, where non-public @inlinable
>> items can be used by public @inlinable ones, which implies that the
>> restrictions should indeed still apply—something @inlinable can only
>> reference public or @inlinable things.
>>
>> Nevin
>> ___
>> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Xiaodi Wu via swift-evolution
This is unduly restrictive; @_versioned (despite being the wrong spelling)
is what we want here. To be callable from an inlinable function, internal
things need only be visible in terms of public ABI, not necessarily
inlinable, just as public things need only be public and not necessarily
inlinable.
On Mon, Oct 2, 2017 at 16:37 Nevin Brackett-Rozinsky via swift-evolution <
swift-evolution@swift.org> wrote:

> On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  wrote:
>
>> Thanks for taking a look!
>>
>> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
>> nevin.brackettrozin...@gmail.com> wrote:
>> > 3. Even though @inlinable will have no effect on declarations which are
>> not public, we should still allow it to be placed there. That way when the
>> access level is later changed to be public, the attribute is already where
>> it should be. This is similar to why we permit, eg., members of an internal
>> type to be declared public, which was discussed and decided previously on
>> Swift Evolution.
>>
>> This is an interesting point. Do you think the attribute should be
>> completely ignored, or should the restrictions on references to non-public
>> things, etc still be enforced?
>>
>
>  Hmm, good question!
>
> I rather like the idea Greg Parker put forth, where non-public @inlinable
> items can be used by public @inlinable ones, which implies that the
> restrictions should indeed still apply—something @inlinable can only
> reference public or @inlinable things.
>
> Nevin
> ___
> 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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Nevin Brackett-Rozinsky via swift-evolution
On Mon, Oct 2, 2017 at 5:21 PM, Slava Pestov  wrote:

> Thanks for taking a look!
>
> > On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky <
> nevin.brackettrozin...@gmail.com> wrote:
> > 3. Even though @inlinable will have no effect on declarations which are
> not public, we should still allow it to be placed there. That way when the
> access level is later changed to be public, the attribute is already where
> it should be. This is similar to why we permit, eg., members of an internal
> type to be declared public, which was discussed and decided previously on
> Swift Evolution.
>
> This is an interesting point. Do you think the attribute should be
> completely ignored, or should the restrictions on references to non-public
> things, etc still be enforced?
>

 Hmm, good question!

I rather like the idea Greg Parker put forth, where non-public @inlinable
items can be used by public @inlinable ones, which implies that the
restrictions should indeed still apply—something @inlinable can only
reference public or @inlinable things.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution

> On Oct 2, 2017, at 2:20 PM, Greg Parker  wrote:
> 
> 
>> On Oct 2, 2017, at 1:31 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> inlinable declarations can only reference other public declarations. This is 
>> because they can be emitted into the client binary, and are therefore 
>> limited to referencing symbols that the client binary can reference.
>> 
> 
> Private @inlinable functions are useful. For example, you might want a helper 
> function to be inlined into a public @inlinable function for performance, but 
> you don't want that helper function to be called by outside clients directly. 
> 
> The restriction would then be "inlinable declarations can only reference 
> other public declarations and other @inlinable non-public declarations". This 
> relaxation would have no affect on ABI: only @inlinable things could be 
> inlined, and only public things could be ultimately referenced by inlined 
> things. 
> 
> Having said that, it should be fine to use "public @inlinable only" for now 
> and consider relaxing the restriction later.

That’s what @_versioned is currently for. You can define a function as 
@_versioned @_inlineable and reference it from other public inlinable 
functions, without making it visible to AST-level lookup.

While I would prefer to punt formalizing  this to a future proposal, we can 
still design the correct spelling and behavior of @_versioned here (I’m pretty 
sure the current attribute isn’t it).

Slava

> 
> 
> -- 
> Greg Parker gpar...@apple.com  Runtime 
> Wrangler
> 
> 

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution
Thanks for taking a look!

> On Oct 2, 2017, at 2:19 PM, Nevin Brackett-Rozinsky 
>  wrote:
> 
> I am hugely in favor of an @inlinable attribute, and I look forward to its 
> arrival with relish!
> 
> Some feedback:
> 
> 1. I think “inlinable” is the right spelling: it indicates that something is 
> *able* to be inlined.

Yeah, it seems this is the spelling we’re going to go with.

> 
> 2. If I want to pass an @inlinable function as an argument (say, to map or 
> filter) can I do so directly or must I use a closure which calls the 
> inlinable function?

You can pass it directly. From the viewpoint of code that uses an inlinable 
function, it behaves exactly the same as one that does not have the attribute.

> 3. Even though @inlinable will have no effect on declarations which are not 
> public, we should still allow it to be placed there. That way when the access 
> level is later changed to be public, the attribute is already where it should 
> be. This is similar to why we permit, eg., members of an internal type to be 
> declared public, which was discussed and decided previously on Swift 
> Evolution.

This is an interesting point. Do you think the attribute should be completely 
ignored, or should the restrictions on references to non-public things, etc 
still be enforced?

Slava

> 
> Other than that the proposal looks great, thanks for writing it up.
> 
> Nevin

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Greg Parker via swift-evolution

> On Oct 2, 2017, at 1:31 PM, Slava Pestov via swift-evolution 
>  wrote:
> inlinable declarations can only reference other public declarations. This is 
> because they can be emitted into the client binary, and are therefore limited 
> to referencing symbols that the client binary can reference.
> 

Private @inlinable functions are useful. For example, you might want a helper 
function to be inlined into a public @inlinable function for performance, but 
you don't want that helper function to be called by outside clients directly. 

The restriction would then be "inlinable declarations can only reference other 
public declarations and other @inlinable non-public declarations". This 
relaxation would have no affect on ABI: only @inlinable things could be 
inlined, and only public things could be ultimately referenced by inlined 
things. 

Having said that, it should be fine to use "public @inlinable only" for now and 
consider relaxing the restriction later.


-- 
Greg Parker gpar...@apple.com  Runtime 
Wrangler


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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Nevin Brackett-Rozinsky via swift-evolution
I am hugely in favor of an @inlinable attribute, and I look forward to its
arrival with relish!

Some feedback:

1. I think “inlinable” is the right spelling: it indicates that something
is *able* to be inlined.

2. If I want to pass an @inlinable function as an argument (say, to map or
filter) can I do so directly or must I use a closure which calls the
inlinable function?

3. Even though @inlinable will have no effect on declarations which are not
public, we should still allow it to be placed there. That way when the
access level is later changed to be public, the attribute is already where
it should be. This is similar to why we permit, eg., members of an internal
type to be declared public, which was discussed and decided previously on
Swift Evolution.

Other than that the proposal looks great, thanks for writing it up.

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


Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Jordan Rose via swift-evolution
Today's @available can't be the thing that makes symbols public, since it's 
also used to affect the availability context for private symbols. The one 
described in the library evolution document is specifically about marking 
something available with respect to the current module. So we would want 
another spelling.

(But it definitely shouldn't be "_versioned", which doesn't mean anything if we 
don't have "versions".)

Jordan


> On Oct 2, 2017, at 13:47, Slava Pestov via swift-evolution 
>  wrote:
> 
> Thanks for taking a look.
> 
> @_versioned is not something we want to keep in the long term. The original 
> idea was to allow @available annotations to be put on internal declarations, 
> which would have the effect of giving their symbols public linkage. I think a 
> follow-up proposal could introduce this feature as well as “conditionally 
> available inlinable”, which I describe in document below. However if people 
> feel strongly we could roll both of them into this proposal, but it would 
> require some more implementation work.
> 
> Slava
> 
>> On Oct 2, 2017, at 1:44 PM, Xiaodi Wu > > wrote:
>> 
>> Very much looking forward to this. Any possibility of rolling in some 
>> version (ha) of @_versioned so that @inlinable functions can reference 
>> internal declarations?
>> 
>> 
>> On Mon, Oct 2, 2017 at 3:31 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> Hi all,
>> 
>> Here is a draft proposal that makes public a feature we’ve had for a while. 
>> Let me know what you think!
>> 
>> Cross-module inlining and specialization ("@inlinable")
>> Proposal: SE- <>
>> Authors: Slava Pestov , Jordan Rose 
>> 
>> Review Manager: TBD
>> Status: Initial pitch
>> Implementation: Already implemented as an underscored attribute @_inlineable
>> Introduction
>> We propose introducing an @inlinable attribute which exports the body of a 
>> function as part of a module's interface, making it available to the 
>> optimizer when referenced from other modules.
>> 
>> Motivation
>> One of the top priorities of the Swift 5 release is a design and 
>> implementation of the Swift ABI. This effort consists of three major tasks:
>> 
>> Finalizing the low-level function calling convention, layout of data types, 
>> and various runtime data structures. The goal here is to maintain 
>> compatibility across compiler versions, ensuring that we can continue to 
>> make improvements to the Swift compiler without breaking binaries built with 
>> an older version of the compiler.
>> 
>> Implementing support for library evolution, or the ability to make certain 
>> source-compatible changes, without breaking binary compatibility. Examples 
>> of source-compatible changes we are considering include adding new stored 
>> properties to structs and classes, removing private stored properties from 
>> structs and classes, adding new public methods to a class, or adding new 
>> protocol requirements that have a default implementation. The goal here is 
>> to maintain compatibility across framework versions, ensuring that framework 
>> authors can evolve their API without breaking binaries built against an 
>> older version of the framework. For more information about the resilience 
>> model, see the library evolution document 
>>  in 
>> the Swift repository.
>> 
>> Stabilizing the API of the standard library. The goal here is to ensure that 
>> the standard library can be deployed separately from client binaries and 
>> frameworks, without forcing recompilation of existing code.
>> 
>> All existing language features of Swift were designed with these goals in 
>> mind. In particular, the implementation of generic types and functions 
>> relies on runtime reified types to allow separate compilation and type 
>> checking of generic code.
>> 
>> Within the scope of a single module, the Swift compiler performs very 
>> aggressive optimization, including full and partial specialization of 
>> generic functions, inlining, and various forms of interprocedural analysis.
>> 
>> On the other hand, across module boundaries, runtime generics introduce 
>> unavoidable overhead, as reified type metadata must be passed between 
>> functions, and various indirect access patterns must be used to manipulate 
>> values of generic type. We believe that for most applications, this overhead 
>> is negligible compared to the actual work performed by the code itself.
>> 
>> However, for some advanced use cases, and in particular for the standard 
>> library, the overhead of runtime generics can dominate any useful work 
>> performed by the library. Examples include the various algorithms defined in 
>> protocol extensions of Sequence and Collection, for instance the mapmethod 
>> of 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution
Thanks for taking a look.

@_versioned is not something we want to keep in the long term. The original 
idea was to allow @available annotations to be put on internal declarations, 
which would have the effect of giving their symbols public linkage. I think a 
follow-up proposal could introduce this feature as well as “conditionally 
available inlinable”, which I describe in document below. However if people 
feel strongly we could roll both of them into this proposal, but it would 
require some more implementation work.

Slava

> On Oct 2, 2017, at 1:44 PM, Xiaodi Wu  wrote:
> 
> Very much looking forward to this. Any possibility of rolling in some version 
> (ha) of @_versioned so that @inlinable functions can reference internal 
> declarations?
> 
> 
> On Mon, Oct 2, 2017 at 3:31 PM, Slava Pestov via swift-evolution 
> > wrote:
> Hi all,
> 
> Here is a draft proposal that makes public a feature we’ve had for a while. 
> Let me know what you think!
> 
> Cross-module inlining and specialization ("@inlinable")
> Proposal: SE- <>
> Authors: Slava Pestov , Jordan Rose 
> 
> Review Manager: TBD
> Status: Initial pitch
> Implementation: Already implemented as an underscored attribute @_inlineable
> Introduction
> We propose introducing an @inlinable attribute which exports the body of a 
> function as part of a module's interface, making it available to the 
> optimizer when referenced from other modules.
> 
> Motivation
> One of the top priorities of the Swift 5 release is a design and 
> implementation of the Swift ABI. This effort consists of three major tasks:
> 
> Finalizing the low-level function calling convention, layout of data types, 
> and various runtime data structures. The goal here is to maintain 
> compatibility across compiler versions, ensuring that we can continue to make 
> improvements to the Swift compiler without breaking binaries built with an 
> older version of the compiler.
> 
> Implementing support for library evolution, or the ability to make certain 
> source-compatible changes, without breaking binary compatibility. Examples of 
> source-compatible changes we are considering include adding new stored 
> properties to structs and classes, removing private stored properties from 
> structs and classes, adding new public methods to a class, or adding new 
> protocol requirements that have a default implementation. The goal here is to 
> maintain compatibility across framework versions, ensuring that framework 
> authors can evolve their API without breaking binaries built against an older 
> version of the framework. For more information about the resilience model, 
> see the library evolution document 
>  in the 
> Swift repository.
> 
> Stabilizing the API of the standard library. The goal here is to ensure that 
> the standard library can be deployed separately from client binaries and 
> frameworks, without forcing recompilation of existing code.
> 
> All existing language features of Swift were designed with these goals in 
> mind. In particular, the implementation of generic types and functions relies 
> on runtime reified types to allow separate compilation and type checking of 
> generic code.
> 
> Within the scope of a single module, the Swift compiler performs very 
> aggressive optimization, including full and partial specialization of generic 
> functions, inlining, and various forms of interprocedural analysis.
> 
> On the other hand, across module boundaries, runtime generics introduce 
> unavoidable overhead, as reified type metadata must be passed between 
> functions, and various indirect access patterns must be used to manipulate 
> values of generic type. We believe that for most applications, this overhead 
> is negligible compared to the actual work performed by the code itself.
> 
> However, for some advanced use cases, and in particular for the standard 
> library, the overhead of runtime generics can dominate any useful work 
> performed by the library. Examples include the various algorithms defined in 
> protocol extensions of Sequence and Collection, for instance the mapmethod of 
> the Sequence protocol. Here the algorithm is very simple and spends most of 
> its time manipulating generic values and calling to a user-supplied closure; 
> specialization and inlining can completely eliminate the algorithm of the 
> higher-order function call and generate equivalent code to a hand-written 
> loop manipulating concrete types.
> 
> We would like to annotate such functions with the @inlinable attribute. This 
> will make their bodies available to the optimizer when building client code; 
> on the other hand, calling such a function will cause it to be emitted into 
> the client binary, meaning that if a library were to change the definition of 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Xiaodi Wu via swift-evolution
Very much looking forward to this. Any possibility of rolling in some
version (ha) of @_versioned so that @inlinable functions can reference
internal declarations?


On Mon, Oct 2, 2017 at 3:31 PM, Slava Pestov via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi all,
>
> Here is a draft proposal that makes public a feature we’ve had for a
> while. Let me know what you think!
>
> Cross-module inlining and specialization ("@inlinable")
>
>- Proposal: SE-
>- Authors: Slava Pestov , Jordan Rose
>
>- Review Manager: TBD
>- Status: *Initial pitch*
>- Implementation: Already implemented as an underscored attribute
>@_inlineable
>
> Introduction
>
> We propose introducing an @inlinable attribute which exports the body of
> a function as part of a module's interface, making it available to the
> optimizer when referenced from other modules.
> Motivation
>
> One of the top priorities of the Swift 5 release is a design and
> implementation of *the Swift ABI*. This effort consists of three major
> tasks:
>
>-
>
>Finalizing the low-level function calling convention, layout of data
>types, and various runtime data structures. The goal here is to maintain
>compatibility across compiler versions, ensuring that we can continue to
>make improvements to the Swift compiler without breaking binaries built
>with an older version of the compiler.
>-
>
>Implementing support for *library evolution*, or the ability to make
>certain source-compatible changes, without breaking binary compatibility.
>Examples of source-compatible changes we are considering include adding new
>stored properties to structs and classes, removing private stored
>properties from structs and classes, adding new public methods to a class,
>or adding new protocol requirements that have a default implementation. The
>goal here is to maintain compatibility across framework versions, ensuring
>that framework authors can evolve their API without breaking binaries built
>against an older version of the framework. For more information about the
>resilience model, see the library evolution document
> in
>the Swift repository.
>-
>
>Stabilizing the API of the standard library. The goal here is to
>ensure that the standard library can be deployed separately from client
>binaries and frameworks, without forcing recompilation of existing code.
>
> All existing language features of Swift were designed with these goals in
> mind. In particular, the implementation of generic types and functions
> relies on runtime reified types to allow separate compilation and type
> checking of generic code.
>
> Within the scope of a single module, the Swift compiler performs very
> aggressive optimization, including full and partial specialization of
> generic functions, inlining, and various forms of interprocedural analysis.
>
> On the other hand, across module boundaries, runtime generics introduce
> unavoidable overhead, as reified type metadata must be passed between
> functions, and various indirect access patterns must be used to manipulate
> values of generic type. We believe that for most applications, this
> overhead is negligible compared to the actual work performed by the code
> itself.
>
> However, for some advanced use cases, and in particular for the standard
> library, the overhead of runtime generics can dominate any useful work
> performed by the library. Examples include the various algorithms defined
> in protocol extensions of Sequence and Collection, for instance the mapmethod
> of the Sequence protocol. Here the algorithm is very simple and spends
> most of its time manipulating generic values and calling to a user-supplied
> closure; specialization and inlining can completely eliminate the algorithm
> of the higher-order function call and generate equivalent code to a
> hand-written loop manipulating concrete types.
>
> We would like to annotate such functions with the @inlinable attribute.
> This will make their bodies available to the optimizer when building client
> code; on the other hand, calling such a function will cause it to be
> emitted into the client binary, meaning that if a library were to change
> the definition of such a function, only binaries built against the newer
> version of library will use the new definition.
> Proposed solution
>
> The @inlinable attribute causes the body of a function to be emitted as
> part of the module interface. For example, a framework can define a rather
> impractical implementation of an algorithm which returns true if all
> elements of a sequence are equal or if the sequence is empty, and false
> otherwise:
>
> @inlinable public func allEqual(_ seq: T) -> Bool
> where T : Sequence, T.Element : Equatable {
>   var iter = seq.makeIterator()
>   

[swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-02 Thread Slava Pestov via swift-evolution
Hi all,

Here is a draft proposal that makes public a feature we’ve had for a while. Let 
me know what you think!

Cross-module inlining and specialization ("@inlinable")
Proposal: SE- 
Authors: Slava Pestov , Jordan Rose 

Review Manager: TBD
Status: Initial pitch
Implementation: Already implemented as an underscored attribute @_inlineable
Introduction
We propose introducing an @inlinable attribute which exports the body of a 
function as part of a module's interface, making it available to the optimizer 
when referenced from other modules.

Motivation
One of the top priorities of the Swift 5 release is a design and implementation 
of the Swift ABI. This effort consists of three major tasks:

Finalizing the low-level function calling convention, layout of data types, and 
various runtime data structures. The goal here is to maintain compatibility 
across compiler versions, ensuring that we can continue to make improvements to 
the Swift compiler without breaking binaries built with an older version of the 
compiler.

Implementing support for library evolution, or the ability to make certain 
source-compatible changes, without breaking binary compatibility. Examples of 
source-compatible changes we are considering include adding new stored 
properties to structs and classes, removing private stored properties from 
structs and classes, adding new public methods to a class, or adding new 
protocol requirements that have a default implementation. The goal here is to 
maintain compatibility across framework versions, ensuring that framework 
authors can evolve their API without breaking binaries built against an older 
version of the framework. For more information about the resilience model, see 
the library evolution document 
 in the 
Swift repository.

Stabilizing the API of the standard library. The goal here is to ensure that 
the standard library can be deployed separately from client binaries and 
frameworks, without forcing recompilation of existing code.

All existing language features of Swift were designed with these goals in mind. 
In particular, the implementation of generic types and functions relies on 
runtime reified types to allow separate compilation and type checking of 
generic code.

Within the scope of a single module, the Swift compiler performs very 
aggressive optimization, including full and partial specialization of generic 
functions, inlining, and various forms of interprocedural analysis.

On the other hand, across module boundaries, runtime generics introduce 
unavoidable overhead, as reified type metadata must be passed between 
functions, and various indirect access patterns must be used to manipulate 
values of generic type. We believe that for most applications, this overhead is 
negligible compared to the actual work performed by the code itself.

However, for some advanced use cases, and in particular for the standard 
library, the overhead of runtime generics can dominate any useful work 
performed by the library. Examples include the various algorithms defined in 
protocol extensions of Sequence and Collection, for instance the mapmethod of 
the Sequence protocol. Here the algorithm is very simple and spends most of its 
time manipulating generic values and calling to a user-supplied closure; 
specialization and inlining can completely eliminate the algorithm of the 
higher-order function call and generate equivalent code to a hand-written loop 
manipulating concrete types.

We would like to annotate such functions with the @inlinable attribute. This 
will make their bodies available to the optimizer when building client code; on 
the other hand, calling such a function will cause it to be emitted into the 
client binary, meaning that if a library were to change the definition of such 
a function, only binaries built against the newer version of library will use 
the new definition.

Proposed solution
The @inlinable attribute causes the body of a function to be emitted as part of 
the module interface. For example, a framework can define a rather impractical 
implementation of an algorithm which returns true if all elements of a sequence 
are equal or if the sequence is empty, and falseotherwise:

@inlinable public func allEqual(_ seq: T) -> Bool
where T : Sequence, T.Element : Equatable {
  var iter = seq.makeIterator()
  guard let first = iter.next() else { return true }

  func rec(_ iter: inout T.Iterator) -> Bool {
guard let next = iter.next() else { return true }
return next == first && rec()
  }

  return rec()
}
A client binary built against this framework can call allEqual() and enjoy a 
possible performance improvement when built with optimizations enabled, due to 
the elimination of abstraction overhead.

On the other hand, once the framework author comes to their senses and 
implements an iterative solution