Merge pull request #13270 from DougGregor/se-0143-better-fail-than-crash-4.1

[4.1] [Runtime] Always fail to find a conditional conformance at runtime.
diff --git a/docs/ABI/TypeMetadata.rst b/docs/ABI/TypeMetadata.rst
index e765d8d..c44aa71 100644
--- a/docs/ABI/TypeMetadata.rst
+++ b/docs/ABI/TypeMetadata.rst
@@ -407,3 +407,29 @@
   * **Bit 31** is set by the Objective-C runtime when it has done its
     initialization of the protocol record. It is unused by the Swift runtime.
 
+
+Protocol Conformance Records
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A *protocol conformance record* states that a given type conforms to a
+particular protocol. Protocol conformance records are emitted into their own
+section, which is scanned by the Swift runtime when needed (e.g., in response to
+a `swift_conformsToProtocol()` query). Each protocol conformance record
+contains:
+
+- The `protocol descriptor`_ describing the protocol of the conformance.
+- A reference to the metadata for the **conforming type**, whose form is
+  determined by the **protocol conformance flags** described below.
+- The **witness table field** that provides access to the witness table
+  describing the conformance itself; the form of this field is determined by the
+  **protocol conformance flags** described below.
+- The **protocol conformance flags** is a 32-bit field comprised of:
+  * **Bits 0-3** contain the type metadata record kind, which indicates how
+    the **conforming type** field is encoded.
+  * **Bits 4-5** contain the kind of witness table. The value can be one of:
+    0) The **witness table field** is a reference to a witness table.
+    1) The **witness table field** is a reference to a **witness table
+       accessor** function for an unconditional conformance.
+    2) The **witness table field** is a reference to a **witness table
+       accessor** function for a conditional conformance.
+
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 69027e2..fdd3a02 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -212,6 +212,10 @@
   /// A function pointer that can be called to access the protocol witness
   /// table.
   WitnessTableAccessor,
+  /// A function pointer that can be called to access the protocol witness
+  /// table whose conformance is conditional on additional requirements that
+  /// must first be evaluated and then provided to the accessor function.
+  ConditionalWitnessTableAccessor,
 };
 
 // Type metadata record discriminant
@@ -245,7 +249,7 @@
 struct ProtocolConformanceFlags : public TypeMetadataRecordFlags {
 private:
   enum : int_type {
-    ConformanceKindMask = 0x00000010U,
+    ConformanceKindMask = 0x00000030U,
     ConformanceKindShift = 4,
   };
 
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index eb786f2..22b647b 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -2454,8 +2454,7 @@
     RelativeDirectPointer<const WitnessTable> WitnessTable;
     
     /// A function that produces the witness table given an instance of the
-    /// type. The function may return null if a specific instance does not
-    /// conform to the protocol.
+    /// type.
     RelativeDirectPointer<WitnessTableAccessorFn> WitnessTableAccessor;
   };
   
@@ -2560,6 +2559,7 @@
       break;
         
     case ProtocolConformanceReferenceKind::WitnessTableAccessor:
+    case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
       assert(false && "not witness table");
     }
     return WitnessTable;
@@ -2568,6 +2568,7 @@
   WitnessTableAccessorFn *getWitnessTableAccessor() const {
     switch (Flags.getConformanceKind()) {
     case ProtocolConformanceReferenceKind::WitnessTableAccessor:
+    case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
       break;
         
     case ProtocolConformanceReferenceKind::WitnessTable:
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 057d50a..5ce97a6 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2339,7 +2339,8 @@
     auto flags = typeEntity.flags;
     llvm::Constant *witnessTableVar;
     if (!isResilient(conformance->getProtocol(),
-                     ResilienceExpansion::Maximal)) {
+                     ResilienceExpansion::Maximal) &&
+        conformance->getConditionalRequirements().empty()) {
       flags = flags.withConformanceKind(
           ProtocolConformanceReferenceKind::WitnessTable);
 
@@ -2348,8 +2349,13 @@
       // it.
       witnessTableVar = getAddrOfWitnessTable(conformance);
     } else {
-      flags = flags.withConformanceKind(
-          ProtocolConformanceReferenceKind::WitnessTableAccessor);
+      if (conformance->getConditionalRequirements().empty()) {
+        flags = flags.withConformanceKind(
+            ProtocolConformanceReferenceKind::WitnessTableAccessor);
+      } else {
+        flags = flags.withConformanceKind(
+            ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor);
+      }
 
       witnessTableVar = getAddrOfWitnessTableAccessFunction(
           conformance, ForDefinition);
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index a028917..dfd4710 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -84,6 +84,10 @@
       printf("witness table accessor %s\n",
              symbolName((const void *)(uintptr_t)getWitnessTableAccessor()));
       break;
+    case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
+      printf("conditional witness table accessor %s\n",
+             symbolName((const void *)(uintptr_t)getWitnessTableAccessor()));
+      break;
   }
 }
 #endif
@@ -136,8 +140,12 @@
     return getStaticWitnessTable();
 
   case ProtocolConformanceReferenceKind::WitnessTableAccessor:
-    // FIXME: this needs information about conditional conformances.
     return getWitnessTableAccessor()(type, nullptr, 0);
+
+  case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
+    // FIXME: this needs to query the conditional requirements to form the
+    // array of witness tables to pass along to the accessor.
+    return nullptr;
   }
 
   swift_runtime_unreachable(
@@ -558,6 +566,7 @@
           break;
 
         case ProtocolConformanceReferenceKind::WitnessTableAccessor:
+        case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
           // If the record provides a dependent witness table accessor,
           // cache the result for the instantiated type metadata.
           C.cacheSuccess(type, P, record.getWitnessTable(type));
diff --git a/test/IRGen/protocol_conformance_records.swift b/test/IRGen/protocol_conformance_records.swift
index ebf0168..2d4fec9 100644
--- a/test/IRGen/protocol_conformance_records.swift
+++ b/test/IRGen/protocol_conformance_records.swift
@@ -1,5 +1,5 @@
-// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
-// RUN: %target-swift-frontend %s -emit-ir -num-threads 8 -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -primary-file %s -emit-ir -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances %s -emit-ir -num-threads 8 -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
 
 import resilient_struct
 
@@ -78,10 +78,25 @@
 // -- flags 0x04: unique direct metadata
 // CHECK-SAME:           i32 1
 // CHECK-SAME:         }
-// CHECK-SAME:       ]
 
 extension Size: Runcible {
   public func runce() {}
 }
 
 // TODO: conformances that need lazy initialization
+public protocol Spoon { }
+
+// Conditional conformances
+// CHECK: %swift.protocol_conformance {
+// -- protocol descriptor
+// CHECK-SAME:           [[SPOON:@_T028protocol_conformance_records5SpoonMp]]
+// -- nominal type descriptor
+// CHECK-SAME:           @_T028protocol_conformance_records17NativeGenericTypeVMn
+// -- witness table accessor
+// CHECK-SAME:           @_T028protocol_conformance_records17NativeGenericTypeVyxGAA5SpoonA2aERzlWa
+// -- flags 0x04: unique nominal type descriptor + conditional accessor
+// CHECK-SAME:           i32 36
+// CHECK-SAME:         }
+extension NativeGenericType : Spoon where T: Spoon {
+  public func runce() {}
+}
diff --git a/test/Inputs/conditional_conformance_basic_conformances.swift b/test/Inputs/conditional_conformance_basic_conformances.swift
index 0a839a3..58f355e 100644
--- a/test/Inputs/conditional_conformance_basic_conformances.swift
+++ b/test/Inputs/conditional_conformance_basic_conformances.swift
@@ -320,3 +320,6 @@
 // CHECK-NEXT:    unreachable
 // CHECK-NEXT:  }
 
+func dynamicCastToP1(_ value: Any) -> P1? {
+  return value as? P1
+}
diff --git a/test/Interpreter/conditional_conformances.swift b/test/Interpreter/conditional_conformances.swift
index a90f295..0981767 100644
--- a/test/Interpreter/conditional_conformances.swift
+++ b/test/Interpreter/conditional_conformances.swift
@@ -19,6 +19,9 @@
 double_generic_concrete(IsP2.self)
 double_concrete_concrete()
 
+assert(dynamicCastToP1(Single<IsP3>()) == nil)
+assert(dynamicCastToP1(Single<IsP2>()) == nil) // FIXME: incorrect result!
+
 #elseif with_assoc
 generic_generic(IsAlsoP2.self, IsP3.self)
 generic_concrete(IsAlsoP2.self)