> On Dec 31, 2017, at 1:21 PM, Cheyo Jimenez <ch...@masters3d.com> wrote:
> On Dec 31, 2017, at 8:59 AM, Ben Rimmington via swift-evolution 
> <swift-evolution@swift.org> wrote:
>>> On 21 Dec 2017, at 03:32, John McCall wrote:
>>>>> On Dec 20, 2017, at 10:16 PM, Brent Royal-Gordon wrote:
>>>>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek wrote:
>>>>>   • What is your evaluation of the proposal?
>>>> I am pleased with the broad strokes of this design. I have quibbles with 
>>>> three areas:
>>>> 1. The `@exhaustive` attribute may be confusing because the term doesn't 
>>>> suggest versioning. My best alternative suggestion is `@frozen`, which 
>>>> matches existing programming terminology: something that has been frozen 
>>>> will not be changed in the future.
>>> I rather like @frozen.  We could use that across language features, so that 
>>> we don't end up with a keyword per kind of declaration.
>> Could this also be used on functions to make them inlinable?
>> i.e. The body of the function has been frozen.
>> ```
>> @frozen
>> public func a()
>> @available(*, frozen)
>> public func b()
>> @available(swift, introduced: 4.1, frozen: 5.0)
>> public func c()
>> ```
> My understanding is that frozen / exhaustible is guaranteed by the compiler 
> while inlineable is more of a strong suggestion to the compiler. It would be 
> confusing to use the same word for both.

Well, this is both true, and false, and true again.

It's true that frozen/inlineable on a function leaves the choice of whether to 
actually perform inlining (or other interprocedural optimizations like 
specialization) up to the compiler, whereas the impact of frozen on a type has 
a direct and reliably-observable impact in the sense of lifting certain 
semantic restrictions.

But from another perspective, the meaning of the attribute to the implementor 
is the same in both cases: it means that the implementation is the same across 
versions.  frozen on a type means that the basic storage structure of the type 
won't change (i.e. it has exactly the same stored properties/cases), and frozen 
on a function means that the behavior of the function won't change.

But then again, while we can reliably check the correctness of frozen on a 
type, we can't really check that for a function.  We can check 
frozen-correctness on a type because we don't mind forbidding non-trivial 
changes to the storage structure: i.e. the set of stored properties/cases (and 
their types) have to remain exactly the same, meaning you can't even do 
"obviously equivalent" changes like combining two stored properties into a 
single property of tuple type.  But we don't want to be that strict with 
functions because we do want to allow some non-trivial differences: it's 
frequently possible to improve the implementation of a function without 
changing its behavior, and we don't want to make that impossible, but we also 
don't really want to get into the business of requiring library authors to 
prove the semantic equivalence of two different function bodies.  That means we 
just have to take implementors at their word that using the new function body 
instead of the old isn't too annoying a difference.  I know Joe Groff has 
proposed in the past that we use a somewhat different semantic model for 
inlineable functions, one that promises that we use the newest available 
functionality, and I think there's some merit to that.

To me, the important questions around keyword choice are:
  - whether the operations feel sufficiently different that using the same 
keyword is going to feel awkward;
  - whether we might be preventing useful expressiveness by using the same 
keyword (the thing that occurs to me is that having a separate attribute for 
inlineable might let us easily mass-annotate an extension, which seems like a 
common use-case); and
  - whether we can get community agreement about it, which might seem "meta", 
but sometimes one must pick one's battles.

swift-evolution mailing list

Reply via email to