Skip to content

Commit e548366

Browse files
committed
[TypeChecker] Add tests for static member refs on protocol metatypes feature
1 parent 30f2557 commit e548366

File tree

3 files changed

+220
-4
lines changed

3 files changed

+220
-4
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7199,7 +7199,7 @@ bool InvalidMemberRefOnProtocolMetatype::diagnoseAsError() {
71997199
if (!overload)
72007200
return false;
72017201

7202-
auto resultTy = overload->openedType;
7202+
auto resultTy = resolveType(overload->openedType);
72037203
if (auto *fnType = resultTy->getAs<FunctionType>())
72047204
resultTy = fnType->getResult();
72057205

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5955,7 +5955,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
59555955
auto anchor = locator.getAnchor();
59565956

59575957
if ((isExpr<UnresolvedDotExpr>(anchor) ||
5958-
isExpr<UnresolvedMemberExpr>(anchor)) &&
5958+
isExpr<UnresolvedMemberExpr>(anchor) ||
5959+
isExpr<SubscriptExpr>(anchor)) &&
59595960
req->is<LocatorPathElt::TypeParameterRequirement>()) {
59605961
auto signature = path[path.size() - 2]
59615962
.castTo<LocatorPathElt::OpenedGeneric>()
@@ -6890,8 +6891,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
68906891

68916892
// If result is not a concrete type which could conform to the
68926893
// expected protocol, this method is only viable for diagnostics.
6893-
if (!(resultTy->is<NominalType>() || resultTy->is<BoundGenericType>()) ||
6894-
resultTy->isExistentialType()) {
6894+
if (resultTy->isExistentialType() || resultTy->is<AnyFunctionType>() ||
6895+
resultTy->is<TupleType>() || resultTy->is<AnyMetatypeType>()) {
68956896
result.addUnviable(
68966897
candidate,
68976898
MemberLookupResult::UR_InvalidStaticMemberOnProtocolMetatype);
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 5
2+
3+
protocol P {}
4+
5+
struct S : P {
6+
var other: S { S() }
7+
}
8+
9+
10+
struct G<T> : P {
11+
var other: G<T> { fatalError() }
12+
}
13+
14+
extension P {
15+
static var property: S { S() }
16+
17+
static var fnProp: () -> S {
18+
{ S() }
19+
}
20+
21+
static func method() -> S {
22+
return S()
23+
}
24+
25+
static func genericFn<T>(_: T) -> G<T> {
26+
return G<T>()
27+
}
28+
29+
static subscript(_: Int) -> S {
30+
get { S() }
31+
}
32+
33+
static subscript<T>(t t: T) -> G<T> {
34+
get { G<T>() }
35+
}
36+
}
37+
38+
_ = P.property // Ok
39+
_ = P.property.other // Ok
40+
_ = P.fnProp() // Ok
41+
_ = P.fnProp().other // Ok
42+
_ = P.method() // Ok
43+
_ = P.method().other // Ok
44+
_ = P.genericFn(42) // Ok
45+
_ = P.genericFn(42).other // Ok
46+
_ = P[42] // Ok
47+
_ = P[42].other // OK
48+
_ = P[t: 42] // Ok
49+
_ = P[t: 42].other // Ok
50+
51+
let _: S = P.property // Ok
52+
let _: S = P.property.other // Ok
53+
let _: S = P.fnProp() // Ok
54+
let _: S = P.fnProp().other // Ok
55+
let _: S = P.method() // Ok
56+
let _: S = P.method().other // Ok
57+
let _: G<Int> = P.genericFn(42) // Ok
58+
let _: G = P.genericFn(42) // Ok
59+
let _: G<String> = P.genericFn(42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
60+
let _: G<Int> = P.genericFn(42).other // Ok
61+
let _: G<String> = P.genericFn(42).other // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
62+
let _: S = P[42] // Ok
63+
let _: S = P[42].other // OK
64+
let _: G<Int> = P[t: 42] // Ok
65+
let _: G = P[t: 42] // Ok
66+
let _: G<String> = P[t: 42] // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
67+
let _: G<Int> = P[t: 42].other // Ok
68+
let _: G<String> = P[t: 42].other // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
69+
70+
func test<T: P>(_: T) {}
71+
72+
test(.property) // Ok, base is inferred as Style.Type
73+
test(.property.other) // Ok
74+
test(.fnProp()) // Ok
75+
test(.fnProp().other) // Ok
76+
test(.method()) // Ok, static method call on the metatype
77+
test(.method().other) // Ok
78+
test(.genericFn(42)) // Ok
79+
test(.genericFn(42).other) // Ok
80+
81+
protocol Q {}
82+
83+
func test_combo<T: P & Q>(_: T) {} // expected-note 2 {{where 'T' = 'G<Int>'}}
84+
85+
extension Q {
86+
static var otherProperty: S { S() }
87+
88+
static func otherMethod() -> S {
89+
return S()
90+
}
91+
92+
static func otherGeneric<T>(_: T) -> S {
93+
return S()
94+
}
95+
}
96+
97+
extension S : Q {
98+
}
99+
100+
test_combo(.property) // Ok
101+
test_combo(.method()) // Ok
102+
test_combo(.otherProperty) // Ok
103+
test_combo(.otherProperty.other) // Ok
104+
test_combo(.otherProperty.property) // expected-error {{static member 'property' cannot be used on instance of type 'S'}}
105+
test_combo(.otherMethod()) // Ok
106+
test_combo(.otherMethod().method()) // expected-error {{static member 'method' cannot be used on instance of type 'S'}}
107+
test_combo(.otherGeneric(42)) // Ok
108+
109+
test_combo(.genericFn(42)) // expected-error {{global function 'test_combo' requires that 'G<Int>' conform to 'Q'}}
110+
111+
/* Invalid result types */
112+
113+
extension P {
114+
static var invalidProp: Int { 42 } // expected-note 5 {{'invalidProp' declared here}}
115+
static var selfProp: Self { fatalError() }
116+
static func invalidMethod() -> Int { 42 } // expected-note 5 {{'invalidMethod()' declared here}}
117+
static func generic<T>(_: T) -> T { fatalError() } // expected-note 5 {{'generic' declared here}}
118+
static func genericWithReqs<T: Collection, Q>(_: T) -> Q where T.Element == Q { // expected-note 3 {{'genericWithReqs' declared here}} expected-note 3 {{required by static method 'genericWithReqs' where 'T' = '()'}}
119+
fatalError()
120+
}
121+
122+
static subscript(q q: String) -> Int { get { 42 } } // expected-note 2 {{'subscript(q:)' declared here}}
123+
}
124+
125+
_ = P.doesntExist // expected-error {{type 'P' has no member 'doesntExist'}}
126+
_ = P.selfProp // expected-error {{generic parameter 'Self' could not be inferred}}
127+
_ = P.invalidProp
128+
// expected-error@-1 {{cannot reference static property 'invalidProp' on 'P.Protocol' with non-conforming result type 'Int'}}
129+
_ = P.invalidProp.other
130+
// expected-error@-1 {{cannot reference static property 'invalidProp' on 'P.Protocol' with non-conforming result type 'Int'}}
131+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
132+
_ = P.invalidMethod()
133+
// expected-error@-1 {{cannot reference static method 'invalidMethod()' on 'P.Protocol' with non-conforming result type 'Int'}}
134+
_ = P.invalidMethod().other
135+
// expected-error@-1 {{cannot reference static method 'invalidMethod()' on 'P.Protocol' with non-conforming result type 'Int'}}
136+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
137+
_ = P.generic(42)
138+
// expected-error@-1 {{cannot reference static method 'generic' on 'P.Protocol' with non-conforming result type 'Int'}}
139+
_ = P.generic(42).other
140+
// expected-error@-1 {{cannot reference static method 'generic' on 'P.Protocol' with non-conforming result type 'Int'}}
141+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
142+
_ = P.generic(S()) // Ok
143+
_ = P.generic(S()).other // Ok
144+
_ = P.generic(G<Int>()) // Ok
145+
_ = P.genericWithReqs([S()]) // Ok
146+
_ = P.genericWithReqs([42])
147+
// expected-error@-1 {{cannot reference static method 'genericWithReqs' on 'P.Protocol' with non-conforming result type 'Int'}}
148+
_ = P.genericWithReqs(())
149+
// expected-error@-1 {{type '()' cannot conform to 'Collection'}} expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
150+
// expected-error@-2 {{generic parameter 'Self' could not be inferred}}
151+
_ = P[q: ""]
152+
// expected-error@-1 {{cannot reference static subscript 'subscript(q:)' on 'P.Protocol' with non-conforming result type 'Int'}}
153+
_ = P[q: ""].other
154+
// expected-error@-1 {{cannot reference static subscript 'subscript(q:)' on 'P.Protocol' with non-conforming result type 'Int'}}
155+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
156+
157+
test(.doesntExist) // expected-error {{type 'P' has no member 'doesntExist'}}
158+
test(.doesnt.exist()) // expected-error {{type 'P' has no member 'doesnt'}}
159+
test(.invalidProp)
160+
// expected-error@-1 {{cannot reference static property 'invalidProp' on 'P.Protocol' with non-conforming result type 'Int'}}
161+
test(.invalidProp.other)
162+
// expected-error@-1 {{cannot reference static property 'invalidProp' on 'P.Protocol' with non-conforming result type 'Int'}}
163+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
164+
test(.invalidMethod())
165+
// expected-error@-1 {{cannot reference static method 'invalidMethod()' on 'P.Protocol' with non-conforming result type 'Int'}}
166+
test(.invalidMethod().other)
167+
// expected-error@-1 {{cannot reference static method 'invalidMethod()' on 'P.Protocol' with non-conforming result type 'Int'}}
168+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
169+
test(.generic(42))
170+
// expected-error@-1 {{cannot reference static method 'generic' on 'P.Protocol' with non-conforming result type 'Int'}}
171+
test(.generic(42).other)
172+
// expected-error@-1 {{cannot reference static method 'generic' on 'P.Protocol' with non-conforming result type 'Int'}}
173+
// expected-error@-2 {{value of type 'Int' has no member 'other'}}
174+
test(.generic(S())) // Ok
175+
test(.generic(G<Int>())) // Ok
176+
test(.genericWithReqs([S()])) // Ok
177+
test(.genericWithReqs([42]))
178+
// expected-error@-1 {{cannot reference static method 'genericWithReqs' on 'P.Protocol' with non-conforming result type 'Int'}}
179+
test(.genericWithReqs(()))
180+
// expected-error@-1 {{type '()' cannot conform to 'Collection'}} expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
181+
182+
test_combo(.doesntExist) // expected-error {{reference to member 'doesntExist' cannot be resolved without a contextual type}}
183+
test_combo(.doesnt.exist()) // expected-error {{reference to member 'doesnt' cannot be resolved without a contextual type}}
184+
test_combo(.invalidProp)
185+
// expected-error@-1 {{cannot reference static property 'invalidProp' on 'P.Protocol' with non-conforming result type 'Int'}}
186+
test_combo(.invalidMethod())
187+
// expected-error@-1 {{cannot reference static method 'invalidMethod()' on 'P.Protocol' with non-conforming result type 'Int'}}
188+
test_combo(.generic(42))
189+
// expected-error@-1 {{cannot reference static method 'generic' on 'P.Protocol' with non-conforming result type 'Int'}}
190+
test_combo(.generic(S())) // Ok
191+
test_combo(.generic(G<Int>())) // expected-error {{global function 'test_combo' requires that 'G<Int>' conform to 'Q'}}
192+
test_combo(.genericWithReqs([S()])) // Ok
193+
test_combo(.genericWithReqs([42]))
194+
// expected-error@-1 {{cannot reference static method 'genericWithReqs' on 'P.Protocol' with non-conforming result type 'Int'}}
195+
test_combo(.genericWithReqs(()))
196+
// expected-error@-1 {{type '()' cannot conform to 'Collection'}} expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
197+
198+
protocol Z {
199+
associatedtype T = Int
200+
201+
static var prop: T { get }
202+
}
203+
204+
extension Z {
205+
static func method() -> T { fatalError() } // expected-note {{'method()' declared here}}
206+
}
207+
208+
_ = Z.prop
209+
// expected-error@-1 {{member 'prop' cannot be used on value of protocol type 'Z.Protocol'; use a generic constraint instead}}
210+
// expected-error@-2 {{protocol 'Z' can only be used as a generic constraint because it has Self or associated type requirements}}
211+
212+
_ = Z.method()
213+
// expected-error@-1 {{cannot reference static method 'method()' on 'Z.Protocol' with non-conforming result type 'Z.T'}}
214+
// expected-error@-2 {{member 'method' cannot be used on value of protocol type 'Z.Protocol'; use a generic constraint instead}}
215+
// expected-error@-3 {{protocol 'Z' can only be used as a generic constraint because it has Self or associated type requirements}}

0 commit comments

Comments
 (0)