Skip to content

Commit ef64209

Browse files
committed
[Typed throws] Parsing and AST representation for typed errors
Parse typed throw specifiers as `throws(X)` in every place where there are effects specified, and record the resulting thrown error type in the AST except the type system. This includes: * `FunctionTypeRepr`, for the parsed representation of types * `AbstractFunctionDecl`, for various function-like declarations * `ClosureExpr`, for closures * `ArrowExpr`, for parsing of types within expression context This also introduces some serialization logic for the thrown error type of function-like declarations, along with an API to extract the thrown interface type from one of those declarations, although right now it will either be `Error` or empty.
1 parent 204d496 commit ef64209

Some content is hidden

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

47 files changed

+473
-145
lines changed

include/swift/AST/CASTBridging.h

Lines changed: 6 additions & 3 deletions
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

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6942,6 +6942,9 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
69426942
/// Location of the 'throws' token.
69436943
SourceLoc ThrowsLoc;
69446944

6945+
/// The error type that is being thrown.
6946+
TypeLoc ThrownType;
6947+
69456948
struct {
69466949
unsigned NeedsNewVTableEntryComputed : 1;
69476950
unsigned NeedsNewVTableEntry : 1;
@@ -6950,12 +6953,13 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
69506953
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
69516954
SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc,
69526955
bool Throws, SourceLoc ThrowsLoc,
6956+
TypeLoc ThrownTy,
69536957
bool HasImplicitSelfDecl,
69546958
GenericParamList *GenericParams)
69556959
: GenericContext(DeclContextKind::AbstractFunctionDecl, Parent,
69566960
GenericParams),
69576961
ValueDecl(Kind, Parent, Name, NameLoc), BodyAndFP(), AsyncLoc(AsyncLoc),
6958-
ThrowsLoc(ThrowsLoc) {
6962+
ThrowsLoc(ThrowsLoc), ThrownType(ThrownTy) {
69596963
setBodyKind(BodyKind::None);
69606964
Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl;
69616965
Bits.AbstractFunctionDecl.Overridden = false;
@@ -7053,6 +7057,14 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
70537057
/// Returns true if the function body throws.
70547058
bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; }
70557059

7060+
/// Retrieves the type representation for the thrown type.
7061+
TypeRepr *getThrownTypeRepr() const {
7062+
return ThrownType.getTypeRepr();
7063+
}
7064+
7065+
/// Retrieves the thrown interface type.
7066+
Type getThrownInterfaceType() const;
7067+
70567068
/// Returns if the function throws or is async.
70577069
bool hasEffect(EffectKind kind) const;
70587070

@@ -7443,12 +7455,13 @@ class FuncDecl : public AbstractFunctionDecl {
74437455
DeclName Name, SourceLoc NameLoc,
74447456
bool Async, SourceLoc AsyncLoc,
74457457
bool Throws, SourceLoc ThrowsLoc,
7458+
TypeLoc ThrownTy,
74467459
bool HasImplicitSelfDecl,
74477460
GenericParamList *GenericParams, DeclContext *Parent)
74487461
: AbstractFunctionDecl(Kind, Parent,
74497462
Name, NameLoc,
74507463
Async, AsyncLoc,
7451-
Throws, ThrowsLoc,
7464+
Throws, ThrowsLoc, ThrownTy,
74527465
HasImplicitSelfDecl, GenericParams),
74537466
StaticLoc(StaticLoc), FuncLoc(FuncLoc) {
74547467
assert(!Name.getBaseName().isSpecial());
@@ -7473,6 +7486,7 @@ class FuncDecl : public AbstractFunctionDecl {
74737486
DeclName Name, SourceLoc NameLoc,
74747487
bool Async, SourceLoc AsyncLoc,
74757488
bool Throws, SourceLoc ThrowsLoc,
7489+
TypeLoc ThrownTy,
74767490
GenericParamList *GenericParams,
74777491
DeclContext *Parent,
74787492
ClangNode ClangN);
@@ -7496,27 +7510,31 @@ class FuncDecl : public AbstractFunctionDecl {
74967510
static FuncDecl *createDeserialized(ASTContext &Context,
74977511
StaticSpellingKind StaticSpelling,
74987512
DeclName Name, bool Async, bool Throws,
7513+
Type ThrownType,
74997514
GenericParamList *GenericParams,
75007515
Type FnRetType, DeclContext *Parent);
75017516

75027517
static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
75037518
StaticSpellingKind StaticSpelling, SourceLoc FuncLoc,
75047519
DeclName Name, SourceLoc NameLoc, bool Async,
75057520
SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc,
7521+
TypeRepr *ThrownTyR,
75067522
GenericParamList *GenericParams,
75077523
ParameterList *BodyParams, TypeRepr *ResultTyR,
75087524
DeclContext *Parent);
75097525

75107526
static FuncDecl *createImplicit(ASTContext &Context,
75117527
StaticSpellingKind StaticSpelling,
75127528
DeclName Name, SourceLoc NameLoc, bool Async,
7513-
bool Throws, GenericParamList *GenericParams,
7529+
bool Throws, Type ThrownType,
7530+
GenericParamList *GenericParams,
75147531
ParameterList *BodyParams, Type FnRetType,
75157532
DeclContext *Parent);
75167533

75177534
static FuncDecl *createImported(ASTContext &Context, SourceLoc FuncLoc,
75187535
DeclName Name, SourceLoc NameLoc, bool Async,
7519-
bool Throws, ParameterList *BodyParams,
7536+
bool Throws, Type ThrownType,
7537+
ParameterList *BodyParams,
75207538
Type FnRetType,
75217539
GenericParamList *GenericParams,
75227540
DeclContext *Parent, ClangNode ClangN);
@@ -7649,11 +7667,12 @@ class AccessorDecl final : public FuncDecl {
76497667
AccessorKind accessorKind, AbstractStorageDecl *storage,
76507668
SourceLoc staticLoc, StaticSpellingKind staticSpelling,
76517669
bool async, SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc,
7670+
TypeLoc thrownTy,
76527671
bool hasImplicitSelfDecl, DeclContext *parent)
76537672
: FuncDecl(DeclKind::Accessor, staticLoc, staticSpelling,
76547673
/*func loc*/ declLoc,
76557674
/*name*/ Identifier(), /*name loc*/ declLoc, async, asyncLoc,
7656-
throws, throwsLoc, hasImplicitSelfDecl,
7675+
throws, throwsLoc, thrownTy, hasImplicitSelfDecl,
76577676
/*genericParams*/ nullptr, parent),
76587677
AccessorKeywordLoc(accessorKeywordLoc), Storage(storage) {
76597678
assert(!async || accessorKind == AccessorKind::Get
@@ -7666,6 +7685,7 @@ class AccessorDecl final : public FuncDecl {
76667685
AccessorKind accessorKind, AbstractStorageDecl *storage,
76677686
SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool async,
76687687
SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc,
7688+
TypeLoc thrownTy,
76697689
DeclContext *parent, ClangNode clangNode);
76707690

76717691
llvm::Optional<bool> getCachedIsTransparent() const {
@@ -7682,14 +7702,16 @@ class AccessorDecl final : public FuncDecl {
76827702
AbstractStorageDecl *storage,
76837703
StaticSpellingKind staticSpelling,
76847704
bool async, bool throws,
7705+
Type thrownType,
76857706
Type fnRetType, DeclContext *parent);
76867707

76877708
static AccessorDecl *
76887709
create(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc,
76897710
AccessorKind accessorKind, AbstractStorageDecl *storage,
76907711
SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool async,
76917712
SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc,
7692-
ParameterList *parameterList, Type fnRetType, DeclContext *parent,
7713+
TypeLoc thrownType, ParameterList *parameterList, Type fnRetType,
7714+
DeclContext *parent,
76937715
ClangNode clangNode = ClangNode());
76947716

76957717
SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }
@@ -8052,6 +8074,7 @@ class ConstructorDecl : public AbstractFunctionDecl {
80528074
bool Failable, SourceLoc FailabilityLoc,
80538075
bool Async, SourceLoc AsyncLoc,
80548076
bool Throws, SourceLoc ThrowsLoc,
8077+
TypeLoc thrownTy,
80558078
ParameterList *BodyParams,
80568079
GenericParamList *GenericParams,
80578080
DeclContext *Parent);
@@ -8062,6 +8085,7 @@ class ConstructorDecl : public AbstractFunctionDecl {
80628085
bool failable, SourceLoc failabilityLoc,
80638086
bool async, SourceLoc asyncLoc,
80648087
bool throws, SourceLoc throwsLoc,
8088+
Type thrownTy,
80658089
ParameterList *bodyParams, GenericParamList *genericParams,
80668090
DeclContext *parent);
80678091

include/swift/AST/DiagnosticsParse.def

Lines changed: 7 additions & 0 deletions
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/Expr.h

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3981,6 +3981,9 @@ class ClosureExpr : public AbstractClosureExpr {
39813981
/// The location of the "in", if present.
39823982
SourceLoc InLoc;
39833983

3984+
/// The explcitly-specified thrown type.
3985+
TypeExpr *ThrownType;
3986+
39843987
/// The explicitly-specified result type.
39853988
llvm::PointerIntPair<TypeExpr *, 2, BodyState> ExplicitResultTypeAndBodyState;
39863989

@@ -3991,14 +3994,14 @@ class ClosureExpr : public AbstractClosureExpr {
39913994
ClosureExpr(const DeclAttributes &attributes,
39923995
SourceRange bracketRange, VarDecl *capturedSelfDecl,
39933996
ParameterList *params, SourceLoc asyncLoc, SourceLoc throwsLoc,
3994-
SourceLoc arrowLoc, SourceLoc inLoc, TypeExpr *explicitResultType,
3995-
DeclContext *parent)
3997+
TypeExpr *thrownType, SourceLoc arrowLoc, SourceLoc inLoc,
3998+
TypeExpr *explicitResultType, DeclContext *parent)
39963999
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
39974000
parent),
39984001
Attributes(attributes), BracketRange(bracketRange),
39994002
CapturedSelfDecl(capturedSelfDecl),
40004003
AsyncLoc(asyncLoc), ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc),
4001-
InLoc(inLoc),
4004+
InLoc(inLoc), ThrownType(thrownType),
40024005
ExplicitResultTypeAndBodyState(explicitResultType, BodyState::Parsed),
40034006
Body(nullptr) {
40044007
setParameterList(params);
@@ -4092,6 +4095,24 @@ class ClosureExpr : public AbstractClosureExpr {
40924095
return ThrowsLoc;
40934096
}
40944097

4098+
/// Retrieve the explicitly-thrown type.
4099+
Type getExplicitThrownType() const {
4100+
if (ThrownType)
4101+
return ThrownType->getInstanceType();
4102+
4103+
return nullptr;
4104+
}
4105+
4106+
void setExplicitThrownType(Type thrownType);
4107+
4108+
/// Retrieve the explicitly-thrown type representation.
4109+
TypeRepr *getExplicitThrownTypeRepr() const {
4110+
if (ThrownType)
4111+
return ThrownType->getTypeRepr();
4112+
4113+
return nullptr;
4114+
}
4115+
40954116
Type getExplicitResultType() const {
40964117
assert(hasExplicitResultType() && "No explicit result type");
40974118
return ExplicitResultTypeAndBodyState.getPointer()->getInstanceType();
@@ -5177,24 +5198,30 @@ class ArrowExpr : public Expr {
51775198
SourceLoc ArrowLoc;
51785199
Expr *Args;
51795200
Expr *Result;
5201+
Expr *ThrownType;
5202+
51805203
public:
51815204
ArrowExpr(Expr *Args, SourceLoc AsyncLoc, SourceLoc ThrowsLoc,
5182-
SourceLoc ArrowLoc, Expr *Result)
5205+
Expr *ThrownType, SourceLoc ArrowLoc, Expr *Result)
51835206
: Expr(ExprKind::Arrow, /*implicit=*/false, Type()),
51845207
AsyncLoc(AsyncLoc), ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc), Args(Args),
5185-
Result(Result)
5208+
Result(Result), ThrownType(ThrownType)
51865209
{ }
51875210

5188-
ArrowExpr(SourceLoc AsyncLoc, SourceLoc ThrowsLoc, SourceLoc ArrowLoc)
5211+
ArrowExpr(SourceLoc AsyncLoc, SourceLoc ThrowsLoc, Expr *ThrownType,
5212+
SourceLoc ArrowLoc)
51895213
: Expr(ExprKind::Arrow, /*implicit=*/false, Type()),
51905214
AsyncLoc(AsyncLoc), ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc),
5191-
Args(nullptr), Result(nullptr)
5215+
Args(nullptr), Result(nullptr), ThrownType(ThrownType)
51925216
{ }
51935217

51945218
Expr *getArgsExpr() const { return Args; }
51955219
void setArgsExpr(Expr *E) { Args = E; }
51965220
Expr *getResultExpr() const { return Result; }
51975221
void setResultExpr(Expr *E) { Result = E; }
5222+
Expr *getThrownTypeExpr() const { return ThrownType; }
5223+
void setThrownTypeExpr(Expr *E) { ThrownType = E; }
5224+
51985225
SourceLoc getAsyncLoc() const { return AsyncLoc; }
51995226
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
52005227
SourceLoc getArrowLoc() const { return ArrowLoc; }

include/swift/AST/TypeRepr.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,13 +499,16 @@ class FunctionTypeRepr : public TypeRepr {
499499

500500
TupleTypeRepr *ArgsTy;
501501
TypeRepr *RetTy;
502+
TypeRepr *ThrownTy;
502503
SourceLoc AsyncLoc;
503504
SourceLoc ThrowsLoc;
504505
SourceLoc ArrowLoc;
505506

506507
public:
507508
FunctionTypeRepr(GenericParamList *genericParams, TupleTypeRepr *argsTy,
508-
SourceLoc asyncLoc, SourceLoc throwsLoc, SourceLoc arrowLoc,
509+
SourceLoc asyncLoc, SourceLoc throwsLoc,
510+
TypeRepr *thrownTy,
511+
SourceLoc arrowLoc,
509512
TypeRepr *retTy,
510513
GenericParamList *patternGenericParams = nullptr,
511514
ArrayRef<TypeRepr *> patternSubs = {},
@@ -515,7 +518,7 @@ class FunctionTypeRepr : public TypeRepr {
515518
InvocationSubs(invocationSubs),
516519
PatternGenericParams(patternGenericParams),
517520
PatternSubs(patternSubs),
518-
ArgsTy(argsTy), RetTy(retTy),
521+
ArgsTy(argsTy), RetTy(retTy), ThrownTy(thrownTy),
519522
AsyncLoc(asyncLoc), ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc) {
520523
}
521524

@@ -545,6 +548,7 @@ class FunctionTypeRepr : public TypeRepr {
545548
}
546549

547550
TupleTypeRepr *getArgsTypeRepr() const { return ArgsTy; }
551+
TypeRepr *getThrownTypeRepr() const { return ThrownTy; }
548552
TypeRepr *getResultTypeRepr() const { return RetTy; }
549553
bool isAsync() const { return AsyncLoc.isValid(); }
550554
bool isThrowing() const { return ThrowsLoc.isValid(); }

include/swift/Parse/Parser.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ class Parser {
12791279
ParserStatus parseGetEffectSpecifier(ParsedAccessors &accessors,
12801280
SourceLoc &asyncLoc,
12811281
SourceLoc &throwsLoc,
1282+
TypeRepr *&thrownTy,
12821283
bool &hasEffectfulGet,
12831284
AccessorKind currentKind,
12841285
SourceLoc const& currentLoc);
@@ -1623,6 +1624,7 @@ class Parser {
16231624
bool &reasync,
16241625
SourceLoc &throws,
16251626
bool &rethrows,
1627+
TypeRepr *&thrownType,
16261628
TypeRepr *&retType);
16271629

16281630
/// Parse 'async' and 'throws', if present, putting the locations of the
@@ -1639,10 +1641,14 @@ class Parser {
16391641
/// lieu of 'throws'.
16401642
ParserStatus parseEffectsSpecifiers(SourceLoc existingArrowLoc,
16411643
SourceLoc &asyncLoc, bool *reasync,
1642-
SourceLoc &throwsLoc, bool *rethrows);
1644+
SourceLoc &throwsLoc, bool *rethrows,
1645+
TypeRepr *&thrownType);
1646+
1647+
/// Returns 'true' if \p T is consider a throwing effect specifier.
1648+
static bool isThrowsEffectSpecifier(const Token &T);
16431649

16441650
/// Returns 'true' if \p T is considered effects specifier.
1645-
bool isEffectsSpecifier(const Token &T);
1651+
static bool isEffectsSpecifier(const Token &T);
16461652

16471653
//===--------------------------------------------------------------------===//
16481654
// Pattern Parsing
@@ -1870,6 +1876,7 @@ class Parser {
18701876
ParameterList *&params,
18711877
SourceLoc &asyncLoc,
18721878
SourceLoc &throwsLoc,
1879+
TypeExpr *&thrownType,
18731880
SourceLoc &arrowLoc,
18741881
TypeExpr *&explicitResultType,
18751882
SourceLoc &inLoc);

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,10 @@ namespace {
14501450
}
14511451
}
14521452

1453+
if (auto thrownTypeRepr = D->getThrownTypeRepr()) {
1454+
printRec(thrownTypeRepr, "thrown_type");
1455+
}
1456+
14531457
if (auto fac = D->getForeignAsyncConvention()) {
14541458
printRecArbitrary([&](StringRef label) {
14551459
printHead("foreign_async_convention", ASTNodeColor, label);

0 commit comments

Comments
 (0)