blob: 55b8fc8070b93870a82bbff75548191dcb245cd8 [file] [log] [blame]
// RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all %s -sil-combine -sil-print-generic-specialization-info | %FileCheck %s
// RUN: %target-swift-frontend -O %s -emit-ir
// These tests exercise the same SILCombine optimization as
// existential_type_propagation.sil, but cover additional corner
// cases. These are pure unit tests. They do not run the devirtualizer
// or inliner.
sil_stage canonical
import Builtin
import Swift
import SwiftShims
//===----------------------------------------------------------------------===//
// testReturnSelf: Call to a protocol extension method with
// an existential self that can be type-propagated.
// SILCombine should bailout since it does not propagate
// type substitutions on the return value.
//
// <rdar://40555427> [SR-7773]:
// SILCombiner::propagateConcreteTypeOfInitExistential fails to full propagate
// type substitutions.
//===----------------------------------------------------------------------===//
public protocol P : AnyObject {
}
extension P {
public func returnSelf() -> Self
}
final class C : P {
init()
deinit
}
public func testReturnSelf() -> P
// P.returnSelf()
sil @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) <Self where Self : P> (@guaranteed Self) -> @owned Self
// C.__allocating_init()
sil @$s21extension_return_self1CCACycfC : $@convention(method) (@thick C.Type) -> @owned C
// public func testReturnSelf() -> P {
// let p: P = C()
// return p.returnSelf().returnSelf()
// }
// Neither apply responds to type propagation.
//
// CHECK-LABEL: sil @$s21extension_return_self14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned P {
// CHECK: [[E1:%.*]] = init_existential_ref %{{.*}} : $C : $C, $P
// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $P to $@opened("{{.*}}") P
// CHECK: [[F1:%.*]] = function_ref @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
// CHECK: [[C1:%.*]] = apply [[F1]]<@opened("{{.*}}") P>([[O1]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
// CHECK: [[E2:%.*]] = init_existential_ref [[C1]] : $@opened("{{.*}}") P : $@opened("{{.*}}") P, $P
// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $P to $@opened("{{.*}}") P
// CHECK: [[F2:%.*]] = function_ref @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
// CHECK: apply [[F2]]<@opened("{{.*}}") P>([[O2]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
// CHECK-LABEL: } // end sil function '$s21extension_return_self14testReturnSelfAA1P_pyF'
sil @$s21extension_return_self14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned P {
bb0:
%0 = metatype $@thick C.Type
// function_ref C.__allocating_init()
%1 = function_ref @$s21extension_return_self1CCACycfC : $@convention(method) (@thick C.Type) -> @owned C
%2 = apply %1(%0) : $@convention(method) (@thick C.Type) -> @owned C
%3 = init_existential_ref %2 : $C : $C, $P
%5 = open_existential_ref %3 : $P to $@opened("1217498E-72AC-11E8-9816-ACDE48001122") P
// function_ref P.returnSelf()
%6 = function_ref @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) _0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
%7 = apply %6<@opened("1217498E-72AC-11E8-9816-ACDE48001122") P>(%5) : $@convention(method) _0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
%8 = init_existential_ref %7 : $@opened("1217498E-72AC-11E8-9816-ACDE48001122") P : $@opened("1217498E-72AC-11E8-9816-ACDE48001122") P, $P
%9 = open_existential_ref %8 : $P to $@opened("12174BD2-72AC-11E8-9816-ACDE48001122") P
// function_ref P.returnSelf()
%10 = function_ref @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) _0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
%11 = apply %10<@opened("12174BD2-72AC-11E8-9816-ACDE48001122") P>(%9) : $@convention(method) _0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
%12 = init_existential_ref %11 : $@opened("12174BD2-72AC-11E8-9816-ACDE48001122") P : $@opened("12174BD2-72AC-11E8-9816-ACDE48001122") P, $P
strong_release %9 : $@opened("12174BD2-72AC-11E8-9816-ACDE48001122") P
strong_release %3 : $P
return %12 : $P
}
//===----------------------------------------------------------------------===//
// testWitnessReturnOptionalSelf: Call to a witness method with an existential
// self that can be type-propagated. SILCombine should bailout since it does
// not propagate type substitutions on the return value, and it must walk the
// Optional type to find Self in the return type.
//===----------------------------------------------------------------------===//
public protocol PP : AnyObject {
func returnOptionalSelf() -> Self?
}
final class CC : PP {
init()
final func returnOptionalSelf() -> Self?
deinit
}
public func testWitnessReturnOptionalSelf() -> PP?
// CC.__allocating_init()
sil @$s28witness_return_optional_self2CCCACycfC : $@convention(method) (@thick CC.Type) -> @owned CC
// public func testWitnessReturnOptionalSelf() -> PP? {
// let p: PP = CC()
// return p.returnOptionalSelf()?.returnOptionalSelf()
// }
//
// Although SILCombine will not replace the self operand, it will still
// rewrite the witness_method.
//
// The first witness_method is rewritten for the concrete lookup type 'CC'.
//
// The second witness_method is rewritten for the first opened existential type.
// Neither apply is rewritten.
//
// CHECK-LABEL: sil @$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional<PP> {
// CHECK: [[E1:%.*]] = init_existential_ref %{{.*}} : $CC : $CC, $PP
// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $PP to $@opened("{{.*}}") PP
// CHECK: [[W1:%.*]] = witness_method $CC, #PP.returnOptionalSelf : <Self where Self : PP> (Self) -> () -> Self? : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0>
// CHECK: apply [[W1]]<@opened("{{.*}}") PP>([[O1]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0>
// CHECK: [[E2:%.*]] = init_existential_ref %{{.*}} : $@opened("{{.*}}") PP : $@opened("{{.*}}") PP, $PP
// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $PP to $@opened("{{.*}}") PP
// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}") PP, #PP.returnOptionalSelf : <Self where Self : PP> (Self) -> () -> Self?, [[O1]] : $@opened("{{.*}}") PP : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0>
// CHECK: apply [[W2]]<@opened("{{.*}}") PP>([[O2]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0>
// CHECK-LABEL: } // end sil function '$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF'
sil @$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional<PP> {
bb0:
%0 = metatype $@thick CC.Type
// function_ref CC.__allocating_init()
%1 = function_ref @$s28witness_return_optional_self2CCCACycfC : $@convention(method) (@thick CC.Type) -> @owned CC
%2 = apply %1(%0) : $@convention(method) (@thick CC.Type) -> @owned CC
%3 = init_existential_ref %2 : $CC : $CC, $PP
%5 = open_existential_ref %3 : $PP to $@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP
%6 = witness_method $@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP, #PP.returnOptionalSelf : <Self where Self : PP> (Self) -> () -> Self?, %5 : $@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0>
%7 = apply %6<@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP>(%5) : $@convention(witness_method: PP) _0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional_0_0>
%8 = unchecked_enum_data %7 : $Optional<@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP>, #Optional.some!enumelt
%11 = init_existential_ref %8 : $@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP : $@opened("00000000-72AD-11E8-88DF-ACDE48001122") PP, $PP
%12 = enum $Optional<PP>, #Optional.some!enumelt, %11 : $PP
%13 = unchecked_enum_data %12 : $Optional<PP>, #Optional.some!enumelt
%18 = open_existential_ref %13 : $PP to $@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP
%19 = witness_method $@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP, #PP.returnOptionalSelf : <Self where Self : PP> (Self) -> () -> Self?, %18 : $@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0>
%20 = apply %19<@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP>(%18) : $@convention(witness_method: PP) _0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional_0_0>
%21 = unchecked_enum_data %20 : $Optional<@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP>, #Optional.some!enumelt
%22 = init_existential_ref %21 : $@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP : $@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP, $PP
%23 = enum $Optional<PP>, #Optional.some!enumelt, %22 : $PP
strong_release %18 : $@opened("FFFFFFFF-72AD-11E8-88DF-ACDE48001122") PP
strong_release %3 : $PP
return %23 : $Optional<PP>
}
//===----------------------------------------------------------------------===//
// testWitnessReturnOptionalIndirectSelf: Call to a witness method with an
// existential self that can be type-propagated. SILCombine should bailout
// since it does not propagate type substitutions on non-self arguments. It must
// walk the Optional type to find Self in the non-self argument.
//===----------------------------------------------------------------------===//
protocol PPP {
func returnsOptionalIndirect() -> Self?
}
struct S : PPP {
func returnsOptionalIndirect() -> S?
init()
}
public func testWitnessReturnOptionalIndirectSelf()
// S.init()
sil @$s37witness_return_optional_indirect_self1SVACycfC : $@convention(method) (@thin S.Type) -> S
// testWitnessReturnOptionalIndirectSelf()
// public func testWitnessReturnOptionalIndirectSelf() {
// let p: PPP = S()
// p.returnsOptionalIndirect()?.returnsOptionalIndirect()
// }
//
// Although SILCombine will not replace the self operand, it will still
// rewrite the witness_method. The devirtualizer could then handle the first call.
//
// CHECK-LABEL: sil @$s37witness_return_optional_indirect_self37testWitnessReturnOptionalIndirectSelfyyF : $@convention(thin) () -> () {
// CHECK: [[O1:%.*]] = open_existential_addr immutable_access %0 : $*PPP to $*@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP
// CHECK: [[R1:%.*]] = alloc_stack $Optional<@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP>
// CHECK: [[W1:%.*]] = witness_method $S, #PPP.returnsOptionalIndirect : <Self where Self : PPP> (Self) -> () -> Self? : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
// CHECK: apply [[W1]]<@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP>([[R1]], [[O1]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
// CHECK: [[E1:%.*]] = unchecked_take_enum_data_addr
// CHECK: [[O2:%.*]] = open_existential_addr immutable_access {{.*}} : $*PPP to $*@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP
// CHECK: [[R2:%.*]] = alloc_stack $Optional<@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP>
// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}") PPP, #PPP.returnsOptionalIndirect
// CHECK: apply [[W2]]<@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP>([[R2]], [[O2]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
// CHECK-LABEL: } // end sil function '$s37witness_return_optional_indirect_self37testWitnessReturnOptionalIndirectSelfyyF'
sil @$s37witness_return_optional_indirect_self37testWitnessReturnOptionalIndirectSelfyyF : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $PPP, let, name "p"
%1 = init_existential_addr %0 : $*PPP, $S
%2 = metatype $@thin S.Type
// function_ref S.init()
%3 = function_ref @$s37witness_return_optional_indirect_self1SVACycfC : $@convention(method) (@thin S.Type) -> S
%4 = apply %3(%2) : $@convention(method) (@thin S.Type) -> S
store %4 to %1 : $*S
%6 = alloc_stack $Optional<PPP>
%7 = alloc_stack $Optional<PPP>
%8 = open_existential_addr immutable_access %0 : $*PPP to $*@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP
%9 = init_enum_data_addr %7 : $*Optional<PPP>, #Optional.some!enumelt
%10 = init_existential_addr %9 : $*PPP, $@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP
%11 = alloc_stack $Optional<@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP>
%12 = witness_method $@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP, #PPP.returnsOptionalIndirect : <Self where Self : PPP> (Self) -> () -> Self?, %8 : $*@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
%13 = apply %12<@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP>(%11, %8) : $@convention(witness_method: PPP) _0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional_0_0>
%14 = unchecked_take_enum_data_addr %11 : $*Optional<@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP>, #Optional.some!enumelt
copy_addr [take] %14 to [initialization] %10 : $*@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP
inject_enum_addr %7 : $*Optional<PPP>, #Optional.some!enumelt
dealloc_stack %11 : $*Optional<@opened("83DE9694-7315-11E8-955C-ACDE48001122") PPP>
%28 = unchecked_take_enum_data_addr %7 : $*Optional<PPP>, #Optional.some!enumelt
%29 = open_existential_addr immutable_access %28 : $*PPP to $*@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP
%30 = init_enum_data_addr %6 : $*Optional<PPP>, #Optional.some!enumelt
%31 = init_existential_addr %30 : $*PPP, $@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP
%32 = alloc_stack $Optional<@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP>
%33 = witness_method $@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP, #PPP.returnsOptionalIndirect : <Self where Self : PPP> (Self) -> () -> Self?, %29 : $*@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
%34 = apply %33<@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP>(%32, %29) : $@convention(witness_method: PPP) _0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional_0_0>
%41 = unchecked_take_enum_data_addr %32 : $*Optional<@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP>, #Optional.some!enumelt
copy_addr [take] %41 to [initialization] %31 : $*@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP
inject_enum_addr %6 : $*Optional<PPP>, #Optional.some!enumelt
dealloc_stack %32 : $*Optional<@opened("83DE97CA-7315-11E8-955C-ACDE48001122") PPP>
destroy_addr %28 : $*PPP
dealloc_stack %7 : $*Optional<PPP>
destroy_addr %6 : $*Optional<PPP>
dealloc_stack %6 : $*Optional<PPP>
destroy_addr %0 : $*PPP
dealloc_stack %0 : $*PPP
%52 = tuple ()
return %52 : $()
}
// ===----------------------------------------------------------------------===//
// testOptionalSelfArg: Call a protocol extension method with an
// existential self that can be type-propagated. SILCombine should
// bailout since it does not know how to rewrite non-self operands.
// SILCombine would previously generate incorrect SIL because it did
// not properly walk all types in the function signature to find
// dependencies on the Self type.
// ===----------------------------------------------------------------------===//
protocol PPPP {}
extension PPPP {
func takeOptionalSelf(_ s: Self?)
}
class CCCC : PPPP {
init()
deinit
}
sil [noinline] @takeOptionalSelf : $@convention(method) <Self where Self : PPPP> (@in_guaranteed Optional<Self>, @in_guaranteed Self) -> ()
// CHECK-LABEL: sil @testOptionalSelfArg : $@convention(thin) (@guaranteed CCCC) -> () {
// CHECK: init_existential_addr [[A:%.*]] : $*PPPP, $CCCC // user: %4
// CHECK: [[OE:%.*]] = open_existential_addr immutable_access [[A]] : $*PPPP to $*@opened("{{.*}}") PPPP // users: %11, %11, %8, %6
// CHECK: [[F:%.*]] = function_ref @takeOptionalSelf : $@convention(method) <τ_0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional<τ_0_0>, @in_guaranteed τ_0_0) -> () // user: %11
// CHECK: apply [[F]]<@opened("{{.*}}") PPPP>(%{{.*}}, [[OE]]) : $@convention(method) <τ_0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional<τ_0_0>, @in_guaranteed τ_0_0) -> () // type-defs: %5
// CHECK-LABEL: } // end sil function 'testOptionalSelfArg'
sil @testOptionalSelfArg : $@convention(thin) (@guaranteed CCCC) -> () {
bb0(%0 : $CCCC):
strong_retain %0 : $CCCC
%pa = alloc_stack $PPPP, let, name "p"
%ea = init_existential_addr %pa : $*PPPP, $CCCC
store %0 to %ea : $*CCCC
%oe = open_existential_addr immutable_access %pa : $*PPPP to $*@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP
%optional = alloc_stack $Optional<@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP>
%someadr = init_enum_data_addr %optional : $*Optional<@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP>, #Optional.some!enumelt
copy_addr %oe to [initialization] %someadr : $*@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP
inject_enum_addr %optional : $*Optional<@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP>, #Optional.some!enumelt
%f = function_ref @takeOptionalSelf : $@convention(method) _0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional_0_0>, @in_guaranteed τ_0_0) -> ()
%call = apply %f<@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP>(%optional, %oe) : $@convention(method) _0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional_0_0>, @in_guaranteed τ_0_0) -> ()
destroy_addr %optional : $*Optional<@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP>
dealloc_stack %optional : $*Optional<@opened("A6DDDAF6-70BD-11E8-ADF1-ACDE48001122") PPPP>
destroy_addr %pa : $*PPPP
dealloc_stack %pa : $*PPPP
%10 = tuple ()
return %10 : $()
}
//===----------------------------------------------------------------------===//
// testExtensionProtocolComposition: Call to a witness method with an
// existential self that can be type-propagated. Handle an existential with
// multiple conformances.
//
// This previously crashed in SILCombiner::propagateConcreteTypeOfInitExistential
// with assertion failed: (proto == Conformance.getRequirement()).
// ===----------------------------------------------------------------------===//
public protocol Q {}
extension P where Self : Q {
public func witnessComposition() {}
}
public class C_PQ: P & Q {}
// P<>.witnessComposition()
sil @$s32sil_combine_concrete_existential1PPA2A1QRzrlE18witnessCompositionyyF : $@convention(method) _0_0 where τ_0_0 : P, τ_0_0 : Q> (@guaranteed τ_0_0) -> ()
// testExtensionProtocolComposition(c:)
// public func testExtensionProtocolComposition(c: C_PQ) {
// let pp: P & Q = c
// pp.witnessComposition()
// }
//
// SILCombine substitutes the applies opened existention parameter with a concrete type <C : P & Q>
// CHECK-LABEL: sil @$s32sil_combine_concrete_existential32testExtensionProtocolComposition1cyAA4C_PQC_tF : $@convention(thin) (@guaranteed C_PQ) -> () {
// CHECK-NOT: init_existential_ref
// CHECK-NOT: open_existential_ref
// function_ref P<>.witnessComposition()
// CHECK: [[F:%.*]] = function_ref @$s32sil_combine_concrete_existential1PPA2A1QRzrlE18witnessCompositionyyF : $@convention(method) <τ_0_0 where τ_0_0 : P, τ_0_0 : Q> (@guaranteed τ_0_0) -> ()
// CHECK: apply [[F]]<C_PQ>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : P, τ_0_0 : Q> (@guaranteed τ_0_0) -> ()
// CHECK-LABEL: } // end sil function '$s32sil_combine_concrete_existential32testExtensionProtocolComposition1cyAA4C_PQC_tF'
sil @$s32sil_combine_concrete_existential32testExtensionProtocolComposition1cyAA4C_PQC_tF : $@convention(thin) (@guaranteed C_PQ) -> () {
bb0(%0 : $C_PQ):
strong_retain %0 : $C_PQ
%3 = init_existential_ref %0 : $C_PQ : $C_PQ, $P & Q
%5 = open_existential_ref %3 : $P & Q to $@opened("044D530E-7327-11E8-A998-ACDE48001122") P & Q
// function_ref P<>.witnessCompositionOwned()
%6 = function_ref @$s32sil_combine_concrete_existential1PPA2A1QRzrlE18witnessCompositionyyF : $@convention(method) _0_0 where τ_0_0 : P, τ_0_0 : Q> (@guaranteed τ_0_0) -> ()
%7 = apply %6<@opened("044D530E-7327-11E8-A998-ACDE48001122") P & Q>(%5) : $@convention(method) _0_0 where τ_0_0 : P, τ_0_0 : Q> (@guaranteed τ_0_0) -> ()
strong_release %3 : $P & Q
%9 = tuple ()
return %9 : $()
}
// ===----------------------------------------------------------------------===//
// testDefaultStaticMethod: Test concrete type propagation into a direct
// apply of a default witness method.
// ===----------------------------------------------------------------------===//
public protocol PDefaultStatic: class {
static func witnessDefaultStatic()
}
extension PDefaultStatic {
@inline(never)
public static func witnessDefaultStatic() {}
}
public class CDefaultStatic : PDefaultStatic {}
public func callDefaultStatic() {
return CDefaultStatic.witnessDefaultStatic()
}
// static P<>.witnessDefaultStatic(_:)
sil @witnessDefaultStatic : $@convention(method) <Self where Self : PDefaultStatic> (@thick Self.Type) -> ()
// CHECK-LABEL: sil @testDefaultStaticMethod : $@convention(thin) () -> () {
// CHECK: %0 = metatype $@thick CDefaultStatic.Type
// CHECK-NOT: init_existential_metatype
// CHECK-NOT: open_existential_metatype
// CHECK: [[F:%.*]] = function_ref @witnessDefaultStatic : $@convention(method) <τ_0_0 where τ_0_0 : PDefaultStatic> (@thick τ_0_0.Type) -> ()
// CHECK: apply [[F]]<CDefaultStatic>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : PDefaultStatic> (@thick τ_0_0.Type) -> ()
// CHECK-LABEL: } // end sil function 'testDefaultStaticMethod'
sil @testDefaultStaticMethod : $@convention(thin) () -> () {
bb0:
%mt = metatype $@thick CDefaultStatic.Type
%em = init_existential_metatype %mt : $@thick CDefaultStatic.Type, $@thick PDefaultStatic.Type
%om = open_existential_metatype %em : $@thick PDefaultStatic.Type to $@thick (@opened("22222222-72AC-11E8-9816-ACDE48001122") PDefaultStatic).Type
%f = function_ref @witnessDefaultStatic : $@convention(method) <Self where Self : PDefaultStatic> (@thick Self.Type) -> ()
%call = apply %f<@opened("22222222-72AC-11E8-9816-ACDE48001122") PDefaultStatic>(%om) : $@convention(method) <Self where Self : PDefaultStatic> (@thick Self.Type) -> ()
%v = tuple ()
return %v : $()
}
//===----------------------------------------------------------------------===//
// testWitnessCopiedSelfWithIndirectResult: Call to a witness method
// with an existential self that can be type-propagated. Exercise
// `SILCombiner::canReplaceArg` when `self` is not in argument position zero.
//
// rdar://45415719 Assertion failed: (Index < Length && "Invalid index!")
// ===----------------------------------------------------------------------===//
protocol AnyP {
func returnsSelf() -> Self
}
struct StructOfAnyP : AnyP {
func returnsSelf() -> StructOfAnyP
}
// CHECK-LABEL: sil @testWitnessCopiedSelfWithIndirectResult : $@convention(thin) () -> () {
// CHECK: [[IN:%[0-9]+]] = alloc_stack $StructOfAnyP
// CHECK: [[OUT:%[0-9]+]] = alloc_stack $StructOfAnyP
// CHECK: witness_method $StructOfAnyP, #AnyP.returnsSelf : <Self where Self : AnyP> (Self) -> () -> Self : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
// CHECK: apply %{{.*}}<StructOfAnyP>([[OUT]], [[IN]]) : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
// CHECK-LABEL: } // end sil function 'testWitnessCopiedSelfWithIndirectResult'
sil @testWitnessCopiedSelfWithIndirectResult : $() -> () {
bb0:
%a0 = alloc_stack $AnyP
%ie0 = init_existential_addr %a0 : $*AnyP, $StructOfAnyP
%a1 = alloc_stack $AnyP
copy_addr %a0 to [initialization] %a1 : $*AnyP
%o0 = open_existential_addr immutable_access %a1 : $*AnyP to $*@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP
%a2 = alloc_stack $StructOfAnyP
%w0 = witness_method $@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP, #AnyP.returnsSelf : <Self where Self : AnyP> (Self) -> () -> Self, %o0 : $*@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
%c0 = apply %w0<@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP>(%a2, %o0) : $@convention(witness_method: AnyP) _0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
dealloc_stack %a2 : $*StructOfAnyP
dealloc_stack %a1 : $*AnyP
dealloc_stack %a0 : $*AnyP
%v = tuple ()
return %v : $()
}
sil @takeany : $@convention(thin) (@in_guaranteed AnyP) -> ()
// CHECK-LABEL: sil @testWitnessCopiedSelfWithIndirectResult2 : $@convention(thin) () -> () {
// CHECK: [[IN:%[0-9]+]] = alloc_stack $AnyP
// CHECK: [[EA:%[0-9]+]] = init_existential_addr [[IN]]
// CHECK: [[OUT:%[0-9]+]] = alloc_stack $StructOfAnyP
// CHECK: witness_method $StructOfAnyP, #AnyP.returnsSelf : <Self where Self : AnyP> (Self) -> () -> Self : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
// CHECK: apply %{{.*}}<StructOfAnyP>([[OUT]], [[EA]]) : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
// CHECK-LABEL: } // end sil function 'testWitnessCopiedSelfWithIndirectResult2'
sil @testWitnessCopiedSelfWithIndirectResult2 : $() -> () {
bb0:
%a0 = alloc_stack $AnyP
%ie0 = init_existential_addr %a0 : $*AnyP, $StructOfAnyP
%f1 = function_ref @takeany : $@convention(thin) (@in_guaranteed AnyP) -> ()
%c1 = apply %f1(%a0) : $@convention(thin) (@in_guaranteed AnyP) -> ()
%a1 = alloc_stack $AnyP
copy_addr %a0 to [initialization] %a1 : $*AnyP
%o0 = open_existential_addr immutable_access %a1 : $*AnyP to $*@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP
%a2 = alloc_stack $StructOfAnyP
%w0 = witness_method $@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP, #AnyP.returnsSelf : <Self where Self : AnyP> (Self) -> () -> Self, %o0 : $*@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
%c0 = apply %w0<@opened("7C4DAF8E-D722-11E8-920A-D0817AD9F6DD") AnyP>(%a2, %o0) : $@convention(witness_method: AnyP) _0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP
dealloc_stack %a2 : $*StructOfAnyP
dealloc_stack %a1 : $*AnyP
dealloc_stack %a0 : $*AnyP
%v = tuple ()
return %v : $()
}
// <rdar://problem/46322928> Failure to devirtualize a protocol method
// applied to an opened existential blocks implemention of
// DataProtocol.
public protocol ContiguousBytes {
func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
}
extension Array : ContiguousBytes {
}
// specialized thunk for @callee_guaranteed (@unowned UnsafeRawBufferPointer) -> (@error @owned Error)
sil [transparent] [reabstraction_thunk] @testDevirtExistentialEnumThunk : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error)
// Test that the witness method's opened archetype is replaced by a
// concrete conformance.
//
// Note that the enum is destroyed by unchecked_take_enum_data_addr
// before the apply (and the extracted data is destroy by the copy
// itself), so SILCombine cannot replace the call's self
// argument. Instead, we expect a later devirtualizer pass to just
// insert a cast of the opened existential.
//
// CHECK-LABEL: sil shared [noinline] @testDevirtExistentialEnum : $@convention(thin) (@guaranteed Array<Int>) -> () {
// CHECK: [[ALLOC_EXISTENTIAL:%.*]] = alloc_stack $ContiguousBytes
// CHECK: [[ALLOC_ENUM:%.*]] = alloc_stack $ContiguousBytes
// CHECK: [[INIT_DATA:%.*]] = init_existential_addr [[ALLOC_ENUM]] : $*ContiguousBytes, $Array<Int>
// CHECK: store %0 to [[INIT_DATA]] : $*Array<Int>
// CHECK: copy_addr [take] [[ALLOC_ENUM]] to [initialization] [[ALLOC_EXISTENTIAL]] : $*ContiguousBytes
// CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access [[ALLOC_EXISTENTIAL]] : $*ContiguousBytes to $*@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD") ContiguousBytes
// CHECK: [[THUNK:%.*]] = function_ref @testDevirtExistentialEnumThunk : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error)
// CHECK: [[TTF:%.*]] = thin_to_thick_function [[THUNK:%.*]] : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error) to $@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out (), @error Error)
// CHECK: [[WM:%.*]] = witness_method $Array<Int>, #ContiguousBytes.withUnsafeBytes : <Self where Self : ContiguousBytes><R> (Self) -> ((UnsafeRawBufferPointer) throws -> R) throws -> R : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error Error)
// CHECK: [[CAST:%.*]] = unchecked_addr_cast [[OPENED]]
// CHECK: apply [nothrow] [[WM]]<Array<Int>, ()>(%{{.*}}, [[TTF]], [[CAST]]) : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error Error)
// CHECK: destroy_addr [[ALLOC_EXISTENTIAL]] : $*ContiguousBytes
// CHECK-LABEL: } // end sil function 'testDevirtExistentialEnum'
sil shared [noinline] @testDevirtExistentialEnum : $@convention(thin) (@guaranteed Array<Int>) -> () {
bb0(%0 : $Array<Int>):
%3 = alloc_stack $ContiguousBytes
%4 = alloc_stack $Optional<ContiguousBytes>
%5 = init_enum_data_addr %4 : $*Optional<ContiguousBytes>, #Optional.some!enumelt
%6 = init_existential_addr %5 : $*ContiguousBytes, $Array<Int>
store %0 to %6 : $*Array<Int>
inject_enum_addr %4 : $*Optional<ContiguousBytes>, #Optional.some!enumelt
%9 = unchecked_take_enum_data_addr %4 : $*Optional<ContiguousBytes>, #Optional.some!enumelt
copy_addr [take] %9 to [initialization] %3 : $*ContiguousBytes
dealloc_stack %4 : $*Optional<ContiguousBytes>
%12 = open_existential_addr immutable_access %3 : $*ContiguousBytes to $*@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD") ContiguousBytes
%13 = alloc_stack $()
%14 = function_ref @testDevirtExistentialEnumThunk : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error)
%15 = thin_to_thick_function %14 : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error) to $@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out (), @error Error)
%16 = witness_method $@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD") ContiguousBytes, #ContiguousBytes.withUnsafeBytes : <Self where Self : ContiguousBytes><R> (Self) -> ((UnsafeRawBufferPointer) throws -> R) throws -> R, %12 : $*@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD") ContiguousBytes : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error Error)
%21 = apply [nothrow] %16<@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD") ContiguousBytes, ()>(%13, %15, %12) : $@convention(witness_method: ContiguousBytes) _0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error Error)
dealloc_stack %13 : $*()
destroy_addr %3 : $*ContiguousBytes
dealloc_stack %3 : $*ContiguousBytes
%25 = tuple ()
return %25 : $()
}
struct InGuaranteedArgTestNativeObjectWrapper {
var i: Builtin.NativeObject
}
protocol InGuaranteedArgTestProtocol {}
extension InGuaranteedArgTestNativeObjectWrapper : InGuaranteedArgTestProtocol {}
sil @in_guaranteed_arg_test_callee : $@convention(thin) _0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> ()
// CHECK-LABEL: sil @in_guaranteed_arg_test_caller : $@convention(thin) <τ_0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> () {
// CHECK: bb0(%0 : $*τ_0_0):
// CHECK: [[ALLOC1:%.*]] = alloc_stack $τ_0_0
// CHECK: copy_addr [take] %0 to [initialization] [[ALLOC1]] : $*τ_0_0
// CHECK: [[F:%.*]] = function_ref @in_guaranteed_arg_test_callee : $@convention(thin) <τ_0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> ()
// CHECK: [[ALLOC2:%.*]] = alloc_stack $τ_0_0
// CHECK: copy_addr %1 to [initialization] [[ALLOC2]] : $*τ_0_0
// CHECK: apply [[F]]<τ_0_0>(%4) : $@convention(thin) <τ_0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> ()
// CHECK: dealloc_stack [[ALLOC2]] : $*τ_0_0
// CHECK: destroy_addr [[ALLOC1]] : $*τ_0_0
// CHECK: dealloc_stack [[ALLOC1]] : $*τ_0_0
// CHECK: } // end sil function 'in_guaranteed_arg_test_caller'
sil @in_guaranteed_arg_test_caller : $@convention(thin) _0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> () {
bb0(%0 : $_0_0):
%1 = alloc_stack $InGuaranteedArgTestProtocol
%2 = init_existential_addr %1 : $*InGuaranteedArgTestProtocol, $τ_0_0
copy_addr [take] %0 to [initialization] %2 : $_0_0
%3 = function_ref @in_guaranteed_arg_test_callee : $@convention(thin) _0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> ()
%4 = alloc_stack $InGuaranteedArgTestProtocol
copy_addr %1 to [initialization] %4 : $*InGuaranteedArgTestProtocol
%5 = open_existential_addr mutable_access %4 : $*InGuaranteedArgTestProtocol to $*@opened("C494A60E-71EA-11E9-B8C0-D0817AD3F8AD") InGuaranteedArgTestProtocol
apply %3<@opened("C494A60E-71EA-11E9-B8C0-D0817AD3F8AD") InGuaranteedArgTestProtocol>(%5) : $@convention(thin) _0_0 where τ_0_0 : InGuaranteedArgTestProtocol> (@in τ_0_0) -> ()
dealloc_stack %4 : $*InGuaranteedArgTestProtocol
destroy_addr %1 : $*InGuaranteedArgTestProtocol
dealloc_stack %1 : $*InGuaranteedArgTestProtocol
%9999 = tuple()
return %9999 : $()
}
//===----------------------------------------------------------------------===//
// Test concrete substitution for an owned references.
//===----------------------------------------------------------------------===//
extension P {
public func witnessOwned()
}
extension C {
public func witnessOwned()
}
sil @$s32sil_combine_concrete_existential1PPAAE12witnessOwnedyyF : $@convention(method) <Self where Self : P> (@owned Self) -> ()
// CHECK-LABEL: sil hidden @$s1t12testOwnedRef1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
// CHECK: bb0(%0 : $C):
// CHECK: strong_retain %0 : $C // id: %1
// CHECK: [[F:%.*]] = function_ref @$s32sil_combine_concrete_existential1PPAAE12witnessOwnedyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@owned τ_0_0) -> ()
// CHECK: apply [[F]]<C>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@owned τ_0_0) -> ()
// CHECK-NEXT: tuple
// CHECK-NEXT: return
// CHECK-LABEL: } // end sil function '$s1t12testOwnedRef1cyAA1CC_tF'
sil hidden @$s1t12testOwnedRef1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
bb0(%0 : $C):
strong_retain %0 : $C
%3 = init_existential_ref %0 : $C : $C, $P
%5 = open_existential_ref %3 : $P to $@opened("044D530E-7327-11E8-A998-ACDE48001133") P
%6 = function_ref @$s32sil_combine_concrete_existential1PPAAE12witnessOwnedyyF : $@convention(method) _0_0 where τ_0_0 : P> (@owned τ_0_0) -> ()
%7 = apply %6<@opened("044D530E-7327-11E8-A998-ACDE48001133") P>(%5) : $@convention(method) _0_0 where τ_0_0 : P> (@owned τ_0_0) -> ()
%9 = tuple ()
return %9 : $()
}
protocol P1 { }
protocol P2 { }
protocol P3 { }
sil @callee : $@convention(thin) _0_0, τ_0_1, τ_0_2 where τ_0_0 : P1, τ_0_1 : P2, τ_0_2 : P3> (@in τ_0_0, @in τ_0_2, @in τ_0_1) -> ()
// Check that the deallocations are created in the right order and the SILVerifier does not complain.
// CHECK-LABEL: sil @test_multiple_propagated_args
// CHECK-NOT: open_existential_addr
// CHECK-LABEL: } // end sil function 'test_multiple_propagated_args'
sil @test_multiple_propagated_args : $@convention(thin) _0_0, τ_0_1, τ_0_2 where τ_0_0 : P1, τ_0_1 : P2, τ_0_2 : P3> (@in τ_0_0, @in τ_0_2, @in τ_0_1) -> () {
bb0(%0 : $_0_0, %1 : $_0_2, %2 : $_0_1):
%5 = alloc_stack $P1
%6 = init_existential_addr %5 : $*P1, $τ_0_0
copy_addr [take] %0 to [initialization] %6 : $_0_0
%8 = alloc_stack $P3
%9 = init_existential_addr %8 : $*P3, $τ_0_2
copy_addr [take] %1 to [initialization] %9 : $_0_2
%11 = alloc_stack $P2
%12 = init_existential_addr %11 : $*P2, $τ_0_1
copy_addr [take] %2 to [initialization] %12 : $_0_1
%15 = function_ref @callee : $@convention(thin) _0_0, τ_0_1, τ_0_2 where τ_0_0 : P1, τ_0_1 : P2, τ_0_2 : P3> (@in τ_0_0, @in τ_0_2, @in τ_0_1) -> ()
%16 = open_existential_addr mutable_access %5 : $*P1 to $*@opened("76D54B80-FF66-11E9-B604-8C8590A6A134") P1
%17 = alloc_stack $@opened("76D54B80-FF66-11E9-B604-8C8590A6A134") P1
copy_addr %16 to [initialization] %17 : $*@opened("76D54B80-FF66-11E9-B604-8C8590A6A134") P1
%19 = open_existential_addr mutable_access %8 : $*P3 to $*@opened("76D54C34-FF66-11E9-B604-8C8590A6A134") P3
%20 = alloc_stack $@opened("76D54C34-FF66-11E9-B604-8C8590A6A134") P3
copy_addr %19 to [initialization] %20 : $*@opened("76D54C34-FF66-11E9-B604-8C8590A6A134") P3
%22 = open_existential_addr mutable_access %11 : $*P2 to $*@opened("76D54C84-FF66-11E9-B604-8C8590A6A134") P2
%23 = alloc_stack $@opened("76D54C84-FF66-11E9-B604-8C8590A6A134") P2
copy_addr %22 to [initialization] %23 : $*@opened("76D54C84-FF66-11E9-B604-8C8590A6A134") P2
%25 = apply %15<@opened("76D54B80-FF66-11E9-B604-8C8590A6A134") P1, @opened("76D54C84-FF66-11E9-B604-8C8590A6A134") P2, @opened("76D54C34-FF66-11E9-B604-8C8590A6A134") P3>(%17, %20, %23) : $@convention(thin) _0_0, τ_0_1, τ_0_2 where τ_0_0 : P1, τ_0_1 : P2, τ_0_2 : P3> (@in τ_0_0, @in τ_0_2, @in τ_0_1) -> ()
destroy_addr %11 : $*P2
dealloc_stack %23 : $*@opened("76D54C84-FF66-11E9-B604-8C8590A6A134") P2
destroy_addr %8 : $*P3
dealloc_stack %20 : $*@opened("76D54C34-FF66-11E9-B604-8C8590A6A134") P3
destroy_addr %5 : $*P1
dealloc_stack %17 : $*@opened("76D54B80-FF66-11E9-B604-8C8590A6A134") P1
dealloc_stack %11 : $*P2
dealloc_stack %8 : $*P3
dealloc_stack %5 : $*P1
return %25 : $()
}
public class MyObject {
deinit
init()
}
public protocol SubscriptionViewControllerDelegate { }
public class SubscriptionViewController {
deinit
init()
}
public protocol ResourceKitProtocol : MyObject { }
public protocol ResourceKitDelegate {
func subscriptionViewController(for resourceKit: ResourceKitProtocol)
}
class ViewController : ResourceKitDelegate {
func subscriptionViewController(for resourceKit: ResourceKitProtocol)
deinit
init()
}
class SubscriptionViewControllerBuilder {
@_hasStorage final let delegate: SubscriptionViewControllerDelegate { get }
init(delegate: SubscriptionViewControllerDelegate)
deinit
}
extension MyObject : SubscriptionViewControllerDelegate { }
// Make sure that we correctly update the substitution map of the apply.
// To satisfy ``τ_0_0 : SubscriptionViewControllerDelegate`` the updated
// substitution map of
// apply %10<$@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol>
// needs to contain the concrete conformance
// ``(normal_conformance type=NSObject protocol=SubscriptionViewControllerDelegate)``
// not ``(abstract_conformance protocol=SubscriptionViewControllerDelegate)``
sil @callee2 : $@convention(thin) _0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
// CHECK: sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed ResourceKitProtocol, @guaranteed ViewController) -> () {
// CHECK: bb0([[ARG:%.*]] : $ResourceKitProtocol, [[ARG2:%.*]] : $ViewController):
// CHECK: [[T1:%.*]] = metatype $@thick SubscriptionViewControllerBuilder.Type
// CHECK: [[T2:%.*]] = open_existential_ref [[ARG]] : $ResourceKitProtocol to $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: [[T3:%.*]] = alloc_stack $SubscriptionViewControllerDelegate
// CHECK: [[T4:%.*]] = init_existential_addr [[T3]] : $*SubscriptionViewControllerDelegate, $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: store [[T2]] to [[T4]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: [[T5:%.*]] = function_ref @callee2 : $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
// CHECK: [[T6:%.*]] = alloc_stack $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: copy_addr [[T4]] to [initialization] [[T6]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: Generic specialization information for call-site callee2 <ResourceKitProtocol> conformances <(inherited_conformance type=ResourceKitProtocol protocol=SubscriptionViewControllerDelegate
// CHECK: (normal_conformance type=MyObject protocol=SubscriptionViewControllerDelegate))>:
// CHECK: apply [[T5]]<@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol>([[T6]], [[T1]])
sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed ResourceKitProtocol, @guaranteed ViewController) -> () {
bb0(%0 : $ResourceKitProtocol, %1 : $ViewController):
%4 = metatype $@thick SubscriptionViewControllerBuilder.Type
%5 = open_existential_ref %0 : $ResourceKitProtocol to $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
%6 = alloc_stack $SubscriptionViewControllerDelegate
%7 = init_existential_addr %6 : $*SubscriptionViewControllerDelegate, $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
strong_retain %5 : $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
store %5 to %7 : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
%10 = function_ref @callee2: $@convention(thin) _0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
%11 = open_existential_addr mutable_access %6 : $*SubscriptionViewControllerDelegate to $*@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
%12 = alloc_stack $@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
copy_addr %11 to [initialization] %12 : $*@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
%14 = apply %10<@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate>(%12, %4) : $@convention(thin) _0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
destroy_addr %6 : $*SubscriptionViewControllerDelegate
dealloc_stack %12 : $*@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
dealloc_stack %6 : $*SubscriptionViewControllerDelegate
strong_release %14 : $SubscriptionViewControllerBuilder
%19 = tuple ()
return %19 : $()
}
sil_vtable SubscriptionViewControllerBuilder {}
sil_vtable SubscriptionViewController {}
sil_vtable ViewController {}
sil_vtable CCCC {}
sil_vtable CC {}
sil_vtable C {}
sil_vtable C_PQ {}
sil_vtable CDefaultStatic {}
sil_vtable MyObject {}