Merge pull request #21014 from slavapestov/backward-deployment-5.0
Backward deployment fixes and tests [5.0]
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index 120b397..99832e9 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -845,13 +845,15 @@
template <typename Runtime>
struct TargetMethodOverrideDescriptor {
/// The class containing the base method.
- TargetRelativeIndirectablePointer<Runtime, TargetClassDescriptor<Runtime>> Class;
+ TargetRelativeIndirectablePointer<Runtime, TargetClassDescriptor<Runtime>,
+ /*nullable*/ true> Class;
/// The base method.
- TargetRelativeIndirectablePointer<Runtime, TargetMethodDescriptor<Runtime>> Method;
+ TargetRelativeIndirectablePointer<Runtime, TargetMethodDescriptor<Runtime>,
+ /*nullable*/ true> Method;
/// The implementation of the override.
- TargetRelativeDirectPointer<Runtime, void, /*Nullable=*/true> Impl;
+ TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> Impl;
};
/// Header for a class vtable override descriptor. This is a variable-sized
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 8693e9b..1e15e8b 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -362,7 +362,7 @@
NotSerialized, 74)
SIMPLE_DECL_ATTR(_weakLinked, WeakLinked,
OnNominalType | OnAssociatedType | OnFunc | OnAccessor | OnVar |
- OnSubscript | OnConstructor | OnEnumElement | UserInaccessible,
+ OnSubscript | OnConstructor | OnEnumElement | OnExtension | UserInaccessible,
75)
SIMPLE_DECL_ATTR(_frozen, Frozen,
OnEnum |
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 417fcb7..f358644 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -356,6 +356,9 @@
bool isInvalid() const;
+ /// Whether this conformance is weak-imported.
+ bool isWeakImported(ModuleDecl *fromModule) const;
+
bool hasWitness(ValueDecl *requirement) const;
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 21a9532..37ff731 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -557,6 +557,12 @@
if (auto *dtor = dyn_cast<DestructorDecl>(this))
return cast<ClassDecl>(dtor->getDeclContext())->isWeakImported(fromModule);
+ auto *dc = getDeclContext();
+ if (auto *ext = dyn_cast<ExtensionDecl>(dc))
+ return ext->isWeakImported(fromModule);
+ if (auto *ntd = dyn_cast<NominalTypeDecl>(dc))
+ return ntd->isWeakImported(fromModule);
+
// FIXME: Also check availability when containingModule is resilient.
return false;
}
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index ac6abac..71c9090 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -394,6 +394,29 @@
ROOT_CONFORMANCE_SUBCLASS_DISPATCH(getLoc, ())
}
+bool RootProtocolConformance::isWeakImported(ModuleDecl *fromModule) const {
+ auto *dc = getDeclContext();
+ if (dc->getParentModule() == fromModule)
+ return false;
+
+ // If the protocol is weak imported, so are any conformances to it.
+ if (getProtocol()->isWeakImported(fromModule))
+ return true;
+
+ // If the conforming type is weak imported, so are any of its conformances.
+ if (auto *nominal = getType()->getAnyNominal())
+ if (nominal->isWeakImported(fromModule))
+ return true;
+
+ // If the conformance is declared in an extension with the @_weakLinked
+ // attribute, it is weak imported.
+ if (auto *ext = dyn_cast<ExtensionDecl>(dc))
+ if (ext->isWeakImported(fromModule))
+ return true;
+
+ return false;
+}
+
bool RootProtocolConformance::hasWitness(ValueDecl *requirement) const {
ROOT_CONFORMANCE_SUBCLASS_DISPATCH(hasWitness, (requirement))
}
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index ba7937b..9cc0b57 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -917,6 +917,11 @@
case Kind::DynamicallyReplaceableFunctionImpl:
return getDecl()->isWeakImported(module);
+ case Kind::ProtocolWitnessTable:
+ case Kind::ProtocolConformanceDescriptor:
+ return getProtocolConformance()->getRootConformance()
+ ->isWeakImported(module);
+
// TODO: Revisit some of the below, for weak conformances.
case Kind::TypeMetadataPattern:
case Kind::TypeMetadataInstantiationCache:
@@ -925,12 +930,10 @@
case Kind::TypeMetadataCompletionFunction:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
- case Kind::ProtocolWitnessTable:
case Kind::ProtocolWitnessTablePattern:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::ReflectionAssociatedTypeDescriptor:
- case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ValueWitness:
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index d5e2725..0f3b905 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -2364,6 +2364,11 @@
auto *baseClass = descriptor.Class.get();
auto *baseMethod = descriptor.Method.get();
+ // If the base method is null, it's an unavailable weak-linked
+ // symbol.
+ if (baseClass == nullptr || baseMethod == nullptr)
+ continue;
+
// Calculate the base method's vtable offset from the
// base method descriptor. The offset will be relative
// to the base class's vtable start offset.
diff --git a/test/IRGen/Inputs/weak_import_native_helper.swift b/test/IRGen/Inputs/weak_import_native_helper.swift
index 6ba6bdf..4be0ee8 100644
--- a/test/IRGen/Inputs/weak_import_native_helper.swift
+++ b/test/IRGen/Inputs/weak_import_native_helper.swift
@@ -83,7 +83,10 @@
}
@_weakLinked
-public struct WeakS {}
+public struct WeakS {
+ public init() {}
+ public func weakMember() {}
+}
@_weakLinked
public enum WeakE {}
@@ -115,3 +118,6 @@
extension ProtocolWithWeakMembers {
@_weakLinked public func f() {}
}
+
+public protocol BaseP {}
+@_weakLinked extension S : BaseP {}
diff --git a/test/IRGen/weak_import_native.swift b/test/IRGen/weak_import_native.swift
index 361c842..20fbbd7 100644
--- a/test/IRGen/weak_import_native.swift
+++ b/test/IRGen/weak_import_native.swift
@@ -55,6 +55,10 @@
let z = s[0]
s[0] = z
s[0] += 1
+
+ // CHECK-DAG: declare extern_weak {{.+}} @"$s25weak_import_native_helper5WeakSV0A6MemberyyF"
+ let w = WeakS()
+ w.weakMember()
}
func testEnum() {
@@ -166,3 +170,8 @@
// CHECK-DAG: declare extern_weak swiftcc {{.+}} @"$s25weak_import_native_helper8GenericCCfd"
}
}
+
+protocol RefinesP : BaseP {}
+
+// CHECK-DAG: @"$s25weak_import_native_helper1SVAA5BasePAAWP" = extern_weak global i8*
+extension S : RefinesP {}
diff --git a/test/lit.cfg b/test/lit.cfg
index d41ca99..3718069 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -1139,11 +1139,17 @@
'%s -target %s %s'
% (config.sil_nm, config.variant_triple, mcp_opt))
+rth_flags = ''
+if swift_execution_tests_extra_flags:
+ rth_flags = swift_execution_tests_extra_flags + ' -wmo'
+
config.target_resilience_test = (
'%s --target-build-swift "%s" --target-run "%s" --t %%t --S %%S --s %%s '
- '--lib-prefix "%s" --lib-suffix ".%s" --target-codesign "%s"'
+ '--lib-prefix "%s" --lib-suffix ".%s" --target-codesign "%s" '
+ '--additional-compile-flags "%s"'
% (config.rth, config.target_build_swift, config.target_run, 'lib',
- config.target_dylib_extension, config.target_codesign))
+ config.target_dylib_extension, config.target_codesign,
+ rth_flags))
# FIXME: Get symbol diffing working with binutils nm as well. The flags are slightly
# different.
diff --git a/utils/rth b/utils/rth
index 7694b33..4221088 100755
--- a/utils/rth
+++ b/utils/rth
@@ -33,8 +33,8 @@
def __init__(self, target_build_swift, target_run, target_codesign,
target_nm, tmp_dir, test_dir, test_src, lib_prefix,
- lib_suffix, additional_compile_flags_library,
- no_backward_deployment, no_symbol_diff):
+ lib_suffix, additional_compile_flags,
+ backward_deployment, no_symbol_diff):
self.target_build_swift = shlex.split(target_build_swift)
self.target_run = shlex.split(target_run)
self.target_codesign = shlex.split(target_codesign)
@@ -44,8 +44,7 @@
self.test_src = test_src
self.lib_prefix = lib_prefix
self.lib_suffix = lib_suffix
- self.additional_compile_flags_library = \
- shlex.split(additional_compile_flags_library)
+ self.additional_compile_flags = shlex.split(additional_compile_flags)
self.before_dir = os.path.join(self.tmp_dir, 'before')
self.after_dir = os.path.join(self.tmp_dir, 'after')
@@ -56,7 +55,7 @@
self.lib_name = self.lib_src_name[:-6]
self.lib_src = os.path.join(self.test_dir, 'Inputs', self.lib_src_name)
- self.no_backward_deployment = no_backward_deployment
+ self.backward_deployment = backward_deployment
self.no_symbol_diff = no_symbol_diff
def run(self):
@@ -95,7 +94,8 @@
os.path.join('@rpath', lib_file)]
command = self.target_build_swift + \
- self.additional_compile_flags_library + compiler_flags
+ self.additional_compile_flags + \
+ compiler_flags
verbose_print_command(command)
returncode = subprocess.call(command)
assert returncode == 0, str(command)
@@ -138,12 +138,20 @@
def compile_main(self):
for config in self.config_dir_map:
+ # If we're testing backward deployment, we only want to build
+ # the app against the new version of the library.
+ if self.backward_deployment and \
+ config == "BEFORE":
+ continue
+
output_obj = os.path.join(self.config_dir_map[config], 'main.o')
compiler_flags = ['-D', config, '-c', self.test_src,
'-Xfrontend', '-enable-class-resilience',
'-I', self.config_dir_map[config],
'-o', output_obj]
- command = self.target_build_swift + compiler_flags
+ command = self.target_build_swift + \
+ self.additional_compile_flags + \
+ compiler_flags
verbose_print_command(command)
returncode = subprocess.call(command)
assert returncode == 0, str(command)
@@ -151,11 +159,8 @@
def configs(self):
for config1 in self.config_dir_map:
for config2 in self.config_dir_map:
- # --no-backward-deployment skips testing a new application
- # linked against an old library.
- if config1 == "BEFORE" and \
- config2 == "AFTER" and \
- self.no_backward_deployment:
+ if self.backward_deployment and \
+ config2 == "BEFORE":
continue
yield (config1, config2)
@@ -183,6 +188,9 @@
'-o', output_obj
]
+ if self.is_apple_platform():
+ compiler_flags += ['-Xlinker', '-bind_at_load']
+
command = self.target_build_swift + compiler_flags
verbose_print_command(command)
returncode = subprocess.call(command)
@@ -218,8 +226,8 @@
parser.add_argument('--s', required=True)
parser.add_argument('--lib-prefix', required=True)
parser.add_argument('--lib-suffix', required=True)
- parser.add_argument('--additional-compile-flags-library', default='')
- parser.add_argument('--no-backward-deployment', default=False,
+ parser.add_argument('--additional-compile-flags', default='')
+ parser.add_argument('--backward-deployment', default=False,
action='store_true')
parser.add_argument('--no-symbol-diff', default=False,
action='store_true')
@@ -230,8 +238,8 @@
args.target_codesign, args.target_nm,
args.t, args.S, args.s, args.lib_prefix,
args.lib_suffix,
- args.additional_compile_flags_library,
- args.no_backward_deployment,
+ args.additional_compile_flags,
+ args.backward_deployment,
args.no_symbol_diff)
return resilience_test.run()
diff --git a/validation-test/Evolution/Inputs/backward_deploy_class.swift b/validation-test/Evolution/Inputs/backward_deploy_class.swift
new file mode 100644
index 0000000..c066ea9
--- /dev/null
+++ b/validation-test/Evolution/Inputs/backward_deploy_class.swift
@@ -0,0 +1,85 @@
+public func getVersion() -> Int {
+#if BEFORE
+ return 0
+#else
+ return 1
+#endif
+}
+
+public struct ResilientStruct {
+ public init() {}
+}
+
+#if AFTER
+@_weakLinked public class ResilientClass {
+ public init() {}
+
+ public func fn(_ x: Int) {}
+
+ public var storedProp: Int = 0
+
+ public var computedProp: Int {
+ get { return 0 }
+ set { }
+ }
+
+ public subscript(idx: Int) -> Int {
+ get { return 0 }
+ set { }
+ }
+}
+
+@_weakLinked @_fixed_layout public class FixedLayoutClass {
+ public init() {}
+
+ public func fn(_ x: Int) {}
+
+ // Make the first field resilient so that the second one has to be accessed
+ // with a field offset global
+ private var resilientField = ResilientStruct()
+
+ public var storedProp: Int = 0
+
+ public var computedProp: Int {
+ get { return 0 }
+ set { }
+ }
+
+ public subscript(idx: Int) -> Int {
+ get { return 0 }
+ set { }
+ }
+}
+#endif
+
+// Overriding a weak-linked method
+open class OpenClass {
+ public init() {}
+
+ open func oldMethod() {}
+
+#if AFTER
+ @_weakLinked open func newMethod() {}
+#endif
+}
+
+// Inserting a superclass
+open class Top {
+ public init() {}
+
+ open func topMethod() {}
+}
+
+#if BEFORE
+
+open class Bottom : Top {}
+
+#else
+
+@_weakLinked open class Middle : Top {
+ open func middleMethod() {}
+}
+
+open class Bottom : Middle {}
+
+#endif
diff --git a/validation-test/Evolution/Inputs/backward_deploy_enum.swift b/validation-test/Evolution/Inputs/backward_deploy_enum.swift
new file mode 100644
index 0000000..afbf6b6
--- /dev/null
+++ b/validation-test/Evolution/Inputs/backward_deploy_enum.swift
@@ -0,0 +1,19 @@
+public func getVersion() -> Int {
+#if BEFORE
+ return 0
+#else
+ return 1
+#endif
+}
+
+public enum ResilientEnum {
+ case first
+ case second
+
+#if AFTER
+ @_weakLinked case third
+#endif
+
+ case fourth
+ case fifth
+}
diff --git a/validation-test/Evolution/Inputs/backward_deploy_protocol.swift b/validation-test/Evolution/Inputs/backward_deploy_protocol.swift
new file mode 100644
index 0000000..a780df2
--- /dev/null
+++ b/validation-test/Evolution/Inputs/backward_deploy_protocol.swift
@@ -0,0 +1,60 @@
+public func getVersion() -> Int {
+#if BEFORE
+ return 0
+#else
+ return 1
+#endif
+}
+
+public protocol OtherProtocol {
+ init()
+}
+
+#if AFTER
+// Protocol is always available, type is weak-linked
+@_weakLinked public struct OtherConforms : OtherProtocol {
+ public init() {}
+}
+#endif
+
+public protocol OldProtocol {
+#if AFTER
+ @_weakLinked associatedtype NewType: OtherProtocol = OtherConforms
+ @_weakLinked func newMethod() -> NewType
+#endif
+}
+
+#if AFTER
+extension OldProtocol {
+ @_weakLinked public func newMethod() -> NewType {
+ return NewType()
+ }
+}
+#endif
+
+// Protocol is weak-linked, type is always available
+#if AFTER
+@_weakLinked public protocol NewProtocol {
+ func newMethod()
+}
+#endif
+
+public struct NewConforms {
+ public init() {}
+}
+
+#if AFTER
+@_weakLinked extension NewConforms : NewProtocol {
+ public func newMethod() {}
+}
+#endif
+
+// Protocol and type are always available, conformace is weak-linked
+public struct NewConformanceConforms {
+ public init() {}
+}
+public protocol NewConformanceProtocol {}
+
+#if AFTER
+@_weakLinked extension NewConformanceConforms : NewConformanceProtocol {}
+#endif
diff --git a/validation-test/Evolution/Inputs/backward_deploy_struct.swift b/validation-test/Evolution/Inputs/backward_deploy_struct.swift
new file mode 100644
index 0000000..18c440c
--- /dev/null
+++ b/validation-test/Evolution/Inputs/backward_deploy_struct.swift
@@ -0,0 +1,45 @@
+public func getVersion() -> Int {
+#if BEFORE
+ return 0
+#else
+ return 1
+#endif
+}
+
+#if AFTER
+@_weakLinked public struct ResilientStruct {
+ public init() {}
+
+ public func fn(_ x: Int) {}
+
+ public var storedProp: Int = 0
+
+ public var computedProp: Int {
+ get { return 0 }
+ set { }
+ }
+
+ public subscript(idx: Int) -> Int {
+ get { return 0 }
+ set { }
+ }
+}
+
+@_weakLinked @_fixed_layout public struct FixedLayoutStruct {
+ public init() {}
+
+ public func fn(_ x: Int) {}
+
+ public var storedProp: Int = 0
+
+ public var computedProp: Int {
+ get { return 0 }
+ set { }
+ }
+
+ public subscript(idx: Int) -> Int {
+ get { return 0 }
+ set { }
+ }
+}
+#endif
diff --git a/validation-test/Evolution/Inputs/backward_deploy_top_level.swift b/validation-test/Evolution/Inputs/backward_deploy_top_level.swift
new file mode 100644
index 0000000..9de4336
--- /dev/null
+++ b/validation-test/Evolution/Inputs/backward_deploy_top_level.swift
@@ -0,0 +1,20 @@
+public func getVersion() -> Int {
+#if BEFORE
+ return 0
+#else
+ return 1
+#endif
+}
+
+#if AFTER
+@_weakLinked public func topLevelFunction(_ x: Int) {}
+
+@_weakLinked public var storedGlobal: Int = 0
+
+@_weakLinked public var computedGlobal: Int {
+ get {
+ return 0
+ }
+ set {}
+}
+#endif
diff --git a/validation-test/Evolution/Inputs/bitwise_takable.swift b/validation-test/Evolution/Inputs/bitwise_takable.swift
index 1c433bb..0081e6a 100644
--- a/validation-test/Evolution/Inputs/bitwise_takable.swift
+++ b/validation-test/Evolution/Inputs/bitwise_takable.swift
@@ -1,5 +1,5 @@
public protocol Reporter {
- func report() -> String;
+ func report() -> String
}
public class Subject {
public var value = 1
diff --git a/validation-test/Evolution/Inputs/protocol_add_requirements.swift b/validation-test/Evolution/Inputs/protocol_add_requirements.swift
index d0c0f2e..505eb8d 100644
--- a/validation-test/Evolution/Inputs/protocol_add_requirements.swift
+++ b/validation-test/Evolution/Inputs/protocol_add_requirements.swift
@@ -149,8 +149,8 @@
associatedtype Key
associatedtype Value
- func get(key key: Key) -> Value
- mutating func set(key key: Key, value: Value)
+ func get(key: Key) -> Value
+ mutating func set(key: Key, value: Value)
#if AFTER
@_weakLinked subscript(key: Key) -> Value { get set }
diff --git a/validation-test/Evolution/test_backward_deploy_class.swift b/validation-test/Evolution/test_backward_deploy_class.swift
new file mode 100644
index 0000000..9038c10
--- /dev/null
+++ b/validation-test/Evolution/test_backward_deploy_class.swift
@@ -0,0 +1,98 @@
+// RUN: %target-resilience-test --backward-deployment
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import backward_deploy_class
+
+
+var BackwardDeployClassTest = TestSuite("BackwardDeployClass")
+
+BackwardDeployClassTest.test("ResilientClass") {
+ if getVersion() == 1 {
+ let s = ResilientClass()
+
+ s.fn(s.storedProp)
+ s.storedProp = 1
+ s.storedProp += 1
+
+ s.fn(s.computedProp)
+ s.computedProp = 1
+ s.computedProp += 1
+
+ s.fn(s[0])
+ s[0] = 1
+ s[0] += 1
+ }
+}
+
+BackwardDeployClassTest.test("FixedLayoutClass") {
+ if getVersion() == 1 {
+ let s = FixedLayoutClass()
+
+ s.fn(s.storedProp)
+ s.storedProp = 1
+ s.storedProp += 1
+
+ s.fn(s.computedProp)
+ s.computedProp = 1
+ s.computedProp += 1
+
+ s.fn(s[0])
+ s[0] = 1
+ s[0] += 1
+ }
+}
+
+BackwardDeployClassTest.test("OpenClass") {
+ class DerivedClass : OpenClass {
+ var count: Int = 0
+
+ override func oldMethod() {
+ count += 1
+ super.oldMethod()
+ }
+
+ override func newMethod() {
+ count += 10
+ super.newMethod()
+ }
+ }
+
+ let d = DerivedClass()
+
+ d.oldMethod()
+ if getVersion() == 1 {
+ d.newMethod()
+ expectEqual(d.count, 11)
+ } else {
+ expectEqual(d.count, 1)
+ }
+}
+
+BackwardDeployClassTest.test("InsertSuperclass") {
+ class DerivedClass : Bottom {
+ var count: Int = 0
+
+ override func topMethod() {
+ count += 1
+ super.topMethod()
+ }
+
+ override func middleMethod() {
+ count += 10
+ super.middleMethod()
+ }
+ }
+
+ let d = DerivedClass()
+
+ d.topMethod()
+ if getVersion() == 1 {
+ d.middleMethod()
+ expectEqual(d.count, 11)
+ } else {
+ expectEqual(d.count, 1)
+ }
+}
+
+runAllTests()
diff --git a/validation-test/Evolution/test_backward_deploy_enum.swift b/validation-test/Evolution/test_backward_deploy_enum.swift
new file mode 100644
index 0000000..65147eb
--- /dev/null
+++ b/validation-test/Evolution/test_backward_deploy_enum.swift
@@ -0,0 +1,39 @@
+// RUN: %target-resilience-test --backward-deployment
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import backward_deploy_enum
+
+// <rdar://problem/46438568>
+// XFAIL: *
+
+var BackwardDeployEnumTest = TestSuite("BackwardDeployEnum")
+
+func checkIt(_ e: ResilientEnum) -> Int {
+ switch e {
+ case .first:
+ return 1
+ case .second:
+ return 2
+ case .third:
+ return 3
+ case .fourth:
+ return 4
+ default:
+ return 5
+ }
+}
+
+BackwardDeployEnumTest.test("ResilientEnum") {
+
+ expectEqual(1, checkIt(.first))
+ expectEqual(2, checkIt(.second))
+ expectEqual(4, checkIt(.fourth))
+ expectEqual(5, checkIt(.fifth))
+
+ if getVersion() == 1 {
+ expectEqual(3, checkIt(.third))
+ }
+}
+
+runAllTests()
diff --git a/validation-test/Evolution/test_backward_deploy_protocol.swift b/validation-test/Evolution/test_backward_deploy_protocol.swift
new file mode 100644
index 0000000..5b4333b
--- /dev/null
+++ b/validation-test/Evolution/test_backward_deploy_protocol.swift
@@ -0,0 +1,111 @@
+// RUN: %target-resilience-test --backward-deployment
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import backward_deploy_protocol
+
+
+var BackwardDeployProtocolTest = TestSuite("BackwardDeployProtocol")
+
+struct ConformsToOldWithDefault : OldProtocol {}
+
+struct MyConcrete : OtherProtocol {}
+struct ConformsToOldWithNonDefault : OldProtocol {
+ typealias NewType = MyConcrete
+}
+
+BackwardDeployProtocolTest.test("OldProtocol") {
+ if getVersion() == 1 {
+ // FIXME: IRGen inserts the metadata load outside the version check
+ // apparently. Work around that here. <rdar://problem/46438608>
+ @inline(never) func helper() {
+ _ = ConformsToOldWithDefault().newMethod()
+ _ = ConformsToOldWithNonDefault().newMethod()
+ }
+
+ helper()
+ }
+}
+
+struct MyNewConforms : NewProtocol {
+ func newMethod() {}
+}
+
+func dynamicCast<T, U>(_ t: T, _: U.Type) -> Bool {
+ return t is U
+}
+
+BackwardDeployProtocolTest.test("NewProtocol") {
+ if getVersion() == 1 {
+ let x1 = NewConforms()
+ let x2 = MyNewConforms()
+ let x3 = ConformsToOldWithDefault()
+
+ expectEqual(true, dynamicCast(x1, NewProtocol.self))
+ expectEqual(true, dynamicCast(x2, NewProtocol.self))
+ expectEqual(false, dynamicCast(x3, NewProtocol.self))
+ }
+
+ // Make sure that dynamic casts don't crash in the backward
+ // deployment case.
+ do {
+ let x1 = ConformsToOldWithDefault()
+ let x2 = MyConcrete()
+
+ expectEqual(false, dynamicCast(x1, OtherProtocol.self))
+ expectEqual(true, dynamicCast(x2, OtherProtocol.self))
+ }
+}
+
+// Weak reference to a conformance descriptor from another module
+public protocol RefinedProtocol : NewProtocol {}
+extension NewConforms : RefinedProtocol {}
+
+BackwardDeployProtocolTest.test("RefinedProtocol") {
+ if getVersion() == 1 {
+ let x1 = NewConforms()
+ let x2 = MyNewConforms()
+ let x3 = ConformsToOldWithDefault()
+
+ expectEqual(true, dynamicCast(x1, RefinedProtocol.self))
+ expectEqual(false, dynamicCast(x2, RefinedProtocol.self))
+ expectEqual(false, dynamicCast(x3, RefinedProtocol.self))
+ }
+}
+
+// Witness tables that are weak-linked for various reasons
+BackwardDeployProtocolTest.test("WeakWitnessTables") {
+ if getVersion() == 1 {
+ // FIXME: IRGen inserts the metadata load outside the version check
+ // apparently. Work around that here. <rdar://problem/46438608>
+ @inline(never) func helper() {
+ func f1<T : OtherProtocol>(_: T) {}
+ func f2<T : NewProtocol>(_: T) {}
+ func f3<T : NewConformanceProtocol>(_: T) {}
+
+ f1(OtherConforms())
+ f2(NewConforms())
+ f3(NewConformanceConforms())
+ }
+ }
+}
+
+// Conditional conformance with weak-linked requirement
+struct Box<T> {}
+
+extension Box : OtherProtocol where T : NewProtocol {}
+
+BackwardDeployProtocolTest.test("ConditionalConformance") {
+ if getVersion() == 1 {
+ let x1 = Box<MyNewConforms>()
+
+ expectEqual(true, dynamicCast(x1, OtherProtocol.self))
+ }
+
+ do {
+ let x2 = Box<Int>()
+ expectEqual(false, dynamicCast(x2, OtherProtocol.self))
+ }
+}
+
+runAllTests()
diff --git a/validation-test/Evolution/test_backward_deploy_struct.swift b/validation-test/Evolution/test_backward_deploy_struct.swift
new file mode 100644
index 0000000..39fd1c0
--- /dev/null
+++ b/validation-test/Evolution/test_backward_deploy_struct.swift
@@ -0,0 +1,52 @@
+// RUN: %target-resilience-test --backward-deployment
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import backward_deploy_struct
+
+
+var BackwardDeployStructTest = TestSuite("BackwardDeployStruct")
+
+BackwardDeployStructTest.test("ResilientStruct") {
+ if getVersion() == 1 {
+ // FIXME: IRGen inserts the metadata load outside the version check
+ // apparently. Work around that here. <rdar://problem/46438608>
+ @inline(never) func helper() {
+ var s = ResilientStruct()
+
+ s.fn(s.storedProp)
+ s.storedProp = 1
+ s.storedProp += 1
+
+ s.fn(s.computedProp)
+ s.computedProp = 1
+ s.computedProp += 1
+
+ s.fn(s[0])
+ s[0] = 1
+ s[0] += 1
+ }
+
+ helper()
+ }
+}
+
+BackwardDeployStructTest.test("FixedLayoutStruct") {
+ if getVersion() == 1 {
+ var s = FixedLayoutStruct()
+
+ s.fn(s.storedProp)
+ s.storedProp = 1
+ s.storedProp += 1
+
+ s.fn(s.computedProp)
+ s.computedProp = 1
+ s.computedProp += 1
+
+ s.fn(s[0])
+ s[0] = 1
+ s[0] += 1
+ }
+}
+
+runAllTests()
diff --git a/validation-test/Evolution/test_backward_deploy_top_level.swift b/validation-test/Evolution/test_backward_deploy_top_level.swift
new file mode 100644
index 0000000..32efe51
--- /dev/null
+++ b/validation-test/Evolution/test_backward_deploy_top_level.swift
@@ -0,0 +1,20 @@
+// RUN: %target-resilience-test --backward-deployment
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import backward_deploy_top_level
+
+
+var BackwardDeployTopLevelTest = TestSuite("BackwardDeployTopLevel")
+
+BackwardDeployTopLevelTest.test("TopLevel") {
+ if getVersion() == 1 {
+ topLevelFunction(storedGlobal)
+ topLevelFunction(computedGlobal)
+
+ storedGlobal += 1
+ computedGlobal += 1
+ }
+}
+
+runAllTests()