mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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`.
This commit is contained in:
@@ -677,16 +677,6 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
|
||||
if (!typeVar || !genericParam)
|
||||
return std::nullopt;
|
||||
|
||||
// Only allow opening the innermost generic parameters.
|
||||
auto genericContext = callee->getAsGenericContext();
|
||||
if (!genericContext || !genericContext->isGeneric())
|
||||
return std::nullopt;
|
||||
|
||||
auto genericSig = callee->getInnermostDeclContext()
|
||||
->getGenericSignatureOfContext().getCanonicalSignature();
|
||||
if (genericParam->getDepth() < genericSig->getMaxDepth())
|
||||
return std::nullopt;
|
||||
|
||||
// The binding could be an existential metatype. Get the instance type for
|
||||
// conformance checks and to build an opened existential signature. If the
|
||||
// instance type is not an existential type, i.e., the metatype is nested,
|
||||
@@ -695,6 +685,28 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
|
||||
if (!existentialTy->isExistentialType())
|
||||
return std::nullopt;
|
||||
|
||||
if (!canOpenExistentialAt(callee, paramIdx, genericParam, existentialTy))
|
||||
return std::nullopt;
|
||||
|
||||
return std::pair(typeVar, bindingTy);
|
||||
}
|
||||
|
||||
bool swift::canOpenExistentialAt(ValueDecl *callee, unsigned paramIdx,
|
||||
GenericTypeParamType *genericParam,
|
||||
Type existentialTy) {
|
||||
ASSERT(existentialTy->isExistentialType());
|
||||
|
||||
// Only allow opening the innermost generic parameters.
|
||||
auto genericContext = callee->getAsGenericContext();
|
||||
if (!genericContext || !genericContext->isGeneric())
|
||||
return false;
|
||||
|
||||
auto genericSig = callee->getInnermostDeclContext()
|
||||
->getGenericSignatureOfContext()
|
||||
.getCanonicalSignature();
|
||||
if (genericParam->getDepth() < genericSig->getMaxDepth())
|
||||
return false;
|
||||
|
||||
auto &ctx = callee->getASTContext();
|
||||
|
||||
// If the existential argument conforms to all of protocol requirements on
|
||||
@@ -715,7 +727,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
|
||||
}
|
||||
|
||||
if (!containsNonSelfConformance)
|
||||
return std::nullopt;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto existentialSig = ctx.getOpenedExistentialSignature(existentialTy);
|
||||
@@ -726,10 +738,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
|
||||
callee, existentialSig.OpenedSig, genericParam,
|
||||
existentialSig.SelfType->castTo<GenericTypeParamType>(),
|
||||
/*skipParamIdx=*/paramIdx);
|
||||
if (referenceInfo.hasNonCovariantRef())
|
||||
return std::nullopt;
|
||||
|
||||
return std::pair(typeVar, bindingTy);
|
||||
return !referenceInfo.hasNonCovariantRef();
|
||||
}
|
||||
|
||||
/// For each occurrence of a type **type** in `refTy` that satisfies
|
||||
|
||||
@@ -150,6 +150,13 @@ std::optional<std::pair<TypeVariableType *, Type>>
|
||||
canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
|
||||
Type paramTy, Type argTy);
|
||||
|
||||
/// A limited form of the check performed by \c canOpenExistentialCallArgument
|
||||
/// that assumes that a declaration where parameter came from, the parameter
|
||||
/// itself, and the types involved have been validated already.
|
||||
bool canOpenExistentialAt(ValueDecl *callee, unsigned paramIdx,
|
||||
GenericTypeParamType *genericParam,
|
||||
Type existentialTy);
|
||||
|
||||
/// Given a type that includes an existential type that has been opened to
|
||||
/// the given type variable, replace the opened type variable and its member
|
||||
/// types with their upper bounds.
|
||||
|
||||
Reference in New Issue
Block a user