@@ -1867,7 +1867,10 @@ class DelayedArgument {
1867
1867
// / A string r-value needs to be converted to a pointer type.
1868
1868
RValueStringToPointer,
1869
1869
1870
- LastRVKind = RValueStringToPointer,
1870
+ // / A function conversion needs to occur.
1871
+ FunctionConversion,
1872
+
1873
+ LastRVKind = FunctionConversion,
1871
1874
1872
1875
// / A default argument that needs to be evaluated.
1873
1876
DefaultArgument,
@@ -2038,6 +2041,7 @@ class DelayedArgument {
2038
2041
case LValueArrayToPointer:
2039
2042
case RValueArrayToPointer:
2040
2043
case RValueStringToPointer:
2044
+ case FunctionConversion:
2041
2045
args[argIndex] = finishOriginalArgument (SGF);
2042
2046
return ;
2043
2047
case DefaultArgument:
@@ -2121,7 +2125,8 @@ class DelayedArgument {
2121
2125
// Done with the recursive cases. Make sure we handled everything.
2122
2126
assert (isa<InOutToPointerExpr>(expr) ||
2123
2127
isa<ArrayToPointerExpr>(expr) ||
2124
- isa<StringToPointerExpr>(expr));
2128
+ isa<StringToPointerExpr>(expr) ||
2129
+ isa<FunctionConversionExpr>(expr));
2125
2130
2126
2131
switch (Kind) {
2127
2132
case InOut:
@@ -2154,6 +2159,17 @@ class DelayedArgument {
2154
2159
return SGF.emitStringToPointer (pointerExpr, stringValue,
2155
2160
pointerExpr->getType ());
2156
2161
}
2162
+ case FunctionConversion: {
2163
+ auto funcConv = cast<FunctionConversionExpr>(expr);
2164
+ auto optFuncValue = RV ().RV ;
2165
+ auto funcValue =
2166
+ emitBindOptionals (SGF, optFuncValue, funcConv->getSubExpr ());
2167
+ return {SGF.emitTransformedValue (funcConv, funcValue,
2168
+ funcConv->getSubExpr ()->getType ()->getCanonicalType (),
2169
+ funcConv->getType ()->getCanonicalType (),
2170
+ SGFContext ()),
2171
+ ManagedValue ()};
2172
+ }
2157
2173
}
2158
2174
llvm_unreachable (" bad kind" );
2159
2175
}
@@ -2747,6 +2763,37 @@ class ArgEmitter {
2747
2763
if (auto stringToPointer = dyn_cast<StringToPointerExpr>(expr)) {
2748
2764
return emitDelayedConversion (stringToPointer, original);
2749
2765
}
2766
+
2767
+ // Delay function conversions involving the opened Self type of an
2768
+ // existential whose opening is itself delayed.
2769
+ //
2770
+ // This comes up when invoking protocol methods on an existential that
2771
+ // have covariant arguments of function type with Self arguments, e.g.:
2772
+ //
2773
+ // protocol P {
2774
+ // mutating func foo(_: (Self) -> Void)
2775
+ // }
2776
+ //
2777
+ // func bar(x: inout P) {
2778
+ // x.foo { y in return }
2779
+ // }
2780
+ //
2781
+ // Although the type-erased method is presented as formally taking an
2782
+ // argument of the existential type P, it still has a conversion thunk to
2783
+ // perform type erasure on the argument coming from the underlying
2784
+ // implementation. Since the `self` argument is inout, it isn't formally
2785
+ // opened until late when formal accesses begin, so this closure conversion
2786
+ // must also be deferred until after that occurs.
2787
+ if (auto funcConv = dyn_cast<FunctionConversionExpr>(expr)) {
2788
+ auto destTy = funcConv->getType ()->castTo <AnyFunctionType>();
2789
+ auto srcTy = funcConv->getSubExpr ()->getType ()->castTo <AnyFunctionType>();
2790
+
2791
+ if (destTy->hasOpenedExistential ()
2792
+ && !srcTy->hasOpenedExistential ()
2793
+ && destTy->getRepresentation () == srcTy->getRepresentation ()) {
2794
+ return emitDelayedConversion (funcConv, original);
2795
+ }
2796
+ }
2750
2797
2751
2798
// Any recursive cases we handle here need to be handled in
2752
2799
// DelayedArgument::finishOriginalExpr.
@@ -2828,6 +2875,16 @@ class ArgEmitter {
2828
2875
Args.push_back (ManagedValue ());
2829
2876
return true ;
2830
2877
}
2878
+
2879
+ bool emitDelayedConversion (FunctionConversionExpr *funcConv,
2880
+ OriginalArgument original) {
2881
+ auto rvalueExpr = lookThroughBindOptionals (funcConv->getSubExpr ());
2882
+ ManagedValue value = SGF.emitRValueAsSingleValue (rvalueExpr);
2883
+ DelayedArguments.emplace_back (DelayedArgument::FunctionConversion,
2884
+ value, original);
2885
+ Args.push_back (ManagedValue ());
2886
+ return true ;
2887
+ }
2831
2888
2832
2889
static Expr *lookThroughBindOptionals (Expr *expr) {
2833
2890
while (true ) {
0 commit comments