Skip to content

Commit 581b9d8

Browse files
authored
Merge pull request #68629 from DougGregor/typed-throws
Typed throws
2 parents e820854 + e51faf2 commit 581b9d8

File tree

93 files changed

+1463
-296
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+1463
-296
lines changed

include/swift/AST/AnyFunctionRef.h

+18
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,24 @@ class AnyFunctionRef {
124124
return TheFunction.get<AbstractClosureExpr *>()->getType();
125125
}
126126

127+
Type getThrownErrorType() const {
128+
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
129+
if (Type thrownError = AFD->getThrownInterfaceType())
130+
return AFD->mapTypeIntoContext(thrownError);
131+
132+
return Type();
133+
}
134+
135+
Type closureType = TheFunction.get<AbstractClosureExpr *>()->getType();
136+
if (!closureType)
137+
return Type();
138+
139+
if (auto closureFnType = closureType->getAs<AnyFunctionType>())
140+
return closureFnType->getThrownError();
141+
142+
return Type();
143+
}
144+
127145
Type getBodyResultType() const {
128146
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
129147
if (auto *FD = dyn_cast<FuncDecl>(AFD))

include/swift/AST/CASTBridging.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -341,24 +341,26 @@ void AbstractFunctionDecl_setBody(void *opaqueBody, void *opaqueDecl);
341341

342342
SWIFT_NAME("FuncDecl_create(astContext:declContext:staticLoc:funcKeywordLoc:"
343343
"name:nameLoc:genericParamList:parameterList:asyncSpecifierLoc:"
344-
"throwsSpecifierLoc:returnType:genericWhereClause:)")
344+
"throwsSpecifierLoc:thrownType:returnType:genericWhereClause:)")
345345
struct BridgedDeclContextAndDecl
346346
FuncDecl_create(BridgedASTContext cContext, BridgedDeclContext cDeclContext,
347347
BridgedSourceLoc cStaticLoc, BridgedSourceLoc cFuncKeywordLoc,
348348
BridgedIdentifier cName, BridgedSourceLoc cNameLoc,
349349
void *_Nullable opaqueGenericParamList,
350350
void *opaqueParameterList, BridgedSourceLoc cAsyncLoc,
351-
BridgedSourceLoc cThrowsLoc, void *_Nullable opaqueReturnType,
351+
BridgedSourceLoc cThrowsLoc, void *_Nullable opaqueThrownType,
352+
void *_Nullable opaqueReturnType,
352353
void *_Nullable opaqueGenericWhereClause);
353354

354355
SWIFT_NAME("ConstructorDecl_create(astContext:declContext:initKeywordLoc:"
355356
"failabilityMarkLoc:isIUO:genericParamList:parameterList:"
356-
"asyncSpecifierLoc:throwsSpecifierLoc:genericWhereClause:)")
357+
"asyncSpecifierLoc:throwsSpecifierLoc:thrownType:genericWhereClause:)")
357358
BridgedDeclContextAndDecl ConstructorDecl_create(
358359
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
359360
BridgedSourceLoc cInitKeywordLoc, BridgedSourceLoc cFailabilityMarkLoc,
360361
_Bool isIUO, void *_Nullable opaqueGenericParams, void *opaqueParameterList,
361362
BridgedSourceLoc cAsyncLoc, BridgedSourceLoc cThrowsLoc,
363+
void *_Nullable opaqueThrownType,
362364
void *_Nullable opaqueGenericWhereClause);
363365

364366
SWIFT_NAME("DestructorDecl_create(astContext:declContext:deinitKeywordLoc:)")
@@ -587,6 +589,7 @@ void *EmptyCompositionTypeRepr_create(BridgedASTContext cContext,
587589
void *FunctionTypeRepr_create(BridgedASTContext cContext, void *argsTy,
588590
BridgedSourceLoc cAsyncLoc,
589591
BridgedSourceLoc cThrowsLoc,
592+
void * _Nullable thrownType,
590593
BridgedSourceLoc cArrowLoc, void *returnType);
591594
void *GenericIdentTypeRepr_create(BridgedASTContext cContext,
592595
BridgedIdentifier name,

include/swift/AST/Decl.h

+38-6
Original file line numberDiff line numberDiff line change
@@ -6839,6 +6839,7 @@ void simple_display(llvm::raw_ostream &out, BodyAndFingerprint value);
68396839
/// Base class for function-like declarations.
68406840
class AbstractFunctionDecl : public GenericContext, public ValueDecl {
68416841
friend class NeedsNewVTableEntryRequest;
6842+
friend class ThrownTypeRequest;
68426843

68436844
public:
68446845
/// records the kind of SILGen-synthesized body this decl represents
@@ -6950,6 +6951,9 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
69506951
/// Location of the 'throws' token.
69516952
SourceLoc ThrowsLoc;
69526953

6954+
/// The error type that is being thrown.
6955+
TypeLoc ThrownType;
6956+
69536957
struct {
69546958
unsigned NeedsNewVTableEntryComputed : 1;
69556959
unsigned NeedsNewVTableEntry : 1;
@@ -6958,12 +6962,13 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
69586962
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
69596963
SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc,
69606964
bool Throws, SourceLoc ThrowsLoc,
6965+
TypeLoc ThrownTy,
69616966
bool HasImplicitSelfDecl,
69626967
GenericParamList *GenericParams)
69636968
: GenericContext(DeclContextKind::AbstractFunctionDecl, Parent,
69646969
GenericParams),
69656970
ValueDecl(Kind, Parent, Name, NameLoc), BodyAndFP(), AsyncLoc(AsyncLoc),
6966-
ThrowsLoc(ThrowsLoc) {
6971+
ThrowsLoc(ThrowsLoc), ThrownType(ThrownTy) {
69676972
setBodyKind(BodyKind::None);
69686973
Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl;
69696974
Bits.AbstractFunctionDecl.Overridden = false;
@@ -7069,6 +7074,21 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
70697074
/// Returns true if the function body throws.
70707075
bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; }
70717076

7077+
/// Retrieves the type representation for the thrown type.
7078+
TypeRepr *getThrownTypeRepr() const {
7079+
return ThrownType.getTypeRepr();
7080+
}
7081+
7082+
/// Retrieves the thrown interface type.
7083+
Type getThrownInterfaceType() const;
7084+
7085+
/// Retrieve the "effective" thrown interface type, or llvm::None if
7086+
/// this function cannot throw.
7087+
///
7088+
/// Functions with untyped throws will produce "any Error", functions that
7089+
/// cannot throw or are specified to throw "Never" will return llvm::None.
7090+
llvm::Optional<Type> getEffectiveThrownInterfaceType() const;
7091+
70727092
/// Returns if the function throws or is async.
70737093
bool hasEffect(EffectKind kind) const;
70747094

@@ -7441,12 +7461,13 @@ class FuncDecl : public AbstractFunctionDecl {
74417461
DeclName Name, SourceLoc NameLoc,
74427462
bool Async, SourceLoc AsyncLoc,
74437463
bool Throws, SourceLoc ThrowsLoc,
7464+
TypeLoc ThrownTy,
74447465
bool HasImplicitSelfDecl,
74457466
GenericParamList *GenericParams, DeclContext *Parent)
74467467
: AbstractFunctionDecl(Kind, Parent,
74477468
Name, NameLoc,
74487469
Async, AsyncLoc,
7449-
Throws, ThrowsLoc,
7470+
Throws, ThrowsLoc, ThrownTy,
74507471
HasImplicitSelfDecl, GenericParams),
74517472
StaticLoc(StaticLoc), FuncLoc(FuncLoc) {
74527473
assert(!Name.getBaseName().isSpecial());
@@ -7471,6 +7492,7 @@ class FuncDecl : public AbstractFunctionDecl {
74717492
DeclName Name, SourceLoc NameLoc,
74727493
bool Async, SourceLoc AsyncLoc,
74737494
bool Throws, SourceLoc ThrowsLoc,
7495+
TypeLoc ThrownTy,
74747496
GenericParamList *GenericParams,
74757497
DeclContext *Parent,
74767498
ClangNode ClangN);
@@ -7494,27 +7516,31 @@ class FuncDecl : public AbstractFunctionDecl {
74947516
static FuncDecl *createDeserialized(ASTContext &Context,
74957517
StaticSpellingKind StaticSpelling,
74967518
DeclName Name, bool Async, bool Throws,
7519+
Type ThrownType,
74977520
GenericParamList *GenericParams,
74987521
Type FnRetType, DeclContext *Parent);
74997522

75007523
static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
75017524
StaticSpellingKind StaticSpelling, SourceLoc FuncLoc,
75027525
DeclName Name, SourceLoc NameLoc, bool Async,
75037526
SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc,
7527+
TypeRepr *ThrownTyR,
75047528
GenericParamList *GenericParams,
75057529
ParameterList *BodyParams, TypeRepr *ResultTyR,
75067530
DeclContext *Parent);
75077531

75087532
static FuncDecl *createImplicit(ASTContext &Context,
75097533
StaticSpellingKind StaticSpelling,
75107534
DeclName Name, SourceLoc NameLoc, bool Async,
7511-
bool Throws, GenericParamList *GenericParams,
7535+
bool Throws, Type ThrownType,
7536+
GenericParamList *GenericParams,
75127537
ParameterList *BodyParams, Type FnRetType,
75137538
DeclContext *Parent);
75147539

75157540
static FuncDecl *createImported(ASTContext &Context, SourceLoc FuncLoc,
75167541
DeclName Name, SourceLoc NameLoc, bool Async,
7517-
bool Throws, ParameterList *BodyParams,
7542+
bool Throws, Type ThrownType,
7543+
ParameterList *BodyParams,
75187544
Type FnRetType,
75197545
GenericParamList *GenericParams,
75207546
DeclContext *Parent, ClangNode ClangN);
@@ -7647,11 +7673,12 @@ class AccessorDecl final : public FuncDecl {
76477673
AccessorKind accessorKind, AbstractStorageDecl *storage,
76487674
SourceLoc staticLoc, StaticSpellingKind staticSpelling,
76497675
bool async, SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc,
7676+
TypeLoc thrownTy,
76507677
bool hasImplicitSelfDecl, DeclContext *parent)
76517678
: FuncDecl(DeclKind::Accessor, staticLoc, staticSpelling,
76527679
/*func loc*/ declLoc,
76537680
/*name*/ Identifier(), /*name loc*/ declLoc, async, asyncLoc,
7654-
throws, throwsLoc, hasImplicitSelfDecl,
7681+
throws, throwsLoc, thrownTy, hasImplicitSelfDecl,
76557682
/*genericParams*/ nullptr, parent),
76567683
AccessorKeywordLoc(accessorKeywordLoc), Storage(storage) {
76577684
assert(!async || accessorKind == AccessorKind::Get
@@ -7664,6 +7691,7 @@ class AccessorDecl final : public FuncDecl {
76647691
AccessorKind accessorKind, AbstractStorageDecl *storage,
76657692
SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool async,
76667693
SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc,
7694+
TypeLoc thrownTy,
76677695
DeclContext *parent, ClangNode clangNode);
76687696

76697697
llvm::Optional<bool> getCachedIsTransparent() const {
@@ -7680,14 +7708,16 @@ class AccessorDecl final : public FuncDecl {
76807708
AbstractStorageDecl *storage,
76817709
StaticSpellingKind staticSpelling,
76827710
bool async, bool throws,
7711+
Type thrownType,
76837712
Type fnRetType, DeclContext *parent);
76847713

76857714
static AccessorDecl *
76867715
create(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc,
76877716
AccessorKind accessorKind, AbstractStorageDecl *storage,
76887717
SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool async,
76897718
SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc,
7690-
ParameterList *parameterList, Type fnRetType, DeclContext *parent,
7719+
TypeLoc thrownType, ParameterList *parameterList, Type fnRetType,
7720+
DeclContext *parent,
76917721
ClangNode clangNode = ClangNode());
76927722

76937723
SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }
@@ -8050,6 +8080,7 @@ class ConstructorDecl : public AbstractFunctionDecl {
80508080
bool Failable, SourceLoc FailabilityLoc,
80518081
bool Async, SourceLoc AsyncLoc,
80528082
bool Throws, SourceLoc ThrowsLoc,
8083+
TypeLoc thrownTy,
80538084
ParameterList *BodyParams,
80548085
GenericParamList *GenericParams,
80558086
DeclContext *Parent);
@@ -8060,6 +8091,7 @@ class ConstructorDecl : public AbstractFunctionDecl {
80608091
bool failable, SourceLoc failabilityLoc,
80618092
bool async, SourceLoc asyncLoc,
80628093
bool throws, SourceLoc throwsLoc,
8094+
Type thrownTy,
80638095
ParameterList *bodyParams, GenericParamList *genericParams,
80648096
DeclContext *parent);
80658097

include/swift/AST/DiagnosticsParse.def

+7
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,13 @@ ERROR(attr_type_eraser_expected_type_name,none,
16901690
ERROR(attr_type_eraser_expected_rparen,none,
16911691
"expected ')' after type name for @_typeEraser", ())
16921692

1693+
ERROR(expected_thrown_error_type,none,
1694+
"expected thrown error type after 'throws('", ())
1695+
ERROR(expected_rparen_after_thrown_error_type,none,
1696+
"expected ')' after thrown error type", ())
1697+
ERROR(rethrows_with_thrown_error,none,
1698+
"'rethrows' cannot be combined with a specific thrown error type", ())
1699+
16931700
ERROR(attr_private_import_expected_rparen,none,
16941701
"expected ')' after function name for @_private", ())
16951702
ERROR(attr_private_import_expected_sourcefile, none,

include/swift/AST/DiagnosticsSema.def

+13-5
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,9 @@ ERROR(cannot_convert_to_return_type_nil,none,
336336
"'nil' is incompatible with return type %0", (Type))
337337

338338
ERROR(cannot_convert_thrown_type,none,
339-
"thrown expression type %0 does not conform to 'Error'", (Type))
339+
"thrown expression type %0 %select{cannot be converted to error type %1|"
340+
"does not conform to 'Error'}2",
341+
(Type, Type, bool))
340342
ERROR(cannot_throw_error_code,none,
341343
"thrown error code type %0 does not conform to 'Error'; construct an %1 "
342344
"instance", (Type, Type))
@@ -2279,10 +2281,10 @@ ERROR(function_type_access,none,
22792281
"%select{private|fileprivate|internal|package|%error|%error}1|private or fileprivate}2"
22802282
"|cannot be declared "
22812283
"%select{in this context|fileprivate|internal|package|public|open}1}0 "
2282-
"because its %select{parameter|result}5 uses "
2284+
"because its %select{parameter|thrown error|result}5 uses "
22832285
"%select{a private|a fileprivate|an internal|a package|an '@_spi'|an '@_spi'}3"
22842286
"%select{| API wrapper}6 type",
2285-
(bool, AccessLevel, bool, AccessLevel, unsigned, bool, bool))
2287+
(bool, AccessLevel, bool, AccessLevel, unsigned, unsigned, bool))
22862288
ERROR(function_type_spi,none,
22872289
"%select{function|method|initializer}0 "
22882290
"cannot be declared '@_spi' "
@@ -2294,10 +2296,10 @@ WARNING(function_type_access_warn,none,
22942296
"%select{function|method|initializer}4 "
22952297
"%select{should be declared %select{private|fileprivate|internal|package|%error|%error}1"
22962298
"|should not be declared %select{in this context|fileprivate|internal|package|public|open}1}0 "
2297-
"because its %select{parameter|result}5 uses "
2299+
"because its %select{parameter|thrown error|result}5 uses "
22982300
"%select{a private|a fileprivate|an internal|a package|%error|%error}3 "
22992301
"%select{|API wrapper}6 type",
2300-
(bool, AccessLevel, bool, AccessLevel, unsigned, bool, bool))
2302+
(bool, AccessLevel, bool, AccessLevel, unsigned, unsigned, bool))
23012303
ERROR(function_type_usable_from_inline,none,
23022304
"the %select{parameter|result}1%select{| API wrapper}2 of a "
23032305
"'@usableFromInline' %select{function|method|initializer}0 "
@@ -5068,6 +5070,12 @@ WARNING(no_throw_in_try,none,
50685070
WARNING(no_throw_in_do_with_catch,none,
50695071
"'catch' block is unreachable because no errors are thrown in 'do' block", ())
50705072

5073+
ERROR(experimental_typed_throws,none,
5074+
"typed throws is an experimental feature", ())
5075+
5076+
ERROR(thrown_type_not_error,none,
5077+
"thrown type %0 does not conform to the 'Error' protocol", (Type))
5078+
50715079
//------------------------------------------------------------------------------
50725080
// MARK: Concurrency
50735081
//------------------------------------------------------------------------------

include/swift/AST/Expr.h

+41-7
Original file line numberDiff line numberDiff line change
@@ -3847,6 +3847,13 @@ class AbstractClosureExpr : public DeclContext, public Expr {
38473847
/// Return whether this closure is throwing when fully applied.
38483848
bool isBodyThrowing() const;
38493849

3850+
/// Retrieve the "effective" thrown interface type, or llvm::None if
3851+
/// this closure cannot throw.
3852+
///
3853+
/// Closures with untyped throws will produce "any Error", functions that
3854+
/// cannot throw or are specified to throw "Never" will return llvm::None.
3855+
llvm::Optional<Type> getEffectiveThrownType() const;
3856+
38503857
/// \brief Return whether this closure is async when fully applied.
38513858
bool isBodyAsync() const;
38523859

@@ -3981,6 +3988,9 @@ class ClosureExpr : public AbstractClosureExpr {
39813988
/// The location of the "in", if present.
39823989
SourceLoc InLoc;
39833990

3991+
/// The explcitly-specified thrown type.
3992+
TypeExpr *ThrownType;
3993+
39843994
/// The explicitly-specified result type.
39853995
llvm::PointerIntPair<TypeExpr *, 2, BodyState> ExplicitResultTypeAndBodyState;
39863996

@@ -3991,14 +4001,14 @@ class ClosureExpr : public AbstractClosureExpr {
39914001
ClosureExpr(const DeclAttributes &attributes,
39924002
SourceRange bracketRange, VarDecl *capturedSelfDecl,
39934003
ParameterList *params, SourceLoc asyncLoc, SourceLoc throwsLoc,
3994-
SourceLoc arrowLoc, SourceLoc inLoc, TypeExpr *explicitResultType,
3995-
DeclContext *parent)
4004+
TypeExpr *thrownType, SourceLoc arrowLoc, SourceLoc inLoc,
4005+
TypeExpr *explicitResultType, DeclContext *parent)
39964006
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
39974007
parent),
39984008
Attributes(attributes), BracketRange(bracketRange),
39994009
CapturedSelfDecl(capturedSelfDecl),
40004010
AsyncLoc(asyncLoc), ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc),
4001-
InLoc(inLoc),
4011+
InLoc(inLoc), ThrownType(thrownType),
40024012
ExplicitResultTypeAndBodyState(explicitResultType, BodyState::Parsed),
40034013
Body(nullptr) {
40044014
setParameterList(params);
@@ -4092,6 +4102,24 @@ class ClosureExpr : public AbstractClosureExpr {
40924102
return ThrowsLoc;
40934103
}
40944104

4105+
/// Retrieve the explicitly-thrown type.
4106+
Type getExplicitThrownType() const {
4107+
if (ThrownType)
4108+
return ThrownType->getInstanceType();
4109+
4110+
return nullptr;
4111+
}
4112+
4113+
void setExplicitThrownType(Type thrownType);
4114+
4115+
/// Retrieve the explicitly-thrown type representation.
4116+
TypeRepr *getExplicitThrownTypeRepr() const {
4117+
if (ThrownType)
4118+
return ThrownType->getTypeRepr();
4119+
4120+
return nullptr;
4121+
}
4122+
40954123
Type getExplicitResultType() const {
40964124
assert(hasExplicitResultType() && "No explicit result type");
40974125
return ExplicitResultTypeAndBodyState.getPointer()->getInstanceType();
@@ -5177,24 +5205,30 @@ class ArrowExpr : public Expr {
51775205
SourceLoc ArrowLoc;
51785206
Expr *Args;
51795207
Expr *Result;
5208+
Expr *ThrownType;
5209+
51805210
public:
51815211
ArrowExpr(Expr *Args, SourceLoc AsyncLoc, SourceLoc ThrowsLoc,
5182-
SourceLoc ArrowLoc, Expr *Result)
5212+
Expr *ThrownType, SourceLoc ArrowLoc, Expr *Result)
51835213
: Expr(ExprKind::Arrow, /*implicit=*/false, Type()),
51845214
AsyncLoc(AsyncLoc), ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc), Args(Args),
5185-
Result(Result)
5215+
Result(Result), ThrownType(ThrownType)
51865216
{ }
51875217

5188-
ArrowExpr(SourceLoc AsyncLoc, SourceLoc ThrowsLoc, SourceLoc ArrowLoc)
5218+
ArrowExpr(SourceLoc AsyncLoc, SourceLoc ThrowsLoc, Expr *ThrownType,
5219+
SourceLoc ArrowLoc)
51895220
: Expr(ExprKind::Arrow, /*implicit=*/false, Type()),
51905221
AsyncLoc(AsyncLoc), ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc),
5191-
Args(nullptr), Result(nullptr)
5222+
Args(nullptr), Result(nullptr), ThrownType(ThrownType)
51925223
{ }
51935224

51945225
Expr *getArgsExpr() const { return Args; }
51955226
void setArgsExpr(Expr *E) { Args = E; }
51965227
Expr *getResultExpr() const { return Result; }
51975228
void setResultExpr(Expr *E) { Result = E; }
5229+
Expr *getThrownTypeExpr() const { return ThrownType; }
5230+
void setThrownTypeExpr(Expr *E) { ThrownType = E; }
5231+
51985232
SourceLoc getAsyncLoc() const { return AsyncLoc; }
51995233
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
52005234
SourceLoc getArrowLoc() const { return ArrowLoc; }

0 commit comments

Comments
 (0)