Skip to content

Commit 31f2c83

Browse files
committed
Sema: Fix inconsistent rethrows conformance checking with 'self' parameter
1 parent 0466c4e commit 31f2c83

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,28 @@ FunctionRethrowingKindRequest::evaluate(Evaluator &evaluator,
169169
return FunctionRethrowingKind::ByConformance;
170170
}
171171
if (markedRethrows) {
172-
GenericSignature genericSig = decl->getGenericSignature();
173-
FunctionRethrowingKind kind = getParameterThrowingKind(decl, genericSig);
174-
// since we have checked all arguments, if we still havent found anything
175-
// check the self parameter
176-
if (kind == FunctionRethrowingKind::Invalid &&
177-
decl->hasImplicitSelfDecl()) {
178-
auto selfParam = decl->getImplicitSelfDecl();
179-
if (selfParam) {
180-
auto interfaceTy = selfParam->getInterfaceType();
181-
kind = getTypeThrowingKind(interfaceTy, genericSig);
172+
if (auto genericSig = decl->getGenericSignature()) {
173+
for (auto req : genericSig->getRequirements()) {
174+
if (req.getKind() == RequirementKind::Conformance) {
175+
if (req.getSecondType()->castTo<ProtocolType>()
176+
->getDecl()
177+
->isRethrowingProtocol()) {
178+
return FunctionRethrowingKind::ByConformance;
179+
}
180+
}
182181
}
183182
}
184-
return kind;
183+
184+
for (auto param : *decl->getParameters()) {
185+
auto interfaceTy = param->getInterfaceType();
186+
if (hasThrowingFunctionClosureParameter(interfaceTy
187+
->lookThroughAllOptionalTypes()
188+
->getCanonicalType())) {
189+
return FunctionRethrowingKind::ByClosure;
190+
}
191+
}
192+
193+
return FunctionRethrowingKind::Invalid;
185194
}
186195
return FunctionRethrowingKind::Throws;
187196
}

test/attr/attr_rethrows_protocol.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ struct InvalidRethrows : InvalidRethrowingProtocol {
3939

4040
func freeFloatingRethrowing<R: RethrowingProtocol>(_ r: R) rethrows { }
4141

42-
func freeFloatingRethrowingFromExistential(_ r: RethrowingProtocol) rethrows { }
42+
func freeFloatingRethrowingFromExistential(_ r: RethrowingProtocol) rethrows {
43+
// expected-error@-1{{'rethrows' function must take a throwing function argument}}
44+
}
4345

4446
func invalidFreeFloatingRethrows() rethrows {
4547
// expected-error@-1{{'rethrows' function must take a throwing function argument}}
@@ -68,11 +70,30 @@ func freeFloatingRethrowing<R: HasAssociatedRethrower>(_ r: R) rethrows { }
6870
protocol InheritsRethrowing: RethrowingProtocol {}
6971

7072
func freeFloatingInheritedRethrowingFunction<I: InheritsRethrowing>(_ r: I) rethrows { }
71-
func freeFloatingInheritedRethrowingFunctionFromExistential(_ r: InheritsRethrowing) rethrows { }
73+
74+
func freeFloatingInheritedRethrowingFunctionFromExistential(_ r: InheritsRethrowing) rethrows {
75+
// expected-error@-1{{'rethrows' function must take a throwing function argument}}
76+
}
7277

7378
func closureAndRethrowing<R: RethrowingProtocol>(_ r: R, _ closure: () throws -> Void) rethrows { }
7479

7580
closureAndRethrowing(NonThrows()) { }
7681
try closureAndRethrowing(NonThrows()) { } // expected-warning{{no calls to throwing functions occur within 'try' expression}}
7782
try closureAndRethrowing(Throws()) { }
7883
try closureAndRethrowing(NonThrows()) { () throws -> Void in }
84+
85+
// Make sure we handle the case where both the 'self' parameter and a closure
86+
// argument are rethrows sources.
87+
extension RethrowingProtocol {
88+
func selfRethrowing() rethrows { }
89+
func closureAndSelfRethrowing(_ closure: () throws -> Void) rethrows { }
90+
}
91+
92+
NonThrows().selfRethrowing()
93+
try Throws().selfRethrowing()
94+
95+
NonThrows().closureAndSelfRethrowing { }
96+
try NonThrows().closureAndSelfRethrowing { () throws -> Void in }
97+
98+
try Throws().closureAndSelfRethrowing { }
99+
try Throws().closureAndSelfRethrowing { () throws -> Void in }

0 commit comments

Comments
 (0)