Skip to content

Commit df9258b

Browse files
committed
Sema: Check availability of key path components
Fixes <https://bugs.swift.org/browse/SR-7406> / <rdar://problem/39319212>.
1 parent 58da061 commit df9258b

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2306,6 +2306,10 @@ class AvailabilityWalker : public ASTWalker {
23062306
maybeDiagStorageAccess(S->getDecl().getDecl(), S->getSourceRange(), DC);
23072307
}
23082308
}
2309+
if (auto KP = dyn_cast<KeyPathExpr>(E)) {
2310+
walkKeyPath(KP);
2311+
return skipChildren();
2312+
}
23092313
if (auto A = dyn_cast<AssignExpr>(E)) {
23102314
walkAssignExpr(A);
23112315
return skipChildren();
@@ -2399,7 +2403,32 @@ class AvailabilityWalker : public ASTWalker {
23992403
// Diagnose for appropriate accessors, given the access context.
24002404
maybeDiagStorageAccess(D, E->getSourceRange(), DC);
24012405
}
2402-
2406+
2407+
/// Walk a keypath expression, checking all of its components for
2408+
/// availability.
2409+
void walkKeyPath(KeyPathExpr *KP) {
2410+
for (auto &component : KP->getComponents()) {
2411+
switch (component.getKind()) {
2412+
case KeyPathExpr::Component::Kind::Property:
2413+
case KeyPathExpr::Component::Kind::Subscript: {
2414+
auto *decl = component.getDeclRef().getDecl();
2415+
auto loc = component.getLoc();
2416+
SourceRange range(loc, loc);
2417+
diagAvailability(decl, range, nullptr);
2418+
break;
2419+
}
2420+
2421+
case KeyPathExpr::Component::Kind::Invalid:
2422+
case KeyPathExpr::Component::Kind::UnresolvedProperty:
2423+
case KeyPathExpr::Component::Kind::UnresolvedSubscript:
2424+
case KeyPathExpr::Component::Kind::OptionalChain:
2425+
case KeyPathExpr::Component::Kind::OptionalWrap:
2426+
case KeyPathExpr::Component::Kind::OptionalForce:
2427+
break;
2428+
}
2429+
}
2430+
}
2431+
24032432
/// Walk an inout expression, checking for availability.
24042433
void walkInOutExpr(InOutExpr *E) {
24052434
walkInContext(E, E->getSubExpr(), MemberAccessContext::InOut);

test/attr/attr_inlinable.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,13 @@ public struct PublicFixedStructWithInit {
251251
var x = internalGlobal // expected-error {{let 'internalGlobal' is internal and cannot be referenced from a property initializer in a '@_fixed_layout' type}}
252252
var y = publicGlobal // OK
253253
}
254+
255+
public struct KeypathStruct {
256+
var x: Int
257+
// expected-note@-1 {{var 'x' is not '@usableFromInline' or public}}
258+
259+
@inlinable public func usesKeypath() {
260+
_ = \KeypathStruct.x
261+
// expected-error@-1 {{var 'x' is internal and cannot be referenced from an '@inlinable' function}}
262+
}
263+
}

test/expr/unary/keypath/keypath.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ struct C<T> {
4444
subscript<X>(noHashableConstraint sub: X) -> X { get { return sub } set { } }
4545
}
4646

47+
struct Unavailable {
48+
@available(*, unavailable)
49+
var unavailableProperty: Int
50+
// expected-note@-1 {{'unavailableProperty' has been explicitly marked unavailable here}}
51+
52+
@available(*, unavailable)
53+
subscript(x: Sub) -> Int { get { } set { } }
54+
// expected-note@-1 {{'subscript' has been explicitly marked unavailable here}}
55+
}
56+
57+
struct Deprecated {
58+
@available(*, deprecated)
59+
var deprecatedProperty: Int
60+
61+
@available(*, deprecated)
62+
subscript(x: Sub) -> Int { get { } set { } }
63+
}
64+
4765
extension Array where Element == A {
4866
var property: Prop { fatalError() }
4967
}
@@ -178,6 +196,12 @@ func testKeyPath(sub: Sub, optSub: OptSub,
178196
let _ = \C<Int>.[sub]
179197
let _ = \C<Int>.[noHashableConstraint: sub]
180198
let _ = \C<Int>.[noHashableConstraint: nonHashableSub] // expected-error{{subscript index of type 'NonHashableSub' in a key path must be Hashable}}
199+
200+
let _ = \Unavailable.unavailableProperty // expected-error {{'unavailableProperty' is unavailable}}
201+
let _ = \Unavailable.[sub] // expected-error {{'subscript' is unavailable}}
202+
203+
let _ = \Deprecated.deprecatedProperty // expected-warning {{'deprecatedProperty' is deprecated}}
204+
let _ = \Deprecated.[sub] // expected-warning {{'subscript' is deprecated}}
181205
}
182206

183207
func testKeyPathInGenericContext<H: Hashable, X>(hashable: H, anything: X) {

0 commit comments

Comments
 (0)