Description
Description
A "generic protocol" P<T>
can be used in the declaration of (say) a property's type by resolving the type in angle brackets (and saying any
). But the compiler refuses to allow the composition (with &
) of two such resolved "generic protocols" in the same spot — even though such composition is legal in, say, a typealias.
Reproduction
Presuppose the following:
@MainActor
protocol P1<T>: AnyObject {
associatedtype T
func f1(_: T)
}
@MainActor
protocol P2<U>: AnyObject {
associatedtype U
func f2(_: U)
}
class MyClass {
var myP1Property: (any P1<Int>)? // ok
var myP2Property: (any P2<String>)? // ok
}
So far so good. Now I want to modify MyClass so that it has just one property whose type is one that adopts both P1<Int>
and P2<String
>. Intuitively I would expect to be able to say:
class MyClass {
var myP1P2Property: (any P1<Int> & P2<String>)? // error
}
But I can't. I get a compiler error about "Non-protocol, non-class type ... cannot be used within a protocol-constrained type."
Expected behavior
I would have expected the given code to compile. This expectation is supported by the following two workarounds:
- I can define a generic protocol conforming to the two given protocols, and use the name of that protocol in my type declaration, resolving both of the given "generics" in order:
@MainActor
protocol P1P2<T, U>: P1, P2 {}
class MyClass {
var myP1P2Property: (any P1P2<Int, String>)? // ok
}
- Alternatively, I can declare a typealias that includes the resolution of the two "generics":
class MyClass {
typealias P1IntP2String = P1<Int> & P2<String> // ok
var mySecondP1P2Property: (any P1IntP2String)? // ok
}
The typealias is, in my opinion, less flexible — but it illustrates the fact that the composition of resolved protocols is possible — which makes it all the weirder that I can't say the thing I originally wanted to say and perform the composition "inline" in the type declaration of the property.
Environment
swift-driver version: 1.115 Apple Swift version 6.0.2 (swiftlang-6.0.2.1.2 clang-1600.0.26.4)
Target: arm64-apple-macosx15.0
Xcode Version 16.1 (16B40)
Additional information
Just to be clear, there is absolutely no downright missing functionality here, since (as I have demonstrated) there are at least two workarounds. Nevertheless, the fact that I can't say the thing I intuitively want to say feels like a kind of hole in the language, perhaps an edge case caused by the intersection of the relatively recent notational innovations any
and P<T>
.