[Effects] Ensure that we properly substitute function types in ByClosure checks

We weren't substituting generic arguments into function types. In the
presence of parameter packs, this could mean that the parameter and
argument lists no longer match up, which would cause the effects
checker to prematurely bail out after treating this as "invalid" code.
The overall effect is that we would not properly check for throwing
behavior in this case, allowing invalid code (as in the example) and
miscompiling valid code by not treating the call as throwing.

Fixes rdar://153926820.
This commit is contained in:
Doug Gregor
2025-06-25 10:01:34 -07:00
parent 9220e686b5
commit 283cb60664
2 changed files with 16 additions and 0 deletions

View File

@@ -1838,6 +1838,8 @@ public:
FunctionType *fnSubstType = nullptr;
if (auto *fnGenericType = fnInterfaceType->getAs<GenericFunctionType>())
fnSubstType = fnGenericType->substGenericArgs(fnRef.getSubstitutions());
else if (fnRef.getSubstitutions())
fnSubstType = fnInterfaceType.subst(fnRef.getSubstitutions())->getAs<FunctionType>();
else
fnSubstType = fnInterfaceType->getAs<FunctionType>();

View File

@@ -256,3 +256,17 @@ func takesClosure(_: (() -> ())) throws -> Int {}
func passesClosure() {
_ = try takesClosure { } // expected-error {{errors thrown from here are not handled}}
}
// Parameter packs checking
struct S {
static func packTest<each T>(_ values: repeat (each T).Type, shouldThrow: Bool) throws -> Bool {
if (shouldThrow) {
throw MSV.Foo
}
return true
}
static func test() -> Bool {
return try packTest(String.self, String.self, shouldThrow: true) // expected-error{{errors thrown from here are not handled}}
}
}