Skip to content

Commit 446dc9d

Browse files
committed
Diagnose mismatched typed throws in @abi
1 parent ef738e6 commit 446dc9d

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

lib/Sema/TypeCheckAttrABI.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,25 @@ class ABIDeclChecker : public ASTComparisonVisitor<ABIDeclChecker> {
453453
bool checkEffects(DeclEffects api, DeclEffects abi, Decl *apiDecl,
454454
Decl *abiDecl) {
455455
bool didDiagnose = false;
456+
456457
// Do the declarations match in throwing behavior? We don't care about
457458
// `throws` vs. `rethrows` here, just whether callers will account for an
458459
// error return.
459-
if (api.anyContains(EffectKind::Throws) != abi.anyContains(EffectKind::Throws)) {
460+
bool apiThrows = api.anyContains(EffectKind::Throws);
461+
bool abiThrows = abi.anyContains(EffectKind::Throws);
462+
463+
if (apiThrows != abiThrows) {
460464
diagnoseAndRemoveAttr(abiAttr, diag::attr_abi_mismatched_throws,
461-
apiDecl, /*abiCanThrow=*/abi.anyContains(EffectKind::Throws));
465+
apiDecl, /*abiCanThrow=*/abiThrows);
462466
didDiagnose = true;
463-
// FIXME: Typed throws?
467+
} else if (apiThrows && abiThrows) {
468+
// If both throw, make sure the throw types are compatible.
469+
auto apiThrowType = api.effectiveThrownType.value_or(ctx.getNeverType());
470+
auto abiThrowType = abi.effectiveThrownType.value_or(ctx.getNeverType());
471+
472+
didDiagnose |= checkType(apiThrowType, abiThrowType,
473+
api.throwsLoc, abi.throwsLoc,
474+
TypeOrigin::forThrowsEffect());
464475
}
465476

466477
// Do the declarations match in async-ness?

test/attr/attr_abi.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ struct SubscriptArity {
164164
// Throws effect checking
165165
//
166166

167+
enum MyError: Error {}
168+
167169
@abi(func throws00(_: () throws -> Void))
168170
func throws00(_: () throws -> Void) {}
169171

@@ -173,6 +175,9 @@ func throws10(_: () throws -> Void) {}
173175
@abi(func throws20(_: () throws -> Void) rethrows) // expected-error {{cannot give 'throws20' the ABI of a global function which can throw}}
174176
func throws20(_: () throws -> Void) {}
175177

178+
@abi(func throws30(_: () throws -> Void) throws(MyError)) // expected-error {{cannot give 'throws30' the ABI of a global function which can throw}}
179+
func throws30(_: () throws -> Void) {}
180+
176181
@abi(func throws01(_: () throws -> Void)) // expected-error {{cannot give 'throws01' the ABI of a global function which cannot throw}}
177182
func throws01(_: () throws -> Void) throws {}
178183

@@ -182,6 +187,9 @@ func throws11(_: () throws -> Void) throws {}
182187
@abi(func throws21(_: () throws -> Void) rethrows)
183188
func throws21(_: () throws -> Void) throws {}
184189
190+
@abi(func throws31(_: () throws -> Void) throws(MyError)) // expected-error {{thrown type 'MyError' in '@abi' should match 'any Error'}}
191+
func throws31(_: () throws -> Void) throws {} // expected-note@:37 {{should match type here}}
192+
185193
@abi(func throws02(_: () throws -> Void)) // expected-error {{cannot give 'throws02' the ABI of a global function which cannot throw}}
186194
func throws02(_: () throws -> Void) rethrows {}
187195
@@ -191,6 +199,21 @@ func throws12(_: () throws -> Void) rethrows {}
191199
@abi(func throws22(_: () throws -> Void) rethrows)
192200
func throws22(_: () throws -> Void) rethrows {}
193201
202+
@abi(func throws32(_: () throws -> Void) throws(MyError)) // expected-error {{thrown type 'MyError' in '@abi' should match 'any Error'}}
203+
func throws32(_: () throws -> Void) rethrows {} // expected-note@:37 {{should match type here}}
204+
205+
@abi(func throws03(_: () throws -> Void)) // expected-error {{cannot give 'throws03' the ABI of a global function which cannot throw}}
206+
func throws03(_: () throws -> Void) throws(MyError) {}
207+
208+
@abi(func throws13(_: () throws -> Void) throws) // expected-error {{thrown type 'any Error' in '@abi' should match 'MyError'}}
209+
func throws13(_: () throws -> Void) throws(MyError) {} // expected-note@:37 {{should match type here}}
210+
211+
@abi(func throws23(_: () throws -> Void) rethrows) // expected-error {{thrown type 'any Error' in '@abi' should match 'MyError'}}
212+
func throws23(_: () throws -> Void) throws(MyError) {} // expected-note@:37 {{should match type here}}
213+
214+
@abi(func throws33(_: () throws -> Void) throws(MyError))
215+
func throws33(_: () throws -> Void) throws(MyError) {}
216+
194217
@abi(var throws00Var: Int)
195218
var throws00Var: Int { get { fatalError() } }
196219

0 commit comments

Comments
 (0)