Newtype without automatic protocol forwarding

I would be quite perturbed if this solution were adopted. Access control should be completely orthogonal to any official forwarding mechanism intended to support composition (including the simple case of newtype). In fact, any such forwarding mechanism should be completely orthogonal to every aspect of the forwarder's interface aside from the part that is being forwarded. Using any protocol to drive forwarding would mean that newtype is translucent rather than opaque, thus violating encapsulation.

The fact that the enum sugar requires exposing rawValue and init(rawValue:) makes it unusable by a library which does not wish to expose rawValue or especially init(rawValue:). This has already caused me to grumble more than once, wishing I could saw public enum Foo: internal Int (or something like that) to derive the rawValue and init(rawValue:) without having to expose them outside a library. It obviously wouldn't be possible to synthesize a RawRepresentable conformance in this case, but synthesis of the members rawValue and init(rawValue:) members themselves would still be useful.

I also believe a forwarding mechanism should be completely orthogonal to every aspect of the forwardee's interface as well, except what is absolutely necessary to perform forwarding (as if it were written manually). This is why [Proposal Draft] automatic protocol forwarding did not require actual protocol conformance by the forwardee. It only required potential protocol conformance. This point was somewhat controversial but I believe is an important one. There are any number of reasons one may not wish to provide an actual conformance for the forwardee (mostly related to access control and dynamic casts).

This would not be an adequate solution IMO. The fact that a type is implemented as a newtype should be an implementation detail of a type, not part of its interface. What if I need to change the implementation later? Under this design that would be a breaking change making newtype a feature that is unavailable to library authors who care about preserving implementation flexibility.

Frankly, I don't see this feature adding much value over what we can already do unless it includes a forwarding mechanism that is able to properly preserve encapsulation of implementation details. If we're going to have such a mechanism, it should be much more general than newtype, supporting encapsulation-preserving composition in general. Of course newtype could be added as syntactic sugar on top of such a mechanism as it would be a very common use case.

In summary, I agree with @Douglas_Gregor that we should be focused on forwarding rather than rushing into adding a half-baked newtype feature that inherently leaks implementation details.

8 Likes