Merge pull request #12456 from slavapestov/id-as-any-except-when-it-crashes

SILGen: Fix bug with bridging peephole
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index 38d9033..4009cc0 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -695,6 +695,7 @@
     assert(existentialTL.isLoadable());
 
     ManagedValue sub = F(SGFContext());
+    assert(concreteFormalType->isBridgeableObjectType());
     return B.createInitExistentialRef(loc, existentialTL.getLoweredType(),
                                       concreteFormalType, sub, conformances);
   }
@@ -726,6 +727,7 @@
     auto eraseToAnyObject =
     [&, concreteFormalType, F](SGFContext C) -> ManagedValue {
       auto concreteValue = F(SGFContext());
+      assert(concreteFormalType->isBridgeableObjectType());
       return B.createInitExistentialRef(
           loc, SILType::getPrimitiveObjectType(anyObjectTy), concreteFormalType,
           concreteValue, {});
@@ -1231,8 +1233,11 @@
 
   // If the result type is AnyObject, then we can always apply the bridge
   // via Any.
-  if (resultType->isAnyObject())
-    return true;
+  if (resultType->isAnyObject()) {
+    // ... as long as the source type is not an Optional.
+    if (sourceType->isBridgeableObjectType())
+      return true;
+  }
 
   // TODO: maybe other class existentials? Existential conversions?
   // They probably aren't important here.
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 8d65a2d..8b19cf9 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -758,6 +758,7 @@
                 base.getType().getObjectType(),
                 SGF.getASTContext().AllocateCopy(conformances));
       } else {
+        assert(getSubstFormalType()->isBridgeableObjectType());
         ref = SGF.B.createInitExistentialRef(
                 loc,
                 base.getType().getObjectType(),
diff --git a/test/SILGen/objc_bridging_peephole.swift b/test/SILGen/objc_bridging_peephole.swift
index 6c25326..6697bd3 100644
--- a/test/SILGen/objc_bridging_peephole.swift
+++ b/test/SILGen/objc_bridging_peephole.swift
@@ -10,6 +10,9 @@
 func makeNS() -> NSString { return "help" as NSString }
 func makeOptNS() -> NSString? { return nil }
 
+func useAnyObject(_: AnyObject) {}
+func useOptAnyObject(_: AnyObject?) {}
+
 /*** Return values ***********************************************************/
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole16testMethodResultySo10DummyClassC5dummy_tF
@@ -37,6 +40,35 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptNS(dummy.fetchNonnullString() as NSString?)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useOptAnyObject(dummy.fetchNullableString() as AnyObject?)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useOptAnyObject(dummy.fetchNullproneString() as AnyObject?)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useOptAnyObject(dummy.fetchNonnullString() as AnyObject?)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonNullMethodResultySo10DummyClassC5dummy_tF
@@ -52,6 +84,21 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.fetchNonnullString() as NSString)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: switch_enum [[RESULT]]
+  // CHECK:    bb3:
+  // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
+  // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useAnyObject(dummy.fetchNonnullString() as AnyObject)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole22testForcedMethodResultySo10DummyClassC5dummy_tF
@@ -67,6 +114,21 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.fetchNullproneString() as NSString)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: switch_enum [[RESULT]]
+  // CHECK:    bb3:
+  // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
+  // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useAnyObject(dummy.fetchNullproneString() as AnyObject)
+
+  // CHECK:      return
 }
 
 /*** Property loads **********************************************************/
@@ -96,6 +158,35 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptNS(dummy.nonnullStringProperty as NSString?)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useOptAnyObject(dummy.nullableStringProperty as AnyObject?)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useOptAnyObject(dummy.nullproneStringProperty as AnyObject?)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useOptAnyObject(dummy.nonnullStringProperty as AnyObject?)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNonNullPropertyValueySo10DummyClassC5dummy_tF
@@ -111,6 +202,21 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.nonnullStringProperty as NSString)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: switch_enum [[RESULT]]
+  // CHECK:    bb3:
+  // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
+  // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useAnyObject(dummy.nonnullStringProperty as AnyObject)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testForcedPropertyValueySo10DummyClassC5dummy_tF
@@ -126,6 +232,21 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.nullproneStringProperty as NSString)
+
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
+  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+  // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: switch_enum [[RESULT]]
+  // CHECK:    bb3:
+  // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
+  // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
+  useAnyObject(dummy.nullproneStringProperty as AnyObject)
+
+  // CHECK:      return
 }
 
 /*** Subscript loads *********************************************************/
@@ -158,6 +279,8 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useNS(object[index] as NSString)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptGetySo0eF0C6object_yXl5indextF
@@ -172,6 +295,8 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useOptNS(object[index] as NSString?)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptGetySo0eF0C6object_yXl5indextF
@@ -200,6 +325,8 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useNS(object[index] as NSString)
+
+  // CHECK:      return
 }
 
 /*** Call arguments **********************************************************/
@@ -237,6 +364,8 @@
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNullproneString(makeNS() as String)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptMethodArgumentySo10DummyClassC5dummy_tF
@@ -262,6 +391,8 @@
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNullproneString(makeNS() as String?)
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14MethodArgumentySo10DummyClassC5dummy_tF
@@ -285,6 +416,8 @@
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNullproneString(makeOptNS() as String?)
+
+  // CHECK:      return
 }
 
 /*** Property assignments ****************************************************/
@@ -322,6 +455,8 @@
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nullproneStringProperty = makeNS() as String
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptPropertySetterySo10DummyClassC5dummy_tF
@@ -347,6 +482,8 @@
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nullproneStringProperty = makeNS() as String?
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14PropertySetterySo10DummyClassC5dummy_tF
@@ -370,6 +507,8 @@
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nullproneStringProperty = makeOptNS() as String?
+
+  // CHECK:      return
 }
 
 /*** Subscript assignments ***************************************************/
@@ -389,6 +528,8 @@
   // CHECK:      destroy_value [[ARG]]
   // CHECK:      end_borrow [[SELF]] from %0
   object[index] = makeNS() as String
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptSetySo0eF0C6object_yXl5indextF
@@ -430,6 +571,8 @@
   // CHECK:      destroy_value [[ARG]]
   // CHECK:      end_borrow [[SELF]] from %0
   object[index] = makeOptNS() as String?
+
+  // CHECK:      return
 }
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptSetySo0eF0C6object_yXl5indextF 
@@ -471,6 +614,8 @@
   // CHECK:      destroy_value [[ARG]]
   // CHECK:      end_borrow [[SELF]] from %0
   object[index] = makeOptNS() as String?
+
+  // CHECK:      return
 }
 
 /*** Bugfixes ***************************************************************/