> On Aug 16, 2016, at 8:51 PM, Slava Pestov <[email protected]> wrote:
> 
> Here is why we must have that requirement. Consider the following code:
> 
> protocol P {
>   init()
> }
> 
> struct A : P {
>   init() {}
> }
> 
> struct B : P {
>   init() {}
> }
> 
> func makeIt<T : P>() -> T {
>   return T()
> }
> 
> I can use this function as follows:
> 
> let a: A = makeIt() // Creates a new ‘A'
> let a: B = makeIt() // Creates a new ‘B’
> 
> Now suppose we allow P to self-conform. Then the following becomes valid:
> 
> let p: P = makeIt()
> 
> What exactly would makeIt() do in this case? There’s no concrete type passed 
> in, or any way of getting one, so there’s nothing to construct. The same 
> issue would come up with static methods here.

Argh, that’s particularly frustrating since in something like ‘func foo<T : 
P>(t: T)’ or ‘func foo<S : Sequence>(s: S) where S.IteratorElement: P’, you’re 
only ever getting instances anyway since the parameter is in the input, so 
calling initializers or static functions isn’t something you can even do 
(unless you call .dynamicType, at which point you *do* have a concrete type at 
runtime thanks to the dynamic check).

I wish there were a way to have partial conformance in cases like these. Like 
how this causes what’s probably Swift’s most confusing compiler error 
(certainly one of its most asked about):

protocol P: Equatable {
    static func ==(l: Self, r: Self) -> Bool
    
    func foo()
}

struct S: P {
    static func ==(l: S, r: S) -> Bool {
        return true
    }
    
    func foo() {
        print("foo")
    }
}

let s = S()
let p = s as P // error: Protocol ‘P’ can only be used as a generic constraint 
because it has Self or associated type requirements

It would make using protocols so much less teeth-grinding if the compiler *did* 
allow you to type the variable as P, but then would just throw an error if you 
tried to call one of the “problem” methods (in this case, using the ‘==' 
operator would be an error, but calling ‘foo’ would be fine). If this were 
possible, the conformance for a variable typed P would just not pick up 
“illegal” things like initializers, and would also leave out conformance for 
things like 'makeIt()' above which return the generic parameter in the output, 
rather than the input, necessitating a concrete type. I’m probably dreaming, I 
know.

Actually, what I wish is that Swift had an equivalent of the 'id <P>’ type in 
Objective-C. That notation always stood for an instance of something that 
conformed to P, rather than "maybe P itself, and maybe something that conforms 
to it”. If we could do that, we could just pass sequences of 'id <P>’ (in 
whatever syntax we gave it in Swift) to a sequence where Element: P, and it’d 
work fine regardless of anything that prevented P from conforming to P.

Charles

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to