Skip to content

Commit 5306170

Browse files
committed
[TypeChecker] Classify nil literal and .none as non-contriburing to throws
Original fix for SR-9102 stripped throws bit from the function types nested inside optionals before attempting bindings, that doesn't work with e.g. default parameter values because conversions from throwing and non-throwing functions are only allowed in subtype relationship but function types nested inside optionals are going to be equated. So this patch takes an alternative approach and attempts to pattern match `nil` literal and `.none` use and classify argument as non-contributing to throws. Resolves: rdar://problem/47550715 (cherry picked from commit 43670cb)
1 parent daac347 commit 5306170

File tree

3 files changed

+20
-29
lines changed

3 files changed

+20
-29
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
365365
auto &tc = getTypeChecker();
366366
bool hasNonDependentMemberRelationalConstraints = false;
367367
bool hasDependentMemberRelationalConstraints = false;
368-
bool sawNilLiteral = false;
369368
for (auto constraint : constraints) {
370369
switch (constraint->getKind()) {
371370
case ConstraintKind::Bind:
@@ -483,7 +482,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
483482
// supertype bindings.
484483
if (constraint->getProtocol()->isSpecificProtocol(
485484
KnownProtocolKind::ExpressibleByNilLiteral)) {
486-
sawNilLiteral = true;
487485
addOptionalSupertypeBindings = true;
488486
}
489487

@@ -724,32 +722,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
724722
result.Bindings.clear();
725723
}
726724

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-
753725
return result;
754726
}
755727

lib/Sema/TypeCheckError.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,16 @@ class ApplyClassifier {
679679
Classification classifyRethrowsArgument(Expr *arg, Type paramType) {
680680
arg = arg->getValueProvidingExpr();
681681

682+
// If this argument is `nil` literal or `.none`,
683+
// it doesn't cause the call to throw.
684+
if (auto *DSCE = dyn_cast<DotSyntaxCallExpr>(arg)) {
685+
if (auto *DE = dyn_cast<DeclRefExpr>(DSCE->getFn())) {
686+
auto &ctx = paramType->getASTContext();
687+
if (DE->getDecl() == ctx.getOptionalNoneDecl())
688+
return Classification();
689+
}
690+
}
691+
682692
// If the parameter was structurally a tuple, try to look through the
683693
// various tuple operations.
684694
if (auto paramTupleType = dyn_cast<TupleType>(paramType.getPointer())) {

test/decl/func/rethrows.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,4 +602,13 @@ class RethrowingConstructor {
602602
try throwingFunc()
603603
}
604604
}
605-
}
605+
}
606+
607+
// default values -vs- throwing function inside optional
608+
func rdar_47550715() {
609+
typealias A<T> = (T) -> Void
610+
typealias F = () throws -> Void
611+
612+
func foo(_: A<F>? = nil) {} // Ok
613+
func bar(_: A<F>? = .none) {} // Ok
614+
}

0 commit comments

Comments
 (0)