mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
The current existential closing logic relies on maintaining a stack of expressions, and closing the existential when the size of the stack goes below a certain threshold. This works fine for cases where we open the existential as a part of an user-written member reference, as we push it onto the stack when walking over the AST. However it doesn't handle cases where we generate an implicit member reference when visiting a part of the AST higher up in the tree. We therefore run into problems with both implicit `callAsFunction` and `@dynamicCallable`, both of which generate implicit member refs when we visit the apply. To hack around this issue, push the apply's fn expr onto the stack before building the member reference, such that we don't try to prematurely close the existential as a part of applying the curried member ref. The good news at least is that this hack allows us to remove the `extraUncurryLevel` param which was previously working around this issue for the `shouldBuildCurryThunk` function. To properly fix this, we'll need to refactor existential opening to not rely on the shape of the AST prior to re-writing. Resolves SR-12590.
79 lines
3.0 KiB
Swift
79 lines
3.0 KiB
Swift
// RUN: %target-swift-emit-silgen -verify %s | %FileCheck %s
|
|
|
|
// Check that dynamic calls resolve to the right `dynamicallyCall` method in SIL.
|
|
|
|
@dynamicCallable
|
|
public struct Callable {
|
|
func dynamicallyCall(withArguments: [Int]) {}
|
|
func dynamicallyCall(withKeywordArguments: KeyValuePairs<String, Int>) {}
|
|
}
|
|
|
|
@_silgen_name("foo")
|
|
public func foo(a: Callable) {
|
|
// The first two calls should resolve to the `withArguments:` method.
|
|
a()
|
|
a(1, 2, 3)
|
|
// The last call should resolve to the `withKeywordArguments:` method.
|
|
a(1, 2, 3, label: 4)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @foo
|
|
// CHECK: bb0(%0 : $Callable):
|
|
// CHECK: [[DYN_CALL_1:%.*]] = function_ref @$s26dynamic_callable_attribute8CallableV15dynamicallyCall13withArgumentsySaySiG_tF
|
|
// CHECK-NEXT: apply [[DYN_CALL_1]]
|
|
// CHECK: [[DYN_CALL_2:%.*]] = function_ref @$s26dynamic_callable_attribute8CallableV15dynamicallyCall13withArgumentsySaySiG_tF
|
|
// CHECK-NEXT: apply [[DYN_CALL_2]]
|
|
// CHECK: [[DYN_CALL_3:%.*]] = function_ref @$s26dynamic_callable_attribute8CallableV15dynamicallyCall20withKeywordArgumentsys13KeyValuePairsVySSSiG_tF
|
|
|
|
|
|
@dynamicCallable
|
|
public struct Callable2 {
|
|
func dynamicallyCall(withKeywordArguments: KeyValuePairs<String, Any>) {}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @keywordCoerceBug
|
|
// CHECK:[[DYN_CALL:%.*]] = function_ref @$s26dynamic_callable_attribute9Callable2V15dynamicallyCall20withKeywordArgumentsys13KeyValuePairsVySSypG_tF
|
|
|
|
@_silgen_name("keywordCoerceBug")
|
|
public func keywordCoerceBug(a: Callable2, s: Int) {
|
|
a(s)
|
|
}
|
|
|
|
@dynamicCallable
|
|
struct S {
|
|
func dynamicallyCall(withArguments x: [Int]) -> Int! { nil }
|
|
}
|
|
|
|
@dynamicCallable
|
|
protocol P1 {
|
|
func dynamicallyCall(withKeywordArguments: [String: Any])
|
|
}
|
|
|
|
@dynamicCallable
|
|
protocol P2 {
|
|
func dynamicallyCall(withArguments x: [Int]) -> Self
|
|
}
|
|
|
|
@dynamicCallable
|
|
class C {
|
|
func dynamicallyCall(withKeywordArguments x: [String: String]) -> Self { return self }
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s26dynamic_callable_attribute05test_A10_callablesyyAA1SV_AA2P1_pAA2P2_pxtAA1CCRbzlF : $@convention(thin) <T where T : C> (S, @in_guaranteed P1, @in_guaranteed P2, @guaranteed T) -> ()
|
|
func test_dynamic_callables<T : C>(_ s: S, _ p1: P1, _ p2: P2, _ t: T) {
|
|
// SR-12615: Compiler crash on @dynamicCallable IUO.
|
|
// CHECK: function_ref @$s26dynamic_callable_attribute1SV15dynamicallyCall13withArgumentsSiSgSaySiG_tF : $@convention(method) (@guaranteed Array<Int>, S) -> Optional<Int>
|
|
// CHECK: switch_enum %{{.+}} : $Optional<Int>
|
|
let _: Int = s(0)
|
|
|
|
// CHECK: witness_method $@opened({{.+}}) P1, #P1.dynamicallyCall : <Self where Self : P1> (Self) -> ([String : Any]) -> ()
|
|
p1(x: 5)
|
|
|
|
// CHECK: witness_method $@opened({{.+}}) P2, #P2.dynamicallyCall : <Self where Self : P2> (Self) -> ([Int]) -> Self
|
|
_ = p2()
|
|
|
|
// CHECK: class_method %{{.+}} : $C, #C.dynamicallyCall : (C) -> ([String : String]) -> @dynamic_self C, $@convention(method) (@guaranteed Dictionary<String, String>, @guaranteed C) -> @owned C
|
|
// CHECK: unchecked_ref_cast %{{.+}} : $C to $T
|
|
_ = t("")
|
|
}
|