Skip to content

Commit 1af01ed

Browse files
authored
Merge pull request #30965 from slavapestov/enable-dynamic-replacement-vs-library-evolution
Enable dynamic replacement with library evolution
2 parents 628bf7b + 23cac67 commit 1af01ed

10 files changed

+132
-69
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4460,11 +4460,6 @@ ERROR(dynamic_with_transparent,none,
44604460
"a declaration cannot be both '@_tranparent' and 'dynamic'",
44614461
())
44624462

4463-
ERROR(dynamic_and_library_evolution_not_supported,none,
4464-
"marking non-'@objc' Swift declaration 'dynamic' in library evolution mode is not supported",
4465-
())
4466-
4467-
44684463
//------------------------------------------------------------------------------
44694464
// MARK: @_dynamicReplacement(for:)
44704465
//------------------------------------------------------------------------------

lib/IRGen/Linking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
629629
return SILLinkage::Private;
630630

631631
case Kind::DynamicallyReplaceableFunctionKey:
632+
return getSILFunction()->getLinkage();
633+
632634
case Kind::SILFunction:
633635
return getSILFunction()->getEffectiveSymbolLinkage();
634636

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,6 @@ void AttributeChecker::visitDynamicAttr(DynamicAttr *attr) {
347347
// Members cannot be both dynamic and @_transparent.
348348
if (D->getAttrs().hasAttribute<TransparentAttr>())
349349
diagnoseAndRemoveAttr(attr, diag::dynamic_with_transparent);
350-
if (!D->getAttrs().hasAttribute<ObjCAttr>() &&
351-
D->getModuleContext()->isResilient())
352-
diagnoseAndRemoveAttr(attr,
353-
diag::dynamic_and_library_evolution_not_supported);
354350
}
355351

356352
static bool
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend -emit-ir -enable-library-evolution %s | %FileCheck %s
2+
3+
public class ResilientClass {
4+
public dynamic func resilientMethod() {}
5+
}
6+
7+
// The dynamic replacement key should be public even though the method
8+
// implementation is hidden.
9+
10+
// CHECK-LABEL: @"$s36class_resilience_dynamic_replacement14ResilientClassC15resilientMethodyyFTx" = {{(protected )?}}constant %swift.dyn_repl_key
11+
// CHECK-LABEL: define hidden swiftcc void @"$s36class_resilience_dynamic_replacement14ResilientClassC15resilientMethodyyF"

test/Interpreter/Inputs/dynamic_replacement_module.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,15 @@ public func replacement_for_public_global_generic_func<T>(_ t: T.Type) -> String
162162
}
163163

164164
extension PublicClass {
165+
166+
// Designated initializers of resilient classes cannot be
167+
// dynamically replaced.
168+
#if !EVOLUTION
165169
@_dynamicReplacement(for: init(x:))
166170
public init(y: Int) {
167171
str = "replacement of public_class_init"
168172
}
173+
#endif
169174

170175
@_dynamicReplacement(for: function())
171176
public func replacement_function() -> String {

test/Interpreter/dynamic_replacement.swift

Lines changed: 98 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,58 @@
4646
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
4747
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
4848

49+
///////////////////////////////////////////////////////////////////////////////
50+
// Now repeat all of the same tests, but with library evolution enabled:
51+
///////////////////////////////////////////////////////////////////////////////
52+
53+
// RUN: %empty-directory(%t)
54+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
55+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
56+
// RUN: %target-build-swift -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
57+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
58+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
59+
60+
// Now the same in optimized mode.
61+
// RUN: %empty-directory(%t)
62+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -O -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
63+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -O -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
64+
// RUN: %target-build-swift -O -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
65+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
66+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
67+
68+
// Now the same in size mode.
69+
// RUN: %empty-directory(%t)
70+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -Osize -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
71+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -Osize -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
72+
// RUN: %target-build-swift -Osize -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
73+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
74+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
75+
76+
// Now the same in optimized wholemodule mode.
77+
// RUN: %empty-directory(%t)
78+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -O -wmo -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -enable-library-evolution
79+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -O -wmo -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
80+
// RUN: %target-build-swift -O -wmo -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
81+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
82+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
83+
84+
// Test the -enable-implicit-dynamic flag.
85+
86+
// RUN: %empty-directory(%t)
87+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -DMODULENODYNAMIC -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -Xfrontend -enable-implicit-dynamic -enable-library-evolution
88+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
89+
// RUN: %target-build-swift -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
90+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
91+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
92+
93+
// Test the -enable-implicit-dynamic flag in optimized wholemodule mode.
94+
// RUN: %empty-directory(%t)
95+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module1)) -O -wmo -DMODULENODYNAMIC -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -Xfrontend -enable-implicit-dynamic -enable-library-evolution
96+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module2)) -O -wmo -I%t -L%t -lModule1 %target-rpath(%t) -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_module.swift -DEVOLUTION
97+
// RUN: %target-build-swift -O -wmo -I%t -L%t -lModule1 -DMAIN -o %t/main %target-rpath(%t) %s -swift-version 5 -DEVOLUTION
98+
// RUN: %target-codesign %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
99+
// RUN: %target-run %t/main %t/%target-library-name(Module1) %t/%target-library-name(Module2)
100+
49101

50102
// REQUIRES: executable_test
51103

@@ -75,42 +127,51 @@ func expectedResult(_ forOriginalLibrary: Bool, _ expectedOriginalString: Strin
75127
}
76128

77129
func checkExpectedResults(forOriginalLibrary useOrig: Bool) {
78-
expectTrue(public_global_var == expectedResult(useOrig, "public_global_var"))
79-
80-
expectTrue(public_global_func() ==
81-
expectedResult(useOrig, "public_global_func"))
82-
expectTrue(public_global_generic_func(Int.self) ==
83-
expectedResult(useOrig, "public_global_generic_func"))
84-
85-
expectTrue(PublicClass().function() ==
86-
expectedResult(useOrig, "public_class_func"))
87-
expectTrue(PublicClass().finalFunction() ==
88-
expectedResult(useOrig, "public_class_final_func"))
89-
expectTrue(PublicClass().genericFunction(Int.self) ==
90-
expectedResult(useOrig, "public_class_generic_func"))
91-
92-
expectTrue(PublicStruct().function() ==
93-
expectedResult(useOrig, "public_struct_func"))
94-
expectTrue(PublicStruct().genericFunction(Int.self) ==
95-
expectedResult(useOrig, "public_struct_generic_func"))
96-
expectTrue(PublicStruct().public_stored_property ==
97-
expectedResult(useOrig, "public_stored_property"))
98-
expectTrue(PublicStruct()[0] ==
99-
expectedResult(useOrig, "public_subscript_get"))
100-
expectTrue(PublicStruct()[y:0] ==
101-
expectedResult(useOrig, "public_subscript_get_modify_read"))
102-
var testSetter = PublicStruct()
103-
testSetter[0] = "public_subscript_set"
104-
expectTrue(testSetter.str ==
105-
expectedResult(useOrig, "public_subscript_set"))
106-
testSetter[y:0] = "public_subscript_set_modify_read"
107-
expectTrue(testSetter.str ==
108-
expectedResult(useOrig, "public_subscript_set_modify_read"))
109-
110-
expectTrue(PublicEnumeration<Int>.A.function() ==
111-
expectedResult(useOrig, "public_enum_func"))
112-
expectTrue(PublicEnumeration<Int>.B.genericFunction(Int.self) ==
113-
expectedResult(useOrig, "public_enum_generic_func"))
130+
expectTrue(public_global_var == expectedResult(useOrig, "public_global_var"))
131+
132+
expectTrue(public_global_func() ==
133+
expectedResult(useOrig, "public_global_func"))
134+
expectTrue(public_global_generic_func(Int.self) ==
135+
expectedResult(useOrig, "public_global_generic_func"))
136+
137+
// Designated initializers of resilient classes cannot be
138+
// dynamically replaced.
139+
#if !EVOLUTION
140+
expectTrue(PublicClass(x: 0).str ==
141+
expectedResult(useOrig, "public_class_init"))
142+
#endif
143+
144+
expectTrue(PublicClass().function() ==
145+
expectedResult(useOrig, "public_class_func"))
146+
expectTrue(PublicClass().finalFunction() ==
147+
expectedResult(useOrig, "public_class_final_func"))
148+
expectTrue(PublicClass().genericFunction(Int.self) ==
149+
expectedResult(useOrig, "public_class_generic_func"))
150+
151+
expectTrue(PublicStruct(x: 0).str ==
152+
expectedResult(useOrig, "public_struct_init"))
153+
expectTrue(PublicStruct().function() ==
154+
expectedResult(useOrig, "public_struct_func"))
155+
expectTrue(PublicStruct().genericFunction(Int.self) ==
156+
expectedResult(useOrig, "public_struct_generic_func"))
157+
expectTrue(PublicStruct().public_stored_property ==
158+
expectedResult(useOrig, "public_stored_property"))
159+
expectTrue(PublicStruct()[0] ==
160+
expectedResult(useOrig, "public_subscript_get"))
161+
expectTrue(PublicStruct()[y:0] ==
162+
expectedResult(useOrig, "public_subscript_get_modify_read"))
163+
var testSetter = PublicStruct()
164+
testSetter[0] = "public_subscript_set"
165+
expectTrue(testSetter.str ==
166+
expectedResult(useOrig, "public_subscript_set"))
167+
testSetter[y:0] = "public_subscript_set_modify_read"
168+
expectTrue(testSetter.str ==
169+
expectedResult(useOrig, "public_subscript_set_modify_read"))
170+
171+
expectTrue(PublicEnumeration<Int>.A.function() ==
172+
expectedResult(useOrig, "public_enum_func"))
173+
expectTrue(PublicEnumeration<Int>.B.genericFunction(Int.self) ==
174+
expectedResult(useOrig, "public_enum_generic_func"))
114175
}
115176

116177
private func target_library_name(_ name: String) -> String {
@@ -135,7 +196,7 @@ DynamicallyReplaceable.test("DynamicallyReplaceable") {
135196
#if os(Linux)
136197
_ = dlopen(target_library_name("Module2"), RTLD_NOW)
137198
#elseif os(Windows)
138-
_ = LoadLibraryA(target_library_name("Module2"))
199+
_ = LoadLibraryA(target_library_name("Module2"))
139200
#else
140201
_ = dlopen(executablePath+target_library_name("Module2"), RTLD_NOW)
141202
#endif

test/Interpreter/dynamic_replacement_chaining.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ DynamicallyReplaceable.test("DynamicallyReplaceable") {
5353
executablePath.removeLast(4)
5454

5555
#if os(Linux)
56-
_ = dlopen(target_library_name("B"), RTLD_NOW)
57-
_ = dlopen(target_library_name("C"), RTLD_NOW)
56+
_ = dlopen(target_library_name("B"), RTLD_NOW)
57+
_ = dlopen(target_library_name("C"), RTLD_NOW)
5858
#elseif os(Windows)
59-
_ = LoadLibraryA(target_library_name("B"))
60-
_ = LoadLibraryA(target_library_name("C"))
59+
_ = LoadLibraryA(target_library_name("B"))
60+
_ = LoadLibraryA(target_library_name("C"))
6161
#else
62-
_ = dlopen(executablePath+target_library_name("B"), RTLD_NOW)
63-
_ = dlopen(executablePath+target_library_name("C"), RTLD_NOW)
62+
_ = dlopen(executablePath+target_library_name("B"), RTLD_NOW)
63+
_ = dlopen(executablePath+target_library_name("C"), RTLD_NOW)
6464
#endif
6565

6666
#if CHAINING

test/Interpreter/dynamic_replacement_opaque_result2.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
// RUN: %target-codesign %t/main
44
// RUN: %target-run %t/main | %FileCheck %s
55

6+
// RUN: %target-build-swift -o %t/main %target-rpath(%t) %s -swift-version 5 -enable-library-evolution
7+
// RUN: %target-codesign %t/main
8+
// RUN: %target-run %t/main | %FileCheck %s
9+
610
// REQUIRES: executable_test
711
// REQUIRES: swift_test_mode_optimize_none
812
// REQUIRES: CPU=arm64 || CPU=arm64e || CPU=x86_64

test/Interpreter/dynamic_replacement_protocol_self.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
// RUN: %empty-directory(%t)
2+
23
// RUN: %target-build-swift-dylib(%t/%target-library-name(TestModuleLinking)) -module-name TestModuleLinking -emit-module -emit-module-path %t/TestModuleLinking.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_protocol_self_orig.swift -Xfrontend -enable-private-imports -Xfrontend -enable-implicit-dynamic
34
// RUN: %target-build-swift -I%t -L%t -lTestModuleLinking -o %t/main %target-rpath(%t) %s -swift-version 5
45
// RUN: %target-codesign %t/main %t/%target-library-name(TestModuleLinking)
56
// RUN: %target-run %t/main %t/%target-library-name(TestModuleLinking) %t/%target-library-name(TestModuleLinking)
67

8+
// RUN: %target-build-swift-dylib(%t/%target-library-name(TestModuleLinking)) -module-name TestModuleLinking -emit-module -emit-module-path %t/TestModuleLinking.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_protocol_self_orig.swift -Xfrontend -enable-private-imports -Xfrontend -enable-implicit-dynamic -enable-library-evolution
9+
// RUN: %target-build-swift -I%t -L%t -lTestModuleLinking -o %t/main %target-rpath(%t) %s -swift-version 5
10+
// RUN: %target-codesign %t/main %t/%target-library-name(TestModuleLinking)
11+
// RUN: %target-run %t/main %t/%target-library-name(TestModuleLinking) %t/%target-library-name(TestModuleLinking)
12+
713
// N.B. We're not actually executing anything here - all we care about is
814
// if the linker is content.
915

test/attr/dynamicReplacement_library_evolution.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)