Skip to content

Commit 90224bf

Browse files
committed
[Typechecker/OpenedExistentials] NFC: Extract some checks from canOpenExistentialCallArgument into a separate function
Some of the logic of `canOpenExistentialCallArgument` has to be shared with constraint optimizer which does it's own validation and most importantly - doesn't open overload choice type. In order to share the logic between the solver and the optimizer, let's extract checking that determines whether it's possible to open existential argument into `canOpenExistentialAt`.
1 parent 030564b commit 90224bf

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

lib/Sema/OpenedExistentials.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -677,16 +677,6 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
677677
if (!typeVar || !genericParam)
678678
return std::nullopt;
679679

680-
// Only allow opening the innermost generic parameters.
681-
auto genericContext = callee->getAsGenericContext();
682-
if (!genericContext || !genericContext->isGeneric())
683-
return std::nullopt;
684-
685-
auto genericSig = callee->getInnermostDeclContext()
686-
->getGenericSignatureOfContext().getCanonicalSignature();
687-
if (genericParam->getDepth() < genericSig->getMaxDepth())
688-
return std::nullopt;
689-
690680
// The binding could be an existential metatype. Get the instance type for
691681
// conformance checks and to build an opened existential signature. If the
692682
// instance type is not an existential type, i.e., the metatype is nested,
@@ -695,6 +685,28 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
695685
if (!existentialTy->isExistentialType())
696686
return std::nullopt;
697687

688+
if (!canOpenExistentialAt(callee, paramIdx, genericParam, existentialTy))
689+
return std::nullopt;
690+
691+
return std::pair(typeVar, bindingTy);
692+
}
693+
694+
bool swift::canOpenExistentialAt(ValueDecl *callee, unsigned paramIdx,
695+
GenericTypeParamType *genericParam,
696+
Type existentialTy) {
697+
ASSERT(existentialTy->isExistentialType());
698+
699+
// Only allow opening the innermost generic parameters.
700+
auto genericContext = callee->getAsGenericContext();
701+
if (!genericContext || !genericContext->isGeneric())
702+
return false;
703+
704+
auto genericSig = callee->getInnermostDeclContext()
705+
->getGenericSignatureOfContext()
706+
.getCanonicalSignature();
707+
if (genericParam->getDepth() < genericSig->getMaxDepth())
708+
return false;
709+
698710
auto &ctx = callee->getASTContext();
699711

700712
// If the existential argument conforms to all of protocol requirements on
@@ -715,7 +727,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
715727
}
716728

717729
if (!containsNonSelfConformance)
718-
return std::nullopt;
730+
return false;
719731
}
720732

721733
auto existentialSig = ctx.getOpenedExistentialSignature(existentialTy);
@@ -726,10 +738,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
726738
callee, existentialSig.OpenedSig, genericParam,
727739
existentialSig.SelfType->castTo<GenericTypeParamType>(),
728740
/*skipParamIdx=*/paramIdx);
729-
if (referenceInfo.hasNonCovariantRef())
730-
return std::nullopt;
731-
732-
return std::pair(typeVar, bindingTy);
741+
return !referenceInfo.hasNonCovariantRef();
733742
}
734743

735744
/// For each occurrence of a type **type** in `refTy` that satisfies

lib/Sema/OpenedExistentials.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ std::optional<std::pair<TypeVariableType *, Type>>
150150
canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
151151
Type paramTy, Type argTy);
152152

153+
/// A limited form of the check performed by \c canOpenExistentialCallArgument
154+
/// that assumes that a declaration where parameter came from, the parameter
155+
/// itself, and the types involved have been validated already.
156+
bool canOpenExistentialAt(ValueDecl *callee, unsigned paramIdx,
157+
GenericTypeParamType *genericParam,
158+
Type existentialTy);
159+
153160
/// Given a type that includes an existential type that has been opened to
154161
/// the given type variable, replace the opened type variable and its member
155162
/// types with their upper bounds.

0 commit comments

Comments
 (0)