> 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