[swift-evolution] [RFC] "Library Evolution Support in Swift ('Resilience')"
David Owens II
david at owensd.io
Wed Feb 10 15:23:03 CST 2016
> On Feb 10, 2016, at 1:03 PM, Jordan Rose <jordan_rose at apple.com> wrote:
>> On Feb 10, 2016, at 12:45, David Owens II <david at owensd.io <mailto:david at owensd.io>> wrote:
>>> On Feb 8, 2016, at 6:24 PM, Jordan Rose via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> This last point is a specific case of a general tenet of Swift: the default behavior is safe. Where possible, choices made when an entity is first published should not limit its evolution in the future.
>> Regarding this:
>>> Changing or removing a default value is permitted but discouraged; it may break or change the meaning of existing source code.
>> Maybe I'm being dense, but how is something with a caveat of "discouraged" and "it may break or change" in-line with "the default behavior is safe"? I've got no qualms with putting the default value in the client code; I actually think that is fine.
>> However, my concern is that you will have different behavior depending on if you simply drop in the updated binary vs recompile against the binary. Even worse if you have multiple components within your app that link against the library. If only one of those components is recompiled on release, you now have a problem of conflicting behavior within your own app because of the client-side calling the API will be using different values.
>> It would seem that removing the default value could be permitted (though maybe still discouraged) because this will result in a compiler error in the scenario above. It's still possible to have different behavior in your components, but now it's no longer implicitly happening. However, changing the default parameter seems highly problematic.
> This is a good point, and I think the "checker" tool described at the end of the document should warn about these kinds of changes as well. I was trying to distinguish between "changing this affects the ABI of your library and therefore breaks memory and type safety" and "changing this merely affects the behavior of your library but will not break memory and type safety", but maybe that's not such an important distinction.
I think the stated desire to use semantic versioning moves the conversation from strictly ABI and satisfying the compiler to the realm of attempting to create behavioral contracts. So when I see things that will have an impact on behavior too, I get a little concerned.
> It's important to note that "it may break or change the meaning of existing source code" is something that applies to any behavior change you make in a library; if version 2.0 of an opaque function 'foo' accesses global memory where it didn't before, existing clients may run into concurrency issues if they assumed the function was concurrency-safe. The specific twist for inlineable code (including default argument expressions) is that the change is triggered by recompiling the client, which is why any changes to inlineable code (including default argument expressions) should really preserve the existing contract of the API.
I agree. Any change to source is a potential breaking change even if the ABI is kept in-tact. This is one of the primary arguments against semantic versioning in the first place in that it's a contract that cannot actually be adhered to.
I think the document would be stronger if it simply stated up-front that you are *only* addressing the ABI compatibility (maybe it does but the semantic version carries a ton of baggage that counters that position). This allows you to have potential behavior breaking changes while not confusing the fact.
It would still be nice to be at least warned on changes that could have a compile-time vs. link-time difference.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution