Skip to content

Commit c5fa0cf

Browse files
authored
Merge pull request #40271 from DougGregor/predates-concurrency-abi-c
2 parents dd93538 + 42c71c9 commit c5fa0cf

File tree

13 files changed

+149
-65
lines changed

13 files changed

+149
-65
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ class ASTMangler : public Mangler {
6767
/// If enabled, marker protocols can be encoded in the mangled name.
6868
bool AllowMarkerProtocols = true;
6969

70+
/// Whether the mangling predates concurrency, and therefore shouldn't
71+
/// include concurrency features such as global actors or @Sendable
72+
/// function types.
73+
bool PredatesConcurrency = false;
74+
7075
public:
7176
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
7277
const OpaqueTypeDecl *>;

include/swift/AST/Types.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,15 @@ class alignas(1 << TypeAlignInBits) TypeBase
11891189
/// types.
11901190
Type lookThroughAllOptionalTypes(SmallVectorImpl<Type> &optionals);
11911191

1192+
/// Remove concurrency-related types and constraints from the given
1193+
/// type
1194+
///
1195+
/// \param recurse Whether to recurse into function types.
1196+
///
1197+
/// \param dropGlobalActor Whether to drop a global actor from a function
1198+
/// type.
1199+
Type stripConcurrency(bool recurse, bool dropGlobalActor);
1200+
11921201
/// Whether this is the AnyObject type.
11931202
bool isAnyObject();
11941203

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3803,6 +3803,10 @@ namespace {
38033803
printFlag(T->isAsync(), "async");
38043804
printFlag(T->isThrowing(), "throws");
38053805

3806+
if (Type globalActor = T->getGlobalActor()) {
3807+
printField("global_actor", globalActor.getString());
3808+
}
3809+
38063810
OS << "\n";
38073811
Indent += 2;
38083812
// [TODO: Improve-Clang-type-printing]
@@ -3815,10 +3819,6 @@ namespace {
38153819
printField("clang_type", os.str());
38163820
}
38173821

3818-
if (Type globalActor = T->getGlobalActor()) {
3819-
printField("global_actor", globalActor.getString());
3820-
}
3821-
38223822
printAnyFunctionParams(T->getParams(), "input");
38233823
Indent -=2;
38243824
printRec("output", T->getResult());

lib/AST/ASTMangler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,6 +2969,13 @@ CanType ASTMangler::getDeclTypeForMangling(
29692969

29702970
Type ty = decl->getInterfaceType()->getReferenceStorageReferent();
29712971

2972+
// If this declaration predates concurrency, adjust its type to not
2973+
// contain type features that were not available pre-concurrency. This
2974+
// cannot alter the ABI in any way.
2975+
if (decl->predatesConcurrency()) {
2976+
ty = ty->stripConcurrency(/*recurse=*/true, /*dropGlobalActor=*/true);
2977+
}
2978+
29722979
auto canTy = ty->getCanonicalType();
29732980

29742981
if (auto gft = dyn_cast<GenericFunctionType>(canTy)) {

lib/AST/Decl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "swift/AST/TypeLoc.h"
4747
#include "swift/AST/SwiftNameTranslation.h"
4848
#include "swift/Basic/Defer.h"
49+
#include "swift/ClangImporter/ClangModule.h"
4950
#include "swift/Parse/Lexer.h" // FIXME: Bad dependency
5051
#include "clang/Lex/MacroInfo.h"
5152
#include "llvm/ADT/SmallPtrSet.h"
@@ -719,7 +720,14 @@ Optional<CustomAttrNominalPair> Decl::getGlobalActorAttr() const {
719720
}
720721

721722
bool Decl::predatesConcurrency() const {
722-
return getAttrs().hasAttribute<PredatesConcurrencyAttr>();
723+
if (getAttrs().hasAttribute<PredatesConcurrencyAttr>())
724+
return true;
725+
726+
// Imported C declarations always predate concurrency.
727+
if (isa<ClangModuleUnit>(getDeclContext()->getModuleScopeContext()))
728+
return true;
729+
730+
return false;
723731
}
724732

725733

lib/AST/Type.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,94 @@ Type TypeBase::lookThroughAllOptionalTypes(SmallVectorImpl<Type> &optionals){
755755
return type;
756756
}
757757

758+
Type TypeBase::stripConcurrency(bool recurse, bool dropGlobalActor) {
759+
// Look through optionals.
760+
if (Type optionalObject = getOptionalObjectType()) {
761+
Type newOptionalObject =
762+
optionalObject->stripConcurrency(recurse, dropGlobalActor);
763+
if (optionalObject->isEqual(newOptionalObject))
764+
return Type(this);
765+
766+
return OptionalType::get(newOptionalObject);
767+
}
768+
769+
// Function types.
770+
if (auto fnType = getAs<AnyFunctionType>()) {
771+
// Strip off Sendable and (possibly) the global actor.
772+
ASTExtInfo extInfo =
773+
fnType->hasExtInfo() ? fnType->getExtInfo() : ASTExtInfo();
774+
extInfo = extInfo.withConcurrent(false);
775+
if (dropGlobalActor)
776+
extInfo = extInfo.withGlobalActor(Type());
777+
778+
ArrayRef<AnyFunctionType::Param> params = fnType->getParams();
779+
Type resultType = fnType->getResult();
780+
781+
SmallVector<AnyFunctionType::Param, 4> newParams;
782+
if (recurse) {
783+
for (unsigned paramIdx : indices(params)) {
784+
const auto &param = params[paramIdx];
785+
Type newParamType = param.getPlainType()->stripConcurrency(
786+
recurse, dropGlobalActor);
787+
788+
if (!newParams.empty()) {
789+
newParams.push_back(param.withType(newParamType));
790+
continue;
791+
}
792+
793+
if (newParamType->isEqual(param.getPlainType()))
794+
continue;
795+
796+
newParams.append(params.begin(), params.begin() + paramIdx);
797+
newParams.push_back(param.withType(newParamType));
798+
}
799+
800+
if (!newParams.empty())
801+
params = newParams;
802+
803+
resultType = resultType->stripConcurrency(recurse, dropGlobalActor);
804+
}
805+
806+
// Drop Sendable requirements.
807+
GenericSignature genericSig;
808+
if (auto genericFnType = dyn_cast<GenericFunctionType>(fnType)) {
809+
auto requirements = genericFnType->getRequirements();
810+
SmallVector<Requirement, 4> newRequirements;
811+
for (unsigned reqIdx : indices(requirements)) {
812+
// If it's a Sendable requirement, skip it.
813+
const auto &req = requirements[reqIdx];
814+
if (req.getKind() == RequirementKind::Conformance &&
815+
req.getSecondType()->castTo<ProtocolType>()->getDecl()
816+
->isSpecificProtocol(KnownProtocolKind::Sendable))
817+
continue;
818+
819+
newRequirements.push_back(req);
820+
}
821+
822+
if (newRequirements.size() == requirements.size()) {
823+
genericSig = genericFnType->getGenericSignature();
824+
} else {
825+
genericSig = GenericSignature::get(
826+
genericFnType->getGenericParams(), newRequirements);
827+
}
828+
}
829+
830+
Type newFnType;
831+
if (genericSig) {
832+
newFnType = GenericFunctionType::get(
833+
genericSig, params, resultType, extInfo);
834+
} else {
835+
newFnType = FunctionType::get(params, resultType, extInfo);
836+
}
837+
if (newFnType->isEqual(this))
838+
return Type(this);
839+
840+
return newFnType;
841+
}
842+
843+
return Type(this);
844+
}
845+
758846
bool TypeBase::isAnyObject() {
759847
auto canTy = getCanonicalType();
760848

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8392,17 +8392,13 @@ SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile(
83928392
return *sourceFile;
83938393
}
83948394

8395-
Optional<bool> swift::importer::isMainActorAttr(
8396-
ASTContext &ctx, const clang::SwiftAttrAttr *swiftAttr) {
8395+
bool swift::importer::isMainActorAttr(const clang::SwiftAttrAttr *swiftAttr) {
83978396
if (swiftAttr->getAttribute() == "@MainActor" ||
8398-
swiftAttr->getAttribute() == "@MainActor(unsafe)" ||
83998397
swiftAttr->getAttribute() == "@UIActor") {
8400-
bool isUnsafe = swiftAttr->getAttribute() == "@MainActor(unsafe)" ||
8401-
!ctx.LangOpts.isSwiftVersionAtLeast(6);
8402-
return isUnsafe;
8398+
return true;
84038399
}
84048400

8405-
return None;
8401+
return false;
84068402
}
84078403

84088404
void
@@ -8430,9 +8426,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84308426
for (auto swiftAttr : ClangDecl->specific_attrs<clang::SwiftAttrAttr>()) {
84318427
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
84328428
// point at which to do name lookup for imported entities.
8433-
if (auto isMainActor = isMainActorAttr(SwiftContext, swiftAttr)) {
8434-
bool isUnsafe = *isMainActor;
8435-
8429+
if (isMainActorAttr(swiftAttr)) {
84368430
if (SeenMainActorAttr) {
84378431
// Cannot add main actor annotation twice. We'll keep the first
84388432
// one and raise a warning about the duplicate.
@@ -8446,7 +8440,6 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84468440
if (Type mainActorType = SwiftContext.getMainActorType()) {
84478441
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
84488442
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
8449-
attr->setArgIsUnsafe(isUnsafe);
84508443
MappedDecl->getAttrs().add(attr);
84518444
SeenMainActorAttr = swiftAttr;
84528445
}

lib/ClangImporter/ImportType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,7 @@ Type ClangImporter::Implementation::applyParamAttributes(
17261726
continue;
17271727

17281728
// Map the main-actor attribute.
1729-
if (isMainActorAttr(SwiftContext, swiftAttr)) {
1729+
if (isMainActorAttr(swiftAttr)) {
17301730
if (Type mainActor = SwiftContext.getMainActorType()) {
17311731
type = applyToFunctionType(type, [&](ASTExtInfo extInfo) {
17321732
return extInfo.withGlobalActor(mainActor);

lib/ClangImporter/ImporterImpl.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,11 +1663,7 @@ class SwiftNameLookupExtension : public clang::ModuleFileExtension {
16631663

16641664
/// Determines whether the given swift_attr attribute describes the main
16651665
/// actor.
1666-
///
1667-
/// \returns None if this is not a main-actor attribute, and a Boolean
1668-
/// indicating whether (unsafe) was provided in the attribute otherwise.
1669-
Optional<bool> isMainActorAttr(
1670-
ASTContext &ctx, const clang::SwiftAttrAttr *swiftAttr);
1666+
bool isMainActorAttr(const clang::SwiftAttrAttr *swiftAttr);
16711667

16721668
}
16731669
}

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4037,34 +4037,6 @@ static Type applyUnsafeConcurrencyToParameterType(
40374037
.withGlobalActor(globalActor));
40384038
}
40394039

4040-
/// Strip concurrency from the given type.
4041-
static Type stripConcurrencyFromType(Type type, bool dropGlobalActor) {
4042-
// Look through optionals.
4043-
if (Type optionalObject = type->getOptionalObjectType()) {
4044-
Type newOptionalObject =
4045-
stripConcurrencyFromType(optionalObject, dropGlobalActor);
4046-
if (optionalObject->isEqual(newOptionalObject))
4047-
return type;
4048-
4049-
return OptionalType::get(newOptionalObject);
4050-
}
4051-
4052-
// For function types, strip off Sendable and possibly the global actor.
4053-
if (auto fnType = type->getAs<FunctionType>()) {
4054-
auto extInfo = fnType->getExtInfo().withConcurrent(false);
4055-
if (dropGlobalActor)
4056-
extInfo = extInfo.withGlobalActor(Type());
4057-
auto newFnType = FunctionType::get(
4058-
fnType->getParams(), fnType->getResult(), extInfo);
4059-
if (newFnType->isEqual(type))
4060-
return type;
4061-
4062-
return newFnType;
4063-
}
4064-
4065-
return type;
4066-
}
4067-
40684040
/// Determine whether the given name is that of a DispatchQueue operation that
40694041
/// takes a closure to be executed on the queue.
40704042
bool swift::isDispatchQueueOperationName(StringRef name) {
@@ -4112,7 +4084,7 @@ Type swift::adjustVarTypeForConcurrency(
41124084
isLValue = true;
41134085
}
41144086

4115-
type = stripConcurrencyFromType(type, /*dropGlobalActor=*/true);
4087+
type = type->stripConcurrency(/*recurse=*/false, /*dropGlobalActor=*/true);
41164088

41174089
if (isLValue)
41184090
type = LValueType::get(type);
@@ -4164,8 +4136,8 @@ static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
41644136
newParamType = applyUnsafeConcurrencyToParameterType(
41654137
param.getPlainType(), addSendable, addMainActor);
41664138
} else if (stripConcurrency) {
4167-
newParamType = stripConcurrencyFromType(
4168-
param.getPlainType(), numApplies == 0);
4139+
newParamType = param.getPlainType()->stripConcurrency(
4140+
/*recurse=*/false, /*dropGlobalActor=*/numApplies == 0);
41694141
}
41704142

41714143
if (!newParamType || newParamType->isEqual(param.getPlainType())) {
@@ -4189,8 +4161,8 @@ static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
41894161
// Compute the new result type.
41904162
Type newResultType = fnType->getResult();
41914163
if (stripConcurrency) {
4192-
newResultType = stripConcurrencyFromType(
4193-
newResultType, /*dropGlobalActor=*/true);
4164+
newResultType = newResultType->stripConcurrency(
4165+
/*recurse=*/false, /*dropGlobalActor=*/true);
41944166

41954167
if (!newResultType->isEqual(fnType->getResult()) && newTypeParams.empty()) {
41964168
newTypeParams.append(typeParams.begin(), typeParams.end());

test/ClangImporter/objc_async.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,14 @@ func testSlowServerOldSchool(slowServer: SlowServer) {
9090
_ = slowServer.allOperations
9191
}
9292

93-
func testSendable(fn: () -> Void) { // expected-note{{parameter 'fn' is implicitly non-sendable}}
94-
doSomethingConcurrently(fn)
95-
// expected-error@-1{{passing non-sendable parameter 'fn' to function expecting a @Sendable closure}}
93+
func testSendable(fn: () -> Void) {
94+
doSomethingConcurrently(fn) // okay, due to implicit @_predatesConcurrency
9695
doSomethingConcurrentlyButUnsafe(fn) // okay, @Sendable not part of the type
9796

9897
var x = 17
9998
doSomethingConcurrently {
100-
print(x) // expected-error{{reference to captured var 'x' in concurrently-executing code}}
101-
x = x + 1 // expected-error{{mutation of captured var 'x' in concurrently-executing code}}
102-
// expected-error@-1{{reference to captured var 'x' in concurrently-executing code}}
99+
print(x)
100+
x = x + 1
103101
}
104102
}
105103

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ typedef void (^CompletionHandler)(NSString * _Nullable, NSString * _Nullable_res
107107
-(void)asyncImportSame:(NSString *)operation completionHandler:(void (^)(NSInteger))handler;
108108
-(void)asyncImportSame:(NSString *)operation replyTo:(void (^)(NSInteger))handler __attribute__((swift_async(none)));
109109

110-
-(void)overridableButRunsOnMainThreadWithCompletionHandler:(MAIN_ACTOR void (^ _Nullable)(NSString *))completion __attribute__((swift_attr("@_predatesConcurrency")));
110+
-(void)overridableButRunsOnMainThreadWithCompletionHandler:(MAIN_ACTOR void (^ _Nullable)(NSString *))completion;
111111
- (void)obtainClosureWithCompletionHandler:(void (^)(void (^_Nullable)(void),
112112
NSError *_Nullable,
113113
BOOL))completionHandler
@@ -178,7 +178,7 @@ typedef void ( ^ObjCErrorHandler )( NSError * _Nullable inError );
178178
#define MAGIC_NUMBER 42
179179

180180

181-
__attribute__((__swift_attr__("@MainActor(unsafe)")))
181+
__attribute__((__swift_attr__("@MainActor")))
182182
@interface NXView : NSObject
183183
-(void)onDisplay;
184184
@end
@@ -192,10 +192,10 @@ void doSomethingConcurrently(__attribute__((noescape)) SENDABLE void (^block)(vo
192192

193193

194194

195-
void doSomethingConcurrentlyButUnsafe(__attribute__((noescape)) __attribute__((swift_attr("@Sendable"))) void (^block)(void)) __attribute__((swift_attr("@_predatesConcurrency")));
195+
void doSomethingConcurrentlyButUnsafe(__attribute__((noescape)) __attribute__((swift_attr("@Sendable"))) void (^block)(void));
196196

197197

198-
MAIN_ACTOR MAIN_ACTOR __attribute__((__swift_attr__("@MainActor(unsafe)"))) @protocol TripleMainActor
198+
MAIN_ACTOR MAIN_ACTOR __attribute__((__swift_attr__("@MainActor"))) @protocol TripleMainActor
199199
@end
200200

201201
@protocol ProtocolWithAsync
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
4+
// CHECK: sil [ossa] @$s29mangling_predates_concurrency16excitingFunction5value4bodyyycx_yycSgtlF : $@convention(thin) <T where T : Sendable> (@in_guaranteed T, @guaranteed Optional<@Sendable @callee_guaranteed () -> ()>) -> @owned @callee_guaranteed () -> ()
5+
@_predatesConcurrency
6+
public func excitingFunction<T: Sendable>(value: T, body: (@Sendable () -> Void)?) -> (@MainActor () -> Void) {
7+
{ }
8+
}

0 commit comments

Comments
 (0)