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()