Skip to content

Commit c6387fd

Browse files
authored
Merge pull request #67839 from slavapestov/tuple-conformance-sendable-copyable
Replace bespoke Sendable and Copyable conformance on tuples with tuple conformances
2 parents 821d374 + c26cafc commit c6387fd

33 files changed

+201
-249
lines changed

include/swift/AST/ASTContext.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,13 +1258,16 @@ class ASTContext final {
12581258
unsigned bumpGeneration() { return CurrentGeneration++; }
12591259

12601260
/// Produce a "normal" conformance for a nominal type.
1261+
///
1262+
/// For ordinary conformance lookups, use ModuleDecl::lookupConformance()
1263+
/// instead.
12611264
NormalProtocolConformance *
1262-
getConformance(Type conformingType,
1263-
ProtocolDecl *protocol,
1264-
SourceLoc loc,
1265-
DeclContext *dc,
1266-
ProtocolConformanceState state,
1267-
bool isUnchecked);
1265+
getNormalConformance(Type conformingType,
1266+
ProtocolDecl *protocol,
1267+
SourceLoc loc,
1268+
DeclContext *dc,
1269+
ProtocolConformanceState state,
1270+
bool isUnchecked);
12681271

12691272
/// Produce a self-conformance for the given protocol.
12701273
SelfProtocolConformance *
@@ -1273,8 +1276,6 @@ class ASTContext final {
12731276
/// Produce the builtin conformance for some structural type to some protocol.
12741277
BuiltinProtocolConformance *
12751278
getBuiltinConformance(Type type, ProtocolDecl *protocol,
1276-
GenericSignature genericSig,
1277-
ArrayRef<Requirement> conditionalRequirements,
12781279
BuiltinConformanceKind kind);
12791280

12801281
/// A callback used to produce a diagnostic for an ill-formed protocol

include/swift/AST/DiagnosticsCommon.def

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,6 @@ ERROR(macro_experimental,none,
228228
ERROR(ambiguous_macro_reference,none,
229229
"ambiguous reference to macro %0", (DeclName))
230230

231-
//------------------------------------------------------------------------------
232-
// MARK: tuple conformances
233-
//------------------------------------------------------------------------------
234-
ERROR(experimental_tuple_extension,none,
235-
"tuple extensions are experimental",
236-
())
237-
238231
//------------------------------------------------------------------------------
239232
// MARK: bridged diagnostics
240233
//------------------------------------------------------------------------------

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,9 @@ NOTE(composition_in_extended_type_alternative,none,
23352335
ERROR(extension_access_with_conformances,none,
23362336
"%0 modifier cannot be used with extensions that declare "
23372337
"protocol conformances", (DeclAttribute))
2338+
ERROR(experimental_tuple_extension,none,
2339+
"tuple extensions are experimental",
2340+
())
23382341
ERROR(extension_metatype,none,
23392342
"cannot extend a metatype %0", (Type))
23402343
ERROR(extension_placeholder,none,

include/swift/AST/ProtocolConformance.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,23 +1019,13 @@ enum class BuiltinConformanceKind {
10191019

10201020
/// A builtin conformance appears when a non-nominal type has a
10211021
/// conformance that is synthesized by the implementation.
1022-
class BuiltinProtocolConformance final : public RootProtocolConformance,
1023-
private llvm::TrailingObjects<BuiltinProtocolConformance, Requirement> {
1022+
class BuiltinProtocolConformance final : public RootProtocolConformance {
10241023
friend ASTContext;
1025-
friend TrailingObjects;
10261024

10271025
ProtocolDecl *protocol;
1028-
GenericSignature genericSig;
1029-
size_t numConditionalRequirements : 31;
1030-
unsigned builtinConformanceKind : 1;
1031-
1032-
size_t numTrailingObjects(OverloadToken<Requirement>) const {
1033-
return numConditionalRequirements;
1034-
}
1026+
unsigned builtinConformanceKind;
10351027

10361028
BuiltinProtocolConformance(Type conformingType, ProtocolDecl *protocol,
1037-
GenericSignature genericSig,
1038-
ArrayRef<Requirement> conditionalRequirements,
10391029
BuiltinConformanceKind kind);
10401030

10411031
public:
@@ -1044,16 +1034,14 @@ class BuiltinProtocolConformance final : public RootProtocolConformance,
10441034
return protocol;
10451035
}
10461036

1047-
/// Retrieve the generic signature that describes the type parameters used
1048-
/// within the conforming type.
1049-
GenericSignature getGenericSignature() const {
1050-
return genericSig;
1051-
}
1052-
10531037
BuiltinConformanceKind getBuiltinConformanceKind() const {
10541038
return static_cast<BuiltinConformanceKind>(builtinConformanceKind);
10551039
}
10561040

1041+
GenericSignature getGenericSignature() const {
1042+
return GenericSignature();
1043+
}
1044+
10571045
/// Whether this represents a "missing" conformance that should be diagnosed
10581046
/// later.
10591047
bool isMissing() const {
@@ -1063,12 +1051,12 @@ class BuiltinProtocolConformance final : public RootProtocolConformance,
10631051
/// Get any requirements that must be satisfied for this conformance to apply.
10641052
llvm::Optional<ArrayRef<Requirement>>
10651053
getConditionalRequirementsIfAvailable() const {
1066-
return getConditionalRequirements();
1054+
return ArrayRef<Requirement>();
10671055
}
10681056

10691057
/// Get any requirements that must be satisfied for this conformance to apply.
10701058
ArrayRef<Requirement> getConditionalRequirements() const {
1071-
return {getTrailingObjects<Requirement>(), numConditionalRequirements};
1059+
return {};
10721060
}
10731061

10741062
/// Get the declaration context that contains the nominal type declaration.

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ NODE(BoundGenericOtherNominalType)
4444
NODE(BoundGenericTypeAlias)
4545
NODE(BoundGenericFunction)
4646
NODE(BuiltinTypeName)
47+
NODE(BuiltinTupleType)
4748
NODE(CFunctionPointer)
4849
NODE(ClangType)
4950
CONTEXT_NODE(Class)

lib/AST/ASTContext.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,12 +2638,12 @@ void ASTContext::setExternalSourceLocs(const Decl *D,
26382638
}
26392639

26402640
NormalProtocolConformance *
2641-
ASTContext::getConformance(Type conformingType,
2642-
ProtocolDecl *protocol,
2643-
SourceLoc loc,
2644-
DeclContext *dc,
2645-
ProtocolConformanceState state,
2646-
bool isUnchecked) {
2641+
ASTContext::getNormalConformance(Type conformingType,
2642+
ProtocolDecl *protocol,
2643+
SourceLoc loc,
2644+
DeclContext *dc,
2645+
ProtocolConformanceState state,
2646+
bool isUnchecked) {
26472647
assert(dc->isTypeContext());
26482648

26492649
llvm::FoldingSetNodeID id;
@@ -2681,23 +2681,15 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) {
26812681

26822682
/// Produce the builtin conformance for some non-nominal to some protocol.
26832683
BuiltinProtocolConformance *
2684-
ASTContext::getBuiltinConformance(
2685-
Type type, ProtocolDecl *protocol,
2686-
GenericSignature genericSig,
2687-
ArrayRef<Requirement> conditionalRequirements,
2688-
BuiltinConformanceKind kind
2689-
) {
2684+
ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol,
2685+
BuiltinConformanceKind kind) {
26902686
auto key = std::make_pair(type, protocol);
26912687
AllocationArena arena = getArena(type->getRecursiveProperties());
26922688
auto &builtinConformances = getImpl().getArena(arena).BuiltinConformances;
26932689

26942690
auto &entry = builtinConformances[key];
26952691
if (!entry) {
2696-
auto size = BuiltinProtocolConformance::
2697-
totalSizeToAlloc<Requirement>(conditionalRequirements.size());
2698-
auto mem = this->Allocate(size, alignof(BuiltinProtocolConformance), arena);
2699-
entry = new (mem) BuiltinProtocolConformance(
2700-
type, protocol, genericSig, conditionalRequirements, kind);
2692+
entry = new (*this) BuiltinProtocolConformance(type, protocol, kind);
27012693
}
27022694
return entry;
27032695
}
@@ -3726,7 +3718,9 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
37263718
}
37273719

37283720
NominalType *NominalType::get(NominalTypeDecl *D, Type Parent, const ASTContext &C) {
3729-
assert((isa<ProtocolDecl>(D) || !D->getGenericParams()) &&
3721+
assert((isa<ProtocolDecl>(D) ||
3722+
isa<BuiltinTupleDecl>(D) ||
3723+
!D->getGenericParams()) &&
37303724
"must be a non-generic type decl");
37313725
assert((!Parent || Parent->is<NominalType>() ||
37323726
Parent->is<BoundGenericType>() ||
@@ -3742,6 +3736,8 @@ NominalType *NominalType::get(NominalTypeDecl *D, Type Parent, const ASTContext
37423736
return ClassType::get(cast<ClassDecl>(D), Parent, C);
37433737
case DeclKind::Protocol: {
37443738
return ProtocolType::get(cast<ProtocolDecl>(D), Parent, C);
3739+
case DeclKind::BuiltinTuple:
3740+
return BuiltinTupleType::get(cast<BuiltinTupleDecl>(D), Parent, C);
37453741
}
37463742

37473743
default:
@@ -6292,10 +6288,44 @@ BuiltinTupleDecl *ASTContext::getBuiltinTupleDecl() {
62926288
if (result)
62936289
return result;
62946290

6295-
result = new (*this) BuiltinTupleDecl(Id_TheTupleType,
6296-
TheBuiltinModule->getFiles()[0]);
6291+
auto *dc = TheBuiltinModule->getFiles()[0];
6292+
6293+
result = new (*this) BuiltinTupleDecl(Id_TheTupleType, dc);
62976294
result->setAccess(AccessLevel::Public);
62986295

6296+
// Cook up conditional conformances to Sendable and Copyable.
6297+
auto buildFakeExtension = [&](ProtocolDecl *proto) {
6298+
auto protoTy = proto->getDeclaredInterfaceType();
6299+
6300+
// extension Builtin.TheTupleType: P { ... }
6301+
SmallVector<InheritedEntry, 1> inherited;
6302+
inherited.emplace_back(TypeLoc::withoutLoc(protoTy));
6303+
auto *ext = ExtensionDecl::create(*this, SourceLoc(), nullptr,
6304+
AllocateCopy(inherited),
6305+
dc, nullptr);
6306+
6307+
// <each T where repeat each T: P>
6308+
auto genericSig = result->getGenericSignature();
6309+
auto params = genericSig.getGenericParams();
6310+
assert(params.size() == 1);
6311+
Requirement req(RequirementKind::Conformance, params[0], protoTy);
6312+
genericSig = GenericSignature::get(params, req);
6313+
ext->setGenericSignature(genericSig);
6314+
6315+
// Bind the extension.
6316+
evaluator.cacheOutput(ExtendedTypeRequest{ext},
6317+
result->getDeclaredInterfaceType());
6318+
ext->setExtendedNominal(result);
6319+
6320+
result->addExtension(ext);
6321+
};
6322+
6323+
if (auto *proto = getProtocol(KnownProtocolKind::Sendable))
6324+
buildFakeExtension(proto);
6325+
6326+
if (auto *proto = getProtocol(KnownProtocolKind::Copyable))
6327+
buildFakeExtension(proto);
6328+
62996329
return result;
63006330
}
63016331

lib/AST/ASTMangler.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,6 +2583,11 @@ void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
25832583
}
25842584

25852585
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
2586+
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
2587+
2588+
if (nominal && isa<BuiltinTupleDecl>(nominal))
2589+
return appendOperator("BT");
2590+
25862591
// Check for certain standard types.
25872592
if (tryAppendStandardSubstitution(decl))
25882593
return;
@@ -2592,8 +2597,6 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
25922597
appendOpaqueDeclName(opaque);
25932598
return;
25942599
}
2595-
2596-
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
25972600

25982601
// For generic types, this uses the unbound type.
25992602
if (nominal) {
@@ -2612,9 +2615,6 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
26122615
return;
26132616
}
26142617

2615-
if (nominal && isa<BuiltinTupleDecl>(nominal))
2616-
return appendOperator("BT");
2617-
26182618
appendContextOf(decl);
26192619

26202620
// Always use Clang names for imported Clang declarations, unless they don't

lib/AST/ConformanceLookupTable.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
202202
for (auto conf : conformances) {
203203
protocols.push_back({conf->getProtocol(), SourceLoc(), SourceLoc()});
204204
}
205-
} else if (next->getParentSourceFile()) {
205+
} else if (next->getParentSourceFile() ||
206+
next->getParentModule()->isBuiltinModule()) {
206207
bool anyObject = false;
207208
for (const auto &found :
208209
getDirectlyInheritedNominalTypeDecls(next, anyObject)) {
@@ -418,8 +419,10 @@ void ConformanceLookupTable::loadAllConformances(
418419
ArrayRef<ProtocolConformance*> conformances) {
419420
// If this declaration context came from source, there's nothing to
420421
// do here.
421-
if (dc->getParentSourceFile())
422+
if (dc->getParentSourceFile() ||
423+
dc->getParentModule()->isBuiltinModule()) {
422424
return;
425+
}
423426

424427
// Add entries for each loaded conformance.
425428
for (auto conformance : conformances) {
@@ -928,9 +931,9 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
928931

929932
// Create or find the normal conformance.
930933
auto normalConf =
931-
ctx.getConformance(conformingType, protocol, conformanceLoc,
932-
conformingDC, ProtocolConformanceState::Incomplete,
933-
entry->Source.getUncheckedLoc().isValid());
934+
ctx.getNormalConformance(conformingType, protocol, conformanceLoc,
935+
conformingDC, ProtocolConformanceState::Incomplete,
936+
entry->Source.getUncheckedLoc().isValid());
934937
// Invalid code may cause the getConformance call below to loop, so break
935938
// the infinite recursion by setting this eagerly to shortcircuit with the
936939
// early return at the start of this function.

0 commit comments

Comments
 (0)