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