Skip to content

[5.4][diagnostics] warn about future reservation of 'await' keyword #35208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,9 @@ NOTE(super_in_closure_with_capture_here,none,
"'self' explicitly captured here", ())

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

// Tuples and parenthesized expressions
ERROR(expected_expr_in_expr_list,none,
Expand Down
24 changes: 15 additions & 9 deletions lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,16 +393,22 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
SyntaxParsingContext ElementContext(SyntaxContext,
SyntaxContextKind::Expr);

if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("await")) {
SourceLoc awaitLoc = consumeToken();
ParserResult<Expr> sub =
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
if (!sub.hasCodeCompletion() && !sub.isNull()) {
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
}
if (Tok.isContextualKeyword("await")) {
if (shouldParseExperimentalConcurrency()) {
SourceLoc awaitLoc = consumeToken();
ParserResult<Expr> sub =
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
if (!sub.hasCodeCompletion() && !sub.isNull()) {
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
}

return sub;
return sub;
} else {
// warn that future versions of Swift will parse this token differently.
diagnose(Tok.getLoc(), diag::warn_await_keyword)
.fixItReplace(Tok.getLoc(), "`await`");
}
}

SourceLoc tryLoc;
Expand Down
68 changes: 68 additions & 0 deletions test/Compatibility/unescaped_await.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// RUN: %target-typecheck-verify-swift
// now check that the fix-its, if applied, will fix the warnings.
// RUN: %empty-directory(%t.scratch)
// RUN: cp %s %t.scratch/fixits.swift
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -fixit-all -emit-fixits-path %t.scratch/fixits.remap 2> /dev/null
// RUN: %{python} %utils/apply-fixit-edits.py %t.scratch
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -warnings-as-errors
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -warnings-as-errors -enable-experimental-concurrency

// REQUIRES: concurrency

func await(_ f : () -> Void) {}

func ordinaryCalls() {
await({})
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}

await {}
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}

let _ = `await`
let _ = `await`({})

let _ = await
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}

let k = Klass()
k.await()
_ = k.await
}

func localVar() {
var await = 1

let two = await + await
// expected-warning@-1 2 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}

_ = await==two-await
// expected-warning@-1 2 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}

takesInout(await: &await)
}

func takesUnitFunc(_ f : () -> Void) {}

func takesInout(await : inout Int) {
await += 1
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
}

class Klass {
init() { await() }
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}

func await() {

takesUnitFunc(await)
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
}

func method() {
let _ = self.await
self.await()

await()
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
}
}