Skip to content

Commit 88eac85

Browse files
committed
[Type checker] Handle 'rethrows' checks for single-parameter functions.
The throw-checking code wasn't properly coping with functions that take a single, labeled argument, due to the longstanding lie that pretends that functions take a tuple argument vs. zero or more separate arguments. Here, the lie manifests as spurious "call can throw, but is not marked as such" errors. Fixes rdar://problem/31794932. (cherry picked from commit b07d995)
1 parent aa14bb4 commit 88eac85

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

lib/Sema/TypeCheckError.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ class ApplyClassifier {
405405
// But if the expression didn't type-check, suppress diagnostics.
406406
if (!E->getType() || E->getType()->hasError())
407407
return Classification::forInvalidCode();
408+
408409
auto type = E->getFn()->getType();
409410
if (!type) return Classification::forInvalidCode();
410411
auto fnType = type->getAs<AnyFunctionType>();
@@ -673,11 +674,18 @@ class ApplyClassifier {
673674
return classifyShuffleRethrowsArgument(shuffle, paramTupleType);
674675
}
675676

676-
// Otherwise, we're passing an opaque tuple expression, and we
677-
// should treat it as contributing to 'rethrows' if the original
678-
// parameter type included a throwing function type.
679-
return classifyArgumentByType(paramType,
677+
int scalarElt = paramTupleType->getElementForScalarInit();
678+
if (scalarElt < 0 ||
679+
!paramTupleType->getElementType(scalarElt)->isEqual(arg->getType())) {
680+
// Otherwise, we're passing an opaque tuple expression, and we
681+
// should treat it as contributing to 'rethrows' if the original
682+
// parameter type included a throwing function type.
683+
return classifyArgumentByType(
684+
paramType,
680685
PotentialReason::forRethrowsArgument(arg));
686+
}
687+
688+
paramType = paramTupleType->getElementType(scalarElt);
681689
}
682690

683691
// Otherwise, if the original parameter type was not a throwing

test/decl/func/rethrows.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,3 +476,10 @@ func throwWhileGettingFoo() throws -> Foo.Type { return Foo.self }
476476

477477
(throwWhileGettingFoo()).foo(Foo())() // expected-error {{can throw}}
478478
(try throwWhileGettingFoo()).foo(Foo())()
479+
480+
// <rdar://problem/31794932> [Source compatibility] Call to sort(by):) can throw, but is not marked with 'try'
481+
func doRethrow(fn: (Int, Int) throws -> Int) rethrows { }
482+
483+
func testDoRethrow() {
484+
doRethrow(fn:) { (a, b) in return a }
485+
}

0 commit comments

Comments
 (0)