Pitch: Protocols with private fields

Actually I'll side with @dabrahams and @xwu on that matter. Their example is indeed one way to implement my use case. Although QImpl has to be exposed, crucially, the implementation details brought by QImpl are not exposed by the conforming type.

The approach proposed in this pitch is to completely encapsulate an implementation from the outside. From the perspective of a type consumer, though, that's a distinction without a difference. Further, as suggested by @dabrahams, scoped conformance would allow a library to vend multiple implementations for the same protocol.

// In module A
protocol P {}
protocol PImplA: P { ... }
protocol PImplB: P { ... }

// In module B
struct S: P, private: PImplA { ... }
struct T: P, private: PImplB { ... }

Here, both B.S and B.T conform to A.P, but they use two different implementations defined in module A.

I disagree with @dabrahams on a couple of points though:

Scoped conformance have their own subtleties. For instance, dynamic dispatch resolution is a rather significant one. In particular, I am worried about that sentence:

The post ends with a handful of other difficult questions. Generally, it seems like dealing with multiple conformance and conformance inheritance will compel us to come up with new rules.

Although I don't claim such mechanisms cannot be designed or understood, having formalized and partially reimplemented Swift's current method resolution I'd argue that it's definitely not "simple".

My pitch does not challenge that assertion. A protocol would describe a single, well-understood API with the addition be that access levels would be part of that API.

While I adhere wholeheartedly to the principle of "economy of concept", I'd like to point out that the setup for implementing my use case with scoped conformance is more involved and feels a little like a "trick".

I'd be interested to discuss things the other way around. What use case solved by scoped conformance cannot be solved by access lower bounds?

1 Like