> On Nov 5, 2016, at 2:44 AM, Karl via swift-evolution > <swift-evolution@swift.org> wrote: > >> >> On 2 Nov 2016, at 20:54, Slava Pestov <spes...@apple.com >> <mailto:spes...@apple.com>> wrote: >> >>> >>> On Nov 2, 2016, at 8:32 AM, Paul Cantrell <cantr...@pobox.com >>> <mailto:cantr...@pobox.com>> wrote: >>> >>> >>>> On Oct 24, 2016, at 4:43 PM, Slava Pestov <spes...@apple.com >>>> <mailto:spes...@apple.com>> wrote: >>>> >>>> >>>>> On Oct 24, 2016, at 8:12 AM, Paul Cantrell <cantr...@pobox.com >>>>> <mailto:cantr...@pobox.com>> wrote: >>>>> >>>>> >>>>>> On Oct 24, 2016, at 5:09 AM, Slava Pestov via swift-evolution >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@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 > <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@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution