Skip to content

Commit e46c5cb

Browse files
committed
[ConstraintSystem] Do not infer 'nil' arguments as optional throwing function types.
I have a follow-up change to correctly classify optional arguments, and with that fix applied we incorrectly emit rethrow diagnostics for 'nil' arguments passed in places where optional throwing functions are expected. This change ensures that we strip the throwing bit off of the nested function type so that we don't consider 'nil' arguments in these positions as potentially throwing functions. (cherry picked from commit 1ed46b4)
1 parent 7f14ddb commit e46c5cb

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
365365
auto &tc = getTypeChecker();
366366
bool hasNonDependentMemberRelationalConstraints = false;
367367
bool hasDependentMemberRelationalConstraints = false;
368+
bool sawNilLiteral = false;
368369
for (auto constraint : constraints) {
369370
switch (constraint->getKind()) {
370371
case ConstraintKind::Bind:
@@ -481,8 +482,10 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
481482
// If there is a 'nil' literal constraint, we might need optional
482483
// supertype bindings.
483484
if (constraint->getProtocol()->isSpecificProtocol(
484-
KnownProtocolKind::ExpressibleByNilLiteral))
485+
KnownProtocolKind::ExpressibleByNilLiteral)) {
486+
sawNilLiteral = true;
485487
addOptionalSupertypeBindings = true;
488+
}
486489

487490
// If there is a default literal type for this protocol, it's a
488491
// potential binding.
@@ -721,6 +724,32 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
721724
result.Bindings.clear();
722725
}
723726

727+
// Revise any optional-of-function-types we may try to nil literals
728+
// to be non-throwing so they don't inadvertantly result in rethrows
729+
// diagnostics.
730+
if (sawNilLiteral) {
731+
for (auto &binding : result.Bindings) {
732+
auto nested = binding.BindingType->lookThroughAllOptionalTypes();
733+
if (!nested)
734+
continue;
735+
736+
if (!nested->is<FunctionType>())
737+
continue;
738+
739+
// Remove throws from the nested function type.
740+
binding.BindingType =
741+
binding.BindingType.transform([&](Type inner) -> Type {
742+
auto *fnTy = dyn_cast<FunctionType>(inner.getPointer());
743+
if (!fnTy)
744+
return inner;
745+
746+
auto extInfo = fnTy->getExtInfo().withThrows(false);
747+
return FunctionType::get(fnTy->getParams(), fnTy->getResult(),
748+
extInfo);
749+
});
750+
}
751+
}
752+
724753
return result;
725754
}
726755

lib/Sema/TypeCheckError.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ class AbstractFunction {
146146
// Look through closure capture lists.
147147
} else if (auto captureList = dyn_cast<CaptureListExpr>(fn)) {
148148
fn = captureList->getClosureBody();
149+
// Look through optional evaluations.
150+
} else if (auto optionalEval = dyn_cast<OptionalEvaluationExpr>(fn)) {
151+
fn = optionalEval->getSubExpr()->getValueProvidingExpr();
149152
} else {
150153
break;
151154
}

0 commit comments

Comments
 (0)