Skip to content

Commit 84098f9

Browse files
committed
Sema: Always mark initializers of lazy vars as subsumed.
Previously, the initializer expressions of lazy vars would only be marked as subsumed when the getter body for the var was synthesized. This didn't work with `-experimental-lazy-typechecking` since accessor synthesis was not guaranteed to happen. Consequently, SILGen would emit the initializer even though it was already subsumed and then assert/crash since the init had also not been checked and contextualized. Now lazy var inits are marked subsumed in the request creating storage. Resolves rdar://118421753
1 parent 29fec06 commit 84098f9

8 files changed

+34
-25
lines changed

lib/AST/Decl.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -9188,13 +9188,6 @@ bool IsFunctionBodySkippedRequest::evaluate(
91889188
// typecheck them.
91899189
if (accessor->hasForcedStaticDispatch())
91909190
return false;
9191-
9192-
if (auto *varDecl = dyn_cast<VarDecl>(accessor->getStorage())) {
9193-
// FIXME: If we don't typecheck the synthesized accessors of lazy storage
9194-
// properties then SILGen crashes when emitting the initializer.
9195-
if (varDecl->getAttrs().hasAttribute<LazyAttr>() && accessor->isSynthesized())
9196-
return false;
9197-
}
91989191
}
91999192

92009193
// Actor initializers need to be checked to determine delegation status.

lib/SILGen/SILGen.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
994994
auto arg = param->getTypeCheckedDefaultExpr();
995995
auto loc = RegularLocation::getAutoGeneratedLocation(arg);
996996
preEmitFunction(constant, f, loc);
997-
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
997+
PrettyStackTraceSILFunction X("silgen default arg initializer", f);
998998
SILGenFunction SGF(*this, *f, initDC);
999999
SGF.emitGeneratorFunction(constant, arg);
10001000
postEmitFunction(constant, f);
@@ -1005,7 +1005,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
10051005
auto arg = param->getStoredProperty();
10061006
auto loc = RegularLocation::getAutoGeneratedLocation(arg);
10071007
preEmitFunction(constant, f, loc);
1008-
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
1008+
PrettyStackTraceSILFunction X("silgen stored property initializer", f);
10091009
SILGenFunction SGF(*this, *f, initDC);
10101010
SGF.emitGeneratorFunction(constant, arg);
10111011
postEmitFunction(constant, f);

lib/Sema/TypeCheckStorage.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -1670,12 +1670,8 @@ synthesizeLazyGetterBody(AccessorDecl *Get, VarDecl *VD, VarDecl *Storage,
16701670

16711671
Expr *InitValue;
16721672
if (PBD->getInit(entryIndex)) {
1673-
PBD->setInitializerSubsumed(entryIndex);
1674-
1675-
if (!PBD->isInitializerChecked(entryIndex))
1676-
TypeChecker::typeCheckPatternBinding(PBD, entryIndex);
1677-
1678-
InitValue = PBD->getInit(entryIndex);
1673+
assert(PBD->isInitializerSubsumed(entryIndex));
1674+
InitValue = PBD->getCheckedAndContextualizedInit(entryIndex);
16791675
} else {
16801676
InitValue = new (Ctx) ErrorExpr(SourceRange(), Tmp2VD->getTypeInContext());
16811677
}
@@ -2786,6 +2782,11 @@ LazyStoragePropertyRequest::evaluate(Evaluator &evaluator,
27862782

27872783
addMemberToContextIfNeeded(PBD, VD->getDeclContext(), Storage);
27882784

2785+
// Make sure the original init is marked as subsumed.
2786+
auto *originalPBD = VD->getParentPatternBinding();
2787+
auto originalIndex = originalPBD->getPatternEntryIndexForVarDecl(VD);
2788+
originalPBD->setInitializerSubsumed(originalIndex);
2789+
27892790
return Storage;
27902791
}
27912792

test/Frontend/skip-function-bodies.swift

+11-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
// RUN: %target-swift-emit-module-interface(%t/NoSkip.swiftinterface) %s -module-name Skip
2727
// RUN: %FileCheck %s --check-prefixes CHECK,CHECK-TEXTUAL --input-file %t/NoSkip.swiftinterface
2828
// RUN: diff -u %t/Skip.noninlinable.swiftinterface %t/NoSkip.swiftinterface
29-
// FIXME: Skipping all function bodies causes the interfaces not to match.
30-
// diff -u %t/Skip.all.swiftinterface %t/NoSkip.swiftinterface
29+
// RUN: diff -u %t/Skip.all.swiftinterface %t/NoSkip.swiftinterface
3130

3231
// Skipping all function bodies should skip *all* SIL.
3332
// CHECK-SIL-SKIP-ALL: sil_stage canonical
@@ -480,6 +479,16 @@ public struct Struct {
480479
// CHECK-SIL-SKIP-NONINLINE: "Struct.varWithInlinableSetter.setter"
481480
// CHECK-SIL-SKIP-WITHOUTTYPES: "Struct.varWithInlinableSetter.setter"
482481

482+
public lazy var varWithLazyInitializer: Int = {
483+
// We currently don't have a way to skip typechecking a pattern binding
484+
// initializer expression
485+
_blackHole("Struct.varWithLazyInitializer.init")
486+
return 0
487+
}()
488+
// CHECK-TEXTUAL-NOT: "Struct.varWithLazyInitializer.init"
489+
// CHECK-SIL-NO-SKIP: "Struct.varWithLazyInitializer.init"
490+
// CHECK-SIL-SKIP-NONINLINE-OR-WITHOUTTYPES-NOT: "Struct.varWithLazyInitializer.init"
491+
483492
public var varWithObserverDidSet: Int = 1 {
484493
didSet {
485494
// Body typechecked regardless

test/Inputs/lazy_typecheck.swift

+4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ protocol InternalProtoConformingToPublicProto: PublicProto {
133133
public struct PublicStruct {
134134
public var publicProperty: Int = NoTypecheck.int
135135
public var publicPropertyInferredType = ""
136+
public var publicLazyProperty: Int = NoTypecheck.int
137+
public var publicLazyPropertyInferred = 1
136138
@PublicWrapper public var publicWrappedProperty = 3.14
137139
@_transparent public var publicTransparentProperty: Int {
138140
get { return 1 }
@@ -192,6 +194,8 @@ struct InternalStruct: NoTypecheckProto {
192194
public class PublicClass {
193195
public var publicProperty: Int = NoTypecheck.int
194196
public var publicPropertyInferredType = ""
197+
public var publicLazyProperty: Int = NoTypecheck.int
198+
public var publicLazyPropertyInferred = 1
195199
@PublicWrapper public final var publicFinalWrappedProperty: Bool = false
196200
public static let publicStaticProperty: Int = NoTypecheck.int
197201
public static let publicStaticPropertyInferred = 2

test/Inputs/lazy_typecheck_client.swift

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ func testPublicStructs() {
3737
let _: Int = s.publicMethod()
3838
let _: Int = s.publicProperty
3939
let _: String = s.publicPropertyInferredType
40+
let _: Int = s.publicLazyProperty
41+
let _: Int = s.publicLazyPropertyInferred
4042
let _: Double = s.publicWrappedProperty
4143
let _: Double = s.$publicWrappedProperty.wrappedValue
4244
let _: Int = s.publicTransparentProperty
@@ -59,6 +61,8 @@ func testPublicClasses() {
5961
let _: Int = c.publicMethod()
6062
let _: Int = c.publicProperty
6163
let _: String = c.publicPropertyInferredType
64+
let _: Int = c.publicLazyProperty
65+
let _: Int = c.publicLazyPropertyInferred
6266
c.publicFinalWrappedProperty = true
6367
PublicClass.publicClassMethod()
6468
let _: Int = PublicClass.publicStaticProperty

test/SILGen/lazy_typecheck_var_init.swift

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ public struct S {
2222
// CHECK-LABEL: sil [transparent]{{.*}} @$s4Test1SV12instanceVar2Sivpfi : $@convention(thin) () -> Int {
2323
public var instanceVar2 = internalFunc(.b)
2424

25-
// FIXME: This initializer should be subsumed.
26-
// CHECK-LAZY: sil [transparent] [ossa] @$s4Test1SV15lazyInstanceVarSivpfi : $@convention(thin) () -> Int {
27-
// CHECK-NON-LAZY-NOT: sil [transparent] [ossa] @$s4Test1SV15lazyInstanceVarSivpfi : $@convention(thin) () -> Int {
25+
// CHECK-NOT: s4Test1SV15lazyInstanceVarSivpfi
2826
// CHECK-LABEL: sil [transparent]{{.*}} @$s4Test1SV018$__lazy_storage_$_B11InstanceVar33_0E4F053AA3AB7D4CDE3A37DBA8EF0430LLSiSgvpfi : $@convention(thin) () -> Optional<Int> {
2927
public lazy var lazyInstanceVar = internalFunc()
3028

test/SILGen/skip_function_bodies_storage.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ public struct S {
1717

1818
public lazy var lazyVar: Int = generateNumber()
1919

20+
// CHECK: sil [transparent] [serialized]{{.*}} @$s4main1SV7lazyVarSivM : $@yield_once @convention(method) (@inout S) -> @yields @inout Int
21+
// CHECK: end sil function '$s4main1SV7lazyVarSivM'
22+
2023
// CHECK: sil [lazy_getter]{{.*}} @$s4main1SV7lazyVarSivg : $@convention(method) (@inout S) -> Int
21-
// CHECK: end sil function '$s4main1SV7lazyVarSivg'
24+
// CHECK-NOT: end sil function '$s4main1SV7lazyVarSivg'
2225

2326
// CHECK: sil{{.*}} @$s4main1SV7lazyVarSivs : $@convention(method) (Int, @inout S) -> ()
24-
// CHECK: end sil function '$s4main1SV7lazyVarSivs'
25-
26-
// CHECK: sil [transparent] [serialized]{{.*}} @$s4main1SV7lazyVarSivM : $@yield_once @convention(method) (@inout S) -> @yields @inout Int
27-
// CHECK: end sil function '$s4main1SV7lazyVarSivM'
27+
// CHECK-NOT: end sil function '$s4main1SV7lazyVarSivs'
2828

2929
// CHECK: sil [transparent]{{.*}} @$s4main1SV018$__lazy_storage_$_B3Var33_39316373847D37F82BD23977A13DEF23LLSiSgvpfi : $@convention(thin) () -> Optional<Int>
3030
// CHECK: end sil function '$s4main1SV018$__lazy_storage_$_B3Var33_39316373847D37F82BD23977A13DEF23LLSiSgvpfi'

0 commit comments

Comments
 (0)