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