Skip to content

Commit a2c64b6

Browse files
authored
Merge pull request #61954 from tshortli/spi-witness-availability
Sema: Relax the availability requirements for `@_spi` protocol witnesses
2 parents 447d9ee + bc11683 commit a2c64b6

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,20 @@ bool TypeChecker::isAvailabilitySafeForConformance(
17071707
AvailabilityContext infoForConformingDecl =
17081708
overApproximateAvailabilityAtLocation(dc->getAsDecl()->getLoc(), dc);
17091709

1710+
// Relax the requirements for @_spi witnesses by treating the requirement as
1711+
// if it were introduced at the deployment target. This is not strictly sound
1712+
// since clients of SPI do not necessarily have the same deployment target as
1713+
// the module declaring the requirement. However, now that the public
1714+
// declarations in API libraries are checked according to the minimum possible
1715+
// deployment target of their clients this relaxation is needed for source
1716+
// compatibility with some existing code and is reasonably safe for the
1717+
// majority of cases.
1718+
if (witness->isSPI()) {
1719+
AvailabilityContext deploymentTarget =
1720+
AvailabilityContext::forDeploymentTarget(Context);
1721+
requirementInfo.constrainWith(deploymentTarget);
1722+
}
1723+
17101724
// Constrain over-approximates intersection of version ranges.
17111725
witnessInfo.constrainWith(infoForConformingDecl);
17121726
requirementInfo.constrainWith(infoForConformingDecl);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// RUN: %target-run-simple-swift(-target %target-cpu-macos10.15) | \
2+
// RUN: %FileCheck %s --check-prefix=CHECK-CONFORMANCES-NOT-AVAILABLE
3+
// RUN: %target-run-simple-swift(-target %target-cpu-macos10.15.4) | \
4+
// RUN: %FileCheck %s --check-prefix=CHECK-CONFORMANCES-AVAILABLE
5+
// RUN: %target-run-simple-swift(-target %target-cpu-macos10.15.4 -library-level api) | \
6+
// RUN: %FileCheck %s --check-prefix=CHECK-CONFORMANCES-AVAILABLE-API
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: OS=macosx
10+
11+
@available(macOS 10.15, *)
12+
public protocol BaseProto {
13+
static var foo: String { get }
14+
}
15+
16+
@available(macOS 10.15, *)
17+
extension BaseProto {
18+
public static var foo: String { return "Base" }
19+
}
20+
21+
@available(macOS 10.15.4, *)
22+
public protocol DerivedProto: BaseProto {}
23+
24+
@available(macOS 10.15.4, *)
25+
extension DerivedProto {
26+
public static var foo: String { return "Derived" }
27+
}
28+
29+
@_spi(Private)
30+
@available(macOS 10.15.4, *)
31+
public protocol SecretDerivedProto: BaseProto {
32+
}
33+
34+
@_spi(Private)
35+
@available(macOS 10.15.4, *)
36+
extension SecretDerivedProto {
37+
public static var foo: String { return "Secret" }
38+
}
39+
40+
@available(macOS 10.15, *)
41+
public struct NoSecrets: BaseProto {
42+
public init() {}
43+
}
44+
45+
@available(macOS 10.15.4, *)
46+
extension NoSecrets: DerivedProto {}
47+
48+
@available(macOS 10.15, *)
49+
public struct HasSecrets: BaseProto {
50+
public init() {}
51+
}
52+
53+
@_spi(Private)
54+
@available(macOS 10.15.4, *)
55+
extension HasSecrets: SecretDerivedProto {}
56+
57+
@available(macOS 10.15, *)
58+
func doIt<T: BaseProto>(_: T) {
59+
print(T.foo)
60+
}
61+
62+
// CHECK-CONFORMANCES-NOT-AVAILABLE: Base
63+
// CHECK-CONFORMANCES-AVAILABLE: Derived
64+
// CHECK-CONFORMANCES-AVAILABLE-API: Base
65+
doIt(NoSecrets())
66+
// CHECK-CONFORMANCES-NOT-AVAILABLE: Base
67+
// CHECK-CONFORMANCES-AVAILABLE: Secret
68+
// CHECK-CONFORMANCES-AVAILABLE-API: Secret
69+
doIt(HasSecrets())

0 commit comments

Comments
 (0)