Skip to content

Commit 4eccbe1

Browse files
committed
[NFC] combine collectExistentialConformances
There are a bunch of static `collectExistentialConformances` copied around Sema and SILGen that are almost the same, save for whether they want to permit missing conformances and/or check conditional conformances. This commit requestifies and combines all but one of these functions into a `ModuleDecl::collectExistentialConformances`. The motivation for this clean-up is another place that will need this procedure.
1 parent bb78171 commit 4eccbe1

File tree

8 files changed

+104
-64
lines changed

8 files changed

+104
-64
lines changed

include/swift/AST/Module.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,13 @@ class ModuleDecl
853853
ProtocolConformanceRef conformsToProtocol(Type sourceTy,
854854
ProtocolDecl *targetProtocol);
855855

856+
/// Collect the conformances of \c fromType each of the protocols of an
857+
/// existential type's layout.
858+
ArrayRef<ProtocolConformanceRef>
859+
collectExistentialConformances(CanType fromType, CanType existential,
860+
bool skipConditionalRequirements = true,
861+
bool allowMissing = false);
862+
856863
/// Find a member named \p name in \p container that was declared in this
857864
/// module.
858865
///

include/swift/AST/TypeCheckRequests.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,34 @@ class ExistentialConformsToSelfRequest :
323323
void cacheResult(bool value) const;
324324
};
325325

326+
class CollectExistentialConformancesRequest
327+
: public SimpleRequest<CollectExistentialConformancesRequest,
328+
ArrayRef<ProtocolConformanceRef>(ModuleDecl*,
329+
CanType,
330+
CanType,
331+
bool,
332+
bool),
333+
RequestFlags::Uncached> { // TODO: maybe cache this?
334+
public:
335+
using SimpleRequest::SimpleRequest;
336+
337+
private:
338+
friend SimpleRequest;
339+
340+
// Evaluation.
341+
ArrayRef<ProtocolConformanceRef>
342+
evaluate(Evaluator &evaluator,
343+
ModuleDecl *module,
344+
CanType fromType,
345+
CanType existential,
346+
bool skipConditionalRequirements,
347+
bool allowMissing) const;
348+
349+
public:
350+
// Caching.
351+
bool isCached() const { return true; }
352+
};
353+
326354
/// Determine whether an existential type conforming to this protocol
327355
/// requires the \c any syntax.
328356
class HasSelfOrAssociatedTypeRequirementsRequest :

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
100100
Type(EnumDecl *), Cached, NoLocationInfo)
101101
SWIFT_REQUEST(TypeChecker, ExistentialConformsToSelfRequest,
102102
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
103+
SWIFT_REQUEST(TypeChecker, CollectExistentialConformancesRequest,
104+
ArrayRef<ProtocolConformanceRef>(ModuleDecl*,
105+
CanType,
106+
CanType,
107+
bool,
108+
bool),
109+
Uncached, NoLocationInfo)
103110
SWIFT_REQUEST(TypeChecker, HasSelfOrAssociatedTypeRequirementsRequest,
104111
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
105112
SWIFT_REQUEST(TypeChecker, ExtendedTypeRequest, Type(ExtensionDecl *), Cached,

lib/AST/Module.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,19 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results, bool Recursive
15681568
#endif
15691569
}
15701570

1571+
ArrayRef<ProtocolConformanceRef>
1572+
ModuleDecl::collectExistentialConformances(CanType fromType,
1573+
CanType existential,
1574+
bool skipConditionalRequirements,
1575+
bool allowMissing) {
1576+
CollectExistentialConformancesRequest request{this,
1577+
fromType,
1578+
existential,
1579+
skipConditionalRequirements,
1580+
allowMissing};
1581+
return evaluateOrDefault(getASTContext().evaluator, request, /*default=*/{});
1582+
}
1583+
15711584
ProtocolConformanceRef
15721585
ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
15731586
ASTContext &ctx = getASTContext();

lib/SILGen/SILGenPoly.cpp

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -240,25 +240,6 @@ namespace {
240240
};
241241
} // end anonymous namespace
242242

243-
244-
static ArrayRef<ProtocolConformanceRef>
245-
collectExistentialConformances(ModuleDecl *M, CanType fromType, CanType toType) {
246-
assert(!fromType.isAnyExistentialType());
247-
248-
auto layout = toType.getExistentialLayout();
249-
auto protocols = layout.getProtocols();
250-
251-
SmallVector<ProtocolConformanceRef, 4> conformances;
252-
for (auto proto : protocols) {
253-
auto conformance =
254-
M->lookupConformance(fromType, proto, /*allowMissing=*/true);
255-
assert(conformance);
256-
conformances.push_back(conformance);
257-
}
258-
259-
return M->getASTContext().AllocateCopy(conformances);
260-
}
261-
262243
static ManagedValue emitTransformExistential(SILGenFunction &SGF,
263244
SILLocation loc,
264245
ManagedValue input,
@@ -292,10 +273,13 @@ static ManagedValue emitTransformExistential(SILGenFunction &SGF,
292273
->getExistentialInstanceType()->getCanonicalType();
293274
}
294275

276+
assert(!fromInstanceType.isAnyExistentialType());
295277
ArrayRef<ProtocolConformanceRef> conformances =
296-
collectExistentialConformances(SGF.SGM.M.getSwiftModule(),
278+
SGF.SGM.M.getSwiftModule()->collectExistentialConformances(
297279
fromInstanceType,
298-
toInstanceType);
280+
toInstanceType,
281+
/*skipConditionalRequirements=*/true,
282+
/*allowMissing=*/true);
299283

300284
// Build result existential
301285
AbstractionPattern opaque = AbstractionPattern::getOpaque();

lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -111,25 +111,6 @@ void ExistentialSpecializerCloner::cloneAndPopulateFunction() {
111111
}
112112
}
113113

114-
// Gather the conformances needed for an existential value based on an opened
115-
// archetype. This adds any conformances inherited from superclass constraints.
116-
static ArrayRef<ProtocolConformanceRef>
117-
collectExistentialConformances(ModuleDecl *M, CanType openedType,
118-
CanType existentialType) {
119-
assert(!openedType.isAnyExistentialType());
120-
121-
auto layout = existentialType.getExistentialLayout();
122-
auto protocols = layout.getProtocols();
123-
124-
SmallVector<ProtocolConformanceRef, 4> conformances;
125-
for (auto proto : protocols) {
126-
auto conformance = M->lookupConformance(openedType, proto);
127-
assert(conformance);
128-
conformances.push_back(conformance);
129-
}
130-
return M->getASTContext().AllocateCopy(conformances);
131-
}
132-
133114
// Create the entry basic block with the function arguments.
134115
void ExistentialSpecializerCloner::cloneArguments(
135116
SmallVectorImpl<SILValue> &entryArgs) {
@@ -180,11 +161,17 @@ void ExistentialSpecializerCloner::cloneArguments(
180161
ValueOwnershipKind(NewF, GenericSILType,
181162
ArgDesc.Arg->getArgumentConvention()));
182163
NewArg->copyFlags(ArgDesc.Arg);
183-
// Determine the Conformances.
164+
165+
// Gather the conformances needed for an existential value based on an
166+
// opened archetype. This adds any conformances inherited from superclass
167+
// constraints.
184168
SILType ExistentialType = ArgDesc.Arg->getType().getObjectType();
185169
CanType OpenedType = NewArg->getType().getASTType();
186-
auto Conformances = collectExistentialConformances(
187-
M.getSwiftModule(), OpenedType, ExistentialType.getASTType());
170+
assert(!OpenedType.isAnyExistentialType());
171+
auto Conformances = M.getSwiftModule()->collectExistentialConformances(
172+
OpenedType,
173+
ExistentialType.getASTType());
174+
188175
auto ExistentialRepr =
189176
ArgDesc.Arg->getType().getPreferredExistentialRepresentation();
190177
auto &EAD = ExistentialArgDescriptor[ArgDesc.Index];

lib/Sema/CSApply.cpp

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5721,25 +5721,6 @@ Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) {
57215721
new (ctx) DerivedToBaseExpr(expr, toType));
57225722
}
57235723

5724-
/// Collect the conformances for all the protocols of an existential type.
5725-
/// If the source type is also existential, we don't want to check conformance
5726-
/// because most protocols do not conform to themselves -- however we still
5727-
/// allow the conversion here, except the ErasureExpr ends up with trivial
5728-
/// conformances.
5729-
static ArrayRef<ProtocolConformanceRef>
5730-
collectExistentialConformances(Type fromType, Type toType,
5731-
ModuleDecl *module) {
5732-
auto layout = toType->getExistentialLayout();
5733-
5734-
SmallVector<ProtocolConformanceRef, 4> conformances;
5735-
for (auto proto : layout.getProtocols()) {
5736-
conformances.push_back(TypeChecker::containsProtocol(
5737-
fromType, proto, module, false, /*allowMissing=*/true));
5738-
}
5739-
5740-
return toType->getASTContext().AllocateCopy(conformances);
5741-
}
5742-
57435724
/// Given that the given expression is an implicit conversion added
57445725
/// to the target by coerceToType, find out how many OptionalEvaluationExprs
57455726
/// it includes and the target.
@@ -6729,9 +6710,17 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType,
67296710

67306711
ASTContext &ctx = cs.getASTContext();
67316712

6713+
/// Collect the conformances for all the protocols of an existential type.
6714+
/// If the source type is also existential, we don't want to check conformance
6715+
/// because most protocols do not conform to themselves -- however we still
6716+
/// allow the conversion here, except the ErasureExpr ends up with trivial
6717+
/// conformances.
67326718
auto conformances =
6733-
collectExistentialConformances(fromInstanceType, toInstanceType,
6734-
dc->getParentModule());
6719+
dc->getParentModule()
6720+
->collectExistentialConformances(fromInstanceType->getCanonicalType(),
6721+
toInstanceType->getCanonicalType(),
6722+
/*skipConditionalRequirements=*/false,
6723+
/*allowMissing=*/true);
67356724

67366725
// Use the requirements of any parameterized protocols to build out fake
67376726
// argument conversions that can be used to infer opaque types.

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,31 @@ Type ResultBuilderTypeRequest::evaluate(Evaluator &evaluator,
414414
return type->mapTypeOutOfContext();
415415
}
416416

417+
ArrayRef<ProtocolConformanceRef>
418+
CollectExistentialConformancesRequest::evaluate(Evaluator &evaluator,
419+
ModuleDecl *module,
420+
CanType fromType,
421+
CanType existential,
422+
bool skipConditionalRequirements,
423+
bool allowMissing) const {
424+
assert(existential.isAnyExistentialType());
425+
426+
auto layout = existential.getExistentialLayout();
427+
auto protocols = layout.getProtocols();
428+
429+
SmallVector<ProtocolConformanceRef, 4> conformances;
430+
for (auto *proto : protocols) {
431+
auto conformance =
432+
TypeChecker::containsProtocol(
433+
fromType, proto, module,
434+
skipConditionalRequirements, allowMissing);
435+
assert(conformance);
436+
conformances.push_back(conformance);
437+
}
438+
439+
return module->getASTContext().AllocateCopy(conformances);
440+
}
441+
417442
// Define request evaluation functions for each of the type checker requests.
418443
static AbstractRequestFunction *typeCheckerRequestFunctions[] = {
419444
#define SWIFT_REQUEST(Zone, Name, Sig, Caching, LocOptions) \

0 commit comments

Comments
 (0)