Skip to content

Commit ede8127

Browse files
committed
Test: Add and update tests for allowing var and let as argument labels
1 parent 2a38b48 commit ede8127

File tree

13 files changed

+91
-62
lines changed

13 files changed

+91
-62
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -852,8 +852,7 @@ ERROR(parameter_specifier_as_attr_disallowed,none,
852852
"'%0' before a parameter name is not allowed, place it before the parameter type instead",
853853
(StringRef))
854854
ERROR(parameter_specifier_repeated,none,
855-
"parameter must not have multiple '__owned', 'inout', '__shared',"
856-
" 'var', or 'let' specifiers", ())
855+
"parameter must not have multiple '__owned', 'inout', or '__shared' specifiers", ())
857856
WARNING(parameter_let_var_as_attr,none,
858857
"'%0' in this position is interpreted as an argument label",
859858
(StringRef))

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ class Parser {
587587

588588
void skipUntilDeclRBrace(tok T1, tok T2);
589589

590-
void skipListUntilDeclRBrace(tok T1, tok T2);
590+
void skipListUntilDeclRBrace(SourceLoc startLoc, tok T1, tok T2);
591591

592592
/// Skip a single token, but match parentheses, braces, and square brackets.
593593
///

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,15 +2109,7 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc) {
21092109
// the syntax for referring to the function pointer (foo(_:)),
21102110
auto escaped = Tok.isEscapedIdentifier();
21112111
auto underscore = Tok.is(tok::kw__) || (escaped && text == "_");
2112-
2113-
auto requiresEscaping = [](StringRef identifier) {
2114-
return llvm::StringSwitch<bool>(identifier)
2115-
.Case("let", false)
2116-
.Case("var", false)
2117-
.Default(canBeArgumentLabel(identifier));
2118-
};
2119-
2120-
if (escaped && !underscore && requiresEscaping(text)) {
2112+
if (escaped && !underscore && canBeArgumentLabel(text)) {
21212113
SourceLoc start = Tok.getLoc();
21222114
SourceLoc end = start.getAdvancedLoc(Tok.getLength());
21232115
diagnose(Tok, diag::escaped_parameter_name, text)

lib/Parse/Parser.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -741,23 +741,29 @@ void Parser::skipUntilDeclStmtRBrace(tok T1, tok T2) {
741741
}
742742
}
743743

744-
void Parser::skipListUntilDeclRBrace(tok T1, tok T2) {
744+
void Parser::skipListUntilDeclRBrace(SourceLoc startLoc, tok T1, tok T2) {
745745
while (Tok.isNot(T1, T2, tok::eof, tok::r_brace, tok::pound_endif,
746746
tok::pound_else, tok::pound_elseif)) {
747+
bool hasDelimiter = Tok.getLoc() == startLoc || consumeIf(tok::comma);
748+
bool possibleDeclStartsLine = Tok.isAtStartOfLine();
749+
747750
if (isStartOfDecl()) {
748751

749752
// Could have encountered something like `_ var:`
750753
// or `let foo:` or `var:`
751754
if (Tok.isAny(tok::kw_var, tok::kw_let)) {
752-
Parser::BacktrackingScope backtrack(*this);
755+
if (possibleDeclStartsLine && !hasDelimiter) {
756+
break;
757+
}
753758

759+
Parser::BacktrackingScope backtrack(*this);
754760
// Consume the let or var
755761
consumeToken();
756762

757763
// If the following token is either <identifier> or :, it means that
758764
// this `var` or `let` shoud be interpreted as a label
759765
if ((Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) ||
760-
peekToken().is(tok::colon)) {
766+
peekToken().is(tok::colon)) {
761767
backtrack.cancelBacktrack();
762768
continue;
763769
}
@@ -1028,7 +1034,7 @@ Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
10281034
// If we haven't made progress, or seeing any error, skip ahead.
10291035
if (Tok.getLoc() == StartLoc || Status.isError()) {
10301036
assert(Status.isError() && "no progress without error");
1031-
skipListUntilDeclRBrace(RightK, tok::comma);
1037+
skipListUntilDeclRBrace(LeftLoc, RightK, tok::comma);
10321038
if (Tok.is(RightK) || Tok.isNot(tok::comma))
10331039
break;
10341040
}

test/IDE/complete_escaped_keyword.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ enum MyEnum {
2727
// STATIC_PRIMARY: Begin completion
2828
// STATIC_PRIMARY-DAG: Decl[LocalVar]/Local: self[#MyEnum.Type#]; name=self
2929
// STATIC_PRIMARY-DAG: Decl[EnumElement]/CurrNominal: `class`({#struct: String#})[#MyEnum#]; name=`class`(struct: String)
30-
// STATIC_PRIMARY-DAG: Decl[EnumElement]/CurrNominal: `let`({#`var`: String#})[#MyEnum#]; name=`let`(`var`: String)
30+
// STATIC_PRIMARY-DAG: Decl[EnumElement]/CurrNominal: `let`({#var: String#})[#MyEnum#]; name=`let`(var: String)
3131
// STATIC_PRIMARY-DAG: Decl[StaticMethod]/CurrNominal: `public`({#private: String#})[#Int#]; name=`public`(private: String)
3232
// STATIC_PRIMARY-DAG: Decl[InstanceMethod]/CurrNominal: `init`({#(self): MyEnum#})[#(deinit: String) -> Int#]; name=`init`(self: MyEnum)
3333
// STATIC_PRIMARY-DAG: Decl[InstanceMethod]/CurrNominal: `if`({#(self): MyEnum#})[#(else: String) -> Int#]; name=`if`(self: MyEnum)
@@ -37,7 +37,7 @@ enum MyEnum {
3737
// STATIC_SELF_NODOT: Begin completions
3838
// STATIC_SELF_NODOT-DAG: Keyword[self]/CurrNominal: .self[#MyEnum.Type#]; name=self
3939
// STATIC_SELF_NODOT-DAG: Decl[EnumElement]/CurrNominal: .class({#struct: String#})[#MyEnum#]; name=class(struct: String)
40-
// STATIC_SELF_NODOT-DAG: Decl[EnumElement]/CurrNominal: .let({#`var`: String#})[#MyEnum#]; name=let(`var`: String)
40+
// STATIC_SELF_NODOT-DAG: Decl[EnumElement]/CurrNominal: .let({#var: String#})[#MyEnum#]; name=let(var: String)
4141
// STATIC_SELF_NODOT-DAG: Decl[Constructor]/CurrNominal: .init({#init: String#})[#MyEnum#]; name=init(init: String)
4242
// STATIC_SELF_NODOT-DAG: Decl[StaticMethod]/CurrNominal: .public({#private: String#})[#Int#]; name=public(private: String)
4343
// STATIC_SELF_NODOT-DAG: Decl[InstanceMethod]/CurrNominal: .`init`({#(self): MyEnum#})[#(deinit: String) -> Int#]; name=`init`(self: MyEnum)
@@ -48,7 +48,7 @@ enum MyEnum {
4848
// STATIC_SELF_DOT: Begin completions
4949
// STATIC_SELF_DOT-DAG: Keyword[self]/CurrNominal: self[#MyEnum.Type#]; name=self
5050
// STATIC_SELF_DOT-DAG: Decl[EnumElement]/CurrNominal: class({#struct: String#})[#MyEnum#]; name=class(struct: String)
51-
// STATIC_SELF_DOT-DAG: Decl[EnumElement]/CurrNominal: let({#`var`: String#})[#MyEnum#]; name=let(`var`: String)
51+
// STATIC_SELF_DOT-DAG: Decl[EnumElement]/CurrNominal: let({#var: String#})[#MyEnum#]; name=let(var: String)
5252
// STATIC_SELF_DOT-DAG: Decl[Constructor]/CurrNominal: init({#init: String#})[#MyEnum#]; name=init(init: String)
5353
// STATIC_SELF_DOT-DAG: Decl[StaticMethod]/CurrNominal: public({#private: String#})[#Int#]; name=public(private: String)
5454
// STATIC_SELF_DOT-DAG: Decl[InstanceMethod]/CurrNominal: `init`({#(self): MyEnum#})[#(deinit: String) -> Int#]; name=`init`(self: MyEnum)

test/IDE/print_ast_tc_decls.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ struct d0200_EscapedIdentifiers {
622622
// PASS_COMMON-NEXT: {{^}} @_hasInitialValue var `var`: {{(d0200_EscapedIdentifiers.)?}}`struct`{{$}}
623623

624624
var tupleType: (`var`: Int, `let`: `struct`)
625-
// PASS_COMMON-NEXT: {{^}} var tupleType: (`var`: Int, `let`: {{(d0200_EscapedIdentifiers.)?}}`struct`){{$}}
625+
// PASS_COMMON-NEXT: {{^}} var tupleType: (var: Int, let: {{(d0200_EscapedIdentifiers.)?}}`struct`){{$}}
626626

627627
var accessors1: Int {
628628
get { return 0 }
@@ -633,7 +633,7 @@ struct d0200_EscapedIdentifiers {
633633
static func `static`(protocol: Int) {}
634634
// PASS_COMMON-NEXT: {{^}} static func `static`(protocol: Int){{$}}
635635

636-
// PASS_COMMON-NEXT: {{^}} init(`var`: {{(d0200_EscapedIdentifiers.)?}}`struct` = {{(d0200_EscapedIdentifiers.)?}}`struct`(), tupleType: (`var`: Int, `let`: {{(d0200_EscapedIdentifiers.)?}}`struct`)){{$}}
636+
// PASS_COMMON-NEXT: {{^}} init(var: {{(d0200_EscapedIdentifiers.)?}}`struct` = {{(d0200_EscapedIdentifiers.)?}}`struct`(), tupleType: (var: Int, let: {{(d0200_EscapedIdentifiers.)?}}`struct`)){{$}}
637637
// PASS_COMMON-NEXT: {{^}}}{{$}}
638638
}
639639

test/Parse/invalid.swift

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,23 +84,15 @@ func SR698(_ a: Int, b: Int) {}
8484
SR698(1, b: 2,) // expected-error {{unexpected ',' separator}}
8585

8686
// SR-979 - Two inout crash compiler
87-
func SR979a(a : inout inout Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{17-23=}}
87+
func SR979a(a : inout inout Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', or '__shared' specifiers}} {{17-23=}}
8888
func SR979b(inout inout b: Int) {} // expected-error {{inout' before a parameter name is not allowed, place it before the parameter type instead}} {{13-18=}} {{28-28=inout }}
89-
// expected-error@-1 {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{19-25=}}
90-
func SR979c(let a: inout Int) {} // expected-warning {{'let' in this position is interpreted as an argument label}} {{13-16=`let`}}
89+
// expected-error@-1 {{parameter must not have multiple '__owned', 'inout', or '__shared' specifiers}} {{19-25=}}
9190
func SR979d(let let a: Int) {} // expected-warning {{'let' in this position is interpreted as an argument label}} {{13-16=`let`}}
9291
// expected-error @-1 {{expected ',' separator}} {{20-20=,}}
9392
// expected-error @-2 {{parameter requires an explicit type}}
9493
// expected-warning @-3 {{extraneous duplicate parameter name; 'let' already has an argument label}} {{13-17=}}
95-
func SR979e(inout x: inout String) {} // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{13-18=}}
96-
func SR979g(inout i: inout Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{13-18=}}
97-
class VarTester {
98-
init(var a: Int, var b: Int) {} // expected-warning {{'var' in this position is interpreted as an argument label}} {{8-11=`var`}}
99-
// expected-warning @-1 {{'var' in this position is interpreted as an argument label}} {{20-23=`var`}}
100-
func x(var b: Int) { //expected-warning {{'var' in this position is interpreted as an argument label}} {{10-13=`var`}}
101-
b += 10 // expected-error {{left side of mutating operator isn't mutable: 'b' is a 'let' constant}}
102-
}
103-
}
94+
func SR979e(inout x: inout String) {} // expected-error {{parameter must not have multiple '__owned', 'inout', or '__shared' specifiers}} {{13-18=}}
95+
func SR979g(inout i: inout Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', or '__shared' specifiers}} {{13-18=}}
10496

10597
func repeat() {}
10698
// expected-error @-1 {{keyword 'repeat' cannot be used as an identifier here}}

test/Sema/immutability.swift

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func test_mutability() {
232232

233233
func test_arguments(_ a : Int,
234234
b : Int,
235-
let c : Int) { // expected-error {{'let' as a parameter attribute is not allowed}} {{21-25=}}
235+
let c : Int) { // expected-warning {{'let' in this position is interpreted as an argument label}} {{21-24=`let`}}
236236
var b = b
237237
a = 1 // expected-error {{cannot assign to value: 'a' is a 'let' constant}}
238238
b = 2 // ok.
@@ -354,7 +354,7 @@ protocol SubscriptNoGetter {
354354
subscript (i: Int) -> Int { get }
355355
}
356356

357-
func testSubscriptNoGetter(let iis: SubscriptNoGetter) { // expected-error {{'let' as a parameter attribute is not allowed}}{{28-31=}}
357+
func testSubscriptNoGetter(let iis: SubscriptNoGetter) { // expected-warning {{'let' in this position is interpreted as an argument label}}{{28-31=`let`}}
358358
var _: Int = iis[17]
359359
}
360360

@@ -367,24 +367,30 @@ func testSelectorStyleArguments1(_ x: Int, bar y: Int) {
367367
_ = y
368368
}
369369

370-
func testSelectorStyleArguments2(let x: Int, // expected-error {{'let' as a parameter attribute is not allowed}}{{34-37=}}
371-
let bar y: Int) { // expected-error {{'let' as a parameter attribute is not allowed}}{{34-38=}}
372-
373-
370+
func testSelectorStyleArguments2(let x: Int, // expected-warning {{'let' in this position is interpreted as an argument label}}{{34-37=`let`}}
371+
let bar y: Int) { // expected-warning {{'let' in this position is interpreted as an argument label}}{{34-37=`let`}}
372+
// expected-error @-1 {{expected ',' separator}}
373+
// expected-error @-2 {{parameter requires an explicit type}}
374374
}
375375
func testSelectorStyleArguments3(_ x: Int, bar y: Int) {
376376
++x // expected-error {{cannot pass immutable value to mutating operator: 'x' is a 'let' constant}}
377377
++y // expected-error {{cannot pass immutable value to mutating operator: 'y' is a 'let' constant}}
378378
}
379379

380-
func invalid_inout(inout var x : Int) { // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{26-30=}}
381-
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}{{20-25=}}{{34-34=inout }}
380+
func invalid_inout(inout var x : Int) { // expected-warning {{'var' in this position is interpreted as an argument label}} {{26-29=`var`}}
381+
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}} {{20-25=}} {{34-34=inout }}
382382
}
383-
func invalid_var(var x: Int) { // expected-error {{'var' as a parameter attribute is not allowed}}
384-
383+
384+
class VarTester {
385+
init(var a: Int, var b: Int) {} // expected-warning {{'var' in this position is interpreted as an argument label}} {{8-11=`var`}}
386+
// expected-warning @-1 {{'var' in this position is interpreted as an argument label}} {{20-23=`var`}}
387+
func x(var b: Int) { //expected-warning {{'var' in this position is interpreted as an argument label}} {{10-13=`var`}}
388+
b += 10 // expected-error {{left side of mutating operator isn't mutable: 'b' is a 'let' constant}}
389+
}
385390
}
391+
386392
func takesClosure(_: (Int) -> Int) {
387-
takesClosure { (var d) in d } // expected-error {{'var' as a parameter attribute is not allowed}}
393+
takesClosure { (var d) in d } // expected-error {{closure cannot have keyword arguments}}
388394
}
389395

390396
func updateInt(_ x : inout Int) {}
@@ -501,9 +507,6 @@ struct StructWithDelegatingInit {
501507
init() { self.init(x: 0); self.x = 22 } // expected-error {{'let' property 'x' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
502508
}
503509

504-
func test_recovery_missing_name_2(let: Int) {} // expected-error {{'let' as a parameter attribute is not allowed}}{{35-38=}}
505-
// expected-error @-1 {{expected parameter name followed by ':'}}
506-
507510
// <rdar://problem/16792027> compiler infinite loops on a really really mutating function
508511
struct F { // expected-note 1 {{in declaration of 'F'}}
509512
mutating mutating mutating f() { // expected-error 2 {{duplicate modifier}} expected-note 2 {{modifier already specified here}} expected-error {{expected declaration}}

test/decl/class/override.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ class H : G {
169169

170170
@objc func manyA(_: AnyObject, _: AnyObject) {}
171171
@objc func manyB(_ a: AnyObject, b: AnyObject) {}
172-
@objc func manyC(var a: AnyObject, // expected-error {{'var' as a parameter attribute is not allowed}}
173-
var b: AnyObject) {} // expected-error {{'var' as a parameter attribute is not allowed}}
172+
@objc func manyC(var a: AnyObject, // expected-warning {{'var' in this position is interpreted as an argument label}} {{20-23=`var`}}
173+
var b: AnyObject) {} // expected-warning {{'var' in this position is interpreted as an argument label}} {{20-23=`var`}}
174174

175175
@objc func result() -> AnyObject? { return nil }
176176
@objc func both(_ x: AnyObject) -> AnyObject? { return x }

test/decl/func/arg_rename.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,38 @@ f1(a: 1, b: 2)
2525
func f2(class cls: Int) { }
2626
f2(class: 5)
2727

28+
func f3(var a: Int) {} // expected-warning {{'var' in this position is interpreted as an argument label}} {{9-12=`var`}}
29+
f3(var: 5)
2830

31+
func f4(let a: Int) {} // expected-warning {{'let' in this position is interpreted as an argument label}} {{9-12=`let`}}
32+
f4(let: 5)
2933

30-
func g2(a a: Int) { } // expected-warning{{extraneous duplicate parameter name; 'a' already has an argument label}}{{9-11=}}
34+
func f5(a var: Int) {}
35+
f5(a: 5)
3136

32-
func g5(_ a: Int) { }
37+
func f6(a let: Int) {}
38+
f6(a: 5)
39+
40+
func f7(var let: Int) { // expected-warning {{'var' in this position is interpreted as an argument label}} {{9-12=`var`}}
41+
let _ = `let`
42+
}
43+
f7(var: 5)
44+
45+
func f8(let var: Int) { // expected-warning {{'let' in this position is interpreted as an argument label}} {{9-12=`let`}}
46+
let _ = `var`
47+
}
48+
f8(let: 5)
49+
50+
51+
func g1(a a: Int) { } // expected-warning{{extraneous duplicate parameter name; 'a' already has an argument label}}{{9-11=}}
52+
53+
func g2(_ a: Int) { }
54+
55+
func g3(var var: Int) {} // expected-warning {{'var' in this position is interpreted as an argument label}} {{9-12=`var`}}
56+
// expected-warning @-1 {{extraneous duplicate parameter name; 'var' already has an argument label}}{{9-13=}}
57+
58+
func g4(let let: Int) {} // expected-warning {{'let' in this position is interpreted as an argument label}} {{9-12=`let`}}
59+
// expected-warning @-1 {{extraneous duplicate parameter name; 'let' already has an argument label}}{{9-13=}}
3360

3461
class X {
3562
init(a a: Int) { } // expected-warning{{extraneous duplicate parameter name; 'a' already has an argument label}}{{8-10=}}

test/decl/func/functions.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,13 @@ func testObjCMethodCurry(_ a : ClassWithObjCMethod) -> (Int) -> () {
123123
}
124124

125125
// We used to crash on this.
126-
func rdar16786220(inout let c: Int) -> () { // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{25-29=}}
126+
func rdar16786220(inout let c: Int) -> () { // expected-warning {{'let' in this position is interpreted as an argument label}} {{25-28=`let`}}
127127
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}{{19-24=}}{{32-32=inout }}
128128

129129
c = 42
130130
}
131131

132+
func multipleSpecifiers(a: inout __owned Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', or '__shared' specifiers}} {{28-34=}}
132133

133134
// <rdar://problem/17763388> ambiguous operator emits same candidate multiple times
134135
infix operator !!!
@@ -139,8 +140,8 @@ _ = [1] !!! [1] // unambiguously picking the array overload.
139140

140141

141142
// <rdar://problem/16786168> Functions currently permit 'var inout' parameters
142-
func var_inout_error(inout var x : Int) {} // expected-error {{parameter must not have multiple '__owned', 'inout', '__shared', 'var', or 'let' specifiers}} {{28-32=}}
143-
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}} {{22-27=}}{{36-36=inout }}
143+
func inout_error(inout var x : Int) {} // expected-warning {{'var' in this position is interpreted as an argument label}} {{24-27=`var`}}
144+
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}} {{18-23=}}{{32-32=inout }}
144145

145146
// Unnamed parameters require the name "_":
146147
func unnamed(Int) { } // expected-error{{unnamed parameters must be written with the empty name '_'}}{{14-14=_: }}

test/decl/var/usage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func basicTests() -> Int {
1212
return y
1313
}
1414

15-
func mutableParameter(_ a : Int, h : Int, var i : Int, j: Int, g: Int) -> Int { // expected-error {{'var' as a parameter attribute is not allowed}}
15+
func mutableParameter(_ a : Int, h : Int, var i : Int, j: Int, g: Int) -> Int { // expected-warning {{'var' in this position is interpreted as an argument label}} {{43-46=`var`}}
1616
i += 1 // expected-error {{left side of mutating operator isn't mutable: 'i' is a 'let' constant}}
1717
var j = j
1818
swap(&i, &j) // expected-error {{cannot pass immutable value as inout argument: 'i' is a 'let' constant}}

0 commit comments

Comments
 (0)