[swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums
rjmccall at apple.com
Mon Jan 1 00:40:16 CST 2018
> On Dec 31, 2017, at 1:21 PM, Cheyo Jimenez <cheyo at masters3d.com> wrote:
> On Dec 31, 2017, at 8:59 AM, Ben Rimmington via swift-evolution <swift-evolution at 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.
>> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution