> 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

Reply via email to