[swift-evolution] Enums and Source Compatibility

Matthew Johnson matthew at anandabits.com
Mon Sep 18 16:59:18 CDT 2017



Sent from my iPad

> On Sep 17, 2017, at 5:02 PM, Jonathan Hull <jhull at gbis.com> wrote:
> 
> 
>> On Sep 17, 2017, at 7:55 AM, Matthew Johnson <matthew at anandabits.com> wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>>> On Sep 17, 2017, at 3:37 AM, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> I run into use cases like this all the time…
>>> 
>>> I think I would prefer to see those concrete cases in a subtype though:
>>> 
>>> 	enum DrinkSize {
>>> 		case small
>>> 		case medium
>>> 		case large
>>> 	}
>>> 
>>> 	enum SummerDrinkSize : DrinkSize {
>>> 		//Inherits DrinkSize’s cases
>>> 		case extraLarge
>>> 	}
>>> 
>>> Because it is a subtype, you could place a SummerDrinkSize anywhere you can put a DrinkSize.  As a result, all switches on it would need a default case to handle cases they hadn’t planned for. If you mark an enum with “final” then it can’t be extended and switches can be exhaustive.
>> 
>> You have the subtype relationship backwards here.  DrinkSize is a subtype of SummerDrinkSize.  All values of DrinkSize are also valid values of SummerDrinkSize but not vice versa.  For this reason, inheritance syntax doesn't make sense.  The syntax that makes more sense is some kind of case embedding syntax:
>> 
>> enum SummerDrinkSize {
>> 		cases DrinkSize
>> 		case extraLarge
>> }
> 
> I disagree.  I get that the shape of a DrinkSize would always fit in a SummerDrinkSize hole (ignoring the overriding/extension of methods), but the fact that we are requiring ‘default’ in switches changes the calculus.  Basically, it changed when we decided to change whether exhaustive was the default.  The point is to make people consider that they may have cases which they may not expect.  That is much easier with a concrete idea of subtype, which people are already used to.

Requiring developers to consider cases that may be added to an enum in the future is orthogonal to any potential subtype relationship between two value types.

> 
> 
>>> 
>>> In addition to inheriting the cases, a subtype would also inherit, and be able to override, methods defined on the super-type.  You could use super to call the super-type’s implementation. 
>> 
>> I think implementation sharing is a bad idea for value types.  Value subtyping should be conceptualized as a restricted mechanism for value-preserving implicit conversion.
> 
> Why?

First, this is how value subtyping already works in the case of Optional where `T` is a subtype of `T?`.

More generally, this approach is roughly analogous to implicit promotion in C-family languages.  We want `Int8` to be a subtype of `Int16`, `Int32`, `Int`, etc.

This approach allows a value type to have multiple value-preserving supertypes without the performance impact of dynamic dispatch or the complexity of multiple inheritance.

> 
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170918/16121ab7/attachment.html>


More information about the swift-evolution mailing list