Skip to content

Commit b00a561

Browse files
authored
Merge pull request #84238 from xymus/spi-avail-in-ext
Sema: Narrow fix to allow `@_spi_available` in extensions
2 parents 014ed51 + 1adbe37 commit b00a561

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

lib/Sema/TypeCheckAccess.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,7 +2124,21 @@ swift::getDisallowedOriginKind(const Decl *decl,
21242124
return DisallowedOriginKind::None;
21252125
}
21262126
}
2127+
2128+
// Allow SPI available use in an extension to an SPI available type.
2129+
// This is a narrow workaround for rdar://159292698 as this should be
2130+
// handled as part of the `where.isSPI()` above, but that context check
2131+
// is currently too permissive. It allows SPI use in SPI available which
2132+
// can break swiftinterfaces. The SPI availability logic likely need to be
2133+
// separated from normal SPI and treated more like availability.
2134+
auto ext = dyn_cast_or_null<ExtensionDecl>(where.getDeclContext());
2135+
if (ext) {
2136+
auto nominal = ext->getExtendedNominal();
2137+
if (nominal && nominal->isAvailableAsSPI())
2138+
return DisallowedOriginKind::None;
2139+
}
21272140
}
2141+
21282142
// SPI can only be exported in SPI.
21292143
return where.getDeclContext()->getParentModule() == M ?
21302144
DisallowedOriginKind::SPILocal :
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-typecheck-verify-swift \
3+
// RUN: -enable-library-evolution -swift-version 5 \
4+
// RUN: -library-level=api -require-explicit-availability=ignore
5+
6+
// REQUIRES: OS=macosx
7+
8+
@_spi_available(macOS, introduced: 12.0) @available(iOS 12.0, *)
9+
public struct SPIAvailableType { // expected-note {{struct declared here}}
10+
public init() {}
11+
}
12+
13+
@_spi(S)
14+
public struct NormalSPIType {
15+
public init() {}
16+
}
17+
18+
// SPI available in SPI available should be accepted.
19+
20+
@_spi_available(macOS, introduced: 12.0) @available(iOS 12.0, *)
21+
public struct OtherSPIAvailableType {
22+
public func foo(s: SPIAvailableType) {}
23+
}
24+
25+
extension OtherSPIAvailableType {
26+
public func bar(s: SPIAvailableType) {} // expected-error {{cannot use struct 'SPIAvailableType' here; it is SPI}} // FIXME We should allow this.
27+
}
28+
29+
// Normal SPI in normal SPI should be accepted.
30+
31+
@_spi(S)
32+
public struct OtherNormalSPIType {
33+
public func foo(s: SPIAvailableType) {}
34+
}
35+
36+
extension OtherNormalSPIType {
37+
public func bar2(s: SPIAvailableType) {}
38+
}
39+
40+
// Normal SPI in SPI available should be rejected.
41+
42+
@_spi_available(macOS, introduced: 12.0) @available(iOS 12.0, *)
43+
public func SPIAvailableToSPI(s: NormalSPIType) {} // FIXME This should be an error
44+
45+
@inlinable
46+
@_spi_available(macOS, introduced: 12.0) @available(iOS 12.0, *)
47+
public func inlinableSPIAvailable() {
48+
let _: NormalSPIType = NormalSPIType() // FIXME There should be many errors here
49+
}
50+
51+
// SPI available in normal SPI is currently accepted.
52+
53+
@_spi(S)
54+
public func SPIToSPIAvailable(s: NormalSPIType) {}
55+
56+
@inlinable
57+
@_spi(S)
58+
public func inlinableSPI() {
59+
let _: SPIAvailableType = SPIAvailableType()
60+
}

0 commit comments

Comments
 (0)