Skip to content

Commit 1ed46b4

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.
1 parent 4b3c821 commit 1ed46b4

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
@@ -389,6 +389,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
389389
auto &tc = getTypeChecker();
390390
bool hasNonDependentMemberRelationalConstraints = false;
391391
bool hasDependentMemberRelationalConstraints = false;
392+
bool sawNilLiteral = false;
392393
for (auto constraint : constraints) {
393394
switch (constraint->getKind()) {
394395
case ConstraintKind::Bind:
@@ -505,8 +506,10 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
505506
// If there is a 'nil' literal constraint, we might need optional
506507
// supertype bindings.
507508
if (constraint->getProtocol()->isSpecificProtocol(
508-
KnownProtocolKind::ExpressibleByNilLiteral))
509+
KnownProtocolKind::ExpressibleByNilLiteral)) {
510+
sawNilLiteral = true;
509511
addOptionalSupertypeBindings = true;
512+
}
510513

511514
// If there is a default literal type for this protocol, it's a
512515
// potential binding.
@@ -745,6 +748,32 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
745748
result.Bindings.clear();
746749
}
747750

751+
// Revise any optional-of-function-types we may try to nil literals
752+
// to be non-throwing so they don't inadvertantly result in rethrows
753+
// diagnostics.
754+
if (sawNilLiteral) {
755+
for (auto &binding : result.Bindings) {
756+
auto nested = binding.BindingType->lookThroughAllOptionalTypes();
757+
if (!nested)
758+
continue;
759+
760+
if (!nested->is<FunctionType>())
761+
continue;
762+
763+
// Remove throws from the nested function type.
764+
binding.BindingType =
765+
binding.BindingType.transform([&](Type inner) -> Type {
766+
auto *fnTy = dyn_cast<FunctionType>(inner.getPointer());
767+
if (!fnTy)
768+
return inner;
769+
770+
auto extInfo = fnTy->getExtInfo().withThrows(false);
771+
return FunctionType::get(fnTy->getParams(), fnTy->getResult(),
772+
extInfo);
773+
});
774+
}
775+
}
776+
748777
return result;
749778
}
750779

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)