From 5f9ff021d48488015cfb0c7a741816f50eb7e332 Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Mon, 8 Oct 2018 17:40:58 -0700 Subject: [PATCH] [Sema] Allow non-public static property initializers in @_fixed_layout types Static properties are not subject to the same restrictions as properties whose initializers are exposed to clients in @_fixed_layout types. rdar://45080912 --- lib/AST/Decl.cpp | 11 ++-- lib/Sema/ResilienceDiagnostics.cpp | 9 ++++ .../fixed-layout-property-initializers.swift | 53 ++++++++----------- test/attr/attr_inlinable.swift | 5 ++ 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4a3780785640..9de42ead6149 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1302,14 +1302,9 @@ VarDecl *PatternBindingDecl::getSingleVar() const { bool VarDecl::isInitExposedToClients() const { auto parent = dyn_cast(getDeclContext()); if (!parent) return false; - if (!hasInitialValue()) - return false; - if (isStatic()) - return false; - if (!parent->getAttrs().hasAttribute()) - return false; - auto *module = parent->getModuleContext(); - return module->getResilienceStrategy() == ResilienceStrategy::Resilient; + if (!hasInitialValue()) return false; + if (isStatic()) return false; + return parent->getAttrs().hasAttribute(); } /// Check whether the given type representation will be diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp index 413c5e7951af..5cf0f3d3e8f1 100644 --- a/lib/Sema/ResilienceDiagnostics.cpp +++ b/lib/Sema/ResilienceDiagnostics.cpp @@ -120,6 +120,15 @@ bool TypeChecker::diagnoseInlinableDeclRef(SourceLoc loc, return false; } + // Property initializers that are not exposed to clients are OK. + if (auto pattern = dyn_cast(DC)) { + auto bindingIndex = pattern->getBindingIndex(); + auto &patternEntry = pattern->getBinding()->getPatternList()[bindingIndex]; + auto varDecl = patternEntry.getAnchoringVarDecl(); + if (!varDecl->isInitExposedToClients()) + return false; + } + DowngradeToWarning downgradeToWarning = DowngradeToWarning::No; // Swift 4.2 did not perform any checks for type aliases. diff --git a/test/ParseableInterface/fixed-layout-property-initializers.swift b/test/ParseableInterface/fixed-layout-property-initializers.swift index 509307cca051..0b817bcc110e 100644 --- a/test/ParseableInterface/fixed-layout-property-initializers.swift +++ b/test/ParseableInterface/fixed-layout-property-initializers.swift @@ -1,76 +1,65 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.swiftinterface %s -// RUN: %FileCheck %s < %t.swiftinterface --check-prefix CHECK --check-prefix COMMON +// RUN: %FileCheck %s < %t.swiftinterface // RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t-resilient.swiftinterface -enable-resilience %s -// RUN: %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON < %t-resilient.swiftinterface +// RUN: %FileCheck %s < %t-resilient.swiftinterface -// FIXME(rdar44993525): %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module -// FIXME(rdar44993525): %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-parseable-module-interface-path - | %FileCheck %s --check-prefix CHECK --check-prefix COMMON +// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module +// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-parseable-module-interface-path - | %FileCheck %s // RUN: %target-swift-frontend -emit-module -o %t/TestResilient.swiftmodule -enable-resilience %t-resilient.swiftinterface -disable-objc-attr-requires-foundation-module -// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-parseable-module-interface-path - | %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON +// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-parseable-module-interface-path - | %FileCheck %s -// COMMON: @_fixed_layout public struct MyStruct { +// CHECK: @_fixed_layout public struct MyStruct { @_fixed_layout public struct MyStruct { - // CHECK: @_hasInitialValue public var publicVar: [[BOOL:(Swift\.)?Bool]]{{$}} - // RESILIENT: public var publicVar: [[BOOL:(Swift\.)?Bool]] = false + // CHECK: public var publicVar: [[BOOL:(Swift\.)?Bool]] = false public var publicVar: Bool = false - // CHECK: @_hasInitialValue internal var internalVar: ([[BOOL]], [[BOOL]]){{$}} - // RESILIENT: internal var internalVar: ([[BOOL]], [[BOOL]]) = (false, true) + // CHECK: internal var internalVar: ([[BOOL]], [[BOOL]]) = (false, true) internal var internalVar: (Bool, Bool) = (false, true) - // CHECK: @_hasInitialValue private var privateVar: [[BOOL]]{{$}} - // RESILIENT: private var privateVar: [[BOOL]] = Bool(4 < 10) + // CHECK: private var privateVar: [[BOOL]] = Bool(4 < 10) private var privateVar: Bool = Bool(4 < 10) // CHECK: @usableFromInline - // CHECK-NEXT: internal var ufiVar: [[BOOL]]{{$}} - // RESILIENT: @usableFromInline - // RESILIENT-NEXT: internal var ufiVar: [[BOOL]] = true + // CHECK-NEXT: internal var ufiVar: [[BOOL]] = true @usableFromInline internal var ufiVar: Bool = true - // CHECK: @_hasInitialValue public var multiVar1: [[BOOL]], (multiVar2, multiVar3): ([[BOOL]], [[BOOL]]) - // RESILIENT: public var multiVar1: [[BOOL]] = Bool(false), (multiVar2, multiVar3): ([[BOOL]], [[BOOL]]) = (true, 3 == 0) + // CHECK: public var multiVar1: [[BOOL]] = Bool(false), (multiVar2, multiVar3): ([[BOOL]], [[BOOL]]) = (true, 3 == 0) public var multiVar1: Bool = Bool(false), (multiVar2, multiVar3): (Bool, Bool) = (true, 3 == 0) - // COMMON: @_hasInitialValue public static var staticVar: [[BOOL]] + // CHECK: @_hasInitialValue public static var staticVar: [[BOOL]] public static var staticVar: Bool = Bool(true && false) - // COMMON: @inlinable internal init() {} + // CHECK: @inlinable internal init() {} @inlinable init() {} } -// COMMON: @_fixed_layout public class MyClass { +// CHECK: @_fixed_layout public class MyClass { @_fixed_layout public class MyClass { - // CHECK: @_hasInitialValue public var publicVar: [[BOOL]]{{$}} - // RESILIENT: public var publicVar: [[BOOL]] = false + // CHECK: public var publicVar: [[BOOL]] = false public var publicVar: Bool = false - // CHECK: @_hasInitialValue internal var internalVar: [[BOOL]]{{$}} - // RESILIENT: internal var internalVar: [[BOOL]] = false + // CHECK: internal var internalVar: [[BOOL]] = false internal var internalVar: Bool = false - // CHECK: @_hasInitialValue private var privateVar: {{(Swift\.)?}}UInt8{{$}} - // RESILIENT: private var privateVar: {{(Swift\.)?}}UInt8 = UInt8(2) + // CHECK: private var privateVar: {{(Swift\.)?}}UInt8 = UInt8(2) private var privateVar: UInt8 = UInt8(2) // CHECK: @usableFromInline - // CHECK-NEXT: internal var ufiVar: [[BOOL]]{{$}} - // RESILIENT: @usableFromInline - // RESILIENT: internal var ufiVar: [[BOOL]] = true + // CHECK-NEXT: internal var ufiVar: [[BOOL]] = true @usableFromInline internal var ufiVar: Bool = true - // COMMON: @_hasInitialValue public static var staticVar: [[BOOL]] + // CHECK: @_hasInitialValue public static var staticVar: [[BOOL]] public static var staticVar: Bool = Bool(true && false) - // COMMON: @inlinable internal init() {} + // CHECK: @inlinable internal init() {} @inlinable init() {} } -// COMMON: @_hasInitialValue public var topLevelVar: [[BOOL]] +// CHECK: @_hasInitialValue public var topLevelVar: [[BOOL]] public var topLevelVar: Bool = Bool(false && !true) diff --git a/test/attr/attr_inlinable.swift b/test/attr/attr_inlinable.swift index e97d16ccdab3..370436683c4b 100644 --- a/test/attr/attr_inlinable.swift +++ b/test/attr/attr_inlinable.swift @@ -247,10 +247,15 @@ public struct PublicResilientStructWithInit { var y = publicGlobal // OK } +private func privateIntReturningFunc() -> Int { return 0 } +internal func internalIntReturningFunc() -> Int { return 0 } + @_fixed_layout public struct PublicFixedStructWithInit { var x = internalGlobal // expected-error {{let 'internalGlobal' is internal and cannot be referenced from a property initializer in a '@_fixed_layout' type}} var y = publicGlobal // OK + static var z = privateIntReturningFunc() // OK + static var a = internalIntReturningFunc() // OK } public struct KeypathStruct {