Skip to content

[Property wrappers] Fix property wrapper backing initializer linkage. #30590

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
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
14 changes: 3 additions & 11 deletions lib/SIL/SILDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,8 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
limit = Limit::NeverPublic;
}

// The property wrapper backing initializer is never public for resilient
// properties.
if (kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer) {
if (cast<VarDecl>(d)->isResilient())
limit = Limit::NeverPublic;
}

// Stored property initializers get the linkage of their containing type.
if (isStoredPropertyInitializer()) {
if (isStoredPropertyInitializer() || isPropertyWrapperBackingInitializer()) {
// Three cases:
//
// 1) Type is formally @_fixed_layout/@frozen. Root initializers can be
Expand Down Expand Up @@ -483,7 +476,7 @@ IsSerialized_t SILDeclRef::isSerialized() const {

// Stored property initializers are inlinable if the type is explicitly
// marked as @frozen.
if (isStoredPropertyInitializer()) {
if (isStoredPropertyInitializer() || isPropertyWrapperBackingInitializer()) {
auto *nominal = cast<NominalTypeDecl>(d->getDeclContext());
auto scope =
nominal->getFormalAccessScope(/*useDC=*/nullptr,
Expand Down Expand Up @@ -1130,8 +1123,7 @@ bool SILDeclRef::canBeDynamicReplacement() const {
bool SILDeclRef::isDynamicallyReplaceable() const {
if (kind == SILDeclRef::Kind::DefaultArgGenerator)
return false;
if (isStoredPropertyInitializer() ||
kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer)
if (isStoredPropertyInitializer() || isPropertyWrapperBackingInitializer())
return false;

// Class allocators are not dynamic replaceable.
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/dynamically_replaceable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ struct WrapperWithInitialValue<T> {
}
}

// CHECK-LABEL: sil hidden [ossa] @$s23dynamically_replaceable10SomeStructV1tSbvpfP
// CHECK-NOT: sil hidden [ossa] @$s23dynamically_replaceable10SomeStructV1tSbvpfP
public struct SomeStruct {
@WrapperWithInitialValue var t = false
}
Expand Down
2 changes: 2 additions & 0 deletions test/SILGen/property_wrappers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ public protocol TestProtocol {}
public class TestClass<T> {
@WrapperWithInitialValue var value: T

// CHECK-LABEL: sil [ossa] @$s17property_wrappers9TestClassC5valuexvpfP : $@convention(thin) <T> (@in T) -> @out WrapperWithInitialValue<T>

// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers9TestClassC5value8protocolACyxGx_qd__tcAA0C8ProtocolRd__lufc
// CHECK: [[BACKING_INIT:%.*]] = function_ref @$s17property_wrappers9TestClassC5valuexvpfP : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out WrapperWithInitialValue<τ_0_0>
// CHECK-NEXT: partial_apply [callee_guaranteed] [[BACKING_INIT]]<T>()
Expand Down
11 changes: 10 additions & 1 deletion test/SILGen/property_wrappers_library_evolution.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t -enable-library-evolution %S/Inputs/property_wrapper_defs.swift
// RUN: %target-swift-emit-silgen -primary-file %s -I %t -enable-library-evolution
// RUN: %target-swift-emit-silgen -primary-file %s -I %t -enable-library-evolution | %FileCheck %s
import property_wrapper_defs

// rdar://problem/55995892
// This is a crash that occurs only with -enable-library-evolution.

public enum E { case a }
struct M { @MyPublished private var e = E.a }

// Ensure that the backing initializer is serialized.
@frozen
public struct StructUsesPublishedAsPrivate {
public var integer: Int = 17

// CHECK: sil non_abi [serialized] [ossa] @$s35property_wrappers_library_evolution28StructUsesPublishedAsPrivateV6stringSSvpfP : $@convention(thin) (@owned String) -> @out MyPublished<String>
@MyPublished var string: String = "Hello"
}
20 changes: 20 additions & 0 deletions test/decl/var/property_wrappers_library_evolution.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %target-swift-frontend -typecheck %s -verify -enable-library-evolution

@propertyWrapper
public struct ResilientWrapper<T> {
public var wrappedValue: T

public init(wrappedValue: T, description: String) {
self.wrappedValue = wrappedValue
}
}

func getHello() -> String { return "hello" } // expected-note 2 {{global function 'getHello()' is not '@usableFromInline' or public}}

@frozen
public struct StructUsesPublishedAsPrivate {
public var integer: Int = 17

@ResilientWrapper(description: getHello()) // expected-error 2 {{global function 'getHello()' is internal and cannot be referenced from a property initializer in a '@frozen' type}}
var otherString: String = "World"
}