From 0df911c45b93cfc8d9e5bbdbf880b93956c9865e Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 15 Jul 2022 12:21:03 -0700 Subject: [PATCH] IRGen: Weakly link associated conformance descriptors when either the protocol or the associated requirement is weak. Previously, only the associated requirement was considered when deciding whether to weakly link an associated conformance descriptor. This lead to unexpected strong linkage for some symbols, interfering with back deployment when integrating with some frameworks. Resolves rdar://96974850 --- lib/IRGen/Linking.cpp | 9 ++- ...rt_associated_conformance_descriptor.swift | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 test/IRGen/weak_import_associated_conformance_descriptor.swift diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp index 67703215902db..98a41119720c3 100644 --- a/lib/IRGen/Linking.cpp +++ b/lib/IRGen/Linking.cpp @@ -1182,9 +1182,12 @@ bool LinkEntity::isWeakImported(ModuleDecl *module) const { case Kind::AssociatedConformanceDescriptor: case Kind::DefaultAssociatedConformanceAccessor: { - // Associated conformance descriptors use the protocol as - // their declaration, but are weak linked if the associated - // type stored in extra storage area is weak linked. + // Associated conformance descriptors use the protocol as their declaration + // and are weak linked if either the protocol or the associated type stored + // in extra storage area is weak linked. + if (cast(getDecl())->isWeakImported(module)) + return true; + auto assocConformance = getAssociatedConformance(); auto *depMemTy = assocConformance.first->castTo(); return depMemTy->getAssocType()->isWeakImported(module); diff --git a/test/IRGen/weak_import_associated_conformance_descriptor.swift b/test/IRGen/weak_import_associated_conformance_descriptor.swift new file mode 100644 index 0000000000000..42d9680083aff --- /dev/null +++ b/test/IRGen/weak_import_associated_conformance_descriptor.swift @@ -0,0 +1,58 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/Library.swiftmodule -parse-as-library %t/Library.swift -enable-library-evolution +// RUN: %target-swift-frontend -primary-file %t/Client.swift -I %t -emit-ir | %FileCheck %s + +// REQUIRES: OS=macosx + +//--- Library.swift + +public protocol P { } +public protocol Q: P { } + +public protocol StrongProtoWithAssoc { + associatedtype Assoc: P +} + +public protocol StrongProtoWithWeakLinkedAssoc { + @_weakLinked associatedtype Assoc: P +} + +@available(macOS 10.50, *) +public protocol WeakProtoWithAssoc { + associatedtype Assoc: P +} + +@available(macOS 10.50, *) +public protocol WeakProtoWithStrongInheritedAssoc: StrongProtoWithAssoc where Self.Assoc: Q { } + + +//--- Client.swift + +import Library + +struct ConformsToP: P { } +struct ConformsToQ: Q { } + +// CHECK: @"$s7Library20StrongProtoWithAssocP0E0AC_AA1PTn" = external global %swift.protocol_requirement, align 4 +struct ConformsToStrongProtoWithAssoc: StrongProtoWithAssoc { + typealias Assoc = ConformsToP +} + +// CHECK: @"$s7Library30StrongProtoWithWeakLinkedAssocP0G0AC_AA1PTn" = extern_weak global %swift.protocol_requirement, align 4 +struct ConformsToStrongProtoWithWeakLinkedAssoc: StrongProtoWithWeakLinkedAssoc { + typealias Assoc = ConformsToP +} + +// CHECK: @"$s7Library18WeakProtoWithAssocP0E0AC_AA1PTn" = extern_weak global %swift.protocol_requirement, align 4 +@available(macOS 10.50, *) +struct ConformsToWeakProtoWithAssoc: WeakProtoWithAssoc { + typealias Assoc = ConformsToP +} + +// CHECK: @"$s7Library33WeakProtoWithStrongInheritedAssocP0G0AA0ecdG0P_AA1QTn" = extern_weak global %swift.protocol_requirement, align 4 +@available(macOS 10.50, *) +struct ConformsToWeakProtoWithStrongInheritedAssoc: WeakProtoWithStrongInheritedAssoc { + typealias Assoc = ConformsToQ +}