Skip to content

Commit 504b6f2

Browse files
authored
Merge pull request #8852 from DougGregor/protocol-conformance-cleanups
2 parents 2f44498 + 51e0059 commit 504b6f2

19 files changed

+119
-129
lines changed

include/swift/AST/ASTContext.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,6 @@ class ASTContext {
662662
/// Produce a new normal conformance for a property behavior.
663663
NormalProtocolConformance *
664664
getBehaviorConformance(Type conformingType,
665-
Type conformingInterfaceType,
666665
ProtocolDecl *protocol,
667666
SourceLoc loc,
668667
AbstractStorageDecl *storage,

include/swift/AST/ProtocolConformance.h

Lines changed: 41 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,9 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
9494
/// conformance definition.
9595
Type ConformingType;
9696

97-
/// \brief The interface type that conforms to the protocol.
98-
Type ConformingInterfaceType;
99-
10097
protected:
101-
ProtocolConformance(ProtocolConformanceKind kind, Type conformingType,
102-
Type conformingInterfaceType)
103-
: Kind(kind), ConformingType(conformingType),
104-
ConformingInterfaceType(conformingInterfaceType) { }
98+
ProtocolConformance(ProtocolConformanceKind kind, Type conformingType)
99+
: Kind(kind), ConformingType(conformingType) { }
105100

106101
public:
107102
/// Determine the kind of protocol conformance.
@@ -110,9 +105,6 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
110105
/// Get the conforming type.
111106
Type getType() const { return ConformingType; }
112107

113-
/// Get the conforming interface type.
114-
Type getInterfaceType() const { return ConformingInterfaceType; }
115-
116108
/// Get the protocol being conformed to.
117109
ProtocolDecl *getProtocol() const;
118110

@@ -190,41 +182,16 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
190182
return false;
191183
}
192184

193-
/// Retrieve the non-type witness for the given requirement.
194-
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
185+
/// Retrieve the value witness declaration corresponding to the given
186+
/// requirement.
187+
ValueDecl *getWitnessDecl(ValueDecl *requirement,
188+
LazyResolver *resolver) const;
195189

196190
private:
197191
/// Determine whether we have a witness for the given requirement.
198192
bool hasWitness(ValueDecl *requirement) const;
199193

200194
public:
201-
/// Apply the given function object to each value witness within this
202-
/// protocol conformance.
203-
///
204-
/// The function object should accept a \c ValueDecl* for the requirement
205-
/// followed by the \c Witness for the witness. Note that a generic
206-
/// witness will only be specialized if the conformance came from the current
207-
/// file.
208-
template<typename F>
209-
void forEachValueWitness(LazyResolver *resolver, F f) const {
210-
const ProtocolDecl *protocol = getProtocol();
211-
for (auto req : protocol->getMembers()) {
212-
auto valueReq = dyn_cast<ValueDecl>(req);
213-
if (!valueReq || isa<AssociatedTypeDecl>(valueReq) ||
214-
valueReq->isInvalid())
215-
continue;
216-
217-
if (!valueReq->isProtocolRequirement())
218-
continue;
219-
220-
// If we don't have and cannot resolve witnesses, skip it.
221-
if (!resolver && !hasWitness(valueReq))
222-
continue;
223-
224-
f(valueReq, getWitness(valueReq, resolver));
225-
}
226-
}
227-
228195
/// Retrieve the protocol conformance for the inherited protocol.
229196
ProtocolConformance *getInheritedConformance(ProtocolDecl *protocol) const;
230197

@@ -357,21 +324,16 @@ class NormalProtocolConformance : public ProtocolConformance,
357324
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
358325
SourceLoc loc, DeclContext *dc,
359326
ProtocolConformanceState state)
360-
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType,
361-
// FIXME: interface type should be passed in
362-
dc->getDeclaredInterfaceType()),
327+
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
363328
ProtocolAndState(protocol, state), Loc(loc), ContextAndInvalid(dc, false)
364329
{
365330
}
366331

367332
NormalProtocolConformance(Type conformingType,
368-
Type conformingInterfaceType,
369333
ProtocolDecl *protocol,
370334
SourceLoc loc, AbstractStorageDecl *behaviorStorage,
371335
ProtocolConformanceState state)
372-
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType,
373-
// FIXME: interface type should be passed in
374-
conformingInterfaceType),
336+
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
375337
ProtocolAndState(protocol, state), Loc(loc),
376338
ContextAndInvalid(behaviorStorage, false)
377339
{
@@ -457,11 +419,6 @@ class NormalProtocolConformance : public ProtocolConformance,
457419
LazyResolver *resolver = nullptr) const;
458420

459421
/// Retrieve the value witness corresponding to the given requirement.
460-
///
461-
/// Note that a generic witness will only be specialized if the conformance
462-
/// came from the current file.
463-
///
464-
/// FIXME: The 'only specialized if from the same file' bit is awful.
465422
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
466423

467424
/// Determine whether the protocol conformance has a witness for the given
@@ -475,6 +432,33 @@ class NormalProtocolConformance : public ProtocolConformance,
475432
/// Set the witness for the given requirement.
476433
void setWitness(ValueDecl *requirement, Witness witness) const;
477434

435+
/// Apply the given function object to each value witness within this
436+
/// protocol conformance.
437+
///
438+
/// The function object should accept a \c ValueDecl* for the requirement
439+
/// followed by the \c Witness for the witness. Note that a generic
440+
/// witness will only be specialized if the conformance came from the current
441+
/// file.
442+
template<typename F>
443+
void forEachValueWitness(LazyResolver *resolver, F f) const {
444+
const ProtocolDecl *protocol = getProtocol();
445+
for (auto req : protocol->getMembers()) {
446+
auto valueReq = dyn_cast<ValueDecl>(req);
447+
if (!valueReq || isa<AssociatedTypeDecl>(valueReq) ||
448+
valueReq->isInvalid())
449+
continue;
450+
451+
if (!valueReq->isProtocolRequirement())
452+
continue;
453+
454+
// If we don't have and cannot resolve witnesses, skip it.
455+
if (!resolver && !hasWitness(valueReq))
456+
continue;
457+
458+
f(valueReq, getWitness(valueReq, resolver));
459+
}
460+
}
461+
478462
/// Retrieve the protocol conformances that satisfy the requirements of the
479463
/// protocol, which line up with the conformance constraints in the
480464
/// protocol's requirement signature.
@@ -583,10 +567,6 @@ class SpecializedProtocolConformance : public ProtocolConformance,
583567
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
584568
LazyResolver *resolver) const;
585569

586-
/// Retrieve the value witness corresponding to the given requirement.
587-
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
588-
589-
590570
/// Given that the requirement signature of the protocol directly states
591571
/// that the given dependent type must conform to the given protocol,
592572
/// return its associated conformance.
@@ -601,17 +581,16 @@ class SpecializedProtocolConformance : public ProtocolConformance,
601581
}
602582

603583
void Profile(llvm::FoldingSetNodeID &ID) {
604-
Profile(ID, getType(), getGenericConformance());
584+
Profile(ID, getType(), getGenericConformance(),
585+
getGenericSubstitutions());
605586
}
606587

607588
static void Profile(llvm::FoldingSetNodeID &ID, Type type,
608-
ProtocolConformance *genericConformance) {
609-
// FIXME: Consider profiling substitutions here. They could differ in
610-
// some crazy cases that also require major diagnostic work, where the
611-
// substitutions involve conformances of the same type to the same
612-
// protocol drawn from different imported modules.
589+
ProtocolConformance *genericConformance,
590+
SubstitutionList subs) {
613591
ID.AddPointer(type.getPointer());
614592
ID.AddPointer(genericConformance);
593+
profileSubstitutionList(ID, subs);
615594
}
616595

617596
static bool classof(const ProtocolConformance *conformance) {
@@ -640,9 +619,7 @@ class InheritedProtocolConformance : public ProtocolConformance,
640619

641620
InheritedProtocolConformance(Type conformingType,
642621
ProtocolConformance *inheritedConformance)
643-
: ProtocolConformance(ProtocolConformanceKind::Inherited, conformingType,
644-
// FIXME: interface type should be passed in
645-
inheritedConformance->getDeclContext()->getDeclaredInterfaceType()),
622+
: ProtocolConformance(ProtocolConformanceKind::Inherited, conformingType),
646623
InheritedConformance(inheritedConformance)
647624
{
648625
}
@@ -686,12 +663,6 @@ class InheritedProtocolConformance : public ProtocolConformance,
686663
return InheritedConformance->getTypeWitnessAndDecl(assocType, resolver);
687664
}
688665

689-
/// Retrieve the value witness corresponding to the given requirement.
690-
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const {
691-
// FIXME: Substitute!
692-
return InheritedConformance->getWitness(requirement, resolver);
693-
}
694-
695666
/// Given that the requirement signature of the protocol directly states
696667
/// that the given dependent type must conform to the given protocol,
697668
/// return its associated conformance.

include/swift/AST/SubstitutionList.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121

2222
#include "swift/AST/Substitution.h"
2323
#include "llvm/ADT/ArrayRef.h"
24+
#include "llvm/ADT/FoldingSet.h"
25+
26+
namespace llvm {
27+
class FoldingSetNodeID;
28+
} // end namespace llvm
2429

2530
namespace swift {
2631

@@ -41,6 +46,10 @@ void dump(SubstitutionList subs);
4146
SubstitutionList
4247
getCanonicalSubstitutionList(SubstitutionList subs,
4348
SmallVectorImpl<Substitution> &canSubs);
49+
50+
/// Profile the substitution list for use in a folding set.
51+
void profileSubstitutionList(llvm::FoldingSetNodeID &id, SubstitutionList subs);
52+
4453
} // end namespace swift
4554

4655
#endif

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,16 +1476,14 @@ void ValueDecl::setLocalDiscriminator(unsigned index) {
14761476

14771477
NormalProtocolConformance *
14781478
ASTContext::getBehaviorConformance(Type conformingType,
1479-
Type conformingInterfaceType,
14801479
ProtocolDecl *protocol,
14811480
SourceLoc loc,
14821481
AbstractStorageDecl *storage,
14831482
ProtocolConformanceState state) {
14841483
auto conformance = new (*this, AllocationArena::Permanent)
1485-
NormalProtocolConformance(conformingType, conformingInterfaceType,
1486-
protocol, loc, storage, state);
1484+
NormalProtocolConformance(conformingType, protocol, loc, storage, state);
14871485

1488-
if (auto nominal = conformingInterfaceType->getAnyNominal()) {
1486+
if (auto nominal = conformingType->getRValueInstanceType()->getAnyNominal()) {
14891487
// Note: this is an egregious hack. The conformances need to be associated
14901488
// with the actual storage declarations.
14911489
SmallVector<ProtocolConformance *, 2> conformances;
@@ -1528,7 +1526,7 @@ ASTContext::getSpecializedConformance(Type type,
15281526
ProtocolConformance *generic,
15291527
SubstitutionList substitutions) {
15301528
llvm::FoldingSetNodeID id;
1531-
SpecializedProtocolConformance::Profile(id, type, generic);
1529+
SpecializedProtocolConformance::Profile(id, type, generic, substitutions);
15321530

15331531
// Figure out which arena this conformance should go into.
15341532
AllocationArena arena = getArena(type->getRecursiveProperties());

lib/AST/ASTMangler.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1839,7 +1839,10 @@ void ASTMangler::appendProtocolConformance(const ProtocolConformance *conformanc
18391839
appendProtocolName(conformance->getProtocol());
18401840
appendIdentifier(behaviorStorage->getName().str());
18411841
} else {
1842-
appendType(conformance->getInterfaceType()->getCanonicalType());
1842+
auto conformanceDC = conformance->getDeclContext();
1843+
auto conformingType =
1844+
conformanceDC->mapTypeOutOfContext(conformance->getType());
1845+
appendType(conformingType->getCanonicalType());
18431846
appendProtocolName(conformance->getProtocol());
18441847
appendModule(conformance->getDeclContext()->getParentModule());
18451848
}

lib/AST/ConformanceLookupTable.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,8 @@ ConformanceLookupTable::getSatisfiedProtocolRequirementsForMember(
11031103
if (conf->isInvalid())
11041104
continue;
11051105

1106-
conf->forEachValueWitness(resolver, [&](ValueDecl *req,
1106+
auto normal = conf->getRootNormalConformance();
1107+
normal->forEachValueWitness(resolver, [&](ValueDecl *req,
11071108
ConcreteDeclRef witness) {
11081109
if (witness.getDecl() == member)
11091110
reqs.push_back(req);

lib/AST/ProtocolConformance.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,22 @@ Type ProtocolConformance::getTypeWitness(AssociatedTypeDecl *assocType,
251251
return getTypeWitnessAndDecl(assocType, resolver).first;
252252
}
253253

254-
Witness ProtocolConformance::getWitness(ValueDecl *requirement,
255-
LazyResolver *resolver) const {
256-
CONFORMANCE_SUBCLASS_DISPATCH(getWitness, (requirement, resolver))
254+
ValueDecl *ProtocolConformance::getWitnessDecl(ValueDecl *requirement,
255+
LazyResolver *resolver) const {
256+
switch (getKind()) {
257+
case ProtocolConformanceKind::Normal:
258+
return cast<NormalProtocolConformance>(this)->getWitness(requirement,
259+
resolver)
260+
.getDecl();
261+
262+
case ProtocolConformanceKind::Inherited:
263+
return cast<InheritedProtocolConformance>(this)
264+
->getInheritedConformance()->getWitnessDecl(requirement, resolver);
265+
266+
case ProtocolConformanceKind::Specialized:
267+
return cast<SpecializedProtocolConformance>(this)
268+
->getGenericConformance()->getWitnessDecl(requirement, resolver);
269+
}
257270
}
258271

259272
/// Determine whether the witness for the given requirement
@@ -266,7 +279,7 @@ usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
266279
bool ProtocolConformance::hasFixedLayout() const {
267280
// A conformance/witness table has fixed layout if type has a fixed layout in
268281
// all resilience domains, and the conformance is externally visible.
269-
if (auto nominal = getInterfaceType()->getAnyNominal())
282+
if (auto nominal = getType()->getAnyNominal())
270283
if (nominal->hasFixedLayout() &&
271284
getProtocol()->getEffectiveAccess() >= Accessibility::Public &&
272285
nominal->getEffectiveAccess() >= Accessibility::Public)
@@ -652,11 +665,7 @@ SpecializedProtocolConformance::SpecializedProtocolConformance(
652665
Type conformingType,
653666
ProtocolConformance *genericConformance,
654667
SubstitutionList substitutions)
655-
: ProtocolConformance(ProtocolConformanceKind::Specialized, conformingType,
656-
// FIXME: interface type should be passed in.
657-
// assumes specialized conformance is always fully
658-
// specialized
659-
conformingType),
668+
: ProtocolConformance(ProtocolConformanceKind::Specialized, conformingType),
660669
GenericConformance(genericConformance),
661670
GenericSubstitutions(substitutions)
662671
{
@@ -708,13 +717,6 @@ SpecializedProtocolConformance::getTypeWitnessAndDecl(
708717
return TypeWitnesses[assocType];
709718
}
710719

711-
Witness
712-
SpecializedProtocolConformance::getWitness(ValueDecl *requirement,
713-
LazyResolver *resolver) const {
714-
// FIXME: Apply substitutions here!
715-
return GenericConformance->getWitness(requirement, resolver);
716-
}
717-
718720
ProtocolConformanceRef
719721
SpecializedProtocolConformance::getAssociatedConformance(Type assocType,
720722
ProtocolDecl *protocol,
@@ -1068,8 +1070,6 @@ bool ProtocolConformance::isCanonical() const {
10681070

10691071
if (!getType()->isCanonical())
10701072
return false;
1071-
if (!getInterfaceType()->isCanonical())
1072-
return false;
10731073

10741074
switch (getKind()) {
10751075
case ProtocolConformanceKind::Normal: {

lib/AST/SubstitutionList.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,17 @@
1717
//===----------------------------------------------------------------------===//
1818

1919
#include "swift/AST/SubstitutionList.h"
20+
#include "swift/AST/ProtocolConformanceRef.h"
21+
#include "llvm/ADT/FoldingSet.h"
2022

2123
using namespace swift;
24+
25+
void swift::profileSubstitutionList(llvm::FoldingSetNodeID &id,
26+
SubstitutionList subs) {
27+
id.AddInteger(subs.size());
28+
for (auto &sub : subs) {
29+
id.AddPointer(sub.getReplacement().getPointer());
30+
for (auto conformance : sub.getConformances())
31+
id.AddPointer(conformance.getOpaqueValue());
32+
}
33+
}

lib/AST/Type.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4060,11 +4060,7 @@ bool TypeBase::usesNativeReferenceCounting(ResilienceExpansion resilience) {
40604060
void SILBoxType::Profile(llvm::FoldingSetNodeID &id, SILLayout *Layout,
40614061
SubstitutionList Args) {
40624062
id.AddPointer(Layout);
4063-
for (auto &arg : Args) {
4064-
id.AddPointer(arg.getReplacement().getPointer());
4065-
for (auto conformance : arg.getConformances())
4066-
id.AddPointer(conformance.getOpaqueValue());
4067-
}
4063+
profileSubstitutionList(id, Args);
40684064
}
40694065

40704066
SILBoxType::SILBoxType(ASTContext &C,

lib/IRGen/GenReflection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
283283
void layout() override {
284284
// If the conforming type is generic, we just want to emit the
285285
// unbound generic type here.
286-
auto *Nominal = Conformance->getInterfaceType()->getAnyNominal();
286+
auto *Nominal = Conformance->getType()->getAnyNominal();
287287
assert(Nominal && "Structural conformance?");
288288

289289
PrettyStackTraceDecl DebugStack("emitting associated type metadata",

0 commit comments

Comments
 (0)