Skip to content

Commit 424b4f1

Browse files
committed
AST: Introduce ProtocolConformanceRef::forAbstract()
1 parent 0c354b4 commit 424b4f1

22 files changed

+82
-67
lines changed

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ class ProtocolConformanceRef {
5959

6060
explicit ProtocolConformanceRef(UnionType value) : Union(value) {}
6161

62-
public:
6362
/// Create an abstract protocol conformance reference.
6463
explicit ProtocolConformanceRef(ProtocolDecl *proto) : Union(proto) {
6564
assert(proto != nullptr &&
6665
"cannot construct ProtocolConformanceRef with null");
6766
}
6867

68+
public:
69+
ProtocolConformanceRef() : Union() {}
70+
6971
/// Create a concrete protocol conformance reference.
7072
explicit ProtocolConformanceRef(ProtocolConformance *conf) : Union(conf) {
7173
assert(conf != nullptr &&
@@ -78,9 +80,6 @@ class ProtocolConformanceRef {
7880
"cannot construct ProtocolConformanceRef with null");
7981
}
8082

81-
ProtocolConformanceRef(std::nullptr_t = nullptr)
82-
: Union((ProtocolDecl *)nullptr) {}
83-
8483
static ProtocolConformanceRef forInvalid() {
8584
return ProtocolConformanceRef();
8685
}
@@ -94,10 +93,9 @@ class ProtocolConformanceRef {
9493

9594
explicit operator bool() const { return !isInvalid(); }
9695

97-
/// Create either a concrete or an abstract protocol conformance reference,
98-
/// depending on whether ProtocolConformance is null.
99-
explicit ProtocolConformanceRef(ProtocolDecl *protocol,
100-
ProtocolConformance *conf);
96+
/// Create an abstract conformance for a type parameter or archetype.
97+
static ProtocolConformanceRef forAbstract(Type subjectType,
98+
ProtocolDecl *protocol);
10199

102100
bool isConcrete() const {
103101
return !isInvalid() && Union.is<ProtocolConformance*>();

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ struct SubstitutionMapWithLocalArchetypes {
9393
if (SubsMap)
9494
return SubsMap->lookupConformance(origType, proto);
9595

96-
return ProtocolConformanceRef(proto);
96+
return ProtocolConformanceRef::forAbstract(substType, proto);
9797
}
9898

9999
void dump(llvm::raw_ostream &out) const {

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,7 +1612,7 @@ class Solution {
16121612

16131613
/// The set of conformances synthesized during solving (i.e. for
16141614
/// ad-hoc distributed `SerializationRequirement` conformances).
1615-
llvm::MapVector<ConstraintLocator *, ProtocolConformanceRef>
1615+
llvm::MapVector<ConstraintLocator *, ProtocolDecl *>
16161616
SynthesizedConformances;
16171617

16181618
/// Record a new argument matching choice for given locator that maps a
@@ -2414,7 +2414,7 @@ class ConstraintSystem {
24142414

24152415
/// The set of conformances synthesized during solving (i.e. for
24162416
/// ad-hoc distributed `SerializationRequirement` conformances).
2417-
llvm::MapVector<ConstraintLocator *, ProtocolConformanceRef>
2417+
llvm::MapVector<ConstraintLocator *, ProtocolDecl *>
24182418
SynthesizedConformances;
24192419

24202420
private:

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,8 @@ SwiftDeclCollector::addConformancesToTypeDecl(SDKNodeDeclType *Root,
19841984
if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
19851985
for (auto *inherited : PD->getAllInheritedProtocols()) {
19861986
if (!Ctx.shouldIgnore(inherited)) {
1987-
ProtocolConformanceRef Conf(inherited);
1987+
auto Conf = ProtocolConformanceRef::forAbstract(
1988+
PD->getSelfInterfaceType(), inherited);
19881989
auto ConfNode = SDKNodeInitInfo(Ctx, Conf)
19891990
.createSDKNode(SDKNodeKind::Conformance);
19901991
Root->addConformance(ConfNode);

lib/AST/ConformanceLookup.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ LookupConformanceInModuleRequest::evaluate(
498498

499499
for (auto ap : archetype->getConformsTo()) {
500500
if (ap == protocol || ap->inheritsFrom(protocol))
501-
return ProtocolConformanceRef(protocol);
501+
return ProtocolConformanceRef::forAbstract(archetype, protocol);
502502
}
503503

504504
return ProtocolConformanceRef::forMissingOrInvalid(type, protocol);
@@ -516,17 +516,17 @@ LookupConformanceInModuleRequest::evaluate(
516516

517517
// Type parameters have trivial conformances.
518518
if (type->isTypeParameter())
519-
return ProtocolConformanceRef(protocol);
519+
return ProtocolConformanceRef::forAbstract(type, protocol);
520520

521521
// Type variables have trivial conformances.
522522
if (type->isTypeVariableOrMember())
523-
return ProtocolConformanceRef(protocol);
523+
return ProtocolConformanceRef::forAbstract(type, protocol);
524524

525525
// UnresolvedType is a placeholder for an unknown type used when generating
526526
// diagnostics. We consider it to conform to all protocols, since the
527527
// intended type might have. Same goes for PlaceholderType.
528528
if (type->is<UnresolvedType>() || type->is<PlaceholderType>())
529-
return ProtocolConformanceRef(protocol);
529+
return ProtocolConformanceRef::forAbstract(type, protocol);
530530

531531
// Pack types can conform to protocols.
532532
if (auto packType = type->getAs<PackType>()) {

lib/AST/ExistentialGeneralization.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -195,35 +195,37 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
195195
newArgs.push_back(generalizeComponentType(CanType(origArg)));
196196
}
197197

198+
auto origSig = origSubs.getGenericSignature();
199+
198200
// Generalize all of the conformances.
199201
// TODO: for abstract requirements, we might not generalize all
200202
// arguments, and we may need to leave corresponding conformances
201203
// concrete.
202204
SmallVector<ProtocolConformanceRef, 4> newConformances;
203-
auto origConformances = origSubs.getConformances();
204-
for (auto origConformance: origConformances) {
205+
for (const auto &req : origSig.getRequirements()) {
206+
if (req.getKind() != RequirementKind::Conformance)
207+
continue;
205208
newConformances.push_back(
206-
ProtocolConformanceRef(origConformance.getRequirement()));
209+
ProtocolConformanceRef::forAbstract(req.getFirstType(),
210+
req.getProtocolDecl()));
207211
}
208212

209-
auto origSig = origSubs.getGenericSignature();
210213
auto newSubs = SubstitutionMap::get(origSig, newArgs, newConformances);
211214

212215
// Add any conformance requirements to the generic signature and
213216
// remember the conformances we generalized.
214-
if (!origConformances.empty()) {
215-
size_t i = 0;
216-
for (auto &origReq: origSig.getRequirements()) {
217-
if (origReq.getKind() != RequirementKind::Conformance) continue;
218-
auto origConformance = origConformances[i++];
219-
220-
auto newReq = origReq.subst(newSubs);
221-
addedRequirements.push_back(newReq);
222-
223-
substConformances.insert({{newReq.getFirstType()->getCanonicalType(),
224-
newReq.getProtocolDecl()},
225-
origConformance});
226-
}
217+
auto origConformances = origSubs.getConformances();
218+
size_t i = 0;
219+
for (auto &origReq: origSig.getRequirements()) {
220+
if (origReq.getKind() != RequirementKind::Conformance) continue;
221+
auto origConformance = origConformances[i++];
222+
223+
auto newReq = origReq.subst(newSubs);
224+
addedRequirements.push_back(newReq);
225+
226+
substConformances.insert({{newReq.getFirstType()->getCanonicalType(),
227+
newReq.getProtocolDecl()},
228+
origConformance});
227229
}
228230

229231
// Build the new type.

lib/AST/LocalArchetypeRequirementCollector.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ swift::buildSubstitutionMapWithCapturedEnvironments(
265265
[&](CanType origType, Type substType,
266266
ProtocolDecl *proto) -> ProtocolConformanceRef {
267267
if (origType->getRootGenericParam()->getDepth() >= baseDepth)
268-
return ProtocolConformanceRef(proto);
268+
return ProtocolConformanceRef::forAbstract(substType, proto);
269269
return baseSubMap.lookupConformance(origType, proto);
270270
});
271271
}

lib/AST/ProtocolConformanceRef.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,10 @@
3333

3434
using namespace swift;
3535

36-
ProtocolConformanceRef::ProtocolConformanceRef(ProtocolDecl *protocol,
37-
ProtocolConformance *conf) {
38-
assert(protocol != nullptr &&
39-
"cannot construct ProtocolConformanceRef with null protocol");
40-
if (conf) {
41-
assert(protocol == conf->getProtocol() && "protocol conformance mismatch");
42-
Union = conf;
43-
} else {
44-
Union = protocol;
45-
}
36+
ProtocolConformanceRef ProtocolConformanceRef::forAbstract(
37+
Type subjectType, ProtocolDecl *proto) {
38+
// Temporary implementation:
39+
return ProtocolConformanceRef(proto);
4640
}
4741

4842
bool ProtocolConformanceRef::isInvalid() const {

lib/AST/RequirementEnvironment.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ RequirementEnvironment::RequirementEnvironment(
139139

140140
// All other generic parameters come from the requirement itself
141141
// and conform abstractly.
142-
return ProtocolConformanceRef(proto);
142+
return ProtocolConformanceRef::forAbstract(substConcreteType, proto);
143143
});
144144

145145
// If the requirement itself is non-generic, the witness thunk signature

lib/AST/SubstitutionMap.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ LookUpConformanceInOverrideSubs::operator()(CanType type,
493493
Type substType,
494494
ProtocolDecl *proto) const {
495495
if (type->getRootGenericParam()->getDepth() >= info.BaseDepth)
496-
return ProtocolConformanceRef(proto);
496+
return ProtocolConformanceRef::forAbstract(substType, proto);
497497

498498
if (auto conformance = info.BaseSubMap.lookupConformance(type, proto))
499499
return conformance;
@@ -667,7 +667,8 @@ ProtocolConformanceRef OuterSubstitutions::operator()(
667667
Type conformingReplacementType,
668668
ProtocolDecl *conformedProtocol) const {
669669
if (isUnsubstitutedTypeParameter(dependentType))
670-
return ProtocolConformanceRef(conformedProtocol);
670+
return ProtocolConformanceRef::forAbstract(
671+
conformingReplacementType, conformedProtocol);
671672

672673
return LookUpConformanceInSubstitutionMap(subs)(
673674
dependentType, conformingReplacementType, conformedProtocol);

lib/AST/TypeSubstitution.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ operator()(CanType dependentType, Type conformingReplacementType,
166166
return lookupConformance(archetypeType, conformedProtocol);
167167
}
168168
}
169-
return ProtocolConformanceRef(conformedProtocol);
169+
return ProtocolConformanceRef::forAbstract(
170+
conformingReplacementType, conformedProtocol);
170171
}
171172

172173
static Type substGenericFunctionType(GenericFunctionType *genericFnType,
@@ -1197,7 +1198,7 @@ ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes(
11971198
ProtocolConformanceRef ReplaceOpaqueTypesWithUnderlyingTypes::
11981199
operator()(CanType maybeOpaqueType, Type replacementType,
11991200
ProtocolDecl *protocol) const {
1200-
auto abstractRef = ProtocolConformanceRef(protocol);
1201+
auto abstractRef = ProtocolConformanceRef::forAbstract(maybeOpaqueType, protocol);
12011202

12021203
auto archetype = dyn_cast<OpaqueTypeArchetypeType>(maybeOpaqueType);
12031204
if (!archetype) {

lib/IRGen/GenArchetype.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,10 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF,
306306
assert(rootWTable && "root witness table not bound in local context!");
307307
}
308308

309+
auto conformance = ProtocolConformanceRef::forAbstract(
310+
rootArchetype, rootProtocol);
309311
wtable = path.followFromWitnessTable(IGF, rootArchetype,
310-
ProtocolConformanceRef(rootProtocol),
312+
conformance,
311313
MetadataResponse::forComplete(rootWTable),
312314
/*request*/ MetadataState::Complete,
313315
nullptr).getMetadata();

lib/IRGen/GenPack.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,12 @@ static void bindElementSignatureRequirementsAtIndex(
354354
patternPackArchetype)
355355
->getCanonicalType();
356356
llvm::Value *_metadata = nullptr;
357-
auto packConformance = ProtocolConformanceRef(proto);
357+
auto packConformance = ProtocolConformanceRef::forAbstract(
358+
patternPackArchetype, proto);
358359
auto *wtablePack = emitWitnessTableRef(IGF, patternPackArchetype,
359360
&_metadata, packConformance);
360-
auto elementConformance = ProtocolConformanceRef(proto);
361+
auto elementConformance = ProtocolConformanceRef::forAbstract(
362+
elementArchetype, proto);
361363
auto *wtable = bindWitnessTableAtIndex(
362364
IGF, elementArchetype, elementConformance, wtablePack, index);
363365
assert(wtable);

lib/IRGen/LocalTypeDataKind.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,10 @@ class LocalTypeDataKind {
186186
ProtocolConformanceRef getProtocolConformance() const {
187187
assert(!isSingletonKind());
188188
if ((Value & KindMask) == Kind_Decl) {
189-
return ProtocolConformanceRef(getAbstractProtocolConformance());
189+
// FIXME: Passing an empty Type() here temporarily while staging in
190+
// new representation for abstract conformances
191+
return ProtocolConformanceRef::forAbstract(
192+
Type(), getAbstractProtocolConformance());
190193
} else if ((Value & KindMask) == Kind_PackConformance) {
191194
return ProtocolConformanceRef(getPackProtocolConformance());
192195
} else {

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3914,7 +3914,8 @@ static CanSILFunctionType getUncachedSILFunctionTypeForConstant(
39143914

39153915
if (silRep == SILFunctionTypeRepresentation::WitnessMethod) {
39163916
auto proto = constant.getDecl()->getDeclContext()->getSelfProtocolDecl();
3917-
witnessMethodConformance = ProtocolConformanceRef(proto);
3917+
witnessMethodConformance = ProtocolConformanceRef::forAbstract(
3918+
proto->getSelfInterfaceType()->getCanonicalType(), proto);
39183919
}
39193920

39203921
// Does this constant have a preferred abstraction pattern set?

lib/SIL/IR/SILTypeSubstitution.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ class SILTypeSubstituter :
7575
Type conformingReplacementType,
7676
ProtocolDecl *conformedProtocol) -> ProtocolConformanceRef {
7777
return substOpaqueTypesWithUnderlyingTypes(
78-
ProtocolConformanceRef(conformedProtocol),
78+
ProtocolConformanceRef::forAbstract(conformingReplacementType,
79+
conformedProtocol),
7980
conformingReplacementType->getCanonicalType(),
8081
typeExpansionContext);
8182
},

lib/SILGen/SILGenLValue.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,8 @@ namespace {
10881088

10891089
SmallVector<ProtocolConformanceRef, 2> conformances;
10901090
for (auto proto : OpenedArchetype->getConformsTo())
1091-
conformances.push_back(ProtocolConformanceRef(proto));
1091+
conformances.push_back(ProtocolConformanceRef::forAbstract(
1092+
OpenedArchetype, proto));
10921093

10931094
SILValue ref;
10941095
if (base.getType().is<ExistentialMetatypeType>()) {

lib/SILGen/SILGenType.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,11 +903,12 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM,
903903
// Open the protocol type.
904904
auto openedType = OpenedArchetypeType::get(
905905
protocol->getDeclaredExistentialType()->getCanonicalType());
906+
auto openedConf = ProtocolConformanceRef::forAbstract(openedType, protocol);
906907

907908
// Form the substitutions for calling the witness.
908909
auto witnessSubs = SubstitutionMap::getProtocolSubstitutions(protocol,
909910
openedType,
910-
ProtocolConformanceRef(protocol));
911+
openedConf);
911912

912913
// Substitute to get the formal substituted type of the thunk.
913914
auto reqtSubstTy =
@@ -1057,8 +1058,10 @@ class SILGenDefaultWitnessTable
10571058
SILDeclRef witnessRef,
10581059
IsFreeFunctionWitness_t isFree,
10591060
Witness witness) {
1061+
auto Conf = ProtocolConformanceRef::forAbstract(
1062+
Proto->getSelfInterfaceType()->getCanonicalType(), Proto);
10601063
SILFunction *witnessFn = SGM.emitProtocolWitness(
1061-
ProtocolConformanceRef(Proto), SILLinkage::Private, IsNotSerialized,
1064+
Conf, SILLinkage::Private, IsNotSerialized,
10621065
requirementRef, witnessRef, isFree, witness);
10631066
auto entry = SILWitnessTable::MethodWitness{requirementRef, witnessFn};
10641067
DefaultWitnesses.push_back(entry);

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
11831183
// base type of the existential's requirements.
11841184
return CEI.lookupExistentialConformance(proto);
11851185
}
1186-
return ProtocolConformanceRef(proto);
1186+
return ProtocolConformanceRef::forAbstract(substTy, proto);
11871187
}, SubstFlags::SubstituteLocalArchetypes);
11881188
continue;
11891189
}
@@ -1221,7 +1221,7 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
12211221
// base type of the existential's requirements.
12221222
return CEI.lookupExistentialConformance(proto);
12231223
}
1224-
return ProtocolConformanceRef(proto);
1224+
return ProtocolConformanceRef::forAbstract(substTy, proto);
12251225
}, SubstFlags::SubstituteLocalArchetypes);
12261226
}
12271227

lib/Sema/CSApply.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
121121
auto lookupConformanceFn =
122122
[&](CanType original, Type replacement,
123123
ProtocolDecl *protoType) -> ProtocolConformanceRef {
124+
assert(!replacement->is<GenericTypeParamType>());
125+
124126
if (replacement->hasError() ||
125127
isOpenedAnyObject(replacement) ||
126128
replacement->is<GenericTypeParamType>()) {
127-
return ProtocolConformanceRef(protoType);
129+
return ProtocolConformanceRef::forAbstract(replacement, protoType);
128130
}
129131

130132
// FIXME: Retrieve the conformance from the solution itself.
@@ -133,8 +135,10 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
133135

134136
if (conformance.isInvalid()) {
135137
auto synthesized = SynthesizedConformances.find(locator);
136-
if (synthesized != SynthesizedConformances.end())
137-
return synthesized->second;
138+
if (synthesized != SynthesizedConformances.end()) {
139+
return ProtocolConformanceRef::forAbstract(
140+
replacement, synthesized->second);
141+
}
138142
}
139143

140144
return conformance;

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8499,11 +8499,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
84998499
// dynamically during IRGen.
85008500
if (auto *witness = dyn_cast<FuncDecl>(witnessInfo->first)) {
85018501
auto synthesizeConformance = [&]() {
8502-
ProtocolConformanceRef synthesized(protocol);
85038502
auto witnessLoc = getConstraintLocator(
85048503
locator.getAnchor(), LocatorPathElt::Witness(witness));
8505-
SynthesizedConformances.insert({witnessLoc, synthesized});
8506-
return recordConformance(synthesized);
8504+
SynthesizedConformances.insert({witnessLoc, protocol});
8505+
return SolutionKind::Solved;
85078506
};
85088507

85098508
if (witness->isGeneric()) {

0 commit comments

Comments
 (0)