Skip to content

Commit 72c5367

Browse files
authored
Merge pull request #19336 from DougGregor/associated-type-defaults
2 parents 78f3017 + ab61aae commit 72c5367

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+753
-502
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ types where the metadata itself has unknown layout.)
140140

141141
global ::= protocol 'TL' // protocol requirements base descriptor
142142
global ::= assoc-type-name 'Tl' // associated type descriptor
143+
global ::= assoc-type-name 'TM' // default associated type witness accessor
143144

144145

145146
REABSTRACT-THUNK-TYPE ::= 'R' // reabstraction thunk helper function

include/swift/AST/Decl.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,8 +3774,6 @@ struct SelfReferenceKind {
37743774
class ProtocolDecl final : public NominalTypeDecl {
37753775
SourceLoc ProtocolLoc;
37763776

3777-
llvm::DenseMap<ValueDecl *, Witness> DefaultWitnesses;
3778-
37793777
/// The generic signature representing exactly the new requirements introduced
37803778
/// by this protocol.
37813779
const Requirement *RequirementSignature = nullptr;
@@ -3967,6 +3965,13 @@ class ProtocolDecl final : public NominalTypeDecl {
39673965
Bits.ProtocolDecl.HasMissingRequirements = newValue;
39683966
}
39693967

3968+
/// Returns the default type witness for an associated type, or a null
3969+
/// type if there is no default.
3970+
Type getDefaultTypeWitness(AssociatedTypeDecl *assocType) const;
3971+
3972+
/// Set the default type witness for an associated type.
3973+
void setDefaultTypeWitness(AssociatedTypeDecl *assocType, Type witness);
3974+
39703975
/// Returns the default witness for a requirement, or nullptr if there is
39713976
/// no default.
39723977
Witness getDefaultWitness(ValueDecl *requirement) const;

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ NODE(ArgumentTuple)
3030
NODE(AssociatedType)
3131
NODE(AssociatedTypeRef)
3232
NODE(AssociatedTypeMetadataAccessor)
33+
NODE(DefaultAssociatedTypeMetadataAccessor)
3334
NODE(AssociatedTypeWitnessTableAccessor)
3435
NODE(AutoClosureType)
3536
NODE(BoundGenericClass)

include/swift/IRGen/Linking.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ class LinkEntity {
206206
/// The pointer is an AssociatedTypeDecl*.
207207
AssociatedTypeDescriptor,
208208

209+
/// A function which returns the default type metadata for the associated
210+
/// type of a protocol. The secondary pointer is a ProtocolDecl*.
211+
/// The index of the associated type declaration is stored in the data.
212+
DefaultAssociatedTypeMetadataAccessFunction,
213+
209214
/// A SIL function. The pointer is a SILFunction*.
210215
SILFunction,
211216

@@ -319,7 +324,7 @@ class LinkEntity {
319324
}
320325

321326
static bool isDeclKind(Kind k) {
322-
return k <= Kind::AssociatedTypeDescriptor;
327+
return k <= Kind::DefaultAssociatedTypeMetadataAccessFunction;
323328
}
324329
static bool isTypeKind(Kind k) {
325330
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
@@ -763,6 +768,14 @@ class LinkEntity {
763768
return entity;
764769
}
765770

771+
static LinkEntity
772+
forDefaultAssociatedTypeMetadataAccessFunction(AssociatedType association) {
773+
LinkEntity entity;
774+
entity.setForDecl(Kind::DefaultAssociatedTypeMetadataAccessFunction,
775+
association.getAssociation());
776+
return entity;
777+
}
778+
766779
static LinkEntity
767780
forAssociatedTypeWitnessTableAccessFunction(const ProtocolConformance *C,
768781
const AssociatedConformance &association) {
@@ -853,7 +866,8 @@ class LinkEntity {
853866
return getAssociatedTypeByIndex(getProtocolConformance(),
854867
LINKENTITY_GET_FIELD(Data, AssociatedTypeIndex));
855868

856-
assert(getKind() == Kind::AssociatedTypeDescriptor);
869+
assert(getKind() == Kind::AssociatedTypeDescriptor ||
870+
getKind() == Kind::DefaultAssociatedTypeMetadataAccessFunction);
857871
return reinterpret_cast<AssociatedTypeDecl *>(Pointer);
858872
}
859873

include/swift/SIL/SILDefaultWitnessTable.h

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/SIL/SILAllocated.h"
2525
#include "swift/SIL/SILDeclRef.h"
2626
#include "swift/SIL/SILFunction.h"
27+
#include "swift/SIL/SILWitnessTable.h"
2728
#include "llvm/ADT/ilist_node.h"
2829
#include "llvm/ADT/ilist.h"
2930
#include <string>
@@ -41,40 +42,9 @@ class SILDefaultWitnessTable : public llvm::ilist_node<SILDefaultWitnessTable>,
4142
public SILAllocated<SILDefaultWitnessTable>
4243
{
4344
public:
44-
/// A default witness table entry describing the default witness for a method.
45-
class Entry {
46-
/// The method required.
47-
SILDeclRef Requirement;
48-
/// The witness for the method.
49-
/// This can be null in case no default implementation is available.
50-
SILFunction *Witness;
51-
52-
public:
53-
Entry()
54-
: Requirement(), Witness(nullptr) {}
55-
56-
Entry(SILDeclRef Requirement, SILFunction *Witness)
57-
: Requirement(Requirement), Witness(Witness) {}
58-
59-
bool isValid() const {
60-
return !Requirement.isNull() && Witness;
61-
}
62-
63-
const SILDeclRef &getRequirement() const {
64-
assert(isValid());
65-
return Requirement;
66-
}
67-
SILFunction *getWitness() const {
68-
assert(Witness != nullptr);
69-
return Witness;
70-
}
71-
void removeWitnessMethod() {
72-
if (Witness) {
73-
Witness->decrementRefCount();
74-
}
75-
Witness = nullptr;
76-
}
77-
};
45+
/// A default witness table entry describing the default witness for a
46+
/// requirement.
47+
using Entry = SILWitnessTable::Entry;
7848

7949
private:
8050
/// The module which contains the SILDefaultWitnessTable.
@@ -147,7 +117,10 @@ class SILDefaultWitnessTable : public llvm::ilist_node<SILDefaultWitnessTable>,
147117
for (Entry &entry : Entries) {
148118
if (!entry.isValid())
149119
continue;
150-
auto *MW = entry.getWitness();
120+
if (entry.getKind() != SILWitnessTable::Method)
121+
continue;
122+
123+
auto *MW = entry.getMethodWitness().Witness;
151124
if (MW && predicate(MW)) {
152125
entry.removeWitnessMethod();
153126
}

include/swift/SIL/SILWitnessTable.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ class SILWitnessTable : public llvm::ilist_node<SILWitnessTable>,
124124
{}
125125

126126
WitnessKind getKind() const { return Kind; }
127-
127+
128+
bool isValid() const { return Kind != WitnessKind::Invalid; }
129+
128130
const MethodWitness &getMethodWitness() const {
129131
assert(Kind == WitnessKind::Method);
130132
return Method;
@@ -150,6 +152,9 @@ class SILWitnessTable : public llvm::ilist_node<SILWitnessTable>,
150152
}
151153
Method.Witness = nullptr;
152154
}
155+
156+
void print(llvm::raw_ostream &out, bool verbose,
157+
const PrintOptions &options) const;
153158
};
154159

155160
/// An entry for a conformance requirement that makes the requirement

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 445; // Last change: generic typealias
58+
const uint16_t VERSION_MINOR = 446; // Last change: sil default witness table
5959

6060
using DeclIDField = BCFixed<31>;
6161

lib/AST/ASTContext.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,14 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
277277
/// Overridden declarations.
278278
llvm::DenseMap<const ValueDecl *, ArrayRef<ValueDecl *>> Overrides;
279279

280+
/// Default witnesses.
281+
llvm::DenseMap<std::pair<const ProtocolDecl *, ValueDecl *>, Witness>
282+
DefaultWitnesses;
283+
284+
/// Default type witnesses for protocols.
285+
llvm::DenseMap<std::pair<const ProtocolDecl *, AssociatedTypeDecl *>, Type>
286+
DefaultTypeWitnesses;
287+
280288
/// \brief Structure that captures data that is segregated into different
281289
/// arenas.
282290
struct Arena {
@@ -1656,6 +1664,51 @@ void OverriddenDeclsRequest::cacheResult(
16561664
(void)ctx.getImpl().Overrides.insert({decl, overriddenCopy});
16571665
}
16581666

1667+
/// Returns the default witness for a requirement, or nullptr if there is
1668+
/// no default.
1669+
Witness ProtocolDecl::getDefaultWitness(ValueDecl *requirement) const {
1670+
loadAllMembers();
1671+
1672+
ASTContext &ctx = getASTContext();
1673+
auto found = ctx.getImpl().DefaultWitnesses.find({this, requirement});
1674+
if (found == ctx.getImpl().DefaultWitnesses.end())
1675+
return Witness();
1676+
return found->second;
1677+
}
1678+
1679+
/// Record the default witness for a requirement.
1680+
void ProtocolDecl::setDefaultWitness(ValueDecl *requirement, Witness witness) {
1681+
assert(witness);
1682+
ASTContext &ctx = getASTContext();
1683+
auto pair = ctx.getImpl().DefaultWitnesses.insert(
1684+
std::make_pair(std::make_pair(this, requirement), witness));
1685+
assert(pair.second && "Already have a default witness!");
1686+
(void) pair;
1687+
}
1688+
1689+
/// Returns the default type witness for an associated type, or a null
1690+
/// type if there is no default.
1691+
Type ProtocolDecl::getDefaultTypeWitness(AssociatedTypeDecl *assocType) const {
1692+
auto &ctx = getASTContext();
1693+
auto found = ctx.getImpl().DefaultTypeWitnesses.find({this, assocType});
1694+
if (found == ctx.getImpl().DefaultTypeWitnesses.end())
1695+
return Type();
1696+
1697+
return found->second;
1698+
}
1699+
1700+
/// Set the default type witness for an associated type.
1701+
void ProtocolDecl::setDefaultTypeWitness(AssociatedTypeDecl *assocType,
1702+
Type witness) {
1703+
assert(witness);
1704+
assert(!witness->hasArchetype() && "Only record interface types");
1705+
ASTContext &ctx = getASTContext();
1706+
auto pair = ctx.getImpl().DefaultTypeWitnesses.insert(
1707+
std::make_pair(std::make_pair(this, assocType), witness));
1708+
assert(pair.second && "Already have a default witness");
1709+
(void)pair;
1710+
}
1711+
16591712
bool ASTContext::canImportModule(std::pair<Identifier, SourceLoc> ModulePath) {
16601713
// If this module has already been successfully imported, it is importable.
16611714
if (getLoadedModule(ModulePath) != nullptr)

lib/AST/Decl.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4050,29 +4050,6 @@ void ProtocolDecl::setRequirementSignature(ArrayRef<Requirement> requirements) {
40504050
}
40514051
}
40524052

4053-
/// Returns the default witness for a requirement, or nullptr if there is
4054-
/// no default.
4055-
Witness ProtocolDecl::getDefaultWitness(ValueDecl *requirement) const {
4056-
loadAllMembers();
4057-
4058-
auto found = DefaultWitnesses.find(requirement);
4059-
if (found == DefaultWitnesses.end())
4060-
return Witness();
4061-
return found->second;
4062-
}
4063-
4064-
/// Record the default witness for a requirement.
4065-
void ProtocolDecl::setDefaultWitness(ValueDecl *requirement, Witness witness) {
4066-
assert(witness);
4067-
// The first type we insert a default witness, register a destructor for
4068-
// this type.
4069-
if (DefaultWitnesses.empty())
4070-
getASTContext().addDestructorCleanup(DefaultWitnesses);
4071-
auto pair = DefaultWitnesses.insert(std::make_pair(requirement, witness));
4072-
assert(pair.second && "Already have a default witness!");
4073-
(void) pair;
4074-
}
4075-
40764053
void AbstractStorageDecl::overwriteImplInfo(StorageImplInfo implInfo) {
40774054
setFieldsFromImplInfo(implInfo);
40784055
Accessors.getPointer()->overwriteImplInfo(implInfo);

lib/Demangling/Demangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,6 +1823,9 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
18231823
case 'L':
18241824
return createWithChild(Node::Kind::ProtocolRequirementsBaseDescriptor,
18251825
popProtocol());
1826+
case 'M':
1827+
return createWithChild(Node::Kind::DefaultAssociatedTypeMetadataAccessor,
1828+
popAssocTypeName());
18261829

18271830
case 'H':
18281831
case 'h': {

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ class NodePrinter {
321321
case Node::Kind::Deallocator:
322322
case Node::Kind::DeclContext:
323323
case Node::Kind::DefaultArgumentInitializer:
324+
case Node::Kind::DefaultAssociatedTypeMetadataAccessor:
324325
case Node::Kind::DependentAssociatedTypeRef:
325326
case Node::Kind::DependentGenericSignature:
326327
case Node::Kind::DependentGenericParamCount:
@@ -1564,6 +1565,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
15641565
Printer << " in ";
15651566
print(Node->getChild(0));
15661567
return nullptr;
1568+
case Node::Kind::DefaultAssociatedTypeMetadataAccessor:
1569+
Printer << "default associated type metadata accessor for ";
1570+
print(Node->getChild(0));
1571+
return nullptr;
15671572
case Node::Kind::AssociatedTypeWitnessTableAccessor:
15681573
Printer << "associated type witness table accessor for ";
15691574
print(Node->getChild(1));

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,10 @@ void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
889889
mangleChildNodes(node); // protocol conformance, identifier
890890
}
891891

892+
void Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node) {
893+
Out << "<default-associated-type-metadata-accessor>";
894+
}
895+
892896
void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
893897
Out << "WT";
894898
assert(node->getNumChildren() == 3);

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,11 @@ void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
579579
Buffer << "Wt";
580580
}
581581

582+
void Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node) {
583+
mangleChildNodes(node); // protocol conformance, identifier
584+
Buffer << "TM";
585+
}
586+
582587
void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
583588
mangleChildNodes(node); // protocol conformance, identifier, type
584589
Buffer << "WT";

lib/IRGen/GenDecl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3949,6 +3949,25 @@ IRGenModule::getAddrOfAssociatedTypeWitnessTableAccessFunction(
39493949
return entry;
39503950
}
39513951

3952+
llvm::Function *
3953+
IRGenModule::getAddrOfDefaultAssociatedTypeMetadataAccessFunction(
3954+
AssociatedType association) {
3955+
auto forDefinition = ForDefinition;
3956+
3957+
LinkEntity entity =
3958+
LinkEntity::forDefaultAssociatedTypeMetadataAccessFunction(association);
3959+
llvm::Function *&entry = GlobalFuncs[entity];
3960+
if (entry) {
3961+
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
3962+
return entry;
3963+
}
3964+
3965+
auto signature = getAssociatedTypeMetadataAccessFunctionSignature();
3966+
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
3967+
entry = createFunction(*this, link, signature);
3968+
return entry;
3969+
}
3970+
39523971
llvm::Function *
39533972
IRGenModule::getAddrOfContinuationPrototype(CanSILFunctionType fnType) {
39543973
LinkEntity entity = LinkEntity::forCoroutineContinuationPrototype(fnType);

0 commit comments

Comments
 (0)