Skip to content

Commit 5e617b5

Browse files
committed
SIL: Verifier checks resilience invariants for keypath instruction
1 parent 128f4a8 commit 5e617b5

File tree

2 files changed

+54
-32
lines changed

2 files changed

+54
-32
lines changed

lib/SIL/SILVerifier.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ namespace {
119119

120120
/// Verify invariants on a key path component.
121121
void verifyKeyPathComponent(SILModule &M,
122+
ResilienceExpansion expansion,
122123
llvm::function_ref<void(bool, StringRef)> require,
123124
CanType &baseTy,
124125
CanType leafTy,
@@ -211,13 +212,21 @@ void verifyKeyPathComponent(SILModule &M,
211212
switch (auto kind = component.getKind()) {
212213
case KeyPathPatternComponent::Kind::StoredProperty: {
213214
auto property = component.getStoredPropertyDecl();
215+
if (expansion == ResilienceExpansion::Minimal) {
216+
require(property->getEffectiveAccess() >= AccessLevel::Public,
217+
"Key path in serialized function cannot reference non-public "
218+
"property");
219+
}
220+
214221
auto fieldTy = baseTy->getTypeOfMember(M.getSwiftModule(), property)
215222
->getReferenceStorageReferent()
216223
->getCanonicalType();
217224
require(fieldTy == componentTy,
218225
"property decl should be a member of the base with the same type "
219226
"as the component");
220227
require(property->hasStorage(), "property must be stored");
228+
require(!property->isResilient(M.getSwiftModule(), expansion),
229+
"cannot access storage of resilient property");
221230
auto propertyTy = loweredBaseTy.getFieldType(property, M);
222231
require(propertyTy.getObjectType()
223232
== loweredComponentTy.getObjectType(),
@@ -247,6 +256,12 @@ void verifyKeyPathComponent(SILModule &M,
247256
// Getter should be <Sig...> @convention(thin) (@in_guaranteed Base) -> @out Result
248257
{
249258
auto getter = component.getComputedPropertyGetter();
259+
if (expansion == ResilienceExpansion::Minimal) {
260+
require(getter->hasValidLinkageForFragileRef(),
261+
"Key path in serialized function should not reference "
262+
"less visible getters");
263+
}
264+
250265
auto substGetterType = getter->getLoweredFunctionType()
251266
->substGenericArgs(M, patternSubs);
252267
require(substGetterType->getRepresentation() ==
@@ -286,6 +301,12 @@ void verifyKeyPathComponent(SILModule &M,
286301
// <Sig...> @convention(thin) (@in_guaranteed Result, @in Base) -> ()
287302

288303
auto setter = component.getComputedPropertySetter();
304+
if (expansion == ResilienceExpansion::Minimal) {
305+
require(setter->hasValidLinkageForFragileRef(),
306+
"Key path in serialized function should not reference "
307+
"less visible setters");
308+
}
309+
289310
auto substSetterType = setter->getLoweredFunctionType()
290311
->substGenericArgs(M, patternSubs);
291312

@@ -4242,7 +4263,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
42424263
break;
42434264
}
42444265

4245-
verifyKeyPathComponent(F.getModule(),
4266+
verifyKeyPathComponent(F.getModule(), F.getResilienceExpansion(),
42464267
[&](bool reqt, StringRef message) { _require(reqt, message); },
42474268
baseTy,
42484269
leafTy,
@@ -4879,15 +4900,16 @@ void SILProperty::verify(const SILModule &M) const {
48794900

48804901
if (auto &component = getComponent()) {
48814902
verifyKeyPathComponent(const_cast<SILModule&>(M),
4882-
require,
4883-
baseTy,
4884-
leafTy,
4885-
*component,
4886-
{},
4887-
canSig,
4888-
subs,
4889-
/*property descriptor*/true,
4890-
hasIndices);
4903+
ResilienceExpansion::Maximal,
4904+
require,
4905+
baseTy,
4906+
leafTy,
4907+
*component,
4908+
{},
4909+
canSig,
4910+
subs,
4911+
/*property descriptor*/true,
4912+
hasIndices);
48914913
// verifyKeyPathComponent updates baseTy to be the projected type of the
48924914
// component, which should be the same as the type of the declared storage
48934915
require(baseTy == leafTy,

test/SIL/Serialization/keypath.sil

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,48 @@
11

22
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
33
// RUN: %empty-directory(%t)
4-
// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name boxes
5-
// RUN: %target-sil-opt %t/tmp.sib -o %t/tmp.2.sib -module-name boxes
6-
// RUN: %target-sil-opt %t/tmp.2.sib -module-name boxes | %FileCheck %s
4+
// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name keypaths
5+
// RUN: %target-sil-opt %t/tmp.sib -emit-sib -o %t/tmp.2.sib -module-name keypaths
6+
// RUN: %target-sil-opt %t/tmp.2.sib -module-name keypaths | %FileCheck %s
77

88
sil_stage canonical
99

1010
import Swift
1111

12-
struct S: Hashable {
13-
var x: Int
14-
let y: String
15-
var z: C
12+
public struct S: Hashable {
13+
public var x: Int
14+
public let y: String
15+
public var z: C
1616

17-
func hash(into hasher: inout Hasher)
18-
static func ==(x: S, y: S) -> Bool
17+
public func hash(into hasher: inout Hasher)
18+
public static func ==(x: S, y: S) -> Bool
1919
}
20-
class C: Hashable {
21-
final var x: Int
22-
final let y: String
23-
final var z: S
20+
public class C: Hashable {
21+
public final var x: Int
22+
public final let y: String
23+
public final var z: S
2424

25-
init()
26-
var overridable: Int {
25+
public init()
26+
public var overridable: Int {
2727
get set
2828
}
2929

30-
func hash(into hasher: inout Hasher)
31-
static func ==(x: C, y: C) -> Bool
30+
public func hash(into hasher: inout Hasher)
31+
public static func ==(x: C, y: C) -> Bool
3232
}
3333

3434
protocol P {}
3535
protocol Q {}
3636
protocol R {}
3737

38-
struct Gen<A: P, B: Q, C: R> {
39-
var x: A
40-
let y: B
41-
var z: C
38+
public struct Gen<A: P, B: Q, C: R> {
39+
public var x: A
40+
public let y: B
41+
public var z: C
4242
}
4343

4444
public struct External<T> {
45-
var ro: T
45+
public var ro: T
4646

4747
subscript<U: Hashable>(ro _: U) -> T { get }
4848

0 commit comments

Comments
 (0)