[Sema] ConstnessChecker: Look through function conversions while checking arguments

In strict concurrency mode some calls could reference a declaration that
is  wrapped in one or more function conversion expressions to apply
concurrency related attributes or erase them (such as `@Sendable` or
`@MainActor`). This shouldn't impact constness checking and the checker
should look through such conversions.

Resolves: rdar://148168219
This commit is contained in:
Pavel Yaskevich
2025-04-23 14:08:34 -07:00
parent 8226f20ddb
commit b484e9645d
2 changed files with 37 additions and 2 deletions

View File

@@ -175,7 +175,8 @@ static Expr *checkConstantness(Expr *expr) {
return expr;
ApplyExpr *apply = cast<ApplyExpr>(expr);
ValueDecl *calledValue = apply->getCalledValue();
ValueDecl *calledValue =
apply->getCalledValue(/*skipFunctionConversions=*/true);
if (!calledValue)
return expr;
@@ -300,7 +301,8 @@ static void diagnoseConstantArgumentRequirementOfCall(const CallExpr *callExpr,
const ASTContext &ctx) {
assert(callExpr && callExpr->getType() &&
"callExpr should have a valid type");
ValueDecl *calledDecl = callExpr->getCalledValue();
ValueDecl *calledDecl =
callExpr->getCalledValue(/*skipFunctionConversions=*/true);
if (!calledDecl || !isa<AbstractFunctionDecl>(calledDecl))
return;
AbstractFunctionDecl *callee = cast<AbstractFunctionDecl>(calledDecl);

View File

@@ -0,0 +1,33 @@
// RUN: %target-typecheck-verify-swift -swift-version 6
// REQUIRES: VENDOR=apple
// REQUIRES: concurrency
import OSLogTestHelper
class Log {
@_semantics("oslog.requires_constant_arguments")
func debug(_: OSLogMessage) {}
}
@_semantics("constant_evaluable")
@_transparent
public func __outputFormatter(_ key: String, fallback: OSLogMessage) -> OSLogMessage {
fallback
}
@MainActor
@_semantics("constant_evaluable")
@_transparent
public func __isolatedOutputFormatter(_ key: String, fallback: OSLogMessage) -> OSLogMessage {
fallback
}
func test(log: Log) {
log.debug(__outputFormatter("1", fallback: "msg")) // Ok
}
@MainActor
func isolatedTest(log: Log) {
log.debug(__isolatedOutputFormatter("1", fallback: "msg")) // Ok
}