Skip to content

Commit 54a3d41

Browse files
authored
Merge pull request #8980 from apple/rethrow-single-arg-func-4.0
[Type checker] Handle 'rethrows' checks for single-parameter functions.
2 parents aa14bb4 + 68e6abf commit 54a3d41

File tree

3 files changed

+41
-21
lines changed

3 files changed

+41
-21
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+
}

unittests/runtime/Metadata.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -443,16 +443,19 @@ TEST(MetadataTest, getExistentialMetadata) {
443443
});
444444

445445
// protocol compositions are order-invariant
446-
const ProtocolDescriptor *protoList4[] = {
447-
&ProtocolA,
448-
&ProtocolB
449-
};
450-
const ProtocolDescriptor *protoList5[] = {
451-
&ProtocolB,
452-
&ProtocolA
453-
};
454446
RaceTest_ExpectEqual<const ExistentialTypeMetadata *>(
455447
[&]() -> const ExistentialTypeMetadata * {
448+
449+
const ProtocolDescriptor *protoList4[] = {
450+
&ProtocolA,
451+
&ProtocolB
452+
};
453+
454+
const ProtocolDescriptor *protoList5[] = {
455+
&ProtocolB,
456+
&ProtocolA
457+
};
458+
456459
auto ab = swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
457460
/*superclass=*/nullptr,
458461
2, protoList4);
@@ -514,13 +517,14 @@ TEST(MetadataTest, getExistentialMetadata) {
514517
return noWitnessTable;
515518
});
516519

517-
const ProtocolDescriptor *protoList8[] = {
518-
&ProtocolNoWitnessTable,
519-
&ProtocolA,
520-
&ProtocolB
521-
};
522520
RaceTest_ExpectEqual<const ExistentialTypeMetadata *>(
523521
[&]() -> const ExistentialTypeMetadata * {
522+
const ProtocolDescriptor *protoList8[] = {
523+
&ProtocolNoWitnessTable,
524+
&ProtocolA,
525+
&ProtocolB
526+
};
527+
524528
auto mixedWitnessTable
525529
= swift_getExistentialTypeMetadata(ProtocolClassConstraint::Class,
526530
/*superclass=*/nullptr,
@@ -560,12 +564,13 @@ TEST(MetadataTest, getExistentialMetadata) {
560564
return special;
561565
});
562566

563-
const ProtocolDescriptor *protoList10[] = {
564-
&ProtocolError,
565-
&ProtocolA
566-
};
567567
RaceTest_ExpectEqual<const ExistentialTypeMetadata *>(
568568
[&]() -> const ExistentialTypeMetadata * {
569+
const ProtocolDescriptor *protoList10[] = {
570+
&ProtocolError,
571+
&ProtocolA
572+
};
573+
569574
auto special
570575
= swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
571576
/*superclass=*/nullptr,

0 commit comments

Comments
 (0)