Skip to content

Commit 233d279

Browse files
committed
[AST] Support @preconcurrency attribute on test/extension inheritance entries
1 parent 574aee0 commit 233d279

File tree

10 files changed

+74
-13
lines changed

10 files changed

+74
-13
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,11 +1604,15 @@ struct InheritedEntry : public TypeLoc {
16041604
/// Whether there was an @retroactive attribute.
16051605
bool isRetroactive = false;
16061606

1607+
/// Whether there was an @preconcurrency attribute.
1608+
bool isPreconcurrency = false;
1609+
16071610
InheritedEntry(const TypeLoc &typeLoc);
16081611

1609-
InheritedEntry(const TypeLoc &typeLoc, bool isUnchecked, bool isRetroactive)
1610-
: TypeLoc(typeLoc), isUnchecked(isUnchecked), isRetroactive(isRetroactive) {
1611-
}
1612+
InheritedEntry(const TypeLoc &typeLoc, bool isUnchecked, bool isRetroactive,
1613+
bool isPreconcurrency)
1614+
: TypeLoc(typeLoc), isUnchecked(isUnchecked),
1615+
isRetroactive(isRetroactive), isPreconcurrency(isPreconcurrency) {}
16121616
};
16131617

16141618
/// A wrapper for the collection of inherited types for either a `TypeDecl` or

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2732,6 +2732,8 @@ void PrintAST::printInherited(const Decl *decl) {
27322732
if (inherited.isRetroactive &&
27332733
!llvm::is_contained(Options.ExcludeAttrList, TAK_retroactive))
27342734
Printer << "@retroactive ";
2735+
if (inherited.isPreconcurrency)
2736+
Printer << "@preconcurrency ";
27352737

27362738
printTypeLoc(inherited);
27372739
}, [&]() {
@@ -8308,7 +8310,8 @@ swift::getInheritedForPrinting(
83088310

83098311
Results.push_back({TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
83108312
isUnchecked,
8311-
/*isRetroactive=*/false});
8313+
/*isRetroactive=*/false,
8314+
/*isPreconcurrency=*/false});
83128315
}
83138316
}
83148317

lib/AST/Decl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,7 @@ InheritedEntry::InheritedEntry(const TypeLoc &typeLoc)
15921592
if (auto typeRepr = typeLoc.getTypeRepr()) {
15931593
isUnchecked = typeRepr->findAttrLoc(TAK_unchecked).isValid();
15941594
isRetroactive = typeRepr->findAttrLoc(TAK_retroactive).isValid();
1595+
isPreconcurrency = typeRepr->findAttrLoc(TAK_preconcurrency).isValid();
15951596
}
15961597
}
15971598

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7273,9 +7273,9 @@ void SwiftDeclConverter::importObjCProtocols(
72737273
Impl.importDecl(*cp, getActiveSwiftVersion()))) {
72747274
addProtocols(proto, protocols, knownProtocols);
72757275
inheritedTypes.push_back(
7276-
InheritedEntry(
7277-
TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
7278-
/*isUnchecked=*/false, /*isRetroactive=*/false));
7276+
InheritedEntry(TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
7277+
/*isUnchecked=*/false, /*isRetroactive=*/false,
7278+
/*isPreconcurrency=*/false));
72797279
}
72807280
}
72817281

lib/Frontend/ModuleInterfaceSupport.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,8 @@ class InheritedProtocolCollector {
746746
ASTContext &ctx = M->getASTContext();
747747
auto inherits = ctx.AllocateCopy(llvm::makeArrayRef(InheritedEntry(
748748
TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()), isUnchecked,
749-
/*isRetroactive=*/false)));
749+
/*isRetroactive=*/false,
750+
/*isPreconcurrency=*/false)));
750751
auto extension =
751752
ExtensionDecl::create(ctx, SourceLoc(), nullptr, inherits,
752753
nominal->getModuleScopeContext(), nullptr);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5556,7 +5556,8 @@ ProtocolConformance *swift::deriveImplicitSendableConformance(
55565556
// FIXME: This is a hack--we should give conformances real availability.
55575557
auto inherits = ctx.AllocateCopy(makeArrayRef(
55585558
InheritedEntry(TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
5559-
/*isUnchecked*/true, /*isRetroactive=*/false)));
5559+
/*isUnchecked*/ true, /*isRetroactive=*/false,
5560+
/*isPreconcurrency=*/false)));
55605561
// If you change the use of AtLoc in the ExtensionDecl, make sure you
55615562
// update isNonSendableExtension() in ASTPrinter.
55625563
auto extension = ExtensionDecl::create(ctx, attrMakingUnavailable->AtLoc,

lib/Serialization/Deserialization.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3144,18 +3144,23 @@ class DeclDeserializer {
31443144
ArrayRef<uint64_t> rawInheritedIDs) {
31453145
SmallVector<InheritedEntry, 2> inheritedTypes;
31463146
for (auto rawID : rawInheritedIDs) {
3147-
// The low bit indicates "@unchecked".
3147+
// The first low bit indicates "@preconcurrency".
3148+
bool isPreconcurrency = rawID & 0x01;
3149+
rawID = rawID >> 1;
3150+
3151+
// The second low bit indicates "@unchecked".
31483152
bool isUnchecked = rawID & 0x01;
3149-
TypeID typeID = rawID >> 1;
3153+
rawID = rawID >> 1;
31503154

3155+
TypeID typeID = rawID;
31513156
auto maybeType = MF.getTypeChecked(typeID);
31523157
if (!maybeType) {
31533158
MF.diagnoseAndConsumeError(maybeType.takeError());
31543159
continue;
31553160
}
31563161
inheritedTypes.push_back(
31573162
InheritedEntry(TypeLoc::withoutLoc(maybeType.get()), isUnchecked,
3158-
/*isRetroactive=*/false));
3163+
/*isRetroactive=*/false, isPreconcurrency));
31593164
}
31603165

31613166
auto inherited = ctx.AllocateCopy(inheritedTypes);

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 835; // remove Swift3Inferred
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 836; // @preconcurrency inheritance entry
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3829,6 +3829,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
38293829

38303830
// Encode "unchecked" in the low bit.
38313831
typeRef = (typeRef << 1) | (inherited.isUnchecked ? 0x01 : 0x00);
3832+
// Encode "preconcurrency" in the low bit.
3833+
typeRef = (typeRef << 1) | (inherited.isPreconcurrency ? 0x01 : 0x00);
38323834

38333835
result.push_back(typeRef);
38343836
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
/// Build the library
5+
// RUN: %target-swift-frontend -emit-module %t/src/PublicModule.swift \
6+
// RUN: -module-name PublicModule -swift-version 5 -enable-library-evolution \
7+
// RUN: -emit-module-path %t/PublicModule.swiftmodule \
8+
// RUN: -emit-module-interface-path %t/PublicModule.swiftinterface
9+
10+
// Build the client and check the interface
11+
// RUN: %target-swift-frontend -emit-module %t/src/Client.swift \
12+
// RUN: -module-name Client -I %t -swift-version 5 -enable-library-evolution \
13+
// RUN: -emit-module-path %t/Client.swiftmodule \
14+
// RUN: -emit-module-interface-path %t/Client.swiftinterface
15+
16+
// RUN: %FileCheck %s < %t/Client.swiftinterface
17+
18+
// RUN: %target-swift-emit-module-interface(%t/Client.swiftinterface) -I %t %s -module-name Client
19+
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t -module-name Client
20+
21+
//--- PublicModule.swift
22+
public protocol P {
23+
func test() -> Int
24+
}
25+
26+
//--- Client.swift
27+
import PublicModule
28+
29+
// CHECK: @_Concurrency.MainActor public struct GlobalActorTest : @preconcurrency PublicModule.P
30+
@MainActor
31+
public struct GlobalActorTest : @preconcurrency P {
32+
public func test() -> Int { 0 }
33+
}
34+
35+
@MainActor
36+
public class ExtTest {
37+
}
38+
39+
// CHECK: extension Client.ExtTest : @preconcurrency PublicModule.P
40+
extension ExtTest : @preconcurrency P {
41+
public func test() -> Int { 1 }
42+
}
43+
44+
// TODO: 'actor' cannot be tested until @preconcurrency conformances are implemented.

0 commit comments

Comments
 (0)