Skip to content

Commit 5553224

Browse files
committed
Support the explicit representation of self-conformances.
Big, but actually NFC because we're never actually creating them.
1 parent 9cc9a94 commit 5553224

Some content is hidden

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

41 files changed

+727
-230
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ Globals
133133

134134
global ::= type 'w' VALUE-WITNESS-KIND // value witness
135135

136+
global ::= protocol 'MS' // protocol self-conformance descriptor
137+
global ::= protocol 'WS' // protocol self-conformance witness table
136138
global ::= protocol-conformance 'Mc' // protocol conformance descriptor
137139
global ::= protocol-conformance 'WP' // protocol witness table
138140
global ::= protocol-conformance 'Wa' // protocol witness table accessor (HISTORICAL)
@@ -181,6 +183,7 @@ types where the metadata itself has unknown layout.)
181183
global ::= type label-list? 'D' // type mangling for the debugger with label list for function types.
182184
global ::= type 'TC' // continuation prototype (not actually used for real symbols)
183185
global ::= protocol-conformance entity 'TW' // protocol witness thunk
186+
global ::= protocol-conformance entity 'TS' // protocol self-conformance witness thunk
184187
global ::= context identifier identifier 'TB' // property behavior initializer thunk (not used currently)
185188
global ::= context identifier identifier 'Tb' // property behavior setter thunk (not used currently)
186189
global ::= global specialization // function specialization

include/swift/AST/ASTContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ namespace swift {
8484
class NominalTypeDecl;
8585
class NormalProtocolConformance;
8686
class InheritedProtocolConformance;
87+
class SelfProtocolConformance;
8788
class SpecializedProtocolConformance;
8889
enum class ProtocolConformanceState;
8990
class Pattern;
@@ -750,6 +751,10 @@ class ASTContext final {
750751
AbstractStorageDecl *storage,
751752
ProtocolConformanceState state);
752753

754+
/// Produce a self-conformance for the given protocol.
755+
SelfProtocolConformance *
756+
getSelfConformance(ProtocolDecl *protocol);
757+
753758
/// A callback used to produce a diagnostic for an ill-formed protocol
754759
/// conformance that was type-checked before we're actually walking the
755760
/// conformance itself, along with a bit indicating whether this diagnostic

include/swift/AST/ASTMangler.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace swift {
2525

2626
class AbstractClosureExpr;
2727
class ConformanceAccessPath;
28+
class RootProtocolConformance;
2829

2930
namespace Mangle {
3031

@@ -114,7 +115,7 @@ class ASTMangler : public Mangler {
114115
const ConstructorDecl *Derived,
115116
bool isAllocating);
116117

117-
std::string mangleWitnessTable(const NormalProtocolConformance *C);
118+
std::string mangleWitnessTable(const RootProtocolConformance *C);
118119

119120
std::string mangleWitnessThunk(const ProtocolConformance *Conformance,
120121
const ValueDecl *Requirement);
@@ -295,8 +296,7 @@ class ASTMangler : public Mangler {
295296
void appendEntity(const ValueDecl *decl);
296297

297298
void appendProtocolConformance(const ProtocolConformance *conformance);
298-
void appendProtocolConformanceRef(
299-
const NormalProtocolConformance *conformance);
299+
void appendProtocolConformanceRef(const RootProtocolConformance *conformance);
300300
void appendConcreteProtocolConformance(
301301
const ProtocolConformance *conformance);
302302
void appendDependentProtocolConformance(const ConformanceAccessPath &path);

include/swift/AST/ProtocolConformance.h

Lines changed: 151 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ASTContext;
3535
class DiagnosticEngine;
3636
class GenericParamList;
3737
class NormalProtocolConformance;
38+
class RootProtocolConformance;
3839
class ProtocolConformance;
3940
class ModuleDecl;
4041
class SubstitutableType;
@@ -58,6 +59,8 @@ enum class ProtocolConformanceKind {
5859
/// "Normal" conformance of a (possibly generic) nominal type, which
5960
/// contains complete mappings.
6061
Normal,
62+
/// Self-conformance of a protocol to itself.
63+
Self,
6164
/// Conformance for a specialization of a generic type, which projects the
6265
/// underlying generic conformance.
6366
Specialized,
@@ -259,6 +262,7 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
259262
SubstitutionMap getSubstitutions(ModuleDecl *M) const;
260263

261264
/// Get the underlying normal conformance.
265+
/// FIXME: remove uses of this.
262266
const NormalProtocolConformance *getRootNormalConformance() const;
263267

264268
/// Get the underlying normal conformance.
@@ -268,6 +272,15 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
268272
->getRootNormalConformance());
269273
}
270274

275+
/// Get the underlying root conformance.
276+
const RootProtocolConformance *getRootConformance() const;
277+
278+
/// Get the underlying root conformance.
279+
RootProtocolConformance *getRootConformance() {
280+
return const_cast<RootProtocolConformance *>(
281+
const_cast<const ProtocolConformance *>(this)->getRootConformance());
282+
}
283+
271284
/// Determine whether this protocol conformance is visible from the
272285
/// given declaration context.
273286
bool isVisibleFrom(const DeclContext *dc) const;
@@ -322,6 +335,41 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
322335
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
323336
};
324337

338+
/// A "root" protocol conformance states some sort of ground truth
339+
/// about the conforming type and the required protocol. Either:
340+
///
341+
/// - the type is directly declared to conform to the protocol (a
342+
/// normal conformance) or
343+
/// - the protocol's existential type is known to conform to itself (a
344+
/// self-conformance).
345+
class RootProtocolConformance : public ProtocolConformance {
346+
protected:
347+
RootProtocolConformance(ProtocolConformanceKind kind, Type conformingType)
348+
: ProtocolConformance(kind, conformingType) {}
349+
350+
public:
351+
/// Retrieve the location of this conformance.
352+
SourceLoc getLoc() const;
353+
354+
/// Is this a behavior conformance?
355+
bool isBehaviorConformance() const;
356+
357+
bool isInvalid() const;
358+
359+
bool hasWitness(ValueDecl *requirement) const;
360+
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
361+
362+
/// Retrieve the witness corresponding to the given value requirement.
363+
/// TODO: maybe this should return a Witness?
364+
ConcreteDeclRef getWitnessDeclRef(ValueDecl *requirement,
365+
LazyResolver *resolver) const;
366+
367+
static bool classof(const ProtocolConformance *conformance) {
368+
return conformance->getKind() == ProtocolConformanceKind::Normal ||
369+
conformance->getKind() == ProtocolConformanceKind::Self;
370+
}
371+
};
372+
325373
/// Normal protocol conformance, which involves mapping each of the protocol
326374
/// requirements to a witness.
327375
///
@@ -337,7 +385,7 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
337385
/// Here, there is a normal protocol conformance for both \c A and \c B<T>,
338386
/// providing the witnesses \c A.foo and \c B<T>.foo, respectively, for the
339387
/// requirement \c foo.
340-
class NormalProtocolConformance : public ProtocolConformance,
388+
class NormalProtocolConformance : public RootProtocolConformance,
341389
public llvm::FoldingSetNode
342390
{
343391
/// \brief The protocol being conformed to and its current state.
@@ -406,7 +454,7 @@ class NormalProtocolConformance : public ProtocolConformance,
406454
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
407455
SourceLoc loc, DeclContext *dc,
408456
ProtocolConformanceState state)
409-
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
457+
: RootProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
410458
ProtocolAndState(protocol, state), Loc(loc), ContextAndInvalid(dc, false)
411459
{
412460
assert(!conformingType->hasArchetype() &&
@@ -417,7 +465,7 @@ class NormalProtocolConformance : public ProtocolConformance,
417465
ProtocolDecl *protocol,
418466
SourceLoc loc, AbstractStorageDecl *behaviorStorage,
419467
ProtocolConformanceState state)
420-
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
468+
: RootProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
421469
ProtocolAndState(protocol, state), Loc(loc),
422470
ContextAndInvalid(behaviorStorage, false)
423471
{
@@ -579,8 +627,6 @@ class NormalProtocolConformance : public ProtocolConformance,
579627

580628
/// Retrieve the value witness corresponding to the given requirement.
581629
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
582-
ConcreteDeclRef getWitnessDeclRef(ValueDecl *requirement,
583-
LazyResolver *resolver) const;
584630

585631
/// Determine whether the protocol conformance has a witness for the given
586632
/// requirement.
@@ -670,6 +716,104 @@ class NormalProtocolConformance : public ProtocolConformance,
670716
}
671717
};
672718

719+
/// The conformance of a protocol to itself.
720+
///
721+
/// For now, we generally do not use this type in ProtocolConformanceRefs;
722+
/// it's only used to anchor structures relating to emitting witness tables
723+
/// for self-conformances.
724+
class SelfProtocolConformance : public RootProtocolConformance {
725+
friend class ASTContext;
726+
727+
SelfProtocolConformance(Type conformingType)
728+
: RootProtocolConformance(ProtocolConformanceKind::Self, conformingType) {
729+
}
730+
731+
public:
732+
/// Get the protocol being conformed to.
733+
ProtocolDecl *getProtocol() const {
734+
return getType()->castTo<ProtocolType>()->getDecl();
735+
}
736+
737+
/// Get the declaration context in which this conformance was declared.
738+
DeclContext *getDeclContext() const {
739+
return getProtocol();
740+
}
741+
742+
/// Retrieve the location of this conformance.
743+
SourceLoc getLoc() const {
744+
return getProtocol()->getLoc();
745+
}
746+
747+
ProtocolConformanceState getState() const {
748+
return ProtocolConformanceState::Complete;
749+
}
750+
751+
bool isInvalid() const {
752+
return false;
753+
}
754+
755+
ConformanceEntryKind getSourceKind() const {
756+
return ConformanceEntryKind::Explicit; // FIXME?
757+
}
758+
759+
NormalProtocolConformance *getImplyingConformance() const {
760+
llvm_unreachable("never an implied conformance");
761+
}
762+
763+
bool hasTypeWitness(AssociatedTypeDecl *assocType,
764+
LazyResolver *resolver) const {
765+
llvm_unreachable("self-conformances never have associated types");
766+
}
767+
768+
std::pair<Type, TypeDecl *>
769+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
770+
LazyResolver *resolver,
771+
SubstOptions options) const {
772+
llvm_unreachable("self-conformances never have associated types");
773+
}
774+
775+
Type getTypeWitness(AssociatedTypeDecl *assocType,
776+
LazyResolver *resolver,
777+
SubstOptions options) const {
778+
llvm_unreachable("self-conformances never have associated types");
779+
}
780+
781+
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
782+
llvm_unreachable("self-conformances never have associated types");
783+
}
784+
785+
ProtocolConformanceRef getAssociatedConformance(Type assocType,
786+
ProtocolDecl *protocol,
787+
LazyResolver *resolver) const{
788+
llvm_unreachable("self-conformances never have associated types");
789+
}
790+
791+
bool hasWitness(ValueDecl *requirement) const {
792+
return true;
793+
}
794+
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
795+
796+
Optional<ArrayRef<Requirement>> getConditionalRequirementsIfAvailable() const{
797+
return ArrayRef<Requirement>();
798+
}
799+
800+
/// Get any additional requirements that are required for this conformance to
801+
/// be satisfied.
802+
ArrayRef<Requirement> getConditionalRequirements() const {
803+
return ArrayRef<Requirement>();
804+
}
805+
806+
static bool classof(const ProtocolConformance *conformance) {
807+
return conformance->getKind() == ProtocolConformanceKind::Self;
808+
}
809+
};
810+
811+
inline bool RootProtocolConformance::isBehaviorConformance() const {
812+
if (auto normal = dyn_cast<NormalProtocolConformance>(this))
813+
return normal->isBehaviorConformance();
814+
return false;
815+
}
816+
673817
/// Specialized protocol conformance, which projects a generic protocol
674818
/// conformance to one of the specializations of the generic type.
675819
///
@@ -934,11 +1078,11 @@ class InheritedProtocolConformance : public ProtocolConformance,
9341078
};
9351079

9361080
inline bool ProtocolConformance::isInvalid() const {
937-
return getRootNormalConformance()->isInvalid();
1081+
return getRootConformance()->isInvalid();
9381082
}
9391083

9401084
inline bool ProtocolConformance::hasWitness(ValueDecl *requirement) const {
941-
return getRootNormalConformance()->hasWitness(requirement);
1085+
return getRootConformance()->hasWitness(requirement);
9421086
}
9431087

9441088
} // end namespace swift

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ NODE(ProtocolConformanceDescriptor)
161161
NODE(ProtocolList)
162162
NODE(ProtocolListWithClass)
163163
NODE(ProtocolListWithAnyObject)
164+
NODE(ProtocolSelfConformanceDescriptor)
165+
NODE(ProtocolSelfConformanceWitness)
166+
NODE(ProtocolSelfConformanceWitnessTable)
164167
NODE(ProtocolWitness)
165168
NODE(ProtocolWitnessTable)
166169
NODE(ProtocolWitnessTableAccessor)

include/swift/IRGen/Linking.h

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,8 @@ class LinkEntity {
262262
// These next few are protocol-conformance kinds.
263263

264264
/// A direct protocol witness table. The secondary pointer is a
265-
/// ProtocolConformance*.
266-
DirectProtocolWitnessTable,
265+
/// RootProtocolConformance*.
266+
ProtocolWitnessTable,
267267

268268
/// A protocol witness table pattern. The secondary pointer is a
269269
/// ProtocolConformance*.
@@ -284,7 +284,7 @@ class LinkEntity {
284284
ReflectionAssociatedTypeDescriptor,
285285

286286
/// The protocol conformance descriptor for a conformance.
287-
/// The pointer is a NormalProtocolConformance*.
287+
/// The pointer is a RootProtocolConformance*.
288288
ProtocolConformanceDescriptor,
289289

290290
// These are both type kinds and protocol-conformance kinds.
@@ -350,8 +350,13 @@ class LinkEntity {
350350
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
351351
}
352352

353+
static bool isRootProtocolConformanceKind(Kind k) {
354+
return (k == Kind::ProtocolConformanceDescriptor ||
355+
k == Kind::ProtocolWitnessTable);
356+
}
357+
353358
static bool isProtocolConformanceKind(Kind k) {
354-
return (k >= Kind::DirectProtocolWitnessTable &&
359+
return (k >= Kind::ProtocolWitnessTable &&
355360
k <= Kind::ProtocolWitnessTableLazyCacheVariable);
356361
}
357362

@@ -746,10 +751,9 @@ class LinkEntity {
746751
return entity;
747752
}
748753

749-
static LinkEntity
750-
forDirectProtocolWitnessTable(const ProtocolConformance *C) {
754+
static LinkEntity forProtocolWitnessTable(const RootProtocolConformance *C) {
751755
LinkEntity entity;
752-
entity.setForProtocolConformance(Kind::DirectProtocolWitnessTable, C);
756+
entity.setForProtocolConformance(Kind::ProtocolWitnessTable, C);
753757
return entity;
754758
}
755759

@@ -848,10 +852,9 @@ class LinkEntity {
848852
}
849853

850854
static LinkEntity
851-
forProtocolConformanceDescriptor(const NormalProtocolConformance *C) {
855+
forProtocolConformanceDescriptor(const RootProtocolConformance *C) {
852856
LinkEntity entity;
853-
entity.setForProtocolConformance(
854-
Kind::ProtocolConformanceDescriptor, C);
857+
entity.setForProtocolConformance(Kind::ProtocolConformanceDescriptor, C);
855858
return entity;
856859
}
857860

@@ -936,6 +939,11 @@ class LinkEntity {
936939
assert(getKind() == Kind::SILGlobalVariable);
937940
return reinterpret_cast<SILGlobalVariable*>(Pointer);
938941
}
942+
943+
const RootProtocolConformance *getRootProtocolConformance() const {
944+
assert(isRootProtocolConformanceKind(getKind()));
945+
return cast<RootProtocolConformance>(getProtocolConformance());
946+
}
939947

940948
const ProtocolConformance *getProtocolConformance() const {
941949
assert(isProtocolConformanceKind(getKind()));

0 commit comments

Comments
 (0)