Skip to content

Commit 1d6726a

Browse files
authored
Merge pull request #35986 from slavapestov/reasync-part-1
Implementing parsing and printing for 'reasync' functions
2 parents 035db92 + cdbba60 commit 1d6726a

18 files changed

+363
-238
lines changed

include/swift/AST/Attr.def

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -353,25 +353,25 @@ SIMPLE_DECL_ATTR(testable, Testable,
353353
DECL_ATTR(_alignment, Alignment,
354354
OnStruct | OnEnum |
355355
UserInaccessible |
356-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
356+
ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
357357
56)
358358
SIMPLE_DECL_ATTR(rethrows, Rethrows,
359-
OnFunc | OnAccessor | OnConstructor |
359+
OnFunc | OnConstructor |
360360
RejectByParser |
361-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
361+
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
362362
57)
363363
SIMPLE_DECL_ATTR(rethrows, AtRethrows,
364364
OnProtocol |
365-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
365+
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
366366
58)
367367
DECL_ATTR(_swift_native_objc_runtime_base, SwiftNativeObjCRuntimeBase,
368368
OnClass |
369369
UserInaccessible |
370-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
370+
ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
371371
59)
372372
CONTEXTUAL_SIMPLE_DECL_ATTR(indirect, Indirect, DeclModifier |
373373
OnEnum | OnEnumElement |
374-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
374+
ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
375375
60)
376376
SIMPLE_DECL_ATTR(warn_unqualified_access, WarnUnqualifiedAccess,
377377
OnFunc | OnAccessor /*| OnVar*/ |
@@ -469,7 +469,7 @@ DECL_ATTR(_dynamicReplacement, DynamicReplacement,
469469
SIMPLE_DECL_ATTR(_borrowed, Borrowed,
470470
OnVar | OnSubscript | UserInaccessible |
471471
NotSerialized |
472-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
472+
ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
473473
81)
474474
DECL_ATTR(_private, PrivateImport,
475475
OnImport |
@@ -479,7 +479,7 @@ DECL_ATTR(_private, PrivateImport,
479479
82)
480480
SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient,
481481
OnVar | OnSubscript | OnAbstractFunction | UserInaccessible |
482-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
482+
ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
483483
83)
484484

485485
SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly,
@@ -613,6 +613,17 @@ SIMPLE_DECL_ATTR(_marker, Marker,
613613
APIBreakingToAdd | APIBreakingToRemove,
614614
108)
615615

616+
SIMPLE_DECL_ATTR(reasync, Reasync,
617+
OnFunc | OnConstructor |
618+
RejectByParser |
619+
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
620+
109)
621+
622+
SIMPLE_DECL_ATTR(reasync, AtReasync,
623+
OnProtocol |
624+
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
625+
110)
626+
616627
#undef TYPE_ATTR
617628
#undef DECL_ATTR_ALIAS
618629
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,9 @@ ERROR(generic_non_function,PointsToFirstBadToken,
731731
ERROR(rethrowing_function_type,none,
732732
"only function declarations may be marked 'rethrows'; "
733733
"did you mean 'throws'?", ())
734+
ERROR(reasync_function_type,none,
735+
"only function declarations may be marked 'reasync'; "
736+
"did you mean 'async'?", ())
734737
ERROR(async_or_throws_in_wrong_position,none,
735738
"'%0' may only occur before '->'", (StringRef))
736739
ERROR(throw_in_function_type,none,
@@ -745,7 +748,8 @@ ERROR(function_type_argument_label,none,
745748
ERROR(expected_dynamic_func_attr,none,
746749
"expected a dynamically_replaceable function", ())
747750
ERROR(async_after_throws,none,
748-
"'async' must precede %select{'throws'|'rethrows'}0", (bool))
751+
"%select{'async'|'reasync'}0 must precede %select{'throws'|'rethrows'}1",
752+
(bool, bool))
749753
ERROR(async_init,none, "initializer cannot be marked 'async'", ())
750754
ERROR(duplicate_effects_specifier,none,
751755
"'%0' has already been specified", (StringRef))

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,8 +2994,10 @@ ERROR(override_rethrows_with_non_rethrows,none,
29942994
"be 'rethrows'", (bool))
29952995
ERROR(rethrows_without_throwing_parameter,none,
29962996
"'rethrows' function must take a throwing function argument", ())
2997-
ERROR(rethrows_attr_on_non_protocol,none,
2998-
"@rethrows may only be used on 'protocol' declarations", ())
2997+
2998+
ERROR(override_reasync_with_non_reasync,none,
2999+
"override of 'reasync' %select{method|initializer}0 should also "
3000+
"be 'reasync'", (bool))
29993001

30003002
ERROR(autoclosure_function_type,none,
30013003
"@autoclosure attribute only applies to function types",

include/swift/Parse/Parser.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,7 @@ class Parser {
13421342
ParameterList *&bodyParams,
13431343
DefaultArgumentInfo &defaultArgs,
13441344
SourceLoc &asyncLoc,
1345+
bool &reasync,
13451346
SourceLoc &throws,
13461347
bool &rethrows,
13471348
TypeRepr *&retType);
@@ -1353,11 +1354,14 @@ class Parser {
13531354
/// one. Parsing 'async' or 'throws' after the `->` is an error we
13541355
/// correct for.
13551356
///
1357+
/// \param reasync If non-NULL, will also parse the 'reasync' keyword in
1358+
/// lieu of 'async'.
1359+
///
13561360
/// \param rethrows If non-NULL, will also parse the 'rethrows' keyword in
13571361
/// lieu of 'throws'.
13581362
ParserStatus parseEffectsSpecifiers(SourceLoc existingArrowLoc,
1359-
SourceLoc &asyncLoc, SourceLoc &throwsLoc,
1360-
bool *rethrows);
1363+
SourceLoc &asyncLoc, bool *reasync,
1364+
SourceLoc &throwsLoc, bool *rethrows);
13611365

13621366
/// Returns 'true' if \p T is considered effects specifier.
13631367
bool isEffectsSpecifier(const Token &T);

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3152,7 +3152,10 @@ void PrintAST::printFunctionParameters(AbstractFunctionDecl *AFD) {
31523152

31533153
if (AFD->hasAsync()) {
31543154
Printer << " ";
3155-
Printer.printKeyword("async", Options);
3155+
if (AFD->getAttrs().hasAttribute<ReasyncAttr>())
3156+
Printer.printKeyword("reasync", Options);
3157+
else
3158+
Printer.printKeyword("async", Options);
31563159
}
31573160

31583161
if (AFD->hasThrows()) {

lib/AST/Attr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
724724
case DAK_ObjCBridged:
725725
case DAK_SynthesizedProtocol:
726726
case DAK_Rethrows:
727+
case DAK_Reasync:
727728
case DAK_Infix:
728729
return false;
729730
case DAK_Override: {

lib/Parse/ParseDecl.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,6 +2801,8 @@ ParserStatus Parser::parseDeclAttribute(
28012801
// over to the alternate parsing path.
28022802
DeclAttrKind DK = DeclAttribute::getAttrKindFromString(Tok.getText());
28032803
if (DK == DAK_Rethrows) { DK = DAK_AtRethrows; }
2804+
if (DK == DAK_Reasync) { DK = DAK_AtReasync; }
2805+
28042806
auto checkInvalidAttrName = [&](StringRef invalidName,
28052807
StringRef correctName,
28062808
DeclAttrKind kind,
@@ -6694,10 +6696,13 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
66946696
DeclName FullName;
66956697
ParameterList *BodyParams;
66966698
SourceLoc asyncLoc;
6699+
bool reasync;
66976700
SourceLoc throwsLoc;
66986701
bool rethrows;
66996702
Status |= parseFunctionSignature(SimpleName, FullName, BodyParams,
6700-
DefaultArgs, asyncLoc, throwsLoc, rethrows,
6703+
DefaultArgs,
6704+
asyncLoc, reasync,
6705+
throwsLoc, rethrows,
67016706
FuncRetTy);
67026707
if (Status.hasCodeCompletion() && !CodeCompletion) {
67036708
// Trigger delayed parsing, no need to continue.
@@ -6753,7 +6758,9 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
67536758
return nullptr;
67546759
}
67556760

6756-
// Add the 'rethrows' attribute.
6761+
if (reasync) {
6762+
Attributes.add(new (Context) ReasyncAttr(asyncLoc));
6763+
}
67576764
if (rethrows) {
67586765
Attributes.add(new (Context) RethrowsAttr(throwsLoc));
67596766
}
@@ -7725,16 +7732,22 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
77257732
return nullptr;
77267733
}
77277734

7728-
// Parse 'async' / 'throws' / 'rethrows'.
7735+
// Parse 'async' / 'reasync' / 'throws' / 'rethrows'.
77297736
SourceLoc asyncLoc;
7737+
bool reasync = false;
77307738
SourceLoc throwsLoc;
77317739
bool rethrows = false;
7732-
Status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc, &rethrows);
7740+
Status |= parseEffectsSpecifiers(SourceLoc(),
7741+
asyncLoc, &reasync,
7742+
throwsLoc, &rethrows);
77337743
if (Status.hasCodeCompletion() && !CodeCompletion) {
77347744
// Trigger delayed parsing, no need to continue.
77357745
return Status;
77367746
}
77377747

7748+
if (reasync) {
7749+
Attributes.add(new (Context) ReasyncAttr(asyncLoc));
7750+
}
77387751
if (rethrows) {
77397752
Attributes.add(new (Context) RethrowsAttr(throwsLoc));
77407753
}

lib/Parse/ParseExpr.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,9 @@ ParserResult<Expr> Parser::parseExprArrow() {
128128
SourceLoc asyncLoc, throwsLoc, arrowLoc;
129129
ParserStatus status;
130130

131-
status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc,
132-
/*rethrows=*/nullptr);
131+
status |= parseEffectsSpecifiers(SourceLoc(),
132+
asyncLoc, /*reasync=*/nullptr,
133+
throwsLoc, /*rethrows=*/nullptr);
133134
if (status.hasCodeCompletion() && !CodeCompletion) {
134135
// Trigger delayed parsing, no need to continue.
135136
return status;
@@ -145,7 +146,9 @@ ParserResult<Expr> Parser::parseExprArrow() {
145146

146147
arrowLoc = consumeToken(tok::arrow);
147148

148-
parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc, /*rethrows=*/nullptr);
149+
parseEffectsSpecifiers(arrowLoc,
150+
asyncLoc, /*reasync=*/nullptr,
151+
throwsLoc, /*rethrows=*/nullptr);
149152

150153
auto arrow = new (Context) ArrowExpr(asyncLoc, throwsLoc, arrowLoc);
151154
return makeParserResult(arrow);
@@ -2600,8 +2603,9 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
26002603
params = ParameterList::create(Context, elements);
26012604
}
26022605

2603-
status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc,
2604-
/*rethrows*/nullptr);
2606+
status |= parseEffectsSpecifiers(SourceLoc(),
2607+
asyncLoc, /*reasync*/nullptr,
2608+
throwsLoc, /*rethrows*/nullptr);
26052609

26062610
// Parse the optional explicit return type.
26072611
if (Tok.is(tok::arrow)) {
@@ -2620,8 +2624,9 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
26202624
explicitResultType = new (Context) TypeExpr(explicitResultTypeRepr);
26212625

26222626
// Check for 'throws' and 'rethrows' after the type and correct it.
2623-
parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc,
2624-
/*rethrows*/nullptr);
2627+
parseEffectsSpecifiers(arrowLoc,
2628+
asyncLoc, /*reasync*/nullptr,
2629+
throwsLoc, /*rethrows*/nullptr);
26252630
}
26262631
}
26272632
}

lib/Parse/ParsePattern.cpp

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ Parser::parseFunctionArguments(SmallVectorImpl<Identifier> &NamePieces,
761761

762762
/// Parse a function definition signature.
763763
/// func-signature:
764-
/// func-arguments 'async'? func-throws? func-signature-result?
764+
/// func-arguments ('async'|'reasync')? func-throws? func-signature-result?
765765
/// func-signature-result:
766766
/// '->' type
767767
///
@@ -772,6 +772,7 @@ Parser::parseFunctionSignature(Identifier SimpleName,
772772
ParameterList *&bodyParams,
773773
DefaultArgumentInfo &defaultArgs,
774774
SourceLoc &asyncLoc,
775+
bool &reasync,
775776
SourceLoc &throwsLoc,
776777
bool &rethrows,
777778
TypeRepr *&retType) {
@@ -786,8 +787,11 @@ Parser::parseFunctionSignature(Identifier SimpleName,
786787
FullName = DeclName(Context, SimpleName, NamePieces);
787788

788789
// Check for the 'async' and 'throws' keywords.
790+
reasync = false;
789791
rethrows = false;
790-
Status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc, &rethrows);
792+
Status |= parseEffectsSpecifiers(SourceLoc(),
793+
asyncLoc, &reasync,
794+
throwsLoc, &rethrows);
791795

792796
// If there's a trailing arrow, parse the rest as the result type.
793797
SourceLoc arrowLoc;
@@ -800,9 +804,9 @@ Parser::parseFunctionSignature(Identifier SimpleName,
800804
arrowLoc = consumeToken(tok::colon);
801805
}
802806

803-
// Check for 'throws' and 'rethrows' after the arrow, but
804-
// before the type, and correct it.
805-
parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc, &rethrows);
807+
// Check for effect specifiers after the arrow, but before the type, and
808+
// correct it.
809+
parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc, &rethrows);
806810

807811
ParserResult<TypeRepr> ResultType =
808812
parseDeclResultType(diag::expected_type_function_result);
@@ -811,8 +815,8 @@ Parser::parseFunctionSignature(Identifier SimpleName,
811815
if (Status.isErrorOrHasCompletion())
812816
return Status;
813817

814-
// Check for 'throws' and 'rethrows' after the type and correct it.
815-
parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc, &rethrows);
818+
// Check for effect specifiers after the type and correct it.
819+
parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc, &rethrows);
816820
} else {
817821
// Otherwise, we leave retType null.
818822
retType = nullptr;
@@ -825,7 +829,8 @@ bool Parser::isEffectsSpecifier(const Token &T) {
825829
// NOTE: If this returns 'true', that token must be handled in
826830
// 'parseEffectsSpecifiers()'.
827831

828-
if (T.isContextualKeyword("async"))
832+
if (T.isContextualKeyword("async") ||
833+
T.isContextualKeyword("reasync"))
829834
return true;
830835

831836
if (T.isAny(tok::kw_throws, tok::kw_rethrows) ||
@@ -837,35 +842,48 @@ bool Parser::isEffectsSpecifier(const Token &T) {
837842

838843
ParserStatus Parser::parseEffectsSpecifiers(SourceLoc existingArrowLoc,
839844
SourceLoc &asyncLoc,
845+
bool *reasync,
840846
SourceLoc &throwsLoc,
841847
bool *rethrows) {
842848
ParserStatus status;
843849

844850
while (true) {
845851
// 'async'
846-
if (Tok.isContextualKeyword("async")) {
847-
852+
bool isReasync = Tok.isContextualKeyword("reasync");
853+
if (Tok.isContextualKeyword("async") ||
854+
isReasync) {
848855
if (asyncLoc.isValid()) {
849856
diagnose(Tok, diag::duplicate_effects_specifier, Tok.getText())
850857
.highlight(asyncLoc)
851858
.fixItRemove(Tok.getLoc());
859+
} else if (!reasync && isReasync) {
860+
// Replace 'reasync' with 'async' unless it's allowed.
861+
diagnose(Tok, diag::reasync_function_type)
862+
.fixItReplace(Tok.getLoc(), "async");
852863
} else if (existingArrowLoc.isValid()) {
853864
SourceLoc insertLoc = existingArrowLoc;
854865
if (throwsLoc.isValid() &&
855866
SourceMgr.isBeforeInBuffer(throwsLoc, insertLoc))
856867
insertLoc = throwsLoc;
857-
diagnose(Tok, diag::async_or_throws_in_wrong_position, "async")
868+
diagnose(Tok, diag::async_or_throws_in_wrong_position,
869+
(reasync && isReasync) ? "reasync" : "async")
858870
.fixItRemove(Tok.getLoc())
859-
.fixItInsert(insertLoc, "async ");
871+
.fixItInsert(insertLoc,
872+
(reasync && isReasync) ? "reasync " : "async ");
860873
} else if (throwsLoc.isValid()) {
861874
// 'async' cannot be after 'throws'.
862875
assert(existingArrowLoc.isInvalid());
863-
diagnose(Tok, diag::async_after_throws, rethrows && *rethrows)
876+
diagnose(Tok, diag::async_after_throws,
877+
reasync && isReasync,
878+
rethrows && *rethrows)
864879
.fixItRemove(Tok.getLoc())
865-
.fixItInsert(throwsLoc, "async ");
880+
.fixItInsert(throwsLoc, isReasync ? "reasync " : "async ");
866881
}
867-
if (asyncLoc.isInvalid())
882+
if (asyncLoc.isInvalid()) {
883+
if (reasync)
884+
*reasync = isReasync;
868885
asyncLoc = Tok.getLoc();
886+
}
869887
consumeToken();
870888
continue;
871889
}

lib/Parse/ParseType.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,16 +371,19 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
371371
SourceLoc asyncLoc;
372372
SourceLoc throwsLoc;
373373
if (isAtFunctionTypeArrow()) {
374-
status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc,
375-
/*rethrows=*/nullptr);
374+
status |= parseEffectsSpecifiers(SourceLoc(),
375+
asyncLoc, /*reasync=*/nullptr,
376+
throwsLoc, /*rethrows=*/nullptr);
376377
}
377378

378379
// Handle type-function if we have an arrow.
379380
if (Tok.is(tok::arrow)) {
380381
SourceLoc arrowLoc = consumeToken();
381382

382383
// Handle async/throws in the wrong place.
383-
parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc, /*rethrows=*/nullptr);
384+
parseEffectsSpecifiers(arrowLoc,
385+
asyncLoc, /*reasync=*/nullptr,
386+
throwsLoc, /*rethrows=*/nullptr);
384387

385388
ParserResult<TypeRepr> SecondHalf =
386389
parseType(diag::expected_type_function_result);

0 commit comments

Comments
 (0)