@@ -2178,6 +2178,41 @@ namespace {
2178
2178
};
2179
2179
} // end anonymous namespace
2180
2180
2181
+ static bool matchFunctionTypes (CanAnyFunctionType fn1, CanAnyFunctionType fn2,
2182
+ TypeMatchOptions matchMode,
2183
+ OptionalUnwrapping insideOptional,
2184
+ std::function<bool ()> paramsAndResultMatch) {
2185
+ // FIXME: Handle generic functions in non-ABI matches.
2186
+ if (!matchMode.contains (TypeMatchFlags::AllowABICompatible)) {
2187
+ if (!isa<FunctionType>(fn1) || !isa<FunctionType>(fn2))
2188
+ return false ;
2189
+ }
2190
+
2191
+ // When checking overrides, allow the base type to be throwing even if the
2192
+ // overriding type isn't.
2193
+ auto ext1 = fn1->getExtInfo ();
2194
+ auto ext2 = fn2->getExtInfo ();
2195
+ if (matchMode.contains (TypeMatchFlags::AllowOverride)) {
2196
+ if (ext2.throws ()) {
2197
+ ext1 = ext1.withThrows (true );
2198
+ }
2199
+ }
2200
+ // If specified, allow an escaping function parameter to override a
2201
+ // non-escaping function parameter when the parameter is optional.
2202
+ // Note that this is checking 'ext2' rather than 'ext1' because parameters
2203
+ // must be contravariant for the containing function to be covariant.
2204
+ if (matchMode.contains (
2205
+ TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam) &&
2206
+ insideOptional == OptionalUnwrapping::OptionalToOptional) {
2207
+ if (!ext2.isNoEscape ())
2208
+ ext1 = ext1.withNoEscape (false );
2209
+ }
2210
+ if (ext1 != ext2)
2211
+ return false ;
2212
+
2213
+ return paramsAndResultMatch ();
2214
+ }
2215
+
2181
2216
static bool matches (CanType t1, CanType t2, TypeMatchOptions matchMode,
2182
2217
ParameterPosition paramPosition,
2183
2218
OptionalUnwrapping insideOptional) {
@@ -2255,39 +2290,17 @@ static bool matches(CanType t1, CanType t2, TypeMatchOptions matchMode,
2255
2290
if (!fn1)
2256
2291
return false ;
2257
2292
2258
- // FIXME: Handle generic functions in non-ABI matches.
2259
- if (!matchMode.contains (TypeMatchFlags::AllowABICompatible)) {
2260
- if (!isa<FunctionType>(t1) || !isa<FunctionType>(t2))
2261
- return false ;
2262
- }
2263
-
2264
- // When checking overrides, allow the base type to be throwing even if the
2265
- // overriding type isn't.
2266
- auto ext1 = fn1->getExtInfo ();
2267
- auto ext2 = fn2->getExtInfo ();
2268
- if (matchMode.contains (TypeMatchFlags::AllowOverride)) {
2269
- if (ext2.throws ()) {
2270
- ext1 = ext1.withThrows (true );
2271
- }
2272
- }
2273
- // If specified, allow an escaping function parameter to override a
2274
- // non-escaping function parameter when the parameter is optional.
2275
- // Note that this is checking 'ext2' rather than 'ext1' because parameters
2276
- // must be contravariant for the containing function to be covariant.
2277
- if (matchMode.contains (
2278
- TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam) &&
2279
- insideOptional == OptionalUnwrapping::OptionalToOptional) {
2280
- if (!ext2.isNoEscape ())
2281
- ext1 = ext1.withNoEscape (false );
2282
- }
2283
- if (ext1 != ext2)
2284
- return false ;
2293
+ std::function<bool ()> paramsAndResultMatch = [=]() {
2294
+ // Inputs are contravariant, results are covariant.
2295
+ return (matches (fn2.getInput (), fn1.getInput (), matchMode,
2296
+ ParameterPosition::Parameter, OptionalUnwrapping::None) &&
2297
+ matches (fn1.getResult (), fn2.getResult (), matchMode,
2298
+ ParameterPosition::NotParameter,
2299
+ OptionalUnwrapping::None));
2300
+ };
2285
2301
2286
- // Inputs are contravariant, results are covariant.
2287
- return (matches (fn2.getInput (), fn1.getInput (), matchMode,
2288
- ParameterPosition::Parameter, OptionalUnwrapping::None) &&
2289
- matches (fn1.getResult (), fn2.getResult (), matchMode,
2290
- ParameterPosition::NotParameter, OptionalUnwrapping::None));
2302
+ return matchFunctionTypes (fn1, fn2, matchMode, insideOptional,
2303
+ paramsAndResultMatch);
2291
2304
}
2292
2305
2293
2306
if (matchMode.contains (TypeMatchFlags::AllowNonOptionalForIUOParam) &&
0 commit comments