Skip to content

Commit dd075c6

Browse files
committed
[Concurrency] Treat 'await' as a contextual keyword.
Replace the uglified '__await' keyword with a contextual keyword 'await'. This is more of what we would actually want for the concurrency model. When concurrency is enabled, this will be a source-breaking change, because this is valid Swift code today: ```swift struct MyFuture<T> { func await() -> } func doSomething() { let result = await() } } ``` but the call to `await()` will be parsed as an await expression when concurrency is enabled. The source break is behind the experimental concurrency flag, but this way we can see how much of an issue it is in practice.
1 parent 8c6e704 commit dd075c6

File tree

6 files changed

+40
-24
lines changed

6 files changed

+40
-24
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
379379
/// parseExprSequenceElement
380380
///
381381
/// expr-sequence-element(Mode):
382-
/// '__await' expr-sequence-element(Mode)
382+
/// 'await' expr-sequence-element(Mode)
383383
/// 'try' expr-sequence-element(Mode)
384384
/// 'try' '?' expr-sequence-element(Mode)
385385
/// 'try' '!' expr-sequence-element(Mode)
@@ -392,8 +392,8 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
392392
SyntaxParsingContext ElementContext(SyntaxContext,
393393
SyntaxContextKind::Expr);
394394

395-
if (shouldParseExperimentalConcurrency() && Tok.is(tok::kw___await)) {
396-
SourceLoc awaitLoc = consumeToken(tok::kw___await);
395+
if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("await")) {
396+
SourceLoc awaitLoc = consumeToken();
397397
ParserResult<Expr> sub = parseExprUnary(message, isExprBasic);
398398
if (!sub.hasCodeCompletion() && !sub.isNull()) {
399399
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);

test/Parse/async-syntax.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ func testTypeExprs() {
1212
}
1313

1414
func testAwaitOperator() async {
15-
let _ = __await asyncGlobal1()
15+
let _ = await asyncGlobal1()
1616
}
1717

1818
func testAsyncClosure() {
1919
let _ = { () async in 5 }
2020
let _ = { () throws in 5 }
2121
let _ = { () async throws in 5 }
2222
}
23+
24+
func testAwait() async {
25+
let _ = await asyncGlobal1()
26+
}

test/Parse/async.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,14 @@ func testTypeExprs() {
4141

4242
let _ = [() -> async ()]() // expected-error{{'async' may only occur before '->'}}{{18-24=}}{{15-15=async }}
4343
}
44+
45+
// Parsing await syntax.
46+
struct MyFuture {
47+
func await() -> Int { 0 }
48+
}
49+
50+
func testAwaitExpr() async {
51+
let _ = await asyncGlobal1()
52+
let myFuture = MyFuture()
53+
let _ = myFuture.await()
54+
}

test/expr/unary/async_await.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
11
// RUN: %target-swift-frontend -typecheck -verify %s -enable-experimental-concurrency
22

33
func test1(asyncfp : () async -> Int, fp : () -> Int) async {
4-
_ = __await asyncfp()
5-
_ = __await asyncfp() + asyncfp()
6-
_ = __await asyncfp() + fp()
7-
_ = __await fp() + 42 // expected-warning {{no calls to 'async' functions occur within 'await' expression}}
4+
_ = await asyncfp()
5+
_ = await asyncfp() + asyncfp()
6+
_ = await asyncfp() + fp()
7+
_ = await fp() + 42 // expected-warning {{no calls to 'async' functions occur within 'await' expression}}
88
_ = asyncfp() // expected-error {{call is 'async' but is not marked with 'await'}}
99
}
1010

1111
func getInt() async -> Int { return 5 }
1212

1313
// Locations where "await" is prohibited.
1414
func test2(
15-
defaulted: Int = __await getInt() // expected-error{{'async' call cannot occur in a default argument}}
15+
defaulted: Int = await getInt() // expected-error{{'async' call cannot occur in a default argument}}
1616
) async {
1717
defer {
18-
_ = __await getInt() // expected-error{{'async' call cannot occur in a defer body}}
18+
_ = await getInt() // expected-error{{'async' call cannot occur in a defer body}}
1919
}
2020
print("foo")
2121
}
2222

2323
func test3() { // expected-note{{add 'async' to function 'test3()' to make it asynchronous}}
24-
_ = __await getInt() // expected-error{{'async' in a function that does not support concurrency}}
24+
_ = await getInt() // expected-error{{'async' in a function that does not support concurrency}}
2525
}
2626

2727
enum SomeEnum: Int {
28-
case foo = __await 5 // expected-error{{raw value for enum case must be a literal}}
28+
case foo = await 5 // expected-error{{raw value for enum case must be a literal}}
2929
}
3030

3131
struct SomeStruct {
32-
var x = __await getInt() // expected-error{{'async' call cannot occur in a property initializer}}
33-
static var y = __await getInt() // expected-error{{'async' call cannot occur in a global variable initializer}}
32+
var x = await getInt() // expected-error{{'async' call cannot occur in a property initializer}}
33+
static var y = await getInt() // expected-error{{'async' call cannot occur in a global variable initializer}}
3434
}
3535

3636
func acceptAutoclosureNonAsync(_: @autoclosure () -> Int) async { }
@@ -46,27 +46,27 @@ struct HasAsyncBad {
4646
}
4747

4848
func testAutoclosure() async {
49-
__await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
50-
__await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
49+
await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
50+
await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
5151

52-
__await acceptAutoclosureAsync(__await getInt())
53-
__await acceptAutoclosureNonAsync(__await getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
52+
await acceptAutoclosureAsync(await getInt())
53+
await acceptAutoclosureNonAsync(await getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
5454

55-
__await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
56-
__await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
55+
await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
56+
await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
5757
}
5858

5959
// Test inference of 'async' from the body of a closure.
6060
func testClosure() {
6161
let closure = {
62-
__await getInt()
62+
await getInt()
6363
}
6464

6565
let _: () -> Int = closure // expected-error{{cannot convert value of type '() async -> Int' to specified type '() -> Int'}}
6666

6767
let closure2 = { () async -> Int in
6868
print("here")
69-
return __await getInt()
69+
return await getInt()
7070
}
7171

7272
let _: () -> Int = closure2 // expected-error{{cannot convert value of type '() async -> Int' to specified type '() -> Int'}}

utils/gyb_syntax_support/ExprNodes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
# await foo()
5050
Node('AwaitExpr', kind='Expr',
5151
children=[
52-
Child('AwaitKeyword', kind='AwaitToken'),
52+
Child('AwaitKeyword', kind='IdentifierToken',
53+
classification='Keyword',
54+
text_choices=['await']),
5355
Child('Expression', kind='Expr'),
5456
]),
5557

utils/gyb_syntax_support/Token.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ def macro_name(self):
196196
ExprKeyword('True', 'true', serialization_code=51),
197197
ExprKeyword('Try', 'try', serialization_code=52),
198198
ExprKeyword('Throws', 'throws', serialization_code=53),
199-
ExprKeyword('Await', '__await', serialization_code=123),
200199

201200
Keyword('__FILE__', '__FILE__', serialization_code=54),
202201
Keyword('__LINE__', '__LINE__', serialization_code=55),

0 commit comments

Comments
 (0)