Some of you will have seen my impassioned pleas on the synthesised 
Equatable/Hashable thread against implementing implicit synthesised behaviour 
on protocols that must, by necessity, make assumptions about a concrete type 
that could be incorrect.

For those that haven't, the concept of synthetic behaviour in discussion here 
is essentially any kind of default behaviour for a protocol that is 
automatically generated based upon the concrete type itself (rather than just 
what the protocol defines). Currently this refers to compiler magic as proposed 
for Codable, Equatable and Hashable, but also includes the reflection API and 
any future native macro support for Swift. Using any of these to implement 
default methods for protocols should IMO be made explicit to developers using 
any such protocol so that they can specifically opt-in to the behaviour only if 
they want to and understand what it does.

This proposal idea is essentially for a new attribute @synthetic (name is up 
for debate). This attribute is required for any default implementation that 
includes reflective type compiler magic, use of the reflection API against 
`self` or, in future, any native Swift macros within the method (possibly 
limited to specific features, will depend on the macro language and its 
capabilities). If a default method does not have this attribute, then the 
compiler will produce an error with the appropriate fix-it. For convenience 
this attribute can be applied to any extension block or even a protocol 
definition in order to mark all methods in that block/type as synthetic, though 
it's worth noting that doing so will prevent these default implementations from 
being provided if they don't actually need this attribute.

Basically the intention is that any protocol default implementation that 
requires more knowledge about the concrete type than merely what the protocol 
(and its parents) provide direct access to, must be marked as synthetic.

To use the synthetic behaviour of a protocol, developers must then use the 
@synthetic keyword when conforming to it, explicitly indicating that they want 
the extra behaviours rather than implementing the method(s) for themselves. To 
ignore the synthetic behaviour (and thus require some kind of manual 
implementation of methods as normal), simply omit the keyword:

        struct Foo : @synthetic Equatable { var someData:String }
                // Type fully conforms to Equatable using synthetic behaviour 
(equatable properties must be equal)
        struct Foo : Equatable { var someData:String }
                // Error due to unimplemented methods, but offers @synthetic as 
a fix-it if all unimplemented methods are @synthetic

It is possible that the attribute could be expanded to have parameters, 
allowing for synthetic conformance only on specific methods, but I'm unsure if 
that'd be the best way to do it, or how likely that is to be needed.

With this kind of explicit declaration it becomes obvious within code when a 
developer is specifically choosing to benefit from synthetic behaviour; this 
hopefully makes it more likely that a developer will fully consider what the 
implications of this may be, rather than doing it accidentally. The idea in 
part is to distinguish such types as having separate protocol and synthesised 
behaviour, where conformance without the @synthetic attribute specifically 
requires that all protocol requirements be met in full, and that any default 
behaviour is implemented only on the basis of the protocol itself, while adding 
@synthetic identifies that more invasive automated behaviour is 
permitted/requested.

At this stage I don't think there should be much of an impact for existing 
code; as far as I can tell it should only affect any protocols that happen to 
be using Mirror(reflecting: self) for some reason within a default 
implementation, which I can't imagine represents a huge subsection of existing 
code, and the fix is the simple addition of an attribute.


Anyway, this is basically just a rough dump of the ideas for how the 
synthesised Codable, Equatable and Hashable behaviours (and anything else 
anyone can think of) should be changed before Swift 4 is released. I'm hoping 
for feedback before I make a formal proposal as I don't have a lot of time at 
the moment, so am looking to do the more structured document once stuff has 
been hammered out a bit.

- Haravikk
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to