Skip to content

Commit e6a6ecf

Browse files
committed
[NameLookup] Lift synthesized protocol check into getDirectlyInheritedNominalTypeDecls
Some places use `getDirectlyInheritedNominalTypeDecls` directly instead of fetching it through a request, so lift the check there instead (direct use of `getDirectlyInheritedNominalTypeDecls` could be refactored separately).
1 parent ab4f8d0 commit e6a6ecf

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

lib/AST/NameLookup.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3187,20 +3187,12 @@ ArrayRef<ProtocolDecl *>
31873187
InheritedProtocolsRequest::evaluate(Evaluator &evaluator,
31883188
ProtocolDecl *PD) const {
31893189
llvm::SmallSetVector<ProtocolDecl *, 2> inherited;
3190-
auto addInherited = [&inherited, &PD](ProtocolDecl *P) {
3191-
if (PD != P)
3192-
inherited.insert(P);
3193-
};
3194-
3195-
for (auto attr : PD->getAttrs().getAttributes<SynthesizedProtocolAttr>()) {
3196-
addInherited(attr->getProtocol());
3197-
}
3198-
31993190
bool anyObject = false;
3200-
for (const auto &found : getDirectlyInheritedNominalTypeDecls(PD, anyObject)) {
3201-
if (auto proto = dyn_cast<ProtocolDecl>(found.Item)) {
3202-
addInherited(proto);
3203-
}
3191+
for (const auto &found :
3192+
getDirectlyInheritedNominalTypeDecls(PD, anyObject)) {
3193+
auto proto = dyn_cast<ProtocolDecl>(found.Item);
3194+
if (proto && proto != PD)
3195+
inherited.insert(proto);
32043196
}
32053197

32063198
return PD->getASTContext().AllocateCopy(inherited.getArrayRef());
@@ -3718,6 +3710,16 @@ swift::getDirectlyInheritedNominalTypeDecls(
37183710
return result;
37193711
}
37203712

3713+
// Check for SynthesizedProtocolAttrs on the protocol. ClangImporter uses
3714+
// these to add `Sendable` conformances to protocols without modifying the
3715+
// inherited type list.
3716+
for (auto attr :
3717+
protoDecl->getAttrs().getAttributes<SynthesizedProtocolAttr>()) {
3718+
auto loc = attr->getLocation();
3719+
result.push_back(
3720+
{attr->getProtocol(), loc, attr->isUnchecked() ? loc : SourceLoc()});
3721+
}
3722+
37213723
// Else we have access to this information on the where clause.
37223724
auto selfBounds = getSelfBoundsFromWhereClause(decl);
37233725
anyObject |= selfBounds.anyObject;

test/Concurrency/sendable_objc_protocol_attr.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ NS_SWIFT_SENDABLE
2222
@property (readonly, nonatomic) NSString *test;
2323
@end
2424

25+
@protocol MyRefinedObjCProtocol <MyObjCProtocol>
26+
@end
27+
2528
#pragma clang assume_nonnull end
2629

2730
//--- main.swift
@@ -38,3 +41,30 @@ extension MyObjCProtocol {
3841
compute() // Ok
3942
}
4043
}
44+
45+
class K : NSObject, MyObjCProtocol {
46+
// expected-warning@-1 {{non-final class 'K' cannot conform to 'Sendable'; use '@unchecked Sendable'}}
47+
let test: String = "k"
48+
}
49+
50+
class UncheckedK : NSObject, MyObjCProtocol, @unchecked Sendable { // ok
51+
let test: String = "unchecked"
52+
}
53+
54+
class KRefined : NSObject, MyRefinedObjCProtocol {
55+
// expected-warning@-1 {{non-final class 'KRefined' cannot conform to 'Sendable'; use '@unchecked Sendable'}}
56+
let test: String = "refined"
57+
}
58+
59+
class KUncheckedRefined : NSObject, MyRefinedObjCProtocol, @unchecked Sendable { // Ok
60+
let test: String = "refined unchecked"
61+
}
62+
63+
do {
64+
func testSendable<T: Sendable>(_: T) {}
65+
66+
testSendable(K()) // Ok
67+
testSendable(UncheckedK()) // Ok
68+
testSendable(KRefined()) // Ok
69+
testSendable(KUncheckedRefined()) // Ok
70+
}

0 commit comments

Comments
 (0)