Skip to content

Commit 179474e

Browse files
authored
Merge pull request #35153 from kavon/warn-unqualified-await
[concurrency] warn about future reservation of 'await' as contextual keyword
2 parents e1f7bd2 + fa0c01f commit 179474e

File tree

3 files changed

+86
-9
lines changed

3 files changed

+86
-9
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,9 @@ NOTE(super_in_closure_with_capture_here,none,
12241224
"'self' explicitly captured here", ())
12251225

12261226
ERROR(try_before_await,none, "'await' must precede 'try'", ())
1227+
WARNING(warn_await_keyword,none,
1228+
"future versions of Swift reserve the word 'await'; "
1229+
"if this name is unavoidable, use backticks to escape it", ())
12271230

12281231
// Tuples and parenthesized expressions
12291232
ERROR(expected_expr_in_expr_list,none,

lib/Parse/ParseExpr.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,16 +399,22 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
399399
SyntaxParsingContext ElementContext(SyntaxContext,
400400
SyntaxContextKind::Expr);
401401

402-
if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("await")) {
403-
SourceLoc awaitLoc = consumeToken();
404-
ParserResult<Expr> sub =
405-
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
406-
if (!sub.hasCodeCompletion() && !sub.isNull()) {
407-
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
408-
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
409-
}
402+
if (Tok.isContextualKeyword("await")) {
403+
if (shouldParseExperimentalConcurrency()) {
404+
SourceLoc awaitLoc = consumeToken();
405+
ParserResult<Expr> sub =
406+
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
407+
if (!sub.hasCodeCompletion() && !sub.isNull()) {
408+
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
409+
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
410+
}
410411

411-
return sub;
412+
return sub;
413+
} else {
414+
// warn that future versions of Swift will parse this token differently.
415+
diagnose(Tok.getLoc(), diag::warn_await_keyword)
416+
.fixItReplace(Tok.getLoc(), "`await`");
417+
}
412418
}
413419

414420
SourceLoc tryLoc;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// now check that the fix-its, if applied, will fix the warnings.
3+
// RUN: %empty-directory(%t.scratch)
4+
// RUN: cp %s %t.scratch/fixits.swift
5+
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -fixit-all -emit-fixits-path %t.scratch/fixits.remap 2> /dev/null
6+
// RUN: %{python} %utils/apply-fixit-edits.py %t.scratch
7+
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -warnings-as-errors
8+
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -warnings-as-errors -enable-experimental-concurrency
9+
10+
// REQUIRES: concurrency
11+
12+
func await(_ f : () -> Void) {}
13+
14+
func ordinaryCalls() {
15+
await({})
16+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
17+
18+
await {}
19+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
20+
21+
let _ = `await`
22+
let _ = `await`({})
23+
24+
let _ = await
25+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
26+
27+
let k = Klass()
28+
k.await()
29+
_ = k.await
30+
}
31+
32+
func localVar() {
33+
var await = 1
34+
35+
let two = await + await
36+
// expected-warning@-1 2 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
37+
38+
_ = await==two-await
39+
// expected-warning@-1 2 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
40+
41+
takesInout(await: &await)
42+
}
43+
44+
func takesUnitFunc(_ f : () -> Void) {}
45+
46+
func takesInout(await : inout Int) {
47+
await += 1
48+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
49+
}
50+
51+
class Klass {
52+
init() { await() }
53+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
54+
55+
func await() {
56+
57+
takesUnitFunc(await)
58+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
59+
}
60+
61+
func method() {
62+
let _ = self.await
63+
self.await()
64+
65+
await()
66+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
67+
}
68+
}

0 commit comments

Comments
 (0)