[swift-evolution] [Pitch] Nested types in protocols (and nesting protocols in types)

T.J. Usiyan griotspeak at gmail.com
Tue Jan 17 18:15:06 CST 2017


+1 to all of that. The proposal in general and the import rule.

On Tue, Jan 17, 2017 at 7:07 PM, Douglas Gregor via swift-evolution <
swift-evolution at swift.org> wrote:

>
> On Nov 5, 2016, at 2:44 AM, Karl via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On 2 Nov 2016, at 20:54, Slava Pestov <spestov at apple.com> wrote:
>
>
> On Nov 2, 2016, at 8:32 AM, Paul Cantrell <cantrell at pobox.com> wrote:
>
>
> On Oct 24, 2016, at 4:43 PM, Slava Pestov <spestov at apple.com> wrote:
>
>
> On Oct 24, 2016, at 8:12 AM, Paul Cantrell <cantrell at pobox.com> wrote:
>
>
> On Oct 24, 2016, at 5:09 AM, Slava Pestov via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> However protocols nested inside types and types nested inside protocols is
> still not supported, because protocols introduce a separate series of
> issues involving associated types and the ’Self’ type.
>
> The hard part of getting nested generics right is what to do if a nested
> type ‘captures’ generic parameters of the outer type. For non-protocol
> types, the behavior here is pretty straightforward.
>
> If we allow protocols to be nested inside other types, we have to decide
> what to do if the protocol ‘closes over’ generic parameters of the outer
> type. For example,
>
> struct A<T> {
> protocol P {
> func requirement() -> T
> }
> }
>
> Presumably A<Int>.P and A<String>.P are distinct types, and A.P has a
> hidden associated type corresponding to the type parameter ’T’?
>
> The other case is problematic too — the nested type might refer to an
> associated type of the outer protocol:
>
> protocol P {
> associatedtype A
>
> struct T {
> var value: A
> }
> }
>
> Now writing P.T does not make sense, for the same reason that we cannot
> form an existential of type P.A. We could prohibit references to outer
> associated types of this form, or we could figure out some way to give it a
> meaning. If C is a concrete type conforming to P, then certainly C.T makes
> sense, for instance. Internally, the nested type A.T could have a hidden
> ‘Self’ generic type parameter, so that writing C.T is really the same as
> P.T<C>.
>
> Protocols nested inside protocols also have the same issue.
>
>
> FWIW, in almost all the situations where I’ve wanted to nest types inside
> protocols and generic types, it’s only as a namespacing convenience. Most
> often, it’s an enum type that’s used only by a single method, and having it
> at the top of the module namespace adds clutter.
>
> Here’s a real life example pared down. I wish I could do this:
>
> public struct ResponseContentTransformer<InputContentType,
> OutputContentType>: ResponseTransformer {
>
>   public init(onInputTypeMismatch mismatchAction: InputTypeMismatchAction
> = .error) {
>     ...
>   }
>
>   public enum InputTypeMismatchAction {  // Does not depend on generic
> types above
>     case error
>     case skip
>     case skipIfOutputTypeMatches
>   }
>
> }
>
> InputTypeMismatchAction is tightly associated with
> ResponseContentTransformer, and is confusing as a top-level type.
>
> What do you think about providing a “no captures” modifier for nested
> types — like static inner classes in Java? Then Swift could provide the
> namespace nesting I wish for this without having to resolve the trickier
> type capture questions yet.
>
> Alternatively, what if (1) outer types aren’t capture unless they’re
> referenced, and (2) nesting is only illegal if there’s a capture? Then my
> code above would compile, as would this:
>
> public struct S<T> {
>   public enum Foo {
>     case yin
>     case yang
>   }
> }
>
> …but this wouldn’t:
>
> public struct S<T> {
>   public enum Foo {
>     case yin(thing: T)  // capture of T illegal (for now)
>     case yang
>   }
> }
>
> Either of these approaches would allow hygienic namespacing now while
> leaving the door open to outer type capture in the future.
>
>
> Yeah, this makes sense for a first cut at this feature.
>
> Slava
>
>
> Should I take a crack at writing up a proposal for this? Now? After ABI
> work is done? (Probably the latter “OK if no captures” approach?) Eager to
> help; don’t want to be in the way.
>
>
> Just speaking for myself and not the whole team — I think you can submit
> the proposal at any time, we’re unlikely to get around to doing it, if you
> want to take a crack that would be great (again, with ‘no captures’ it’s
> “trivial”).
>
> Slava
>
>
> P
>
>
>
> Sorry, let this slip. Proposal sent - https://github.com/apple/
> swift-evolution/pull/552
>
>
> (Coming back to this after a very long time)
>
> One very high-level comment: one of your early examples is making the
> Delegate of a view. Did you consider making this an Objective-C translation
> rule as well, so that *Delegate and *DataSource protocols would be imported
> as nested types within a class with the name signified by *, e.g.,
>
> class UITableView {
>   @objc(UITableViewDataSource)
>   protocol DataSource { … }
>
>   @objc(UITableViewDelegate)
>   protocol Delegate { … }
> }
>
> - Doug
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170117/688907ea/attachment.html>


More information about the swift-evolution mailing list