Skip to content

Commit 54c1e46

Browse files
authored
Merge pull request #72340 from ahoppen/ahoppen/disallow-specifier-before-param
[Parse] Disallow specifiers in front of parameter declarations
2 parents 5ae1834 + d3511c1 commit 54c1e46

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

lib/Parse/ParsePattern.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
232232
// ('inout' | '__shared' | '__owned' | isolated)?
233233
bool hasSpecifier = false;
234234
while (isParameterSpecifier()) {
235+
// Placing 'inout' in front of the parameter specifiers was allowed in
236+
// the Swift 2-ish era and got moved to the return type in Swift 3
237+
// (SE-0031).
238+
// But new parameters that don't store there location in
239+
// `SpecifierLoc` were added afterwards and didn't get diagnosed.
240+
// We thus need to parameter specifiers that don't store their location
241+
// in `SpecifierLoc` here. `SpecifierLoc` parameters get diagnosed in
242+
// `validateParameterWithOwnership`
243+
235244
// is this token the identifier of an argument label? `inout` is a
236245
// reserved keyword but the other modifiers are not.
237246
if (!Tok.is(tok::kw_inout)) {
@@ -247,6 +256,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
247256
}
248257

249258
if (Tok.isContextualKeyword("isolated")) {
259+
diagnose(Tok, diag::parameter_specifier_as_attr_disallowed, Tok.getText())
260+
.warnUntilSwiftVersion(6);
250261
// did we already find an 'isolated' type modifier?
251262
if (param.IsolatedLoc.isValid()) {
252263
diagnose(Tok, diag::parameter_specifier_repeated)
@@ -261,12 +272,16 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
261272
}
262273

263274
if (Tok.isContextualKeyword("_const")) {
275+
diagnose(Tok, diag::parameter_specifier_as_attr_disallowed, Tok.getText())
276+
.warnUntilSwiftVersion(6);
264277
param.CompileConstLoc = consumeToken();
265278
continue;
266279
}
267280

268281
if (Context.LangOpts.hasFeature(Feature::TransferringArgsAndResults) &&
269282
Tok.isContextualKeyword("transferring")) {
283+
diagnose(Tok, diag::parameter_specifier_as_attr_disallowed, Tok.getText())
284+
.warnUntilSwiftVersion(6);
270285
if (param.TransferringLoc.isValid()) {
271286
diagnose(Tok, diag::parameter_specifier_repeated)
272287
.fixItRemove(Tok.getLoc());
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// REQUIRES: concurrency
3+
4+
@available(SwiftStdlib 5.1, *)
5+
actor MyActor {}
6+
7+
class MyClass {}
8+
9+
// Lifetime specifiers before parameter names were disallowed in Swift 3 (SE-0031).
10+
// `isolated`, `transferring` and `_const` got added after Swift 3 without a diagnostic
11+
// to disallow them before parameter names.
12+
13+
func foo(inout x b: MyClass) {} // expected-error {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}
14+
15+
func foo(borrowing x b: MyClass) {} // expected-error {{'borrowing' before a parameter name is not allowed, place it before the parameter type instead}}
16+
17+
@available(SwiftStdlib 5.1, *)
18+
func foo(isolated x b: MyActor) {} // expected-warning {{'isolated' before a parameter name is not allowed, place it before the parameter type instead; this is an error in the Swift 6 language mode}}
19+
20+
func foo(_const x b: MyClass) {} // expected-warning {{'_const' before a parameter name is not allowed, place it before the parameter type instead; this is an error in the Swift 6 language mode}}
21+
22+
// expected-error@+3 {{expected ',' separator}}
23+
// expected-error@+2 {{expected ':' following argument label and parameter name}}
24+
@available(SwiftStdlib 5.1, *)
25+
func foo(transferring x b: MyActor) {}

test/Sema/const_keypath.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ struct Article {
66

77
let keypath = \Article.id
88
func keypath_generator() -> KeyPath<Article, String> { return \.id }
9-
func const_map(_const _ map: KeyPath<Article, String>) {}
9+
func const_map(_ map: _const KeyPath<Article, String>) {}
10+
func const_map_in_wrong_position(_const _ map: KeyPath<Article, String>) {} // expected-warning {{'_const' before a parameter name is not allowed, place it before the parameter type instead; this is an error in the Swift 6 language mode}}
1011

1112
const_map(\.id)
1213
const_map(\Article.id)

0 commit comments

Comments
 (0)