Skip to content

Commit dd5a350

Browse files
committed
[Sema] Forbid stored property marked SPI in frozen structs
1 parent 093f0a6 commit dd5a350

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,9 @@ ERROR(spi_attribute_on_protocol_requirement,none,
17091709
"protocol requirement %0 cannot be declared '@_spi' without "
17101710
"a default implementation in a protocol extension",
17111711
(DeclName))
1712+
ERROR(spi_attribute_on_frozen_stored_properties,none,
1713+
"stored property %0 cannot be declared '@_spi' in a '@frozen' struct",
1714+
(DeclName))
17121715

17131716
// Opaque return types
17141717
ERROR(opaque_type_invalid_constraint,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,14 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
908908
diag::spi_attribute_on_protocol_requirement,
909909
VD->getName());
910910
}
911+
912+
// Forbid stored properties marked SPI in frozen types.
913+
if (auto property = dyn_cast<AbstractStorageDecl>(VD))
914+
if (auto DC = dyn_cast<NominalTypeDecl>(D->getDeclContext()))
915+
if (property->hasStorage() && !DC->isFormallyResilient())
916+
diagnoseAndRemoveAttr(attr,
917+
diag::spi_attribute_on_frozen_stored_properties,
918+
VD->getName());
911919
}
912920
}
913921

test/SPI/local_spi_decls.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ func inlinable() -> SPIClass { // expected-error {{class 'SPIClass' is '@_spi' a
3131
@_spi(S) public struct SPIStruct {} // expected-note 2 {{struct 'SPIStruct' is not '@usableFromInline' or public}}
3232

3333
@frozen public struct FrozenStruct {
34-
@_spi(S) public var asdf = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
34+
@_spi(S) public var spiInFrozen = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
35+
// expected-error @-1 {{stored property 'spiInFrozen' cannot be declared '@_spi' in a '@frozen' struct}}
36+
3537
var asdf = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
3638
}
3739

test/SPI/resilience.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Test limits of SPI members in frozen types.
2+
3+
// RUN: %target-typecheck-verify-swift
4+
5+
@frozen
6+
public struct FrozenStruct {
7+
public var okProperty: Int
8+
9+
@_spi(S)
10+
public var okComputedProperty: Int { get { return 42 } }
11+
12+
@_spi(S) // expected-error {{stored property 'spiProperty' cannot be declared '@_spi' in a '@frozen' struct}}
13+
public var spiProperty: Int
14+
15+
@_spi(S) // expected-error {{stored property 'spiPropertySet' cannot be declared '@_spi' in a '@frozen' struct}}
16+
public var spiPropertySet = 4
17+
18+
@_spi(S) // expected-error {{stored property 'spiPropertyDoubleErrors' cannot be declared '@_spi' in a '@frozen' struct}}
19+
// expected-error @-1 {{internal property cannot be declared '@_spi' because only public and open declarations can be '@_spi'}}
20+
var spiPropertyDoubleErrors: Int
21+
}
22+
23+
public struct UnfrozenStruct {
24+
@_spi(S)
25+
public var spiProperty: Int
26+
27+
@_spi(S)
28+
public var spiPropertySet = 4
29+
}

0 commit comments

Comments
 (0)