Skip to content

Commit 4771ce0

Browse files
committed
AST: Weak-link declarations in extensions of weak-linked types
This is a workaround to fix weak linking of frameworks that define types with availability, but then define extensions of those types without availability. This can come up if the framework itself is built with a newer deployment target than the client that uses the framework. Since the type checker only enforces that an extension has availability if the extension is less available than the deployment target, we were failing to weak link the members of the extension in this case. This is not a perfect fix; ideally such frameworks should be built with -require-explicit-availability, and all reported warnings fixed by adding explicit availability. However, it allows clients to weak link when using existing swiftinterface files that have already shipped in the mean time, and it should not cause any problems once the frameworks are properly annotated in the future. Fixes <rdar://problem/58490723>.
1 parent b73adbe commit 4771ce0

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,10 @@ AvailabilityContext Decl::getAvailabilityForLinkage() const {
785785
if (auto *accessor = dyn_cast<AccessorDecl>(this))
786786
return accessor->getStorage()->getAvailabilityForLinkage();
787787

788+
if (auto *ext = dyn_cast<ExtensionDecl>(this))
789+
if (auto *nominal = ext->getExtendedNominal())
790+
return nominal->getAvailabilityForLinkage();
791+
788792
auto *dc = getDeclContext();
789793
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
790794
return ext->getAvailabilityForLinkage();
@@ -806,6 +810,10 @@ bool Decl::isAlwaysWeakImported() const {
806810
if (auto *accessor = dyn_cast<AccessorDecl>(this))
807811
return accessor->getStorage()->isAlwaysWeakImported();
808812

813+
if (auto *ext = dyn_cast<ExtensionDecl>(this))
814+
if (auto *nominal = ext->getExtendedNominal())
815+
return nominal->isAlwaysWeakImported();
816+
809817
auto *dc = getDeclContext();
810818
if (auto *ext = dyn_cast<ExtensionDecl>(dc))
811819
return ext->isAlwaysWeakImported();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@available(macOS 10.60, *)
2+
public struct Foo {
3+
public init() {}
4+
}
5+
6+
extension Foo {
7+
public func extensionMethod() {}
8+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %empty-directory(%t)
2+
//
3+
// RUN: %target-swift-frontend -enable-library-evolution -emit-module -target x86_64-apple-macosx10.60 -emit-module-path %t/weak_import_extension_helper.swiftmodule -parse-as-library %S/Inputs/weak_import_extension_helper.swift
4+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target x86_64-apple-macosx10.50 | %FileCheck %s --check-prefix=CHECK-OLD
5+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target x86_64-apple-macosx10.60 | %FileCheck %s --check-prefix=CHECK-NEW
6+
//
7+
// REQUIRES: OS=macosx
8+
9+
import weak_import_extension_helper
10+
11+
@available(macOS 10.60, *)
12+
public func callsExtensionMethod() {
13+
Foo().extensionMethod()
14+
}
15+
16+
// CHECK-OLD: declare extern_weak swiftcc %swift.metadata_response @"$s28weak_import_extension_helper3FooVMa"
17+
// CHECK-OLD: declare extern_weak swiftcc void @"$s28weak_import_extension_helper3FooVACycfC"
18+
// CHECK-OLD: declare extern_weak swiftcc void @"$s28weak_import_extension_helper3FooV0C6MethodyyF"
19+
20+
// CHECK-NEW: declare swiftcc %swift.metadata_response @"$s28weak_import_extension_helper3FooVMa"
21+
// CHECK-NEW: declare swiftcc void @"$s28weak_import_extension_helper3FooVACycfC"
22+
// CHECK-NEW: declare swiftcc void @"$s28weak_import_extension_helper3FooV0C6MethodyyF"

0 commit comments

Comments
 (0)