Skip to content

Commit 43670cb

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
1 parent dbfc430 commit 43670cb

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
@@ -389,7 +389,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
389389
auto &tc = getTypeChecker();
390390
bool hasNonDependentMemberRelationalConstraints = false;
391391
bool hasDependentMemberRelationalConstraints = false;
392-
bool sawNilLiteral = false;
393392
for (auto constraint : constraints) {
394393
switch (constraint->getKind()) {
395394
case ConstraintKind::Bind:
@@ -507,7 +506,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
507506
// supertype bindings.
508507
if (constraint->getProtocol()->isSpecificProtocol(
509508
KnownProtocolKind::ExpressibleByNilLiteral)) {
510-
sawNilLiteral = true;
511509
addOptionalSupertypeBindings = true;
512510
}
513511

@@ -748,32 +746,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
748746
result.Bindings.clear();
749747
}
750748

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-
777749
return result;
778750
}
779751

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)