Skip to content

Commit 2c277fc

Browse files
committed
[Sema] Add test cases for odd behaviour of typealias on constrained protocol extensions
I stumbled across this rather weird and inconsistent behaviour of `typealias` declerations on protocol extensions and thought to document it in a test case to make sure we’re accidentally breaking source compatibility.
1 parent 38a8b00 commit 2c277fc

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// typealias on constrained extension
4+
5+
protocol ConstrainedTypealias {
6+
associatedtype MyAssocType
7+
}
8+
extension ConstrainedTypealias where MyAssocType == String { // expected-note {{requirement specified as 'Self.MyAssocType' == 'String' [with Self = Self]}} (from useConstrainedTypealiasInExtension)
9+
typealias Content = String
10+
}
11+
extension ConstrainedTypealias where MyAssocType == Int {
12+
func useConstrainedTypealiasInExtension() -> Content {} // expected-error {{'Self.Content' (aka 'String') requires the types 'Int' and 'String' be equivalent}}
13+
}
14+
func useTypealiasOnConstrainedExtension() -> ConstrainedTypealias.Content {}
15+
16+
// define different typealiases on differently constrained extensions
17+
18+
protocol DoubleOverloadedTypealias {
19+
associatedtype MyAssocType
20+
}
21+
extension DoubleOverloadedTypealias where MyAssocType == String { // expected-note {{requirement specified as 'Self.MyAssocType' == 'String' [with Self = Self]}} (from useDoubleOverloadedTypealiasInExtension)
22+
typealias Content = String // expected-note {{found candidate with type 'String'}} (from useDoubleOverloadedTypealias)
23+
}
24+
extension DoubleOverloadedTypealias where MyAssocType == Int {
25+
typealias Content = Int // expected-note {{found candidate with type 'Int'}} (from useDoubleOverloadedTypealias)
26+
func useDoubleOverloadedTypealiasInExtension() -> Content {} // expected-error {{'Self.Content' (aka 'String') requires the types 'Int' and 'String' be equivalent}}
27+
}
28+
func useDoubleOverloadedTypealias() -> DoubleOverloadedTypealias.Content {} // expected-error {{ambiguous type name 'Content' in 'DoubleOverloadedTypealias'}}
29+
30+
// define the same typealias on differently constrained extensions
31+
32+
protocol DoubleOverloadedSameTypealias {
33+
associatedtype MyAssocType
34+
}
35+
extension DoubleOverloadedSameTypealias where MyAssocType == String { // expected-note {{requirement specified as 'Self.MyAssocType' == 'String' [with Self = Self]}} (from useDoubleOverloadedSameTypealiasInExtension)
36+
typealias Content = Int
37+
}
38+
extension DoubleOverloadedSameTypealias where MyAssocType == Int {
39+
typealias Content = Int
40+
func useDoubleOverloadedSameTypealiasInExtension() -> Content {} // expected-error {{'Self.Content' (aka 'Int') requires the types 'Int' and 'String' be equivalent}}
41+
}
42+
func useDoubleOverloadedSameTypealias() -> DoubleOverloadedSameTypealias.Content {}
43+
44+
// Overload associatedtype with typealias (SR-8274)
45+
46+
protocol MarkerProtocol {}
47+
protocol ProtocolWithAssoctype {
48+
associatedtype MyAssocType // expected-note {{found this candidate}} (from useAssocTypeInExtension) expected-note {{found candidate with type 'Self.MyAssocType'}} (from useAssocTypeOutsideExtension)
49+
}
50+
extension ProtocolWithAssoctype where Self: MarkerProtocol {
51+
typealias MyAssocType = Int // expected-note {{found this candidate}} (from useAssocTypeInExtension) expected-note {{found candidate with type 'Int'}} (from useAssocTypeOutsideExtension)
52+
func useAssocTypeInExtension() -> MyAssocType {} // expected-error {{'MyAssocType' is ambiguous for type lookup in this context}}
53+
}
54+
func useAssocTypeOutsideExtension() -> ProtocolWithAssoctype.MyAssocType {} // expected-error {{ambiguous type name 'MyAssocType' in 'ProtocolWithAssoctype'}}

0 commit comments

Comments
 (0)