Skip to content

Sema: Always mark initializers of lazy vars as subsumed #69946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9188,13 +9188,6 @@ bool IsFunctionBodySkippedRequest::evaluate(
// typecheck them.
if (accessor->hasForcedStaticDispatch())
return false;

if (auto *varDecl = dyn_cast<VarDecl>(accessor->getStorage())) {
// FIXME: If we don't typecheck the synthesized accessors of lazy storage
// properties then SILGen crashes when emitting the initializer.
if (varDecl->getAttrs().hasAttribute<LazyAttr>() && accessor->isSynthesized())
return false;
}
}

// Actor initializers need to be checked to determine delegation status.
Expand Down
4 changes: 2 additions & 2 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
auto arg = param->getTypeCheckedDefaultExpr();
auto loc = RegularLocation::getAutoGeneratedLocation(arg);
preEmitFunction(constant, f, loc);
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
PrettyStackTraceSILFunction X("silgen default arg initializer", f);
SILGenFunction SGF(*this, *f, initDC);
SGF.emitGeneratorFunction(constant, arg);
postEmitFunction(constant, f);
Expand All @@ -1005,7 +1005,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
auto arg = param->getStoredProperty();
auto loc = RegularLocation::getAutoGeneratedLocation(arg);
preEmitFunction(constant, f, loc);
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
PrettyStackTraceSILFunction X("silgen stored property initializer", f);
SILGenFunction SGF(*this, *f, initDC);
SGF.emitGeneratorFunction(constant, arg);
postEmitFunction(constant, f);
Expand Down
13 changes: 7 additions & 6 deletions lib/Sema/TypeCheckStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1670,12 +1670,8 @@ synthesizeLazyGetterBody(AccessorDecl *Get, VarDecl *VD, VarDecl *Storage,

Expr *InitValue;
if (PBD->getInit(entryIndex)) {
PBD->setInitializerSubsumed(entryIndex);

if (!PBD->isInitializerChecked(entryIndex))
TypeChecker::typeCheckPatternBinding(PBD, entryIndex);

InitValue = PBD->getInit(entryIndex);
assert(PBD->isInitializerSubsumed(entryIndex));
InitValue = PBD->getCheckedAndContextualizedInit(entryIndex);
} else {
InitValue = new (Ctx) ErrorExpr(SourceRange(), Tmp2VD->getTypeInContext());
}
Expand Down Expand Up @@ -2786,6 +2782,11 @@ LazyStoragePropertyRequest::evaluate(Evaluator &evaluator,

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

// Make sure the original init is marked as subsumed.
auto *originalPBD = VD->getParentPatternBinding();
auto originalIndex = originalPBD->getPatternEntryIndexForVarDecl(VD);
originalPBD->setInitializerSubsumed(originalIndex);

return Storage;
}

Expand Down
13 changes: 11 additions & 2 deletions test/Frontend/skip-function-bodies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
// RUN: %target-swift-emit-module-interface(%t/NoSkip.swiftinterface) %s -module-name Skip
// RUN: %FileCheck %s --check-prefixes CHECK,CHECK-TEXTUAL --input-file %t/NoSkip.swiftinterface
// RUN: diff -u %t/Skip.noninlinable.swiftinterface %t/NoSkip.swiftinterface
// FIXME: Skipping all function bodies causes the interfaces not to match.
// diff -u %t/Skip.all.swiftinterface %t/NoSkip.swiftinterface
// RUN: diff -u %t/Skip.all.swiftinterface %t/NoSkip.swiftinterface

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

public lazy var varWithLazyInitializer: Int = {
// We currently don't have a way to skip typechecking a pattern binding
// initializer expression
_blackHole("Struct.varWithLazyInitializer.init")
return 0
}()
// CHECK-TEXTUAL-NOT: "Struct.varWithLazyInitializer.init"
// CHECK-SIL-NO-SKIP: "Struct.varWithLazyInitializer.init"
// CHECK-SIL-SKIP-NONINLINE-OR-WITHOUTTYPES-NOT: "Struct.varWithLazyInitializer.init"

public var varWithObserverDidSet: Int = 1 {
didSet {
// Body typechecked regardless
Expand Down
4 changes: 4 additions & 0 deletions test/Inputs/lazy_typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ protocol InternalProtoConformingToPublicProto: PublicProto {
public struct PublicStruct {
public var publicProperty: Int = NoTypecheck.int
public var publicPropertyInferredType = ""
public var publicLazyProperty: Int = NoTypecheck.int
public var publicLazyPropertyInferred = 1
@PublicWrapper public var publicWrappedProperty = 3.14
@_transparent public var publicTransparentProperty: Int {
get { return 1 }
Expand Down Expand Up @@ -192,6 +194,8 @@ struct InternalStruct: NoTypecheckProto {
public class PublicClass {
public var publicProperty: Int = NoTypecheck.int
public var publicPropertyInferredType = ""
public var publicLazyProperty: Int = NoTypecheck.int
public var publicLazyPropertyInferred = 1
@PublicWrapper public final var publicFinalWrappedProperty: Bool = false
public static let publicStaticProperty: Int = NoTypecheck.int
public static let publicStaticPropertyInferred = 2
Expand Down
4 changes: 4 additions & 0 deletions test/Inputs/lazy_typecheck_client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func testPublicStructs() {
let _: Int = s.publicMethod()
let _: Int = s.publicProperty
let _: String = s.publicPropertyInferredType
let _: Int = s.publicLazyProperty
let _: Int = s.publicLazyPropertyInferred
let _: Double = s.publicWrappedProperty
let _: Double = s.$publicWrappedProperty.wrappedValue
let _: Int = s.publicTransparentProperty
Expand All @@ -59,6 +61,8 @@ func testPublicClasses() {
let _: Int = c.publicMethod()
let _: Int = c.publicProperty
let _: String = c.publicPropertyInferredType
let _: Int = c.publicLazyProperty
let _: Int = c.publicLazyPropertyInferred
c.publicFinalWrappedProperty = true
PublicClass.publicClassMethod()
let _: Int = PublicClass.publicStaticProperty
Expand Down
4 changes: 1 addition & 3 deletions test/SILGen/lazy_typecheck_var_init.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ public struct S {
// CHECK-LABEL: sil [transparent]{{.*}} @$s4Test1SV12instanceVar2Sivpfi : $@convention(thin) () -> Int {
public var instanceVar2 = internalFunc(.b)

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

Expand Down

This file was deleted.

15 changes: 0 additions & 15 deletions test/SILGen/skip-function-bodies-lazy-property.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-silgen %s -import-objc-header %S/Inputs/open_enum.h -experimental-skip-non-inlinable-function-bodies | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -import-objc-header %S/Inputs/open_enum.h -experimental-skip-non-inlinable-function-bodies-without-types | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -import-objc-header %S/Inputs/open_enum.h -debug-forbid-typecheck-prefix SKIP_ALL_NO_TYPECHECK -experimental-skip-all-function-bodies | %FileCheck %s --check-prefix=CHECK-SKIP-ALL
// RUN: %target-swift-frontend -emit-silgen %s -module-name main -import-objc-header %S/Inputs/open_enum.h -experimental-skip-non-inlinable-function-bodies | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -module-name main -import-objc-header %S/Inputs/open_enum.h -experimental-skip-non-inlinable-function-bodies-without-types | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -module-name main -import-objc-header %S/Inputs/open_enum.h -debug-forbid-typecheck-prefix SKIP_ALL_NO_TYPECHECK -experimental-skip-all-function-bodies | %FileCheck %s --check-prefix=CHECK-SKIP-ALL

// CHECK-SKIP-ALL-NOT: s4main13inlinableFuncSo7YesOrNoVyF

Expand Down
41 changes: 41 additions & 0 deletions test/SILGen/skip_function_bodies_storage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-silgen %s -module-name main -experimental-skip-non-inlinable-function-bodies | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -module-name main -experimental-skip-non-inlinable-function-bodies-without-types | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -module-name main -import-objc-header %S/Inputs/open_enum.h -debug-forbid-typecheck-prefix SKIP_ALL_NO_TYPECHECK -experimental-skip-all-function-bodies | %FileCheck %s --check-prefix=CHECK-SKIP-ALL

// CHECK-SKIP-ALL: sil_stage raw
// CHECK-SKIP-ALL-NOT: sil

public protocol P {
@_borrowed var borrowedVar: Int { get }
}

func generateNumber() -> Int { return 1 }

public struct S {
public var borrowedVar: Int

public lazy var lazyVar: Int = generateNumber()

// CHECK: sil [transparent] [serialized]{{.*}} @$s4main1SV7lazyVarSivM : $@yield_once @convention(method) (@inout S) -> @yields @inout Int
// CHECK: end sil function '$s4main1SV7lazyVarSivM'

// CHECK: sil [lazy_getter]{{.*}} @$s4main1SV7lazyVarSivg : $@convention(method) (@inout S) -> Int
// CHECK-NOT: end sil function '$s4main1SV7lazyVarSivg'

// CHECK: sil{{.*}} @$s4main1SV7lazyVarSivs : $@convention(method) (Int, @inout S) -> ()
// CHECK-NOT: end sil function '$s4main1SV7lazyVarSivs'

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

}

/// Since `borrowedVar` implements a `@_borrowed` requirement of `P` the synthesized
/// `_read` accessor has forced static dispatch and is a serialized function
/// even though it is not `@_transparent`.
extension S: P {}

// CHECK: sil shared [serialized]{{.*}} @$s4main1SV11borrowedVarSivr : $@yield_once @convention(method) (S) -> @yields Int {
// CHECK: yield
// CHECK: } // end sil function '$s4main1SV11borrowedVarSivr'
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import Swift

// CHECK: sil_global @$s4Test15publicGlobalVarSivp : $Int

// CHECK-NO-SKIP: sil private{{.*}} @$s4Test11privateFunc33_E3F0E1C7B46D05C8067CB98677DE566CLLyyF : $@convention(thin) () -> () {
// CHECK-SKIP-NOT: s4Test11privateFunc33_E3F0E1C7B46D05C8067CB98677DE566CLLyyF
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test11privateFunc33_CFB3F9DC47F5EF9E1D08B58758351A08LLyyF : $@convention(thin) () -> () {
// CHECK-SKIP-NOT: s4Test11privateFunc33_CFB3F9DC47F5EF9E1D08B58758351A08LLyyF
private func privateFunc() {}

// CHECK-NO-SKIP: sil hidden{{.*}} @$s4Test12internalFuncyyF : $@convention(thin) () -> () {
Expand Down Expand Up @@ -71,17 +71,17 @@ public var publicGlobalVar = 1
// CHECK: sil shared [serialized]{{.*}} @$s4Test023inlinableFuncWithNestedC0yyF6nestedL_yyF : $@convention(thin) () -> () {

private class PrivateClass {
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCfd : $@convention(method) (@guaranteed PrivateClass) -> @owned Builtin.NativeObject {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCfd
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCfd : $@convention(method) (@guaranteed PrivateClass) -> @owned Builtin.NativeObject {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCfd

// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCfD : $@convention(method) (@owned PrivateClass) -> () {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCfD
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCfD : $@convention(method) (@owned PrivateClass) -> () {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCfD

// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCADycfC : $@convention(method) (@thick PrivateClass.Type) -> @owned PrivateClass {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCADycfC
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCADycfC : $@convention(method) (@thick PrivateClass.Type) -> @owned PrivateClass {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCADycfC

// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCADycfc : $@convention(method) (@owned PrivateClass) -> @owned PrivateClass {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCADycfc
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCADycfc : $@convention(method) (@owned PrivateClass) -> @owned PrivateClass {
// CHECK-SKIP-NOT: s4Test12PrivateClass33_CFB3F9DC47F5EF9E1D08B58758351A08LLCADycfc
}

public class PublicClass {
Expand Down