to me at least, @retroactive
is one of the highest cost, lowest value features introduced with Swift 6. i can grasp the theoretical appeal of annotating every place where a conformance might not have the intended effect, but when you have a large code base with many dozens of packages, all authored by the same company, it just gets absurd.
consider the following protocol, which refines three other protocols, and has a bunch of retroactive conformances for types from an upstream package:
public protocol Storable: Serializable, Deserializable, CustomStringConvertible {}
you can’t just do this, because the compiler will complain that Storable
is already in the same module as the extensions:
extension Account: @retroactive Storable {}
extension Incident: @retroactive Storable {}
extension Incident.Update: @retroactive Storable {}
extension Instrument: @retroactive Storable {}
extension Instrument.Update: @retroactive Storable {}
extension MetadataEntry: @retroactive Storable {}
extension Order: @retroactive Storable {}
extension Order.Update: @retroactive Storable {}
extension ConnectivityState: @retroactive Storable {}
extension ProductGroup: @retroactive Storable {}
extension PublicOrder: @retroactive Storable {}
extension PublicTrade: @retroactive Storable {}
extension PublicTrade.Update: @retroactive Storable {}
extension StoredProperties: @retroactive Storable {}
extension StoredProperties.Update: @retroactive Storable {}
extension Tag: @retroactive Storable {}
extension Tag.Update: @retroactive Storable {}
extension TickRule: @retroactive Storable {}
extension TickRule.Update: @retroactive Storable {}
extension Transaction: @retroactive Storable {}
extension Transaction.Update: @retroactive Storable {}
extension OperationRejection: @retroactive Storable {}
extension User: @retroactive Storable {}
extension Plugin: @retroactive Storable {}
you also can’t do this, because @retroactive
doesn’t affect protocol compositions:
extension Account: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Incident: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Incident.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Instrument: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Instrument.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension MetadataEntry: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Order: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Order.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension ConnectivityState: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension ProductGroup: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension PublicOrder: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension PublicTrade: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension PublicTrade.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension StoredProperties: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension StoredProperties.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Tag: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Tag.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension TickRule: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension TickRule.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Transaction: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Transaction.Update: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension OperationRejection: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension User: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
extension Plugin: Storable, @retroactive (Serializable & Deserializable & CustomStringConvertible) {}
instead, you actually have to insert @retroactive
before every single upstream protocol that was refined by the local protocol:
extension Account: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Incident: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Incident.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Instrument: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Instrument.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension MetadataEntry: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Order: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Order.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension ConnectivityState: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension ProductGroup: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension PublicOrder: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension PublicTrade: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension PublicTrade.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension StoredProperties: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension StoredProperties.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Tag: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Tag.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension TickRule: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension TickRule.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Transaction: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Transaction.Update: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension OperationRejection: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension User: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
extension Plugin: Storable, @retroactive Serializable, @retroactive Deserializable, @retroactive CustomStringConvertible {}
what value is disallowing extension Foo: @retroactive Storable {}
actually bringing us?