@@ -598,3 +598,59 @@ func convTupleAny(_ f1: @escaping () -> (),
598
598
// CHECK-NEXT: dealloc_stack [[OPTIONAL_VALUE]]
599
599
// CHECK-NEXT: dealloc_stack [[ANY_VALUE]]
600
600
// CHECK-NEXT: return
601
+
602
+ // ==== Support collection subtyping in function argument position
603
+
604
+ protocol Z { }
605
+ class A : Z { }
606
+
607
+ func foo_arr< T: Z > ( type: T . Type , _ fn: ( [ T ] ? ) -> Void ) { }
608
+ func foo_map< T: Z > ( type: T . Type , _ fn: ( [ Int : T ] ) -> Void ) { }
609
+
610
+ func rdar35702810( ) {
611
+ let fn_arr : ( [ Z ] ? ) -> Void = { _ in }
612
+ let fn_map : ( [ Int : Z ] ) -> Void = { _ in }
613
+
614
+ // CHECK: function_ref @_T0s15_arrayForceCastSayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@owned Array<τ_0_0>) -> @owned Array<τ_0_1>
615
+ // CHECK: apply %4<A, Z>(%3) : $@convention(thin) <τ_0_0, τ_0_1> (@owned Array<τ_0_0>) -> @owned Array<τ_0_1>
616
+ foo_arr ( type: A . self, fn_arr)
617
+
618
+ // CHECK: function_ref @_T0s17_dictionaryUpCasts10DictionaryVyq0_q1_GACyxq_Gs8HashableRzsAFR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@owned Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
619
+ // CHECK: apply %2<Int, A, Int, Z>(%0) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@owned Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
620
+ // CHECK: apply %1(%3) : $@callee_guaranteed (@owned Dictionary<Int, Z>) -> ()
621
+ foo_map ( type: A . self, fn_map)
622
+ }
623
+
624
+ protocol X : Hashable { }
625
+ class B : X {
626
+ var hashValue : Int { return 42 }
627
+ static func == ( lhs: B , rhs: B ) -> Bool {
628
+ return lhs. hashValue == rhs. hashValue
629
+ }
630
+ }
631
+
632
+ func bar_arr< T: X > ( type: T . Type , _ fn: ( [ T ] ? ) -> Void ) { }
633
+ func bar_map< T: X > ( type: T . Type , _ fn: ( [ T : Int ] ) -> Void ) { }
634
+ func bar_set< T: X > ( type: T . Type , _ fn: ( Set < T > ) -> Void ) { }
635
+
636
+ func rdar35702810_anyhashable( ) {
637
+ let fn_arr : ( [ AnyHashable ] ? ) -> Void = { _ in }
638
+ let fn_map : ( [ AnyHashable : Int ] ) -> Void = { _ in }
639
+ let fn_set : ( Set < AnyHashable > ) -> Void = { _ in }
640
+
641
+
642
+ // CHECK: function_ref @_T0Says11AnyHashableVGSgIegx_Say19function_conversion1BCGSgIgx_TR : $@convention(thin) (@owned Optional<Array<B>>, @guaranteed @callee_guaranteed (@owned Optional<Array<AnyHashable>>) -> ()) -> ()
643
+ // CHECK: partial_apply [callee_guaranteed] %12(%11) : $@convention(thin) (@owned Optional<Array<B>>, @guaranteed @callee_guaranteed (@owned Optional<Array<AnyHashable>>) -> ()) -> ()
644
+ // CHECK: convert_function %13 : $@callee_guaranteed (@owned Optional<Array<B>>) -> () to $@noescape @callee_guaranteed (@owned Optional<Array<B>>) -> ()
645
+ bar_arr ( type: B . self, fn_arr)
646
+
647
+ // CHECK: function_ref @_T0s10DictionaryVys11AnyHashableVSiGIegx_ABy19function_conversion1BCSiGIgx_TR : $@convention(thin) (@owned Dictionary<B, Int>, @guaranteed @callee_guaranteed (@owned Dictionary<AnyHashable, Int>) -> ()) -> ()
648
+ // CHECK: partial_apply [callee_guaranteed] %21(%20) : $@convention(thin) (@owned Dictionary<B, Int>, @guaranteed @callee_guaranteed (@owned Dictionary<AnyHashable, Int>) -> ()) -> ()
649
+ // CHECK: convert_function %22 : $@callee_guaranteed (@owned Dictionary<B, Int>) -> () to $@noescape @callee_guaranteed (@owned Dictionary<B, Int>) -> ()
650
+ bar_map ( type: B . self, fn_map)
651
+
652
+ // CHECK: function_ref @_T0s3SetVys11AnyHashableVGIegx_ABy19function_conversion1BCGIgx_TR : $@convention(thin) (@owned Set<B>, @guaranteed @callee_guaranteed (@owned Set<AnyHashable>) -> ()) -> ()
653
+ // CHECK: partial_apply [callee_guaranteed] %30(%29) : $@convention(thin) (@owned Set<B>, @guaranteed @callee_guaranteed (@owned Set<AnyHashable>) -> ()) -> ()
654
+ // CHECK: convert_function %31 : $@callee_guaranteed (@owned Set<B>) -> () to $@noescape @callee_guaranteed (@owned Set<B>) -> ()
655
+ bar_set ( type: B . self, fn_set)
656
+ }
0 commit comments