Skip to content

Commit 7dcb0ea

Browse files
authored
Merge pull request swiftlang#33861 from xymus/spi-non-public
[Sema] Evaluate SPI groups for all decls, not only public ones
2 parents 5f98d39 + cbb7228 commit 7dcb0ea

File tree

4 files changed

+37
-16
lines changed

4 files changed

+37
-16
lines changed

lib/AST/Module.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,10 +2049,8 @@ bool Decl::isSPI() const {
20492049
}
20502050

20512051
ArrayRef<Identifier> Decl::getSPIGroups() const {
2052-
if (auto vd = dyn_cast<ValueDecl>(this)) {
2053-
if (vd->getFormalAccess() < AccessLevel::Public)
2054-
return ArrayRef<Identifier>();
2055-
} else if (!isa<ExtensionDecl>(this))
2052+
if (!isa<ValueDecl>(this) &&
2053+
!isa<ExtensionDecl>(this))
20562054
return ArrayRef<Identifier>();
20572055

20582056
return evaluateOrDefault(getASTContext().evaluator,
@@ -2063,10 +2061,8 @@ ArrayRef<Identifier> Decl::getSPIGroups() const {
20632061
llvm::ArrayRef<Identifier>
20642062
SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
20652063
// Applies only to public ValueDecls and ExtensionDecls.
2066-
if (auto vd = dyn_cast<ValueDecl>(decl))
2067-
assert(vd->getFormalAccess() >= AccessLevel::Public);
2068-
else
2069-
assert(isa<ExtensionDecl>(decl));
2064+
assert (isa<ValueDecl>(decl) ||
2065+
isa<ExtensionDecl>(decl));
20702066

20712067
// First, look for local attributes.
20722068
llvm::SetVector<Identifier> spiGroups;

lib/Sema/TypeCheckAttr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,8 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
885885
if (auto VD = dyn_cast<ValueDecl>(D)) {
886886
// VD must be public or open to use an @_spi attribute.
887887
auto declAccess = VD->getFormalAccess();
888-
if (declAccess < AccessLevel::Public) {
888+
if (declAccess < AccessLevel::Public &&
889+
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
889890
diagnoseAndRemoveAttr(attr,
890891
diag::spi_attribute_on_non_public,
891892
declAccess,

test/SPI/local_spi_decls.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
// Checks for SPI declarations and limited exposability
1+
// Checks for SPI declarations and limited exportability.
22

33
// RUN: %empty-directory(%t)
44
// RUN: %target-typecheck-verify-swift -I %t -verify-ignore-unknown -enable-library-evolution -swift-version 5
55

6+
// Without -enable-library-evolution the exportability check looks at struct internal properties.
7+
// RUN: %target-typecheck-verify-swift -I %t -verify-ignore-unknown -swift-version 5
8+
69
// SPI declarations
710
@_spi(MySPI) public func spiFunc() {} // expected-note {{global function 'spiFunc()' is not '@usableFromInline' or public}}
811
@_spi(+) public func invalidSPIName() {} // expected-error {{expected an SPI identifier as subject of the '@_spi' attribute}}
@@ -55,3 +58,26 @@ public struct PublicStructWithProperties {
5558
public var a: SPIClass // expected-error {{cannot use class 'SPIClass' here; it is SPI}}
5659
public var b = SPIClass() // expected-error {{cannot use class 'SPIClass' here; it is SPI}}
5760
}
61+
62+
@_spi(S)
63+
@usableFromInline
64+
func usableFromInlineFunc(_ a: SPIStruct) -> SPIStruct {
65+
fatalError()
66+
}
67+
68+
@_spi(S)
69+
public final class ClassWithUsables {
70+
@usableFromInline
71+
var usableFromInlineVar = SPIClass()
72+
73+
@usableFromInline
74+
func usableFromInlineFunc(_ a: SPIStruct) -> SPIStruct {
75+
fatalError()
76+
}
77+
}
78+
79+
@_spi(S)
80+
public struct NestedParent {
81+
public struct Nested { }
82+
let nested: Nested
83+
}

test/Sema/spi-inlinable-conformances.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,8 @@ extension NormalProtoAssocHolder {
241241

242242
@_spi(AcceptInSPI)
243243
@inlinable public func SPIlocalTypeAlias() {
244-
// FIXME these should be accepted.
245-
typealias LocalUser = NormalProtoAssocHolder<NormalStruct> // expected-error{{cannot use conformance of 'NormalStruct' to 'NormalProto' here; the conformance is declared as SPI}}
246-
typealias LocalGenericUser<T> = (T, NormalProtoAssocHolder<NormalStruct>) // expected-error{{cannot use conformance of 'NormalStruct' to 'NormalProto' here; the conformance is declared as SPI}}
244+
typealias LocalUser = NormalProtoAssocHolder<NormalStruct>
245+
typealias LocalGenericUser<T> = (T, NormalProtoAssocHolder<NormalStruct>)
247246

248247
typealias LocalProtoAssoc<T: NormalProto> = T.Assoc
249248
_ = LocalProtoAssoc<NormalStruct>()
@@ -258,9 +257,8 @@ extension NormalProtoAssocHolder {
258257

259258
@_spi(AcceptInSPI)
260259
@inlinable public func SPIlocalFunctions() {
261-
// FIXME these should be accepted.
262-
func local(_: NormalProtoAssocHolder<NormalStruct>) {} // expected-error{{cannot use conformance of 'NormalStruct' to 'NormalProto' here; the conformance is declared as SPI}}
263-
func localReturn() -> NormalProtoAssocHolder<NormalStruct> { fatalError() } // expected-error{{cannot use conformance of 'NormalStruct' to 'NormalProto' here; the conformance is declared as SPI}}
260+
func local(_: NormalProtoAssocHolder<NormalStruct>) {}
261+
func localReturn() -> NormalProtoAssocHolder<NormalStruct> { fatalError() }
264262
let _ = { (_: NormalProtoAssocHolder<NormalStruct>) in return }
265263
let _ = { () -> NormalProtoAssocHolder<NormalStruct> in fatalError() }
266264
}

0 commit comments

Comments
 (0)