Skip to content

Commit 88d6304

Browse files
committed
[Constraint solver] Delay Sendable on static method references involving possibly-nonsendable metatypes
Thank you, Pavel!
1 parent 53707a1 commit 88d6304

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10565,26 +10565,34 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
1056510565
if (Context.LangOpts.hasFeature(Feature::InferSendableFromCaptures)) {
1056610566
auto shouldCheckSendabilityOfBase = [&]() {
1056710567
if (!Context.getProtocol(KnownProtocolKind::Sendable))
10568-
return false;
10568+
return Type();
1056910569

10570-
return llvm::any_of(lookup, [&](const auto &result) {
10570+
for (const auto &result : lookup) {
1057110571
auto decl = result.getValueDecl();
1057210572
if (!isa_and_nonnull<FuncDecl>(decl))
10573-
return false;
10573+
continue;
1057410574

10575-
if (!decl->isInstanceMember())
10576-
return false;
10575+
if (!decl->isInstanceMember() &&
10576+
!decl->getDeclContext()->getSelfProtocolDecl())
10577+
continue;
1057710578

1057810579
auto hasAppliedSelf = decl->hasCurriedSelf() &&
1057910580
doesMemberRefApplyCurriedSelf(baseObjTy, decl);
1058010581
auto numApplies = getNumApplications(hasAppliedSelf, functionRefInfo);
10581-
return numApplies < decl->getNumCurryLevels();
10582-
});
10582+
if (numApplies >= decl->getNumCurryLevels())
10583+
continue;
10584+
10585+
return decl->isInstanceMember()
10586+
? instanceTy
10587+
: MetatypeType::get(instanceTy);
10588+
}
10589+
10590+
return Type();
1058310591
};
1058410592

10585-
if (shouldCheckSendabilityOfBase()) {
10593+
if (Type baseTyToCheck = shouldCheckSendabilityOfBase()) {
1058610594
auto sendableProtocol = Context.getProtocol(KnownProtocolKind::Sendable);
10587-
auto baseConformance = lookupConformance(instanceTy, sendableProtocol);
10595+
auto baseConformance = lookupConformance(baseTyToCheck, sendableProtocol);
1058810596

1058910597
if (llvm::any_of(
1059010598
baseConformance.getConditionalRequirements(),
@@ -10593,8 +10601,10 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
1059310601
return false;
1059410602

1059510603
return (req.getFirstType()->hasTypeVariable() &&
10596-
req.getProtocolDecl()->isSpecificProtocol(
10597-
KnownProtocolKind::Sendable));
10604+
(req.getProtocolDecl()->isSpecificProtocol(
10605+
KnownProtocolKind::Sendable) ||
10606+
req.getProtocolDecl()->isSpecificProtocol(
10607+
KnownProtocolKind::SendableMetatype)));
1059810608
})) {
1059910609
result.OverallResult = MemberLookupResult::Unsolved;
1060010610
return result;

test/Concurrency/sendable_metatype_typecheck.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,25 @@ case q(Q.Type, Int) // expected-warning{{associated value 'q' of 'Sendable'-conf
125125
struct S: Sendable {
126126
var tuple: ([Q.Type], Int) // expected-warning{{stored property 'tuple' of 'Sendable'-conforming struct 'S' has non-sendable type '([any Q.Type], Int)'}}
127127
}
128+
129+
extension Q {
130+
static func h() -> Self { }
131+
}
132+
133+
extension Array: Q where Element: Q {
134+
static func g() { }
135+
}
136+
137+
struct GenericS<T> { }
138+
139+
extension GenericS: Q where T: Q {
140+
static func g() { }
141+
}
142+
143+
extension GenericS: Sendable where T: Sendable { }
144+
145+
final class TestStaticMembers<T> {
146+
init(_: T) {
147+
let _: @Sendable () -> GenericS<Int> = GenericS.h // Ok
148+
}
149+
}

0 commit comments

Comments
 (0)